diff options
308 files changed, 30069 insertions, 15820 deletions
diff --git a/OsuLogin/Android.bp b/OsuLogin/Android.bp index 864883f443..ff8748c31e 100644 --- a/OsuLogin/Android.bp +++ b/OsuLogin/Android.bp @@ -15,6 +15,9 @@ android_app { "com.android.wifi", "test_com.android.wifi", ], + optimize: { + shrink_resources: true, + }, } android_app_certificate { diff --git a/WifiDialog/Android.bp b/WifiDialog/Android.bp index 8a9de613cf..1941294fa8 100644 --- a/WifiDialog/Android.bp +++ b/WifiDialog/Android.bp @@ -35,7 +35,10 @@ android_app { apex_available: [ "com.android.wifi", "test_com.android.wifi", - ] + ], + optimize: { + shrink_resources: true, + }, } android_app_certificate { diff --git a/WifiDialog/AndroidManifest.xml b/WifiDialog/AndroidManifest.xml index 66132822c6..dfeafabda0 100644 --- a/WifiDialog/AndroidManifest.xml +++ b/WifiDialog/AndroidManifest.xml @@ -42,6 +42,7 @@ android:configChanges="keyboardHidden|screenSize" android:hardwareAccelerated="true" android:launchMode="singleInstance" + android:excludeFromRecents="true" android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" /> </application> </manifest> diff --git a/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java b/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java index b73bee04be..c73afa9134 100644 --- a/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java +++ b/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java @@ -37,7 +37,6 @@ import android.os.CountDownTimer; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; -import android.os.Process; import android.os.SystemClock; import android.os.Vibrator; import android.text.Editable; @@ -72,8 +71,6 @@ import java.util.Set; * Main Activity of the WifiDialog application. All dialogs should be created and managed from here. */ public class WifiDialogActivity extends Activity { - private static int sNumActiveInstances = 0; - private static final String TAG = "WifiDialog"; private static final String KEY_DIALOG_INTENTS = "KEY_DIALOG_INTENTS"; private static final String EXTRA_DIALOG_EXPIRATION_TIME_MS = @@ -213,10 +210,6 @@ public class WifiDialogActivity extends Activity { @Override protected void onStart() { super.onStart(); - sNumActiveInstances++; - if (mIsVerboseLoggingEnabled) { - Log.v(TAG, "onStart() incrementing sActiveInstances to " + sNumActiveInstances); - } registerReceiver( mCloseSystemDialogsReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); ArraySet<Integer> invalidDialogIds = new ArraySet<>(); @@ -260,10 +253,6 @@ public class WifiDialogActivity extends Activity { @Override protected void onStop() { super.onStop(); - sNumActiveInstances--; - if (mIsVerboseLoggingEnabled) { - Log.v(TAG, "onStop() decrementing sActiveInstances to " + sNumActiveInstances); - } unregisterReceiver(mCloseSystemDialogsReceiver); if (isChangingConfigurations()) { @@ -328,28 +317,11 @@ public class WifiDialogActivity extends Activity { } } - @Override - protected void onDestroy() { - super.onDestroy(); - if (isFinishing()) { - if (sNumActiveInstances > 0) { - if (mIsVerboseLoggingEnabled) { - Log.v(TAG, "Finished with sNumActiveInstances: " + sNumActiveInstances); - } - return; - } - if (mIsVerboseLoggingEnabled) { - Log.v(TAG, "Finished with no active instances left. Killing process."); - } - Process.killProcess(android.os.Process.myPid()); - } - } - /** * Creates and shows a dialog for the given dialogId and Intent. * Returns {@code true} if the dialog was successfully created, {@code false} otherwise. */ - private @Nullable boolean createAndShowDialogForIntent(int dialogId, @NonNull Intent intent) { + private boolean createAndShowDialogForIntent(int dialogId, @NonNull Intent intent) { String action = intent.getAction(); if (!WifiManager.ACTION_LAUNCH_DIALOG.equals(action)) { return false; @@ -389,9 +361,6 @@ public class WifiDialogActivity extends Activity { } return false; } - if (dialog == null) { - return false; - } dialog.setOnDismissListener((dialogDismiss) -> { if (mIsVerboseLoggingEnabled) { Log.v(TAG, "Dialog id=" + dialogId @@ -480,9 +449,9 @@ public class WifiDialogActivity extends Activity { } /** - * Returns a simple dialog for the given Intent, or {@code null} if no dialog could be created. + * Returns a simple dialog for the given Intent. */ - private @Nullable AlertDialog createSimpleDialog( + private @NonNull AlertDialog createSimpleDialog( int dialogId, @Nullable String title, @Nullable String message, @@ -495,10 +464,18 @@ public class WifiDialogActivity extends Activity { SpannableString spannableMessage = null; if (message != null) { spannableMessage = new SpannableString(message); - if (messageUrlStart >= 0 && messageUrlEnd <= message.length() - && messageUrlStart < messageUrlEnd) { - spannableMessage.setSpan(new URLSpan(messageUrl), messageUrlStart, messageUrlEnd, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (messageUrl != null) { + if (messageUrlStart < 0) { + Log.w(TAG, "Span start cannot be less than 0!"); + } else if (messageUrlEnd > message.length()) { + Log.w(TAG, "Span end index " + messageUrlEnd + + " cannot be greater than message length " + message.length() + "!"); + } else if (messageUrlStart > messageUrlEnd) { + Log.w(TAG, "Span start index cannot be greater than end index!"); + } else { + spannableMessage.setSpan(new URLSpan(messageUrl), messageUrlStart, + messageUrlEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } } } AlertDialog dialog = new AlertDialog.Builder( @@ -552,27 +529,21 @@ public class WifiDialogActivity extends Activity { } /** - * Returns a P2P Invitation Sent Dialog for the given Intent, or {@code null} if no Dialog - * could be created. + * Returns a P2P Invitation Sent Dialog for the given Intent. */ - private @Nullable AlertDialog createP2pInvitationSentDialog( + private @NonNull AlertDialog createP2pInvitationSentDialog( final int dialogId, - final @NonNull String deviceName, - @Nullable String displayPin) { - if (TextUtils.isEmpty(deviceName)) { - if (mIsVerboseLoggingEnabled) { - Log.v(TAG, "Could not create P2P Invitation Sent dialog with null or empty" - + " device name." - + " id=" + dialogId - + " deviceName=" + deviceName - + " displayPin=" + displayPin); - } - return null; - } - + @Nullable final String deviceName, + @Nullable final String displayPin) { final View textEntryView = LayoutInflater.from(this) .inflate(getLayoutId("wifi_p2p_dialog"), null); ViewGroup group = textEntryView.findViewById(getViewId("info")); + if (TextUtils.isEmpty(deviceName)) { + Log.w(TAG, "P2P Invitation Sent dialog device name is null or empty." + + " id=" + dialogId + + " deviceName=" + deviceName + + " displayPin=" + displayPin); + } addRowToP2pDialog(group, getStringId("wifi_p2p_to_message"), deviceName); if (displayPin != null) { @@ -601,29 +572,22 @@ public class WifiDialogActivity extends Activity { } /** - * Returns a P2P Invitation Received Dialog for the given Intent, or {@code null} if no Dialog - * could be created. + * Returns a P2P Invitation Received Dialog for the given Intent. */ - private @Nullable AlertDialog createP2pInvitationReceivedDialog( + private @NonNull AlertDialog createP2pInvitationReceivedDialog( final int dialogId, - final @NonNull String deviceName, + @Nullable final String deviceName, final boolean isPinRequested, - @Nullable String displayPin) { - if (TextUtils.isEmpty(deviceName)) { - if (mIsVerboseLoggingEnabled) { - Log.v(TAG, "Could not create P2P Invitation Received dialog with null or empty" - + " device name." - + " id=" + dialogId - + " deviceName=" + deviceName - + " isPinRequested=" + isPinRequested - + " displayPin=" + displayPin); - } - return null; - } - + @Nullable final String displayPin) { final View textEntryView = LayoutInflater.from(this) .inflate(getLayoutId("wifi_p2p_dialog"), null); ViewGroup group = textEntryView.findViewById(getViewId("info")); + if (TextUtils.isEmpty(deviceName)) { + Log.w(TAG, "P2P Invitation Received dialog device name is null or empty." + + " id=" + dialogId + + " deviceName=" + deviceName + + " displayPin=" + displayPin); + } addRowToP2pDialog(group, getStringId("wifi_p2p_from_message"), deviceName); final EditText pinEditText; diff --git a/framework/Android.bp b/framework/Android.bp index 3c1d0a0fdf..f2ea514792 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -19,7 +19,6 @@ package { java_defaults { name: "wifi-module-sdk-version-defaults", min_sdk_version: "30", - target_sdk_version: "33", } filegroup { @@ -104,6 +103,7 @@ java_defaults { "app-compat-annotations", ], aidl: { + generate_get_transaction_name: true, include_dirs: [ "packages/modules/Connectivity/framework/aidl-export", ], @@ -121,8 +121,6 @@ java_library { defaults: ["framework-wifi-defaults"], sdk_version: "module_current", libs: ["framework-annotations-lib"], - // java_api_finder must accompany `srcs` (`srcs` defined in `framework-wifi-defaults`) - plugins: ["java_api_finder"], installable: false, visibility: [ "//frameworks/opt/net/wifi/service", diff --git a/framework/api/current.txt b/framework/api/current.txt index f78a462c90..8bda5fa395 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -137,6 +137,21 @@ package android.net.wifi { enum_constant public static final android.net.wifi.SupplicantState UNINITIALIZED; } + public final class WifiAvailableChannel implements android.os.Parcelable { + ctor public WifiAvailableChannel(int, int); + method public int describeContents(); + method public int getFrequencyMhz(); + method public int getOperationalModes(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiAvailableChannel> CREATOR; + field public static final int OP_MODE_SAP = 2; // 0x2 + field public static final int OP_MODE_STA = 1; // 0x1 + field public static final int OP_MODE_TDLS = 32; // 0x20 + field public static final int OP_MODE_WIFI_AWARE = 16; // 0x10 + field public static final int OP_MODE_WIFI_DIRECT_CLI = 4; // 0x4 + field public static final int OP_MODE_WIFI_DIRECT_GO = 8; // 0x8 + } + @Deprecated public class WifiConfiguration implements android.os.Parcelable { ctor @Deprecated public WifiConfiguration(); ctor @Deprecated public WifiConfiguration(@NonNull android.net.wifi.WifiConfiguration); @@ -273,6 +288,7 @@ package android.net.wifi { method public String getDomainSuffixMatch(); method public int getEapMethod(); method public String getIdentity(); + method public int getMinimumTlsVersion(); method public String getPassword(); method public int getPhase2Method(); method public String getPlmn(); @@ -294,6 +310,7 @@ package android.net.wifi { method public void setDomainSuffixMatch(String); method public void setEapMethod(int); method public void setIdentity(String); + method public void setMinimumTlsVersion(int) throws java.lang.IllegalArgumentException; method public void setPassword(String); method public void setPhase2Method(int); method public void setPlmn(String); @@ -305,6 +322,10 @@ package android.net.wifi { field public static final String EXTRA_WAPI_AS_CERTIFICATE_NAME = "android.net.wifi.extra.WAPI_AS_CERTIFICATE_NAME"; field public static final String EXTRA_WAPI_USER_CERTIFICATE_DATA = "android.net.wifi.extra.WAPI_USER_CERTIFICATE_DATA"; field public static final String EXTRA_WAPI_USER_CERTIFICATE_NAME = "android.net.wifi.extra.WAPI_USER_CERTIFICATE_NAME"; + field public static final int TLS_V1_0 = 0; // 0x0 + field public static final int TLS_V1_1 = 1; // 0x1 + field public static final int TLS_V1_2 = 2; // 0x2 + field public static final int TLS_V1_3 = 3; // 0x3 field public static final String WAPI_AS_CERTIFICATE = "WAPIAS_"; field public static final String WAPI_USER_CERTIFICATE = "WAPIUSR_"; } @@ -411,16 +432,19 @@ package android.net.wifi { method @Deprecated public boolean disconnect(); method @Deprecated public boolean enableNetwork(int, boolean); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}, conditional=true) public void flushPasspointAnqpCache(); + method @NonNull @RequiresPermission(android.Manifest.permission.NEARBY_WIFI_DEVICES) public java.util.List<android.net.wifi.WifiAvailableChannel> getAllowedChannels(int, int); method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiConfiguration> getCallerConfiguredNetworks(); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks(); method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public android.net.wifi.WifiInfo getConnectionInfo(); method @Deprecated public android.net.DhcpInfo getDhcpInfo(); + method public int getMaxNumberOfChannelsPerNetworkSpecifierRequest(); method public int getMaxNumberOfNetworkSuggestionsPerApp(); method @IntRange(from=0) public int getMaxSignalLevel(); method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions(); method @Deprecated public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations(); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public java.util.List<android.net.wifi.ScanResult> getScanResults(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getStaConcurrencyForMultiInternetMode(); + method @NonNull @RequiresPermission(android.Manifest.permission.NEARBY_WIFI_DEVICES) public java.util.List<android.net.wifi.WifiAvailableChannel> getUsableChannels(int, int); method public int getWifiState(); method public boolean is24GHzBandSupported(); method public boolean is5GHzBandSupported(); @@ -431,6 +455,7 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isCarrierNetworkOffloadEnabled(int, boolean); method public boolean isDecoratedIdentitySupported(); method @Deprecated public boolean isDeviceToApRttSupported(); + method public boolean isDualBandSimultaneousSupported(); method public boolean isEasyConnectDppAkmSupported(); method public boolean isEasyConnectEnrolleeResponderModeSupported(); method public boolean isEasyConnectSupported(); @@ -447,6 +472,8 @@ package android.net.wifi { method public boolean isStaConcurrencyForLocalOnlyConnectionsSupported(); method public boolean isStaConcurrencyForMultiInternetSupported(); method public boolean isTdlsSupported(); + method public boolean isTlsMinimumVersionSupported(); + method public boolean isTlsV13Supported(); method public boolean isTrustOnFirstUseSupported(); method public boolean isWapiSupported(); method public boolean isWifiDisplayR2Supported(); @@ -481,6 +508,7 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void unregisterScanResultsCallback(@NonNull android.net.wifi.WifiManager.ScanResultsCallback); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void unregisterSubsystemRestartTrackingCallback(@NonNull android.net.wifi.WifiManager.SubsystemRestartTrackingCallback); method @Deprecated public int updateNetwork(android.net.wifi.WifiConfiguration); + method public boolean validateSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration); field public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; field public static final int ACTION_REMOVE_SUGGESTION_DISCONNECT = 2; // 0x2 field public static final int ACTION_REMOVE_SUGGESTION_LINGER = 1; // 0x1 @@ -636,6 +664,7 @@ package android.net.wifi { public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { method public int describeContents(); method public int getBand(); + method @NonNull public int[] getPreferredChannelFrequenciesMhz(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSpecifier> CREATOR; } @@ -648,6 +677,7 @@ package android.net.wifi { method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssidPattern(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress); method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsEnhancedOpen(boolean); method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsHiddenSsid(boolean); + method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setPreferredChannelsFrequenciesMhz(@NonNull int[]); method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setSsid(@NonNull String); method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setSsidPattern(@NonNull android.os.PatternMatcher); method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig); @@ -1019,6 +1049,7 @@ package android.net.wifi.hotspot2.pps { method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential(); method public java.security.cert.X509Certificate[] getClientCertificateChain(); method public java.security.PrivateKey getClientPrivateKey(); + method public int getMinimumTlsVersion(); method public String getRealm(); method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential(); method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential(); @@ -1026,6 +1057,7 @@ package android.net.wifi.hotspot2.pps { method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential); method public void setClientCertificateChain(java.security.cert.X509Certificate[]); method public void setClientPrivateKey(java.security.PrivateKey); + method public void setMinimumTlsVersion(int) throws java.lang.IllegalArgumentException; method public void setRealm(String); method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential); method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential); @@ -1101,12 +1133,15 @@ package android.net.wifi.p2p { ctor public WifiP2pConfig(); ctor public WifiP2pConfig(android.net.wifi.p2p.WifiP2pConfig); method public int describeContents(); + method public int getGroupClientIpProvisioningMode(); method public int getGroupOwnerBand(); method public int getNetworkId(); method @Nullable public String getNetworkName(); method @Nullable public String getPassphrase(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pConfig> CREATOR; + field public static final int GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP = 0; // 0x0 + field public static final int GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL = 1; // 0x1 field public static final int GROUP_OWNER_BAND_2GHZ = 1; // 0x1 field public static final int GROUP_OWNER_BAND_5GHZ = 2; // 0x2 field public static final int GROUP_OWNER_BAND_AUTO = 0; // 0x0 @@ -1123,6 +1158,7 @@ package android.net.wifi.p2p { method @NonNull public android.net.wifi.p2p.WifiP2pConfig build(); method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder enablePersistentMode(boolean); method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setDeviceAddress(@Nullable android.net.MacAddress); + method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupClientIpProvisioningMode(int); method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingBand(int); method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingFrequency(int); method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setNetworkName(@NonNull String); @@ -1231,6 +1267,7 @@ package android.net.wifi.p2p { method public void setServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ServiceResponseListener); method public void setUpnpServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.UpnpServiceResponseListener); method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public void setVendorElements(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull java.util.List<android.net.wifi.ScanResult.InformationElement>, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener); + method @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) public void setWfdInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pWfdInfo, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener); method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void startListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener); method public void stopListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener); method public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener); @@ -1579,9 +1616,13 @@ package android.net.wifi.rtt { } public class WifiRttManager { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.os.Bundle getRttCharacteristics(); method public boolean isAvailable(); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.NEARBY_WIFI_DEVICES}) public void startRanging(@NonNull android.net.wifi.rtt.RangingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.rtt.RangingResultCallback); field public static final String ACTION_WIFI_RTT_STATE_CHANGED = "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED"; + field public static final String CHARACTERISTICS_KEY_BOOLEAN_LCI = "key_lci"; + field public static final String CHARACTERISTICS_KEY_BOOLEAN_LCR = "key_lcr"; + field public static final String CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT = "key_one_sided_rtt"; } } diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 2249e02e1c..d41553f7ef 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -360,21 +360,6 @@ package android.net.wifi { field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR; } - public final class WifiAvailableChannel implements android.os.Parcelable { - ctor public WifiAvailableChannel(int, int); - method public int describeContents(); - method public int getFrequencyMhz(); - method public int getOperationalModes(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiAvailableChannel> CREATOR; - field public static final int OP_MODE_SAP = 2; // 0x2 - field public static final int OP_MODE_STA = 1; // 0x1 - field public static final int OP_MODE_TDLS = 32; // 0x20 - field public static final int OP_MODE_WIFI_AWARE = 16; // 0x10 - field public static final int OP_MODE_WIFI_DIRECT_CLI = 4; // 0x4 - field public static final int OP_MODE_WIFI_DIRECT_GO = 8; // 0x8 - } - public final class WifiClient implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.net.MacAddress getMacAddress(); @@ -405,6 +390,7 @@ package android.net.wifi { method @Deprecated public void setDeletionPriority(int) throws java.lang.IllegalArgumentException; method @Deprecated public void setNetworkSelectionStatus(@NonNull android.net.wifi.WifiConfiguration.NetworkSelectionStatus); method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setRepeaterEnabled(boolean); + field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiConfiguration> CREATOR; field @Deprecated public static final int INVALID_NETWORK_ID = -1; // 0xffffffff field @Deprecated public static final int METERED_OVERRIDE_METERED = 1; // 0x1 field @Deprecated public static final int METERED_OVERRIDE_NONE = 0; // 0x0 @@ -429,12 +415,14 @@ package android.net.wifi { field @Deprecated public boolean fromWifiNetworkSpecifier; field @Deprecated public boolean fromWifiNetworkSuggestion; field @Deprecated public int lastConnectUid; + field @Deprecated public long lastConnected; field @Deprecated public String lastUpdateName; field @Deprecated public int lastUpdateUid; field @Deprecated public int macRandomizationSetting; field @Deprecated public boolean meteredHint; field @Deprecated public int meteredOverride; field @Deprecated public int numAssociation; + field @Deprecated public int numRebootsSinceLastUse; field @Deprecated public int numScorerOverride; field @Deprecated public int numScorerOverrideAndSwitchedNetwork; field @Deprecated public boolean requirePmf; @@ -471,6 +459,7 @@ package android.net.wifi { field @Deprecated public static final int DISABLED_NONE = 0; // 0x0 field @Deprecated public static final int DISABLED_NO_INTERNET_PERMANENT = 6; // 0x6 field @Deprecated public static final int DISABLED_NO_INTERNET_TEMPORARY = 4; // 0x4 + field @Deprecated public static final int DISABLED_TRANSITION_DISABLE_INDICATION = 13; // 0xd field @Deprecated public static final int NETWORK_SELECTION_ENABLED = 0; // 0x0 field @Deprecated public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2; // 0x2 field @Deprecated public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1; // 0x1 @@ -554,7 +543,6 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void factoryReset(); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>); - method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.net.wifi.WifiAvailableChannel> getAllowedChannels(int, int); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getCountryCode(); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.Network getCurrentNetwork(); method public static int getEasyConnectMaxAllowedResponderDeviceInfoLength(); @@ -568,7 +556,6 @@ package android.net.wifi { method @Nullable @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}, conditional=true) public android.net.wifi.WifiConfiguration getPrivilegedConnectedNetwork(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public android.net.wifi.SoftApConfiguration getSoftApConfiguration(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional=true) public java.util.Set<android.net.wifi.WifiSsid> getSsidsAllowlist(); - method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.net.wifi.WifiAvailableChannel> getUsableChannels(int, int); method public int getVerboseLoggingLevel(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void getWifiActivityEnergyInfoAsync(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration(); @@ -579,6 +566,7 @@ package android.net.wifi { method @Deprecated public boolean isDeviceToDeviceRttSupported(); method public boolean isPortableHotspotSupported(); method public boolean isStaConcurrencyForRestrictedConnectionsSupported(); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled(); method public boolean isVerboseLoggingEnabled(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled(); method public boolean isWifiScannerSupported(); @@ -607,6 +595,8 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}) public void setExternalPnoScanRequest(@NonNull java.util.List<android.net.wifi.WifiSsid>, @Nullable int[], @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.PnoScanResultsCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}) public void setNetworkSelectionConfig(@NonNull android.net.wifi.WifiNetworkSelectionConfig); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}) public void setOneShotScreenOnConnectivityScanDelayMillis(@IntRange(from=0) int); method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) public void setOverrideCountryCode(@NonNull String); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setPasspointMeteredOverride(@NonNull String, int); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setScanAlwaysAvailable(boolean); @@ -615,6 +605,7 @@ package android.net.wifi { method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional=true) public void setSsidsAllowlist(@NonNull java.util.Set<android.net.wifi.WifiSsid>); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean setStaConcurrencyForMultiInternetMode(int); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setVerboseLoggingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setVerboseLoggingLevel(int); method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration); @@ -646,12 +637,39 @@ package android.net.wifi { field @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public static final String ACTION_REFRESH_USER_PROVISIONING = "android.net.wifi.action.REFRESH_USER_PROVISIONING"; field public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; field public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; + field public static final int API_ADD_NETWORK = 10; // 0xa + field public static final int API_ALLOW_AUTOJOIN = 12; // 0xc field public static final int API_AUTOJOIN_GLOBAL = 5; // 0x5 + field public static final int API_CONNECT_CONFIG = 13; // 0xd + field public static final int API_CONNECT_NETWORK_ID = 14; // 0xe + field public static final int API_DISABLE_NETWORK = 15; // 0xf + field public static final int API_ENABLE_NETWORK = 16; // 0x10 + field public static final int API_FORGET = 17; // 0x11 + field public static final int API_P2P_CANCEL_CONNECT = 26; // 0x1a + field public static final int API_P2P_CONNECT = 25; // 0x19 + field public static final int API_P2P_CREATE_GROUP = 27; // 0x1b + field public static final int API_P2P_CREATE_GROUP_P2P_CONFIG = 28; // 0x1c + field public static final int API_P2P_DISCOVER_PEERS = 21; // 0x15 + field public static final int API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS = 22; // 0x16 + field public static final int API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY = 23; // 0x17 + field public static final int API_P2P_REMOVE_GROUP = 29; // 0x1d + field public static final int API_P2P_SET_CHANNELS = 32; // 0x20 + field public static final int API_P2P_START_LISTENING = 30; // 0x1e + field public static final int API_P2P_STOP_LISTENING = 31; // 0x1f + field public static final int API_P2P_STOP_PEER_DISCOVERY = 24; // 0x18 + field public static final int API_SAVE = 18; // 0x12 field public static final int API_SCANNING_ENABLED = 1; // 0x1 + field public static final int API_SET_NETWORK_SELECTION_CONFIG = 8; // 0x8 + field public static final int API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY = 7; // 0x7 field public static final int API_SET_SCAN_SCHEDULE = 6; // 0x6 + field public static final int API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG = 9; // 0x9 field public static final int API_SOFT_AP = 3; // 0x3 + field public static final int API_START_LOCAL_ONLY_HOTSPOT = 20; // 0x14 + field public static final int API_START_SCAN = 19; // 0x13 field public static final int API_TETHERED_HOTSPOT = 4; // 0x4 + field public static final int API_UPDATE_NETWORK = 11; // 0xb field public static final int API_WIFI_ENABLED = 2; // 0x2 + field public static final int API_WIFI_SCANNER_START_SCAN = 33; // 0x21 field public static final int CHANGE_REASON_ADDED = 0; // 0x0 field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2 field public static final int CHANGE_REASON_REMOVED = 1; // 0x1 @@ -695,6 +713,7 @@ package android.net.wifi { field public static final int SAP_START_FAILURE_GENERAL = 0; // 0x0 field public static final int SAP_START_FAILURE_NO_CHANNEL = 1; // 0x1 field public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2; // 0x2 + field public static final int SAP_START_FAILURE_USER_REJECTED = 3; // 0x3 field public static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0; // 0x0 field public static final int VERBOSE_LOGGING_LEVEL_ENABLED = 1; // 0x1 field public static final int VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY = 2; // 0x2 @@ -818,6 +837,30 @@ package android.net.wifi { field @Deprecated public int numUsage; } + public final class WifiNetworkSelectionConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getAssociatedNetworkSelectionOverride(); + method public boolean isLastSelectionWeightEnabled(); + method public boolean isSufficiencyCheckEnabledWhenScreenOff(); + method public boolean isSufficiencyCheckEnabledWhenScreenOn(); + method public boolean isUserConnectChoiceOverrideEnabled(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int ASSOCIATED_NETWORK_SELECTION_OVERRIDE_DISABLED = 2; // 0x2 + field public static final int ASSOCIATED_NETWORK_SELECTION_OVERRIDE_ENABLED = 1; // 0x1 + field public static final int ASSOCIATED_NETWORK_SELECTION_OVERRIDE_NONE = 0; // 0x0 + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSelectionConfig> CREATOR; + } + + public static final class WifiNetworkSelectionConfig.Builder { + ctor public WifiNetworkSelectionConfig.Builder(); + method @NonNull public android.net.wifi.WifiNetworkSelectionConfig build(); + method @NonNull public android.net.wifi.WifiNetworkSelectionConfig.Builder setAssociatedNetworkSelectionOverride(int) throws java.lang.IllegalArgumentException; + method @NonNull public android.net.wifi.WifiNetworkSelectionConfig.Builder setLastSelectionWeightEnabled(boolean); + method @NonNull public android.net.wifi.WifiNetworkSelectionConfig.Builder setSufficiencyCheckEnabledWhenScreenOff(boolean); + method @NonNull public android.net.wifi.WifiNetworkSelectionConfig.Builder setSufficiencyCheckEnabledWhenScreenOn(boolean); + method @NonNull public android.net.wifi.WifiNetworkSelectionConfig.Builder setUserConnectChoiceOverrideEnabled(boolean); + } + public final class WifiNetworkSuggestion implements android.os.Parcelable { method public int getCarrierId(); method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration(); @@ -834,7 +877,7 @@ package android.net.wifi { public class WifiScanner { method @Deprecated public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.BssidInfo[]); method @Deprecated public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings); - method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<java.lang.Integer> getAvailableChannels(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NEARBY_WIFI_DEVICES) public java.util.List<java.lang.Integer> getAvailableChannels(int); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean getScanResults(); method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.net.wifi.ScanResult> getSingleScanResults(); method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean isScanning(); @@ -1206,7 +1249,6 @@ package android.net.wifi.p2p { method @RequiresPermission(allOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.READ_WIFI_CREDENTIAL, android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void requestPersistentGroupInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.PersistentGroupInfoListener); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public void setDeviceName(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull String, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener); method @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) public void setMiracastMode(int); - method @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) public void setWfdInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pWfdInfo, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public void setWifiP2pChannels(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, int, int, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener); field public static final String ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED"; field public static final int MIRACAST_DISABLED = 0; // 0x0 diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt index 64c2138afa..719a37eefa 100644 --- a/framework/jarjar-rules.txt +++ b/framework/jarjar-rules.txt @@ -60,9 +60,6 @@ rule android.net.shared.InetAddressUtils* com.android.wifi.x.@0 rule android.net.shared.InitialConfiguration* com.android.wifi.x.@0 rule android.net.shared.IpConfigurationParcelableUtil* com.android.wifi.x.@0 rule android.net.shared.Layer2Information* com.android.wifi.x.@0 -rule android.net.shared.LinkPropertiesParcelableUtil* com.android.wifi.x.@0 -rule android.net.shared.NetdUtils* com.android.wifi.x.@0 -rule android.net.shared.NetworkMonitorUtils* com.android.wifi.x.@0 rule android.net.shared.ParcelableUtil* com.android.wifi.x.@0 rule android.net.shared.PrivateDnsConfig* com.android.wifi.x.@0 rule android.net.shared.ProvisioningConfiguration* com.android.wifi.x.@0 diff --git a/framework/java/android/net/wifi/BaseWifiService.java b/framework/java/android/net/wifi/BaseWifiService.java index 785f5c0202..bc1b9759ff 100644 --- a/framework/java/android/net/wifi/BaseWifiService.java +++ b/framework/java/android/net/wifi/BaseWifiService.java @@ -438,6 +438,11 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override + public boolean validateSoftApConfiguration(SoftApConfiguration config) { + throw new UnsupportedOperationException(); + } + + @Override public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, String featureId, SoftApConfiguration customConfig, Bundle extras) { throw new UnsupportedOperationException(); @@ -854,13 +859,19 @@ public class BaseWifiService extends IWifiManager.Stub { throw new UnsupportedOperationException(); } - @Override + /** TO BE REMOVED */ public List<WifiAvailableChannel> getUsableChannels( int band, int mode, int filter) { throw new UnsupportedOperationException(); } @Override + public List<WifiAvailableChannel> getUsableChannels( + int band, int mode, int filter, String packageName, Bundle extras) { + throw new UnsupportedOperationException(); + } + + @Override public boolean isWifiPasspointEnabled() { throw new UnsupportedOperationException(); } @@ -922,4 +933,9 @@ public class BaseWifiService extends IWifiManager.Stub { boolean requireNewInterface, IInterfaceCreationInfoCallback callback) { throw new UnsupportedOperationException(); } + + @Override + public int getMaxNumberOfChannelsPerRequest() { + throw new UnsupportedOperationException(); + } } diff --git a/framework/java/android/net/wifi/IWifiManager.aidl b/framework/java/android/net/wifi/IWifiManager.aidl index 010e222100..e669316de2 100644 --- a/framework/java/android/net/wifi/IWifiManager.aidl +++ b/framework/java/android/net/wifi/IWifiManager.aidl @@ -211,6 +211,8 @@ interface IWifiManager boolean stopSoftAp(); + boolean validateSoftApConfiguration(in SoftApConfiguration config); + int startLocalOnlyHotspot(in ILocalOnlyHotspotCallback callback, String packageName, String featureId, in SoftApConfiguration customConfig, in Bundle extras); @@ -380,7 +382,7 @@ interface IWifiManager void flushPasspointAnqpCache(String packageName); - List<WifiAvailableChannel> getUsableChannels(int band, int mode, int filter); + List<WifiAvailableChannel> getUsableChannels(int band, int mode, int filter, String packageName, in Bundle extras); boolean isWifiPasspointEnabled(); @@ -405,4 +407,6 @@ interface IWifiManager void removeCustomDhcpOptions(in WifiSsid ssid, in byte[] oui); void reportCreateInterfaceImpact(String packageName, int interfaceType, boolean requireNewInterface, in IInterfaceCreationInfoCallback callback); + + int getMaxNumberOfChannelsPerRequest(); } diff --git a/framework/java/android/net/wifi/IWifiScanner.aidl b/framework/java/android/net/wifi/IWifiScanner.aidl index 9c1b7ab586..bb1b34b5a5 100644 --- a/framework/java/android/net/wifi/IWifiScanner.aidl +++ b/framework/java/android/net/wifi/IWifiScanner.aidl @@ -28,7 +28,7 @@ import android.net.wifi.IWifiScannerListener; */ interface IWifiScanner { - Bundle getAvailableChannels(int band, String packageName, String featureId); + Bundle getAvailableChannels(int band, String packageName, String featureId, in Bundle extras); boolean isScanning(); diff --git a/framework/java/android/net/wifi/WifiAvailableChannel.java b/framework/java/android/net/wifi/WifiAvailableChannel.java index 6e56214448..11a4054c52 100644 --- a/framework/java/android/net/wifi/WifiAvailableChannel.java +++ b/framework/java/android/net/wifi/WifiAvailableChannel.java @@ -18,7 +18,6 @@ package android.net.wifi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -32,10 +31,7 @@ import java.util.Objects; * filtered by regulatory constraints. Use {@link WifiManager#getUsableChannels(int, int)} to * retrieve the list of channels filtered by regulatory and dynamic constraints like concurrency and * interference due to other radios. - * - * @hide */ -@SystemApi public final class WifiAvailableChannel implements Parcelable { /** diff --git a/framework/java/android/net/wifi/WifiConfiguration.java b/framework/java/android/net/wifi/WifiConfiguration.java index 1c3bc7934b..798b903ed1 100644 --- a/framework/java/android/net/wifi/WifiConfiguration.java +++ b/framework/java/android/net/wifi/WifiConfiguration.java @@ -1474,9 +1474,15 @@ public class WifiConfiguration implements Parcelable { public boolean osu; /** - * Last time the system was connected to this configuration. + * Last time the system was connected to this configuration represented as the difference, + * measured in milliseconds, between the last connected time and midnight, January 1, 1970 UTC. + * <P> + * Note that this information is only in memory will be cleared (reset to 0) for all + * WifiConfiguration(s) after a reboot. * @hide */ + @SuppressLint("MutableBareField") + @SystemApi public long lastConnected; /** @@ -1497,6 +1503,8 @@ public class WifiConfiguration implements Parcelable { * Number of reboots since this config was last used (either connected or updated). * @hide */ + @SuppressLint("MutableBareField") + @SystemApi public int numRebootsSinceLastUse; /** @@ -1564,14 +1572,6 @@ public class WifiConfiguration implements Parcelable { public boolean oemPrivate; /** - * Indicate whether or not the network is a secondary network with internet, associated with - * a DBS AP same as the primary network on a different band. - * This bit is set when this Wifi configuration is created from {@link WifiConnectivityManager}. - * @hide - */ - public boolean dbsSecondaryInternet; - - /** * Indicate whether or not the network is a carrier merged network. * This bit can only be used by suggestion network, see * {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} @@ -2127,7 +2127,6 @@ public class WifiConfiguration implements Parcelable { /** * This code is used to disable a network when a security params is disabled * by the transition disable indication. - * @hide */ public static final int DISABLED_TRANSITION_DISABLE_INDICATION = 13; /** @@ -3205,7 +3204,6 @@ public class WifiConfiguration implements Parcelable { carrierMerged = false; fromWifiNetworkSuggestion = false; fromWifiNetworkSpecifier = false; - dbsSecondaryInternet = false; meteredHint = false; mIsRepeaterEnabled = false; meteredOverride = METERED_OVERRIDE_NONE; @@ -3354,14 +3352,13 @@ public class WifiConfiguration implements Parcelable { if (this.carrierMerged) sbuf.append(" carrierMerged"); if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion"); if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier"); - if (this.dbsSecondaryInternet) sbuf.append(" dbsSecondaryInternet"); if (this.meteredHint) sbuf.append(" meteredHint"); if (this.mIsRepeaterEnabled) sbuf.append(" repeaterEnabled"); if (this.useExternalScores) sbuf.append(" useExternalScores"); if (this.validatedInternetAccess || this.ephemeral || this.trusted || this.oemPaid || this.oemPrivate || this.carrierMerged || this.fromWifiNetworkSuggestion || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores - || this.restricted || this.dbsSecondaryInternet) { + || this.restricted) { sbuf.append("\n"); } if (this.meteredOverride != METERED_OVERRIDE_NONE) { @@ -3641,6 +3638,7 @@ public class WifiConfiguration implements Parcelable { /** * Get the authentication type of the network. * @return One of the {@link KeyMgmt} constants. e.g. {@link KeyMgmt#WPA2_PSK}. + * @throws IllegalStateException if config is invalid for authentication type. * @hide */ @SystemApi @@ -3936,7 +3934,6 @@ public class WifiConfiguration implements Parcelable { carrierMerged = source.carrierMerged; fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion; fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier; - dbsSecondaryInternet = source.dbsSecondaryInternet; meteredHint = source.meteredHint; mIsRepeaterEnabled = source.mIsRepeaterEnabled; meteredOverride = source.meteredOverride; @@ -4040,7 +4037,6 @@ public class WifiConfiguration implements Parcelable { dest.writeInt(carrierMerged ? 1 : 0); dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0); dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0); - dest.writeInt(dbsSecondaryInternet ? 1 : 0); dest.writeInt(meteredHint ? 1 : 0); dest.writeBoolean(mIsRepeaterEnabled); dest.writeInt(meteredOverride); @@ -4080,7 +4076,7 @@ public class WifiConfiguration implements Parcelable { } /** Implement the Parcelable interface {@hide} */ - @UnsupportedAppUsage + @SystemApi public static final @android.annotation.NonNull Creator<WifiConfiguration> CREATOR = new Creator<WifiConfiguration>() { public WifiConfiguration createFromParcel(Parcel in) { @@ -4137,7 +4133,6 @@ public class WifiConfiguration implements Parcelable { config.carrierMerged = in.readInt() != 0; config.fromWifiNetworkSuggestion = in.readInt() != 0; config.fromWifiNetworkSpecifier = in.readInt() != 0; - config.dbsSecondaryInternet = in.readInt() != 0; config.meteredHint = in.readInt() != 0; config.mIsRepeaterEnabled = in.readBoolean(); config.meteredOverride = in.readInt(); diff --git a/framework/java/android/net/wifi/WifiEnterpriseConfig.java b/framework/java/android/net/wifi/WifiEnterpriseConfig.java index 2a53e35f16..0f6c1d605e 100644 --- a/framework/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/framework/java/android/net/wifi/WifiEnterpriseConfig.java @@ -246,6 +246,39 @@ public class WifiEnterpriseConfig implements Parcelable { */ private static final List<String> UNQUOTED_KEYS = Arrays.asList(ENGINE_KEY, OPP_KEY_CACHING, EAP_ERP); + /** Constant definition for TLS v1.0 which is used in {@link #setMinimumTlsVersion(int)} */ + public static final int TLS_V1_0 = 0; + + /** Constant definition for TLS v1.1 which is used in {@link #setMinimumTlsVersion(int)} */ + public static final int TLS_V1_1 = 1; + + /** Constant definition for TLS v1.2 which is used in {@link #setMinimumTlsVersion(int)} */ + public static final int TLS_V1_2 = 2; + + /** Constant definition for TLS v1.3 which is used in {@link #setMinimumTlsVersion(int)} */ + public static final int TLS_V1_3 = 3; + + /** + * The minimum valid value for a TLS version. + * @hide + */ + public static final int TLS_VERSION_MIN = TLS_V1_0; + + /** + * The maximum valid value for a TLS version. + * @hide + */ + public static final int TLS_VERSION_MAX = TLS_V1_3; + + /** @hide */ + @IntDef(prefix = {"TLS_"}, value = { + TLS_V1_0, + TLS_V1_1, + TLS_V1_2, + TLS_V1_3 + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TlsVersion {} @UnsupportedAppUsage private HashMap<String, String> mFields = new HashMap<String, String>(); @@ -259,6 +292,8 @@ public class WifiEnterpriseConfig implements Parcelable { private String mKeyChainAlias; private boolean mIsTrustOnFirstUseEnabled = false; private boolean mUserApproveNoCaCert = false; + // Default is 1.0, i.e. accept any TLS version. + private int mMinimumTlsVersion = TLS_V1_0; // Not included in parceling, hashing, or equality because it is an internal, temporary value // which is valid only during an actual connection to a Passpoint network with an RCOI-based @@ -313,6 +348,7 @@ public class WifiEnterpriseConfig implements Parcelable { mIsTrustOnFirstUseEnabled = source.mIsTrustOnFirstUseEnabled; mUserApproveNoCaCert = source.mUserApproveNoCaCert; mSelectedRcoi = source.mSelectedRcoi; + mMinimumTlsVersion = source.mMinimumTlsVersion; } /** @@ -362,6 +398,7 @@ public class WifiEnterpriseConfig implements Parcelable { dest.writeInt(mOcsp); dest.writeBoolean(mIsTrustOnFirstUseEnabled); dest.writeBoolean(mUserApproveNoCaCert); + dest.writeInt(mMinimumTlsVersion); } public static final @android.annotation.NonNull Creator<WifiEnterpriseConfig> CREATOR = @@ -387,6 +424,7 @@ public class WifiEnterpriseConfig implements Parcelable { enterpriseConfig.mOcsp = in.readInt(); enterpriseConfig.mIsTrustOnFirstUseEnabled = in.readBoolean(); enterpriseConfig.mUserApproveNoCaCert = in.readBoolean(); + enterpriseConfig.mMinimumTlsVersion = in.readInt(); return enterpriseConfig; } @@ -1409,6 +1447,7 @@ public class WifiEnterpriseConfig implements Parcelable { sb.append(" trust_on_first_use: ").append(mIsTrustOnFirstUseEnabled).append("\n"); sb.append(" user_approve_no_ca_cert: ").append(mUserApproveNoCaCert).append("\n"); sb.append(" selected_rcoi: ").append(mSelectedRcoi).append("\n"); + sb.append(" minimum_tls_version: ").append(mMinimumTlsVersion).append("\n"); return sb.toString(); } @@ -1736,4 +1775,32 @@ public class WifiEnterpriseConfig implements Parcelable { return mUserApproveNoCaCert; } + /** + * Set the minimum TLS version for TLS-based EAP methods. + * + * {@link WifiManager#isTlsMinimumVersionSupported()} indicates whether or not a minimum + * TLS version can be set. If not supported, the minimum TLS version is always TLS v1.0. + * <p> + * {@link WifiManager#isTlsV13Supported()} indicates whether or not TLS v1.3 is supported. + * If requested minimum is not supported, it will default to the maximum supported version. + * + * @param tlsVersion the TLS version + * @throws IllegalArgumentException if the TLS version is invalid. + */ + public void setMinimumTlsVersion(@TlsVersion int tlsVersion) throws IllegalArgumentException { + if (tlsVersion < TLS_VERSION_MIN || tlsVersion > TLS_VERSION_MAX) { + throw new IllegalArgumentException( + "Invalid TLS version: " + tlsVersion); + } + mMinimumTlsVersion = tlsVersion; + } + + /** + * Get the minimum TLS version for TLS-based EAP methods. + * + * @return the TLS version + */ + public @TlsVersion int getMinimumTlsVersion() { + return mMinimumTlsVersion; + } } diff --git a/framework/java/android/net/wifi/WifiManager.java b/framework/java/android/net/wifi/WifiManager.java index 13746c78d8..07005c1f0c 100644 --- a/framework/java/android/net/wifi/WifiManager.java +++ b/framework/java/android/net/wifi/WifiManager.java @@ -56,6 +56,8 @@ import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.ProvisioningCallback; +import android.net.wifi.p2p.WifiP2pConfig; +import android.net.wifi.p2p.WifiP2pManager; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -428,7 +430,33 @@ public class WifiManager { API_AUTOJOIN_GLOBAL, API_SET_SCAN_SCHEDULE, API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY, - API_SET_NETWORK_SELECTION_CONFIG}) + API_SET_NETWORK_SELECTION_CONFIG, + API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG, + API_ADD_NETWORK, + API_UPDATE_NETWORK, + API_ALLOW_AUTOJOIN, + API_CONNECT_CONFIG, + API_CONNECT_NETWORK_ID, + API_DISABLE_NETWORK, + API_ENABLE_NETWORK, + API_FORGET, + API_SAVE, + API_START_SCAN, + API_START_LOCAL_ONLY_HOTSPOT, + API_P2P_DISCOVER_PEERS, + API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS, + API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY, + API_P2P_STOP_PEER_DISCOVERY, + API_P2P_CONNECT, + API_P2P_CANCEL_CONNECT, + API_P2P_CREATE_GROUP, + API_P2P_CREATE_GROUP_P2P_CONFIG, + API_P2P_REMOVE_GROUP, + API_P2P_START_LISTENING, + API_P2P_STOP_LISTENING, + API_P2P_SET_CHANNELS, + API_WIFI_SCANNER_START_SCAN + }) public @interface ApiType {} /** @@ -487,6 +515,7 @@ public class WifiManager { * Tracks usage of {@link WifiManager#setOneShotScreenOnConnectivityScanDelayMillis(int)}. * @hide */ + @SystemApi public static final int API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY = 7; /** @@ -496,6 +525,7 @@ public class WifiManager { * {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} * @hide */ + @SystemApi public static final int API_SET_NETWORK_SELECTION_CONFIG = 8; /** @@ -505,13 +535,260 @@ public class WifiManager { * {@link WifiManager#setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} * @hide */ + @SystemApi public static final int API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG = 9; /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#addNetwork(WifiConfiguration)} + * @hide + */ + @SystemApi + public static final int API_ADD_NETWORK = 10; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#updateNetwork(WifiConfiguration)} + * @hide + */ + @SystemApi + public static final int API_UPDATE_NETWORK = 11; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#allowAutojoin(int, boolean)} + * @hide + */ + @SystemApi + public static final int API_ALLOW_AUTOJOIN = 12; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#connect(WifiConfiguration, ActionListener)} + * @hide + */ + @SystemApi + public static final int API_CONNECT_CONFIG = 13; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#connect(int, ActionListener)} + * @hide + */ + @SystemApi + public static final int API_CONNECT_NETWORK_ID = 14; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#disableNetwork(int)} + * @hide + */ + @SystemApi + public static final int API_DISABLE_NETWORK = 15; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#enableNetwork(int, boolean)} + * @hide + */ + @SystemApi + public static final int API_ENABLE_NETWORK = 16; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#forget(int, ActionListener)} + * @hide + */ + @SystemApi + public static final int API_FORGET = 17; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#save(WifiConfiguration, ActionListener)} + * @hide + */ + @SystemApi + public static final int API_SAVE = 18; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#startScan()} + * @hide + */ + @SystemApi + public static final int API_START_SCAN = 19; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} + * @hide + */ + @SystemApi + public static final int API_START_LOCAL_ONLY_HOTSPOT = 20; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#discoverPeers(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_DISCOVER_PEERS = 21; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#discoverPeersOnSocialChannels(WifiP2pManager.Channel, + * WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS = 22; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#discoverPeersOnSpecificFrequency(WifiP2pManager.Channel, int, + * WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY = 23; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#stopPeerDiscovery(WifiP2pManager.Channel, + * WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_STOP_PEER_DISCOVERY = 24; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig, + * WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_CONNECT = 25; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#cancelConnect(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_CANCEL_CONNECT = 26; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_CREATE_GROUP = 27; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pConfig, + * WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_CREATE_GROUP_P2P_CONFIG = 28; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#removeGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_REMOVE_GROUP = 29; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#startListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_START_LISTENING = 30; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#stopListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_STOP_LISTENING = 31; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiP2pManager#setWifiP2pChannels(WifiP2pManager.Channel, int, int, + * WifiP2pManager.ActionListener)} + * @hide + */ + @SystemApi + public static final int API_P2P_SET_CHANNELS = 32; + + /** + * A constant used in + * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} + * Tracks usage of + * {@link WifiScanner#startScan(WifiScanner.ScanSettings, WifiScanner.ScanListener)} + * @hide + */ + @SystemApi + public static final int API_WIFI_SCANNER_START_SCAN = 33; + + /** * Used internally to keep track of boundary. * @hide */ - public static final int API_MAX = 10; + public static final int API_MAX = 34; /** * Broadcast intent action indicating that a Passpoint provider icon has been received. @@ -941,6 +1218,7 @@ public class WifiManager { * * @hide */ + @SystemApi public static final int SAP_START_FAILURE_USER_REJECTED = 3; /** @hide */ @@ -1887,6 +2165,7 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETTINGS, MANAGE_WIFI_NETWORK_SELECTION }) + @SystemApi public void setNetworkSelectionConfig(@NonNull WifiNetworkSelectionConfig nsConfig) { try { if (nsConfig == null) { @@ -1920,6 +2199,7 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD }) + @SystemApi public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) { try { mService.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(enable); @@ -1948,6 +2228,7 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD }) + @SystemApi public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() { try { return mService.isThirdPartyAppEnablingWifiConfirmationDialogEnabled(); @@ -2036,6 +2317,7 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETTINGS, MANAGE_WIFI_NETWORK_SELECTION }) + @SystemApi public void setOneShotScreenOnConnectivityScanDelayMillis(@IntRange(from = 0) int delayMs) { try { mService.setOneShotScreenOnConnectivityScanDelayMillis(delayMs); @@ -3213,159 +3495,166 @@ public class WifiManager { return isWifiEnabled(); } - /** TODO(b/181364583): Convert all of these to 1 << X form. */ - /** @hide */ - public static final long WIFI_FEATURE_INFRA = 0x0001L; // Basic infrastructure mode - /** @hide */ - public static final long WIFI_FEATURE_PASSPOINT = 0x0004L; // Support for GAS/ANQP /** @hide */ - public static final long WIFI_FEATURE_P2P = 0x0008L; // Wifi-Direct + public static final long WIFI_FEATURE_INFRA = 1L << 0; // Basic infrastructure mode /** @hide */ - public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 0x0010L; // Soft AP + public static final long WIFI_FEATURE_PASSPOINT = 1L << 2; // Support for GAS/ANQP /** @hide */ - public static final long WIFI_FEATURE_SCANNER = 0x0020L; // WifiScanner APIs + public static final long WIFI_FEATURE_P2P = 1L << 3; // Wifi-Direct /** @hide */ - public static final long WIFI_FEATURE_AWARE = 0x0040L; // Wi-Fi AWare networking + public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 1L << 4; // Soft AP /** @hide */ - public static final long WIFI_FEATURE_D2D_RTT = 0x0080L; // Device-to-device RTT + public static final long WIFI_FEATURE_SCANNER = 1L << 5; // WifiScanner APIs /** @hide */ - public static final long WIFI_FEATURE_D2AP_RTT = 0x0100L; // Device-to-AP RTT + public static final long WIFI_FEATURE_AWARE = 1L << 6; // Wi-Fi Aware networking /** @hide */ - public static final long WIFI_FEATURE_BATCH_SCAN = 0x0200L; // Batched Scan (deprecated) + public static final long WIFI_FEATURE_D2D_RTT = 1L << 7; // Device-to-device RTT /** @hide */ - public static final long WIFI_FEATURE_PNO = 0x0400L; // Preferred network offload + public static final long WIFI_FEATURE_D2AP_RTT = 1L << 8; // Device-to-AP RTT /** @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA = 0x0800L; // (unused) + public static final long WIFI_FEATURE_PNO = 1L << 10; // Preferred network offload /** @hide */ - public static final long WIFI_FEATURE_TDLS = 0x1000L; // Tunnel directed link setup + public static final long WIFI_FEATURE_TDLS = 1L << 12; // Tunnel directed link setup /** @hide */ - public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000L; // TDLS off channel + public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 1L << 13; // TDLS off channel /** @hide */ - public static final long WIFI_FEATURE_EPR = 0x4000L; // Enhanced power reporting + public static final long WIFI_FEATURE_AP_STA = 1L << 15; // AP STA Concurrency /** @hide */ - public static final long WIFI_FEATURE_AP_STA = 0x8000L; // AP STA Concurrency + public static final long WIFI_FEATURE_LINK_LAYER_STATS = 1L << 16; // Link layer stats /** @hide */ - public static final long WIFI_FEATURE_LINK_LAYER_STATS = 0x10000L; // Link layer stats + public static final long WIFI_FEATURE_LOGGER = 1L << 17; // WiFi Logger /** @hide */ - public static final long WIFI_FEATURE_LOGGER = 0x20000L; // WiFi Logger + public static final long WIFI_FEATURE_RSSI_MONITOR = 1L << 19; // RSSI Monitor /** @hide */ - public static final long WIFI_FEATURE_HAL_EPNO = 0x40000L; // Enhanced PNO + public static final long WIFI_FEATURE_MKEEP_ALIVE = 1L << 20; // mkeep_alive /** @hide */ - public static final long WIFI_FEATURE_RSSI_MONITOR = 0x80000L; // RSSI Monitor + public static final long WIFI_FEATURE_CONFIG_NDO = 1L << 21; // ND offload /** @hide */ - public static final long WIFI_FEATURE_MKEEP_ALIVE = 0x100000L; // mkeep_alive + public static final long WIFI_FEATURE_CONTROL_ROAMING = 1L << 23; // Control firmware roaming /** @hide */ - public static final long WIFI_FEATURE_CONFIG_NDO = 0x200000L; // ND offload + public static final long WIFI_FEATURE_IE_WHITELIST = 1L << 24; // Probe IE white listing /** @hide */ - public static final long WIFI_FEATURE_TRANSMIT_POWER = 0x400000L; // Capture transmit power + public static final long WIFI_FEATURE_SCAN_RAND = 1L << 25; // Random MAC & Probe seq /** @hide */ - public static final long WIFI_FEATURE_CONTROL_ROAMING = 0x800000L; // Control firmware roaming + public static final long WIFI_FEATURE_TX_POWER_LIMIT = 1L << 26; // Set Tx power limit /** @hide */ - public static final long WIFI_FEATURE_IE_WHITELIST = 0x1000000L; // Probe IE white listing + public static final long WIFI_FEATURE_WPA3_SAE = 1L << 27; // WPA3-Personal SAE /** @hide */ - public static final long WIFI_FEATURE_SCAN_RAND = 0x2000000L; // Random MAC & Probe seq + public static final long WIFI_FEATURE_WPA3_SUITE_B = 1L << 28; // WPA3-Enterprise Suite-B /** @hide */ - public static final long WIFI_FEATURE_TX_POWER_LIMIT = 0x4000000L; // Set Tx power limit + public static final long WIFI_FEATURE_OWE = 1L << 29; // Enhanced Open /** @hide */ - public static final long WIFI_FEATURE_WPA3_SAE = 0x8000000L; // WPA3-Personal SAE + public static final long WIFI_FEATURE_LOW_LATENCY = 1L << 30; // Low Latency modes /** @hide */ - public static final long WIFI_FEATURE_WPA3_SUITE_B = 0x10000000L; // WPA3-Enterprise Suite-B + public static final long WIFI_FEATURE_DPP = 1L << 31; // DPP (Easy-Connect) /** @hide */ - public static final long WIFI_FEATURE_OWE = 0x20000000L; // Enhanced Open + public static final long WIFI_FEATURE_P2P_RAND_MAC = 1L << 32; // Random P2P MAC /** @hide */ - public static final long WIFI_FEATURE_LOW_LATENCY = 0x40000000L; // Low Latency modes + public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 1L << 33; // Random STA MAC /** @hide */ - public static final long WIFI_FEATURE_DPP = 0x80000000L; // DPP (Easy-Connect) + public static final long WIFI_FEATURE_AP_RAND_MAC = 1L << 34; // Random AP MAC /** @hide */ - public static final long WIFI_FEATURE_P2P_RAND_MAC = 0x100000000L; // Random P2P MAC + public static final long WIFI_FEATURE_MBO = 1L << 35; // MBO Support /** @hide */ - public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 0x200000000L; // Random STA MAC + public static final long WIFI_FEATURE_OCE = 1L << 36; // OCE Support /** @hide */ - public static final long WIFI_FEATURE_AP_RAND_MAC = 0x400000000L; // Random AP MAC - /** @hide */ - public static final long WIFI_FEATURE_MBO = 0x800000000L; // MBO Support - /** @hide */ - public static final long WIFI_FEATURE_OCE = 0x1000000000L; // OCE Support - /** @hide */ - public static final long WIFI_FEATURE_WAPI = 0x2000000000L; // WAPI + public static final long WIFI_FEATURE_WAPI = 1L << 37; // WAPI /** @hide */ - public static final long WIFI_FEATURE_FILS_SHA256 = 0x4000000000L; // FILS-SHA256 + public static final long WIFI_FEATURE_FILS_SHA256 = 1L << 38; // FILS-SHA256 /** @hide */ - public static final long WIFI_FEATURE_FILS_SHA384 = 0x8000000000L; // FILS-SHA384 + public static final long WIFI_FEATURE_FILS_SHA384 = 1L << 39; // FILS-SHA384 /** @hide */ - public static final long WIFI_FEATURE_SAE_PK = 0x10000000000L; // SAE-PK + public static final long WIFI_FEATURE_SAE_PK = 1L << 40; // SAE-PK /** @hide */ - public static final long WIFI_FEATURE_STA_BRIDGED_AP = 0x20000000000L; // STA + Bridged AP + public static final long WIFI_FEATURE_STA_BRIDGED_AP = 1L << 41; // STA + Bridged AP /** @hide */ - public static final long WIFI_FEATURE_BRIDGED_AP = 0x40000000000L; // Bridged AP + public static final long WIFI_FEATURE_BRIDGED_AP = 1L << 42; // Bridged AP /** @hide */ - public static final long WIFI_FEATURE_INFRA_60G = 0x80000000000L; // 60 GHz Band Support + public static final long WIFI_FEATURE_INFRA_60G = 1L << 43; // 60 GHz Band Support /** * Support for 2 STA's for the local-only (peer to peer) connection + internet connection * concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 0x100000000000L; + public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 1L << 44; /** * Support for 2 STA's for the make before break concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 0x200000000000L; + public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 1L << 45; /** * Support for 2 STA's for the restricted connection + internet connection concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 0x400000000000L; + public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 1L << 46; /** * DPP (Easy-Connect) Enrollee Responder mode support * @hide */ - public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 0x800000000000L; + public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 1L << 47; /** * Passpoint Terms and Conditions feature support * @hide */ - public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 0x1000000000000L; + public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 1L << 48; /** @hide */ - public static final long WIFI_FEATURE_SAE_H2E = 0x2000000000000L; // Hash-to-Element + public static final long WIFI_FEATURE_SAE_H2E = 1L << 49; // Hash-to-Element /** @hide */ - public static final long WIFI_FEATURE_WFD_R2 = 0x4000000000000L; // Wi-Fi Display R2 + public static final long WIFI_FEATURE_WFD_R2 = 1L << 50; // Wi-Fi Display R2 /** * RFC 7542 decorated identity support * @hide */ - public static final long WIFI_FEATURE_DECORATED_IDENTITY = 0x8000000000000L; + public static final long WIFI_FEATURE_DECORATED_IDENTITY = 1L << 51; /** * Trust On First Use support for WPA Enterprise network * @hide */ - public static final long WIFI_FEATURE_TRUST_ON_FIRST_USE = 0x10000000000000L; + public static final long WIFI_FEATURE_TRUST_ON_FIRST_USE = 1L << 52; /** * Support for 2 STA's multi internet concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 0x20000000000000L; + public static final long WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 1L << 53; /** * Support for DPP (Easy-Connect) AKM. * @hide */ - public static final long WIFI_FEATURE_DPP_AKM = 0x40000000000000L; + public static final long WIFI_FEATURE_DPP_AKM = 1L << 54; + + /** + * Support for setting TLS minimum version. + * @hide + */ + public static final long WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 1L << 55; + + /** + * Support for TLS v.13. + * @hide + */ + public static final long WIFI_FEATURE_TLS_V1_3 = 1L << 56; + + /** + * Support for Dual Band Simultaneous (DBS) operation. + * @hide + */ + public static final long WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 1L << 57; private long getSupportedFeatures() { try { @@ -4769,9 +5058,13 @@ public class WifiManager { * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. * Note that starting Soft AP mode may disable station mode operation if the device does not * support concurrency. - * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP, - * or null to use the persisted Soft AP configuration that was previously - * set using {@link #setSoftApConfiguration(softApConfiguration)}. + * + * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid + * unexpected error due to invalid configuration. + * + * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP, or + * null to use the persisted Soft AP configuration that was previously set + * using {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)}. * @return {@code true} if the operation succeeded, {@code false} otherwise * * @hide @@ -4811,6 +5104,23 @@ public class WifiManager { } /** + * Check if input configuration is valid. + * + * @param config a configuration would like to be checked. + * @return true if config is valid, otherwise false. + */ + public boolean validateSoftApConfiguration(@NonNull SoftApConfiguration config) { + if (config == null) { + throw new IllegalArgumentException(TAG + ": config can not be null"); + } + try { + return mService.validateSoftApConfiguration(config); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Request a local only hotspot that an application can use to communicate between co-located * devices connected to the created WiFi hotspot. The network created by this method will not * have Internet access. Each application can make a single request for the hotspot, but @@ -5254,6 +5564,9 @@ public class WifiManager { * Otherwise, the configuration changes will be applied when the Soft AP is next started * (the framework will not stop/start the AP). * + * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid + * unexpected error due to invalid configuration. + * * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP. * @return {@code true} if the operation succeeded, {@code false} otherwise * @@ -7529,6 +7842,35 @@ public class WifiManager { } /** + * Indicate that whether or not settings required TLS minimum version is supported. + * + * If the device doesn't support this capability, the minimum accepted TLS version is 1.0. + * + * @return true if this device supports setting TLS minimum version. + */ + public boolean isTlsMinimumVersionSupported() { + return isFeatureSupported(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION); + } + + /** + * Indicate that whether or not TLS v1.3 is supported. + * + * If requested minimum is not supported, it will default to the maximum supported version. + * + * @return true if this device supports TLS v1.3. + */ + public boolean isTlsV13Supported() { + return isFeatureSupported(WIFI_FEATURE_TLS_V1_3); + } + + /** + * @return true if this device supports Dual Band Simultaneous (DBS) operation. + */ + public boolean isDualBandSimultaneousSupported() { + return isFeatureSupported(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS); + } + + /** * Gets the factory Wi-Fi MAC addresses. * @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array * if failed. @@ -9318,6 +9660,13 @@ public class WifiManager { * mode(s), that is allowed for the current regulatory domain. An empty list implies that there * are no available channels for use. * + * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} + * constant is limited to one of the band values specified below. Specifically, if the 5GHz + * band is included then it must include the DFS channels - an exception will be thrown + * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. + * This API will indicate whether DFS channels are allowed for the specified operation mode(s) + * per device policy. + * * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} * constants. * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED} - no band specified; Looks for the @@ -9336,12 +9685,10 @@ public class WifiManager { * @throws UnsupportedOperationException - if this API is not supported on this device * or IllegalArgumentException - if the band specified is not one among the list * of bands mentioned above. - * @hide */ @RequiresApi(Build.VERSION_CODES.S) - @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) + @RequiresPermission(NEARBY_WIFI_DEVICES) public List<WifiAvailableChannel> getAllowedChannels( @WifiScanner.WifiBand int band, @WifiAvailableChannel.OpMode int mode) { @@ -9349,8 +9696,13 @@ public class WifiManager { throw new UnsupportedOperationException(); } try { + Bundle extras = new Bundle(); + if (SdkLevel.isAtLeastS()) { + extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, + mContext.getAttributionSource()); + } return mService.getUsableChannels(band, mode, - WifiAvailableChannel.FILTER_REGULATORY); + WifiAvailableChannel.FILTER_REGULATORY, mContext.getOpPackageName(), extras); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -9362,6 +9714,13 @@ public class WifiManager { * state and interference due to other radios. An empty list implies that there are no available * channels for use. * + * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} + * constant is limited to one of the band values specified below. Specifically, if the 5GHz + * band is included then it must include the DFS channels - an exception will be thrown + * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. + * This API will indicate whether DFS channels are allowed for the specified operation mode(s) + * per device policy. + * * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} * constants. * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED} - no band specified; Looks for the @@ -9380,12 +9739,10 @@ public class WifiManager { * @throws UnsupportedOperationException - if this API is not supported on this device * or IllegalArgumentException - if the band specified is not one among the list * of bands mentioned above. - * @hide */ @RequiresApi(Build.VERSION_CODES.S) - @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) + @RequiresPermission(NEARBY_WIFI_DEVICES) public List<WifiAvailableChannel> getUsableChannels( @WifiScanner.WifiBand int band, @WifiAvailableChannel.OpMode int mode) { @@ -9393,8 +9750,13 @@ public class WifiManager { throw new UnsupportedOperationException(); } try { + Bundle extras = new Bundle(); + if (SdkLevel.isAtLeastS()) { + extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, + mContext.getAttributionSource()); + } return mService.getUsableChannels(band, mode, - WifiAvailableChannel.getUsableFilter()); + WifiAvailableChannel.getUsableFilter(), mContext.getOpPackageName(), extras); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -10017,4 +10379,20 @@ public class WifiManager { throw e.rethrowFromSystemServer(); } } + + /** + * Returns the max number of channels that is allowed to be set on a + * {@link WifiNetworkSpecifier}. + * @see WifiNetworkSpecifier.Builder#setPreferredChannelsFrequenciesMhz(int[]) + * + * @return The max number of channels can be set on a request. + */ + + public int getMaxNumberOfChannelsPerNetworkSpecifierRequest() { + try { + return mService.getMaxNumberOfChannelsPerRequest(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/framework/java/android/net/wifi/WifiNetworkSelectionConfig.java b/framework/java/android/net/wifi/WifiNetworkSelectionConfig.java index 69dc2f70d6..672cb1863d 100644 --- a/framework/java/android/net/wifi/WifiNetworkSelectionConfig.java +++ b/framework/java/android/net/wifi/WifiNetworkSelectionConfig.java @@ -18,6 +18,7 @@ package android.net.wifi; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -30,6 +31,7 @@ import java.util.function.Consumer; * An Object used in {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)}. * @hide */ +@SystemApi public final class WifiNetworkSelectionConfig implements Parcelable { /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -60,6 +62,8 @@ public final class WifiNetworkSelectionConfig implements Parcelable { private boolean mSufficiencyCheckEnabledWhenScreenOff = true; private boolean mSufficiencyCheckEnabledWhenScreenOn = true; + private boolean mUserConnectChoiceOverrideEnabled = true; + private boolean mLastSelectionWeightEnabled = true; private int mAssociatedNetworkSelectionOverride = ASSOCIATED_NETWORK_SELECTION_OVERRIDE_NONE; // empty constructor @@ -72,6 +76,8 @@ public final class WifiNetworkSelectionConfig implements Parcelable { mSufficiencyCheckEnabledWhenScreenOff = that.mSufficiencyCheckEnabledWhenScreenOff; mSufficiencyCheckEnabledWhenScreenOn = that.mSufficiencyCheckEnabledWhenScreenOn; mAssociatedNetworkSelectionOverride = that.mAssociatedNetworkSelectionOverride; + mUserConnectChoiceOverrideEnabled = that.mUserConnectChoiceOverrideEnabled; + mLastSelectionWeightEnabled = that.mLastSelectionWeightEnabled; } /** @@ -89,6 +95,20 @@ public final class WifiNetworkSelectionConfig implements Parcelable { } /** + * See {@link Builder#setUserConnectChoiceOverrideEnabled(boolean)}. + */ + public boolean isUserConnectChoiceOverrideEnabled() { + return mUserConnectChoiceOverrideEnabled; + } + + /** + * See {@link Builder#setLastSelectionWeightEnabled(boolean)}. + */ + public boolean isLastSelectionWeightEnabled() { + return mLastSelectionWeightEnabled; + } + + /** * See {@link Builder#setAssociatedNetworkSelectionOverride(int)}. * @return */ @@ -118,6 +138,8 @@ public final class WifiNetworkSelectionConfig implements Parcelable { public Builder() { mWifiNetworkSelectionConfig.mSufficiencyCheckEnabledWhenScreenOff = true; mWifiNetworkSelectionConfig.mSufficiencyCheckEnabledWhenScreenOn = true; + mWifiNetworkSelectionConfig.mUserConnectChoiceOverrideEnabled = true; + mWifiNetworkSelectionConfig.mLastSelectionWeightEnabled = true; mWifiNetworkSelectionConfig.mAssociatedNetworkSelectionOverride = ASSOCIATED_NETWORK_SELECTION_OVERRIDE_NONE; } @@ -198,6 +220,44 @@ public final class WifiNetworkSelectionConfig implements Parcelable { } /** + * Enable or disable candidate override with the user connect choice. + * <p> + * If the override is enabled, the network selector overrides any selected candidate + * with a network previously chosen by the user over the candidate (i.e. when the + * candidate was connected the user explicitly selected another network), if one exists. + * <p> + * If the override is disabled, network selector uses the network nominator candidate + * and does not override it with the user chosen configuration. + * <p> + * By default, user connect choice override is enabled. + * @param enabled Set to true to enable candidate override with the user connect choice, + * and false to disable the override. + */ + public @NonNull Builder setUserConnectChoiceOverrideEnabled(boolean enabled) { + mWifiNetworkSelectionConfig.mUserConnectChoiceOverrideEnabled = enabled; + return this; + } + + /** + * Enable or disable last selection weight. + * <p> + * If the last selection weight is enabled, network selector prefers the latest + * user selected network over all other networks for a limited duration. + * This duration is configurable via {@code config_wifiFrameworkLastSelectionMinutes}. + * <p> + * If the last selection weight is disabled, network selector does not prefer a + * recently selected network over other networks. + * <p> + * By default, last selection weight is enabled. + * @param enabled Set to true to enable the last selection weight, + * and false to disable it. + */ + public @NonNull Builder setLastSelectionWeightEnabled(boolean enabled) { + mWifiNetworkSelectionConfig.mLastSelectionWeightEnabled = enabled; + return this; + } + + /** * Creates a WifiNetworkSelectionConfig for use in * {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig, Consumer)} */ @@ -209,7 +269,8 @@ public final class WifiNetworkSelectionConfig implements Parcelable { @Override public int hashCode() { return Objects.hash(mSufficiencyCheckEnabledWhenScreenOff, - mSufficiencyCheckEnabledWhenScreenOn, mAssociatedNetworkSelectionOverride); + mSufficiencyCheckEnabledWhenScreenOn, mAssociatedNetworkSelectionOverride, + mUserConnectChoiceOverrideEnabled, mLastSelectionWeightEnabled); } @Override @@ -223,7 +284,9 @@ public final class WifiNetworkSelectionConfig implements Parcelable { WifiNetworkSelectionConfig lhs = (WifiNetworkSelectionConfig) obj; return mSufficiencyCheckEnabledWhenScreenOff == lhs.mSufficiencyCheckEnabledWhenScreenOff && mSufficiencyCheckEnabledWhenScreenOn == lhs.mSufficiencyCheckEnabledWhenScreenOn - && mAssociatedNetworkSelectionOverride == lhs.mAssociatedNetworkSelectionOverride; + && mAssociatedNetworkSelectionOverride == lhs.mAssociatedNetworkSelectionOverride + && mUserConnectChoiceOverrideEnabled == lhs.mUserConnectChoiceOverrideEnabled + && mLastSelectionWeightEnabled == lhs.mLastSelectionWeightEnabled; } public static final @NonNull Creator<WifiNetworkSelectionConfig> CREATOR = @@ -234,6 +297,8 @@ public final class WifiNetworkSelectionConfig implements Parcelable { config.mSufficiencyCheckEnabledWhenScreenOff = in.readBoolean(); config.mSufficiencyCheckEnabledWhenScreenOn = in.readBoolean(); config.mAssociatedNetworkSelectionOverride = in.readInt(); + config.mUserConnectChoiceOverrideEnabled = in.readBoolean(); + config.mLastSelectionWeightEnabled = in.readBoolean(); return config; } @@ -253,6 +318,8 @@ public final class WifiNetworkSelectionConfig implements Parcelable { dest.writeBoolean(mSufficiencyCheckEnabledWhenScreenOff); dest.writeBoolean(mSufficiencyCheckEnabledWhenScreenOn); dest.writeInt(mAssociatedNetworkSelectionOverride); + dest.writeBoolean(mUserConnectChoiceOverrideEnabled); + dest.writeBoolean(mLastSelectionWeightEnabled); } @Override @@ -263,7 +330,11 @@ public final class WifiNetworkSelectionConfig implements Parcelable { .append(", mSufficiencyCheckEnabledWhenScreenOn=") .append(mSufficiencyCheckEnabledWhenScreenOn) .append(", mAssociatedNetworkSelectionOverride=") - .append(mAssociatedNetworkSelectionOverride); + .append(mAssociatedNetworkSelectionOverride) + .append(", mUserConnectChoiceOverrideEnabled=") + .append(mUserConnectChoiceOverrideEnabled) + .append(", mLastSelectionWeightEnabled=") + .append(mLastSelectionWeightEnabled); return sb.toString(); } } diff --git a/framework/java/android/net/wifi/WifiNetworkSpecifier.java b/framework/java/android/net/wifi/WifiNetworkSpecifier.java index 045a9a4c90..3b1042de64 100644 --- a/framework/java/android/net/wifi/WifiNetworkSpecifier.java +++ b/framework/java/android/net/wifi/WifiNetworkSpecifier.java @@ -16,6 +16,8 @@ package android.net.wifi; +import static android.net.wifi.ScanResult.UNSPECIFIED; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -37,6 +39,7 @@ import com.android.modules.utils.build.SdkLevel; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Objects; /** @@ -60,6 +63,7 @@ import java.util.Objects; * </p> */ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parcelable { + private static final String TAG = "WifiNetworkSpecifier"; /** @@ -76,7 +80,23 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc } else if (ScanResult.is60GHz(freqMHz)) { return ScanResult.WIFI_BAND_60_GHZ; } - return ScanResult.UNSPECIFIED; + return UNSPECIFIED; + } + + /** + * Check the channel in the array is valid. + * @hide + */ + public static boolean validateChannelFrequencyInMhz(@NonNull int[] channels) { + if (channels == null) { + return false; + } + for (int channel : channels) { + if (ScanResult.convertFrequencyMhzToChannelIfSupported(channel) == UNSPECIFIED) { + return false; + } + } + return true; } /** @@ -87,7 +107,7 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc */ public static boolean validateBand(@WifiBand int band) { switch (band) { - case ScanResult.UNSPECIFIED: + case UNSPECIFIED: case ScanResult.WIFI_BAND_24_GHZ: case ScanResult.WIFI_BAND_5_GHZ: case ScanResult.WIFI_BAND_6_GHZ: @@ -168,6 +188,8 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc */ @WifiBand private int mBand; + private int[] mChannels; + public Builder() { mSsidPatternMatcher = null; mBssidPatternMatcher = null; @@ -177,7 +199,8 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc mWpa2EnterpriseConfig = null; mWpa3EnterpriseConfig = null; mIsHiddenSSID = false; - mBand = ScanResult.UNSPECIFIED; + mBand = UNSPECIFIED; + mChannels = new int[0]; } /** @@ -426,6 +449,27 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc return this; } + /** + * Specifies the preferred channels for this network. The channels set in the request will + * be used to optimize the scan and connection. + * <p> + * <li>Should only be set to request local-only network</li> + * <li>If not set, defaults to an empty array and device will do a full band scan.</li> + * + * @param channelFreqs an Array of the channels in MHz. The length of the array must not + * exceed {@link WifiManager#getMaxNumberOfChannelsPerNetworkSpecifierRequest()} + * + * @return Instance of {@link Builder} to enable chaining of the builder method. + */ + @NonNull public Builder setPreferredChannelsFrequenciesMhz(@NonNull int[] channelFreqs) { + Objects.requireNonNull(channelFreqs); + if (!validateChannelFrequencyInMhz(channelFreqs)) { + throw new IllegalArgumentException("Invalid channel frequency in the input array"); + } + mChannels = channelFreqs.clone(); + return this; + } + private void setSecurityParamsInWifiConfiguration( @NonNull WifiConfiguration configuration) { if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network. @@ -604,7 +648,7 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc * @throws IllegalStateException on invalid params set. */ public @NonNull WifiNetworkSpecifier build() { - if (!hasSetAnyPattern() && mBand == ScanResult.UNSPECIFIED) { + if (!hasSetAnyPattern() && mBand == UNSPECIFIED) { throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/" + "setBssid/setBand should be invoked for specifier"); } @@ -612,20 +656,25 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc if (hasSetMatchNonePattern()) { throw new IllegalStateException("cannot set match-none pattern for specifier"); } - if (hasSetMatchAllPattern() && mBand == ScanResult.UNSPECIFIED) { + if (hasSetMatchAllPattern() && mBand == UNSPECIFIED) { throw new IllegalStateException("cannot set match-all pattern for specifier"); } if (mIsHiddenSSID && mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL) { throw new IllegalStateException("setSsid should also be invoked when " + "setIsHiddenSsid is invoked for network specifier"); } + if (mChannels.length != 0 && mBand != UNSPECIFIED) { + throw new IllegalStateException("cannot setPreferredChannelsFrequencyInMhz with " + + "setBand together"); + } validateSecurityParams(); return new WifiNetworkSpecifier( mSsidPatternMatcher, mBssidPatternMatcher, mBand, - buildWifiConfiguration()); + buildWifiConfiguration(), + mChannels); } } @@ -647,6 +696,8 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc */ @WifiBand private final int mBand; + private final int[] mChannelFreqs; + /** * Security credentials for the network. * <p> @@ -665,9 +716,10 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc /** @hide */ public WifiNetworkSpecifier(@NonNull PatternMatcher ssidPatternMatcher, - @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher, - @WifiBand int band, - @NonNull WifiConfiguration wifiConfiguration) { + @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher, + @WifiBand int band, + @NonNull WifiConfiguration wifiConfiguration, + @NonNull int[] channelFreqs) { checkNotNull(ssidPatternMatcher); checkNotNull(bssidPatternMatcher); checkNotNull(wifiConfiguration); @@ -676,6 +728,7 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc this.bssidPatternMatcher = bssidPatternMatcher; this.mBand = band; this.wifiConfiguration = wifiConfiguration; + this.mChannelFreqs = channelFreqs; } /** @@ -685,6 +738,14 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc return mBand; } + /** + * The preferred channels fot this network specifier. + * @see Builder#setPreferredChannelsFrequenciesMhz(int[]) + */ + @NonNull public int[] getPreferredChannelFrequenciesMhz() { + return mChannelFreqs.clone(); + } + public static final @NonNull Creator<WifiNetworkSpecifier> CREATOR = new Creator<WifiNetworkSpecifier>() { @Override @@ -696,8 +757,9 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc Pair.create(baseAddress, mask); int band = in.readInt(); WifiConfiguration wifiConfiguration = in.readParcelable(null); + int[] mChannels = in.createIntArray(); return new WifiNetworkSpecifier(ssidPatternMatcher, bssidPatternMatcher, band, - wifiConfiguration); + wifiConfiguration, mChannels); } @Override @@ -718,13 +780,14 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc dest.writeParcelable(bssidPatternMatcher.second, flags); dest.writeInt(mBand); dest.writeParcelable(wifiConfiguration, flags); + dest.writeIntArray(mChannelFreqs); } @Override public int hashCode() { return Objects.hash( ssidPatternMatcher.getPath(), ssidPatternMatcher.getType(), bssidPatternMatcher, - mBand, wifiConfiguration.allowedKeyManagement); + mBand, wifiConfiguration.allowedKeyManagement, Arrays.hashCode(mChannelFreqs)); } @Override @@ -744,7 +807,8 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc lhs.bssidPatternMatcher) && this.mBand == lhs.mBand && Objects.equals(this.wifiConfiguration.allowedKeyManagement, - lhs.wifiConfiguration.allowedKeyManagement); + lhs.wifiConfiguration.allowedKeyManagement) + && Arrays.equals(mChannelFreqs, lhs.mChannelFreqs); } @Override diff --git a/framework/java/android/net/wifi/WifiScanner.java b/framework/java/android/net/wifi/WifiScanner.java index a2257d99dd..b21ffe69d2 100644 --- a/framework/java/android/net/wifi/WifiScanner.java +++ b/framework/java/android/net/wifi/WifiScanner.java @@ -16,6 +16,8 @@ package android.net.wifi; +import static android.Manifest.permission.NEARBY_WIFI_DEVICES; + import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; @@ -244,16 +246,18 @@ public class WifiScanner { * @param band one of the WifiScanner#WIFI_BAND_* constants, e.g. {@link #WIFI_BAND_24_GHZ} * @return a list of all the frequencies, in MHz, for the given band(s) e.g. channel 1 is * 2412, or null if an error occurred. - * - * @hide */ - @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) + @RequiresPermission(NEARBY_WIFI_DEVICES) public List<Integer> getAvailableChannels(int band) { try { + Bundle extras = new Bundle(); + if (SdkLevel.isAtLeastS()) { + extras.putParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, + mContext.getAttributionSource()); + } Bundle bundle = mService.getAvailableChannels(band, mContext.getOpPackageName(), - mContext.getAttributionTag()); + mContext.getAttributionTag(), extras); List<Integer> channels = bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA); return channels == null ? new ArrayList<>() : channels; } catch (RemoteException e) { diff --git a/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java b/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java index 5c1f4b21c4..f4c9bbb7d6 100644 --- a/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java +++ b/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java @@ -879,7 +879,8 @@ public final class WifiUsabilityStatsEntry implements Parcelable { && mContentionTimeStats.length == NUM_WME_ACCESS_CATEGORIES) { return mContentionTimeStats[ac]; } - Log.e(TAG, "The ContentionTimeStats is not filled out correctly: " + mContentionTimeStats); + Log.e(TAG, "The ContentionTimeStats is not filled out correctly: " + + Arrays.toString(mContentionTimeStats)); return new ContentionTimeStats(); } diff --git a/framework/java/android/net/wifi/hotspot2/pps/Credential.java b/framework/java/android/net/wifi/hotspot2/pps/Credential.java index 4ca724a58c..658588ae8b 100644 --- a/framework/java/android/net/wifi/hotspot2/pps/Credential.java +++ b/framework/java/android/net/wifi/hotspot2/pps/Credential.java @@ -20,6 +20,7 @@ import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH import android.net.wifi.EAPConstants; import android.net.wifi.ParcelUtil; +import android.net.wifi.WifiEnterpriseConfig; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -959,6 +960,43 @@ public final class Credential implements Parcelable { } /** + * The required minimum TLS version. + */ + private @WifiEnterpriseConfig.TlsVersion int mMinimumTlsVersion = WifiEnterpriseConfig.TLS_V1_0; + /** + * Set the minimum TLS version for TLS-based EAP methods. + * + * {@link android.net.wifi.WifiManager#isTlsMinimumVersionSupported()} indicates whether + * or not a minimum TLS version can be set. If not supported, the minimum TLS version + * is always TLS v1.0. + * <p> + * {@link android.net.wifi.WifiManager#isTlsV13Supported()} indicates whether or not + * TLS v1.3 is supported. If requested minimum is not supported, it will default to + * the maximum supported version. + * + * @param tlsVersion the TLS version + * @throws IllegalArgumentException if the TLS version is invalid. + */ + public void setMinimumTlsVersion(@WifiEnterpriseConfig.TlsVersion int tlsVersion) + throws IllegalArgumentException { + if (tlsVersion < WifiEnterpriseConfig.TLS_VERSION_MIN + || tlsVersion > WifiEnterpriseConfig.TLS_VERSION_MAX) { + throw new IllegalArgumentException( + "Invalid TLS version: " + tlsVersion); + } + mMinimumTlsVersion = tlsVersion; + } + + /** + * Get the minimum TLS version for TLS-based EAP methods. + * + * @return the TLS version + */ + public @WifiEnterpriseConfig.TlsVersion int getMinimumTlsVersion() { + return mMinimumTlsVersion; + } + + /** * Constructor for creating Credential with default values. */ public Credential() {} @@ -993,6 +1031,7 @@ public final class Credential implements Parcelable { } mClientPrivateKey = source.mClientPrivateKey; + mMinimumTlsVersion = source.mMinimumTlsVersion; } } @@ -1013,6 +1052,7 @@ public final class Credential implements Parcelable { ParcelUtil.writeCertificates(dest, mCaCertificates); ParcelUtil.writeCertificates(dest, mClientCertificateChain); ParcelUtil.writePrivateKey(dest, mClientPrivateKey); + dest.writeInt(mMinimumTlsVersion); } @Override @@ -1037,7 +1077,8 @@ public final class Credential implements Parcelable { : mSimCredential.equals(that.mSimCredential)) && isX509CertificatesEquals(mCaCertificates, that.mCaCertificates) && isX509CertificatesEquals(mClientCertificateChain, that.mClientCertificateChain) - && isPrivateKeyEquals(mClientPrivateKey, that.mClientPrivateKey); + && isPrivateKeyEquals(mClientPrivateKey, that.mClientPrivateKey) + && mMinimumTlsVersion == that.mMinimumTlsVersion; } @Override @@ -1045,7 +1086,7 @@ public final class Credential implements Parcelable { return Objects.hash(mCreationTimeInMillis, mExpirationTimeInMillis, mRealm, mCheckAaaServerCertStatus, mUserCredential, mCertCredential, mSimCredential, mClientPrivateKey, Arrays.hashCode(mCaCertificates), - Arrays.hashCode(mClientCertificateChain)); + Arrays.hashCode(mClientCertificateChain), mMinimumTlsVersion); } /** @@ -1079,6 +1120,7 @@ public final class Credential implements Parcelable { builder.append(mCertCredential); builder.append("CertificateCredential End ---\n"); } + builder.append("MinimumTlsVersion: ").append(mMinimumTlsVersion).append("\n"); if (mSimCredential != null) { builder.append("SIMCredential Begin ---\n"); builder.append(mSimCredential); @@ -1140,6 +1182,7 @@ public final class Credential implements Parcelable { credential.setCaCertificates(ParcelUtil.readCertificates(in)); credential.setClientCertificateChain(ParcelUtil.readCertificates(in)); credential.setClientPrivateKey(ParcelUtil.readPrivateKey(in)); + credential.setMinimumTlsVersion(in.readInt()); return credential; } diff --git a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java index 34aff6c027..e90502c6a5 100644 --- a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java +++ b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java @@ -393,10 +393,12 @@ public final class HomeSp implements Parcelable { builder.append("FriendlyName: ").append(mFriendlyName).append("\n"); builder.append("IconURL: ").append(mIconUrl).append("\n"); builder.append("HomeNetworkIDs: ").append(mHomeNetworkIds).append("\n"); - builder.append("MatchAllOIs: ").append(mMatchAllOis).append("\n"); - builder.append("MatchAnyOIs: ").append(mMatchAnyOis).append("\n"); - builder.append("OtherHomePartners: ").append(mOtherHomePartners).append("\n"); - builder.append("RoamingConsortiumOIs: ").append(mRoamingConsortiumOis).append("\n"); + builder.append("MatchAllOIs: ").append(Arrays.toString(mMatchAllOis)).append("\n"); + builder.append("MatchAnyOIs: ").append(Arrays.toString(mMatchAnyOis)).append("\n"); + builder.append("OtherHomePartners: ").append(Arrays.toString(mOtherHomePartners)) + .append("\n"); + builder.append("RoamingConsortiumOIs: ").append(Arrays.toString(mRoamingConsortiumOis)) + .append("\n"); return builder.toString(); } diff --git a/framework/java/android/net/wifi/hotspot2/pps/Policy.java b/framework/java/android/net/wifi/hotspot2/pps/Policy.java index b0a2cc397c..f0a1751064 100644 --- a/framework/java/android/net/wifi/hotspot2/pps/Policy.java +++ b/framework/java/android/net/wifi/hotspot2/pps/Policy.java @@ -397,9 +397,9 @@ public final class Policy implements Parcelable { @Override public int hashCode() { return Objects.hash(mMinHomeDownlinkBandwidth, mMinHomeUplinkBandwidth, - mMinRoamingDownlinkBandwidth, mMinRoamingUplinkBandwidth, mExcludedSsidList, - mRequiredProtoPortMap, mMaximumBssLoadValue, mPreferredRoamingPartnerList, - mPolicyUpdate); + mMinRoamingDownlinkBandwidth, mMinRoamingUplinkBandwidth, + Arrays.hashCode(mExcludedSsidList), mRequiredProtoPortMap, mMaximumBssLoadValue, + mPreferredRoamingPartnerList, mPolicyUpdate); } @Override @@ -412,7 +412,8 @@ public final class Policy implements Parcelable { .append("\n"); builder.append("MinRoamingUplinkBandwidth: ").append(mMinRoamingUplinkBandwidth) .append("\n"); - builder.append("ExcludedSSIDList: ").append(mExcludedSsidList).append("\n"); + builder.append("ExcludedSSIDList: ").append(Arrays.toString(mExcludedSsidList)) + .append("\n"); builder.append("RequiredProtoPortMap: ").append(mRequiredProtoPortMap).append("\n"); builder.append("MaximumBSSLoadValue: ").append(mMaximumBssLoadValue).append("\n"); builder.append("PreferredRoamingPartnerList: ").append(mPreferredRoamingPartnerList) diff --git a/framework/java/android/net/wifi/p2p/WifiP2pConfig.java b/framework/java/android/net/wifi/p2p/WifiP2pConfig.java index d8658cc900..4444bcdefb 100644 --- a/framework/java/android/net/wifi/p2p/WifiP2pConfig.java +++ b/framework/java/android/net/wifi/p2p/WifiP2pConfig.java @@ -28,6 +28,10 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import androidx.annotation.RequiresApi; + +import com.android.modules.utils.build.SdkLevel; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.nio.charset.StandardCharsets; @@ -94,6 +98,16 @@ public class WifiP2pConfig implements Parcelable { public @interface GroupOperatingBandType {} /** + * IP provisioning via IPv4 DHCP, when joining a group as a group client. + */ + public static final int GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP = 0; + + /** + * IP provisioning via IPv6 link-local, when joining a group as a group client. + */ + public static final int GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL = 1; + + /** * Allow the system to pick the operating frequency from all supported bands. */ public static final int GROUP_OWNER_BAND_AUTO = 0; @@ -139,6 +153,17 @@ public class WifiP2pConfig implements Parcelable { public int groupOwnerIntent = GROUP_OWNER_INTENT_AUTO; /** @hide */ + @IntDef(prefix = { "GROUP_CLIENT_IP_PROVISIONING_MODE_" }, value = { + GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP, + GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL + }) + @Retention(RetentionPolicy.SOURCE) + public @interface GroupClientIpProvisioningMode {} + + @GroupClientIpProvisioningMode + private int mGroupClientIpProvisioningMode = GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP; + + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int netId = WifiP2pGroup.NETWORK_ID_PERSISTENT; @@ -203,6 +228,17 @@ public class WifiP2pConfig implements Parcelable { } } + /** + * Get the IP provisioning mode when joining a group as a group client. + * The result will be one of the following: + * {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP}, + * {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL} + */ + @GroupClientIpProvisioningMode + public int getGroupClientIpProvisioningMode() { + return mGroupClientIpProvisioningMode; + } + public String toString() { StringBuffer sbuf = new StringBuffer(); sbuf.append("\n address: ").append(deviceAddress); @@ -213,6 +249,7 @@ public class WifiP2pConfig implements Parcelable { sbuf.append("\n passphrase: ").append( TextUtils.isEmpty(passphrase) ? "<empty>" : "<non-empty>"); sbuf.append("\n groupOwnerBand: ").append(groupOwnerBand); + sbuf.append("\n groupClientIpProvisioningMode: ").append(mGroupClientIpProvisioningMode); return sbuf.toString(); } @@ -231,6 +268,7 @@ public class WifiP2pConfig implements Parcelable { networkName = source.networkName; passphrase = source.passphrase; groupOwnerBand = source.groupOwnerBand; + mGroupClientIpProvisioningMode = source.mGroupClientIpProvisioningMode; } } @@ -243,10 +281,12 @@ public class WifiP2pConfig implements Parcelable { dest.writeString(networkName); dest.writeString(passphrase); dest.writeInt(groupOwnerBand); + dest.writeInt(mGroupClientIpProvisioningMode); } /** Implement the Parcelable interface */ - public static final @android.annotation.NonNull Creator<WifiP2pConfig> CREATOR = + @NonNull + public static final Creator<WifiP2pConfig> CREATOR = new Creator<WifiP2pConfig>() { public WifiP2pConfig createFromParcel(Parcel in) { WifiP2pConfig config = new WifiP2pConfig(); @@ -257,6 +297,7 @@ public class WifiP2pConfig implements Parcelable { config.networkName = in.readString(); config.passphrase = in.readString(); config.groupOwnerBand = in.readInt(); + config.mGroupClientIpProvisioningMode = in.readInt(); return config; } @@ -292,6 +333,7 @@ public class WifiP2pConfig implements Parcelable { private int mGroupOperatingBand = GROUP_OWNER_BAND_AUTO; private int mGroupOperatingFrequency = GROUP_OWNER_BAND_AUTO; private int mNetId = WifiP2pGroup.NETWORK_ID_TEMPORARY; + private int mGroupClientIpProvisioningMode = GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP; /** * Specify the peer's MAC address. If not set, the device will @@ -307,7 +349,8 @@ public class WifiP2pConfig implements Parcelable { * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */ - public @NonNull Builder setDeviceAddress(@Nullable MacAddress deviceAddress) { + @NonNull + public Builder setDeviceAddress(@Nullable MacAddress deviceAddress) { if (deviceAddress == null) { mDeviceAddress = MAC_ANY_ADDRESS; } else { @@ -333,7 +376,8 @@ public class WifiP2pConfig implements Parcelable { * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */ - public @NonNull Builder setNetworkName(@NonNull String networkName) { + @NonNull + public Builder setNetworkName(@NonNull String networkName) { if (TextUtils.isEmpty(networkName)) { throw new IllegalArgumentException( "network name must be non-empty."); @@ -366,7 +410,8 @@ public class WifiP2pConfig implements Parcelable { * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */ - public @NonNull Builder setPassphrase(@NonNull String passphrase) { + @NonNull + public Builder setPassphrase(@NonNull String passphrase) { if (TextUtils.isEmpty(passphrase)) { throw new IllegalArgumentException( "passphrase must be non-empty."); @@ -411,7 +456,8 @@ public class WifiP2pConfig implements Parcelable { * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */ - public @NonNull Builder setGroupOperatingBand(@GroupOperatingBandType int band) { + @NonNull + public Builder setGroupOperatingBand(@GroupOperatingBandType int band) { switch (band) { case GROUP_OWNER_BAND_AUTO: case GROUP_OWNER_BAND_2GHZ: @@ -452,7 +498,8 @@ public class WifiP2pConfig implements Parcelable { * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */ - public @NonNull Builder setGroupOperatingFrequency(int frequency) { + @NonNull + public Builder setGroupOperatingFrequency(int frequency) { if (frequency < 0) { throw new IllegalArgumentException( "Invalid group operating frequency!"); @@ -471,7 +518,8 @@ public class WifiP2pConfig implements Parcelable { * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */ - public @NonNull Builder enablePersistentMode(boolean persistent) { + @NonNull + public Builder enablePersistentMode(boolean persistent) { if (persistent) { mNetId = WifiP2pGroup.NETWORK_ID_PERSISTENT; } else { @@ -481,10 +529,53 @@ public class WifiP2pConfig implements Parcelable { } /** + * Specify the IP provisioning mode when joining a group as a group client. The IP + * provisioning mode should be {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP} or + * {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL}. + * <p> + * When joining a group as Group Client using {@link + * WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig, + * WifiP2pManager.ActionListener)}, + * specifying {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP} directs the system to + * assign a IPv4 to the group client using DHCP. Specifying + * {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL} directs the system to assign + * a link-local IPv6 to the group client. + * <p> + * Optional. {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP} by default. + * + * @param groupClientIpProvisioningMode the IP provisioning mode of the group client. + * This should be one of {@link #GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP}, + * {@link #GROUP_OWNER_BAND_2GHZ}, {@link #GROUP_OWNER_BAND_5GHZ}. + * @return The builder to facilitate chaining + * {@code builder.setXXX(..).setXXX(..)}. + */ + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + @NonNull + public Builder setGroupClientIpProvisioningMode( + @GroupClientIpProvisioningMode int groupClientIpProvisioningMode) { + // Since group client IP provisioning modes use NetworkStack functionalities introduced + // in T, hence we need at least T sdk for this to be supported. + if (!SdkLevel.isAtLeastT()) { + throw new UnsupportedOperationException(); + } + switch (groupClientIpProvisioningMode) { + case GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP: + case GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL: + mGroupClientIpProvisioningMode = groupClientIpProvisioningMode; + break; + default: + throw new IllegalArgumentException( + "Invalid constant for the group client IP provisioning mode!"); + } + return this; + } + + /** * Build {@link WifiP2pConfig} given the current requests made on the builder. * @return {@link WifiP2pConfig} constructed based on builder method calls. */ - public @NonNull WifiP2pConfig build() { + @NonNull + public WifiP2pConfig build() { if ((TextUtils.isEmpty(mNetworkName) && !TextUtils.isEmpty(mPassphrase)) || (!TextUtils.isEmpty(mNetworkName) && TextUtils.isEmpty(mPassphrase))) { throw new IllegalStateException( @@ -512,6 +603,7 @@ public class WifiP2pConfig implements Parcelable { config.groupOwnerBand = mGroupOperatingBand; } config.netId = mNetId; + config.mGroupClientIpProvisioningMode = mGroupClientIpProvisioningMode; return config; } } diff --git a/framework/java/android/net/wifi/p2p/WifiP2pGroup.java b/framework/java/android/net/wifi/p2p/WifiP2pGroup.java index e497b22d77..f761b80a0d 100644 --- a/framework/java/android/net/wifi/p2p/WifiP2pGroup.java +++ b/framework/java/android/net/wifi/p2p/WifiP2pGroup.java @@ -59,6 +59,13 @@ public class WifiP2pGroup implements Parcelable { */ public static final int NETWORK_ID_PERSISTENT = -2; + /** + * Group owner P2P interface MAC address. + * @hide + */ + @UnsupportedAppUsage + public byte[] interfaceAddress; + /** The network name */ private String mNetworkName; diff --git a/framework/java/android/net/wifi/p2p/WifiP2pManager.java b/framework/java/android/net/wifi/p2p/WifiP2pManager.java index 5de438a5f2..a99ad564da 100644 --- a/framework/java/android/net/wifi/p2p/WifiP2pManager.java +++ b/framework/java/android/net/wifi/p2p/WifiP2pManager.java @@ -2326,10 +2326,7 @@ public class WifiP2pManager { * @param channel is the channel created at {@link #initialize} * @param wfdInfo the Wifi Display information to set * @param listener for callbacks on success or failure. Can be null. - * - * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) public void setWfdInfo(@NonNull Channel channel, @NonNull WifiP2pWfdInfo wfdInfo, @Nullable ActionListener listener) { diff --git a/framework/java/android/net/wifi/rtt/CivicLocation.java b/framework/java/android/net/wifi/rtt/CivicLocation.java index 1d41177926..60b745ddfd 100644 --- a/framework/java/android/net/wifi/rtt/CivicLocation.java +++ b/framework/java/android/net/wifi/rtt/CivicLocation.java @@ -25,6 +25,7 @@ import android.os.Parcelable.Creator; import android.util.SparseArray; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Locale; import java.util.Objects; @@ -267,7 +268,8 @@ public final class CivicLocation implements Parcelable { public int hashCode() { int[] civicAddressKeys = getSparseArrayKeys(mCivicAddressElements); String[] civicAddressValues = getSparseArrayValues(mCivicAddressElements); - return Objects.hash(mIsValid, mCountryCode, civicAddressKeys, civicAddressValues); + return Objects.hash(mIsValid, mCountryCode, Arrays.hashCode(civicAddressKeys), + Arrays.hashCode(civicAddressValues)); } /** diff --git a/framework/java/android/net/wifi/rtt/IWifiRttManager.aidl b/framework/java/android/net/wifi/rtt/IWifiRttManager.aidl index facbd87041..3618ce2f59 100644 --- a/framework/java/android/net/wifi/rtt/IWifiRttManager.aidl +++ b/framework/java/android/net/wifi/rtt/IWifiRttManager.aidl @@ -32,4 +32,5 @@ interface IWifiRttManager in WorkSource workSource, in RangingRequest request, in IRttCallback callback, in Bundle extras); void cancelRanging(in WorkSource workSource); + Bundle getRttCharacteristics(); } diff --git a/framework/java/android/net/wifi/rtt/RangingResult.java b/framework/java/android/net/wifi/rtt/RangingResult.java index d9d0717d60..c5854c9446 100644 --- a/framework/java/android/net/wifi/rtt/RangingResult.java +++ b/framework/java/android/net/wifi/rtt/RangingResult.java @@ -445,14 +445,18 @@ public final class RangingResult implements Parcelable { /** @hide */ @Override public String toString() { - return new StringBuilder("RangingResult: [status=").append(mStatus).append(", mac=").append( - mMac).append(", peerHandle=").append( - mPeerHandle == null ? "<null>" : mPeerHandle.peerId).append(", distanceMm=").append( - mDistanceMm).append(", distanceStdDevMm=").append(mDistanceStdDevMm).append( - ", rssi=").append(mRssi).append(", numAttemptedMeasurements=").append( - mNumAttemptedMeasurements).append(", numSuccessfulMeasurements=").append( - mNumSuccessfulMeasurements).append(", lci=").append(mLci).append(", lcr=").append( - mLcr).append(", responderLocation=").append(mResponderLocation) + return new StringBuilder("RangingResult: [status=").append(mStatus) + .append(", mac=").append(mMac) + .append(", peerHandle=").append( + mPeerHandle == null ? "<null>" : mPeerHandle.peerId) + .append(", distanceMm=").append(mDistanceMm) + .append(", distanceStdDevMm=").append(mDistanceStdDevMm) + .append(", rssi=").append(mRssi) + .append(", numAttemptedMeasurements=").append(mNumAttemptedMeasurements) + .append(", numSuccessfulMeasurements=").append(mNumSuccessfulMeasurements) + .append(", lci=").append(Arrays.toString(mLci)) + .append(", lcr=").append(Arrays.toString(mLcr)) + .append(", responderLocation=").append(mResponderLocation) .append(", timestamp=").append(mTimestamp).append(", is80211mcMeasurement=") .append(mIs80211mcMeasurement).append("]").toString(); } @@ -483,7 +487,7 @@ public final class RangingResult implements Parcelable { @Override public int hashCode() { return Objects.hash(mStatus, mMac, mPeerHandle, mDistanceMm, mDistanceStdDevMm, mRssi, - mNumAttemptedMeasurements, mNumSuccessfulMeasurements, mLci, mLcr, - mResponderLocation, mTimestamp, mIs80211mcMeasurement); + mNumAttemptedMeasurements, mNumSuccessfulMeasurements, Arrays.hashCode(mLci), + Arrays.hashCode(mLcr), mResponderLocation, mTimestamp, mIs80211mcMeasurement); } } diff --git a/framework/java/android/net/wifi/rtt/WifiRttManager.java b/framework/java/android/net/wifi/rtt/WifiRttManager.java index 3ef865c66b..60f4c2805a 100644 --- a/framework/java/android/net/wifi/rtt/WifiRttManager.java +++ b/framework/java/android/net/wifi/rtt/WifiRttManager.java @@ -27,9 +27,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; +import android.annotation.StringDef; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; +import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Bundle; @@ -39,6 +41,8 @@ import android.util.Log; import com.android.modules.utils.build.SdkLevel; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.concurrent.Executor; @@ -81,6 +85,33 @@ public class WifiRttManager { public static final String ACTION_WIFI_RTT_STATE_CHANGED = "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED"; + /** + * Bundle key to access if one-sided Wi-Fi RTT is supported. When it is not supported, only + * two-sided RTT can be performed, which requires responder supports IEEE 802.11mc and this can + * be determined by the method {@link ScanResult#is80211mcResponder()} + */ + public static final String CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT = "key_one_sided_rtt"; + /** + * Bundle key to access if getting the Location Configuration Information(LCI) from responder is + * supported. + * @see ResponderLocation + */ + public static final String CHARACTERISTICS_KEY_BOOLEAN_LCI = "key_lci"; + /** + * Bundle key to access if getting the Location Civic Report(LCR) from responder is supported. + * @see ResponderLocation + */ + public static final String CHARACTERISTICS_KEY_BOOLEAN_LCR = "key_lcr"; + + /** @hide */ + @StringDef(prefix = { "CHARACTERISTICS_KEY_"}, value = { + CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT, + CHARACTERISTICS_KEY_BOOLEAN_LCI, + CHARACTERISTICS_KEY_BOOLEAN_LCR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RttCharacteristicsKey {} + /** @hide */ public WifiRttManager(@NonNull Context context, @NonNull IWifiRttManager service) { mContext = context; @@ -210,4 +241,23 @@ public class WifiRttManager { throw e.rethrowFromSystemServer(); } } + + /** + * Returns a Bundle which represents the characteristics of the Wi-Fi RTT interface: a set of + * parameters which specify feature support. Each parameter can be accessed by the specified + * Bundle key, one of the {@code CHARACTERISTICS_KEY_*} value. + * <p> + * May return an empty Bundle if the Wi-Fi RTT service is not initialized. + * + * @return A Bundle specifying feature support of RTT. + */ + @RequiresPermission(ACCESS_WIFI_STATE) + @NonNull + public Bundle getRttCharacteristics() { + try { + return mService.getRttCharacteristics(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/framework/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/framework/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java index 940a612d3b..35cafcd791 100644 --- a/framework/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java +++ b/framework/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java @@ -754,4 +754,38 @@ public class WifiEnterpriseConfigTest { mEnterpriseConfig.setCaCertificateForTrustOnFirstUse(mockCert); } + + /** + * Verify setMinimumTlsVersion sunny cases. + */ + @Test + public void testSetMinimumTlsVersionWithValidValues() throws Exception { + for (int i = WifiEnterpriseConfig.TLS_VERSION_MIN; + i <= WifiEnterpriseConfig.TLS_VERSION_MAX; i++) { + mEnterpriseConfig.setMinimumTlsVersion(i); + assertEquals(i, mEnterpriseConfig.getMinimumTlsVersion()); + } + } + + /** + * Verify that setMinimumTlsVersion() raises IllegalArgumentException when + * an invalid TLS version is set. + * + * @throws IllegalArgumentException + */ + @Test (expected = IllegalArgumentException.class) + public void testSetMinimumTlsVersionWithVersionLargerThanMaxVersion() throws Exception { + mEnterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_VERSION_MAX + 1); + } + + /** + * Verify that setMinimumTlsVersion() raises IllegalArgumentException when + * an invalid TLS version is set. + * + * @throws IllegalArgumentException + */ + @Test (expected = IllegalArgumentException.class) + public void testSetMinimumTlsVersionWithVersionSmallerThanMinVersion() throws Exception { + mEnterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_VERSION_MIN - 1); + } } diff --git a/framework/tests/src/android/net/wifi/WifiManagerTest.java b/framework/tests/src/android/net/wifi/WifiManagerTest.java index 8e78900a9c..68ac135f89 100644 --- a/framework/tests/src/android/net/wifi/WifiManagerTest.java +++ b/framework/tests/src/android/net/wifi/WifiManagerTest.java @@ -45,6 +45,7 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_DECORATED_IDENTITY; import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP; import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_AKM; import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_ENROLLEE_RESPONDER; +import static android.net.wifi.WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS; import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; import static android.net.wifi.WifiManager.WIFI_FEATURE_P2P; import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT; @@ -60,6 +61,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; @@ -512,6 +514,29 @@ public class WifiManagerTest { } /** + * Check the call to validateSoftApConfiguration calls WifiService to + * validateSoftApConfiguration. + */ + @Test + public void testValidateSoftApConfigurationCallsService() throws Exception { + SoftApConfiguration apConfig = generatorTestSoftApConfig(); + when(mWifiService.validateSoftApConfiguration(any())).thenReturn(true); + assertTrue(mWifiManager.validateSoftApConfiguration(apConfig)); + + when(mWifiService.validateSoftApConfiguration(any())).thenReturn(false); + assertFalse(mWifiManager.validateSoftApConfiguration(apConfig)); + } + + /** + * Throws IllegalArgumentException when calling validateSoftApConfiguration with null. + */ + @Test + public void testValidateSoftApConfigurationWithNullConfiguration() throws Exception { + assertThrows(IllegalArgumentException.class, + () -> mWifiManager.validateSoftApConfiguration(null)); + } + + /** * Check the call to startSoftAp calls WifiService to startSoftAp with the provided * WifiConfiguration. Verify that the return value is propagated to the caller. */ @@ -3573,7 +3598,7 @@ public class WifiManagerTest { | WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI; mWifiManager.getAllowedChannels(band, mode); verify(mWifiService).getUsableChannels(eq(band), eq(mode), - eq(WifiAvailableChannel.FILTER_REGULATORY)); + eq(WifiAvailableChannel.FILTER_REGULATORY), eq(TEST_PACKAGE_NAME), any()); } /** @@ -3588,7 +3613,8 @@ public class WifiManagerTest { mWifiManager.getUsableChannels(band, mode); verify(mWifiService).getUsableChannels(eq(band), eq(mode), eq(WifiAvailableChannel.FILTER_CONCURRENCY - | WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE)); + | WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE), + eq(TEST_PACKAGE_NAME), any()); } /** @@ -3852,6 +3878,19 @@ public class WifiManagerTest { WifiManager.WIFI_MULTI_INTERNET_MODE_DBS_AP); } + /* + * Verify call to {@link WifiManager#isDualBandSimultaneousSupported}. + */ + @Test + public void testIsDualBandSimultaneousSupported() throws Exception { + when(mWifiService.getSupportedFeatures()) + .thenReturn(new Long(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS)); + assertTrue(mWifiManager.isDualBandSimultaneousSupported()); + when(mWifiService.getSupportedFeatures()) + .thenReturn(new Long(~WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS)); + assertFalse(mWifiManager.isDualBandSimultaneousSupported()); + } + /** * Verify call to * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. diff --git a/framework/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java b/framework/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java index 9d1d55d21c..53a0130366 100644 --- a/framework/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java +++ b/framework/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java @@ -195,7 +195,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_5_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -224,7 +224,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_5_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -253,7 +253,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_5_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -285,7 +285,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_24_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -316,7 +316,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_5_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -325,7 +325,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_24_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -334,7 +334,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.UNSPECIFIED, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); } @@ -364,7 +364,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_5_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -383,7 +383,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_24_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -393,7 +393,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.UNSPECIFIED, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); } @@ -425,7 +425,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_5_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -458,7 +458,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.WIFI_BAND_24_GHZ, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); @@ -486,7 +486,7 @@ public class WifiNetworkAgentSpecifierTest { ssidPattern, bssidPattern, ScanResult.UNSPECIFIED, - wificonfigurationNetworkSpecifier); + wificonfigurationNetworkSpecifier, new int[0]); assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier)); assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier)); diff --git a/framework/tests/src/android/net/wifi/WifiNetworkSelectionConfigTest.java b/framework/tests/src/android/net/wifi/WifiNetworkSelectionConfigTest.java index 34248273d6..0f1c8812ef 100644 --- a/framework/tests/src/android/net/wifi/WifiNetworkSelectionConfigTest.java +++ b/framework/tests/src/android/net/wifi/WifiNetworkSelectionConfigTest.java @@ -42,6 +42,8 @@ public class WifiNetworkSelectionConfigTest { .setAssociatedNetworkSelectionOverride( WifiNetworkSelectionConfig.ASSOCIATED_NETWORK_SELECTION_OVERRIDE_ENABLED) .setSufficiencyCheckEnabledWhenScreenOff(false) + .setUserConnectChoiceOverrideEnabled(false) + .setLastSelectionWeightEnabled(false) .build(); Parcel parcelW = Parcel.obtain(); @@ -59,6 +61,8 @@ public class WifiNetworkSelectionConfigTest { parcelConfig.getAssociatedNetworkSelectionOverride()); assertFalse(parcelConfig.isSufficiencyCheckEnabledWhenScreenOff()); assertTrue(parcelConfig.isSufficiencyCheckEnabledWhenScreenOn()); + assertFalse(parcelConfig.isUserConnectChoiceOverrideEnabled()); + assertFalse(parcelConfig.isLastSelectionWeightEnabled()); assertEquals(config, parcelConfig); assertEquals(config.hashCode(), parcelConfig.hashCode()); } @@ -81,5 +85,7 @@ public class WifiNetworkSelectionConfigTest { config.getAssociatedNetworkSelectionOverride()); assertTrue(config.isSufficiencyCheckEnabledWhenScreenOff()); assertTrue(config.isSufficiencyCheckEnabledWhenScreenOn()); + assertTrue(config.isUserConnectChoiceOverrideEnabled()); + assertTrue(config.isLastSelectionWeightEnabled()); } } diff --git a/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java index 0a24523b3a..12dfd6e9a5 100644 --- a/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java +++ b/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java @@ -16,14 +16,17 @@ package android.net.wifi; +import static android.net.wifi.ScanResult.WIFI_BAND_5_GHZ; import static android.os.PatternMatcher.PATTERN_LITERAL; import static android.os.PatternMatcher.PATTERN_PREFIX; import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; @@ -653,8 +656,8 @@ public class WifiNetworkSpecifierTest { new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), - ScanResult.WIFI_BAND_5_GHZ, - wifiConfiguration); + WIFI_BAND_5_GHZ, + wifiConfiguration, new int[0]); Parcel parcelW = Parcel.obtain(); specifier.writeToParcel(parcelW, 0); @@ -686,7 +689,7 @@ public class WifiNetworkSpecifierTest { Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), ScanResult.UNSPECIFIED, /* band */ - wifiConfiguration); + wifiConfiguration, new int[0]); assertFalse(specifier.canBeSatisfiedBy(null)); assertFalse(specifier.canBeSatisfiedBy(new MatchAllNetworkSpecifier())); @@ -708,15 +711,15 @@ public class WifiNetworkSpecifierTest { new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), - ScanResult.WIFI_BAND_5_GHZ, - wifiConfiguration); + WIFI_BAND_5_GHZ, + wifiConfiguration, new int[0]); WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), - ScanResult.WIFI_BAND_5_GHZ, - wifiConfiguration); + WIFI_BAND_5_GHZ, + wifiConfiguration, new int[0]); assertTrue(specifier2.canBeSatisfiedBy(specifier1)); } @@ -738,7 +741,7 @@ public class WifiNetworkSpecifierTest { Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), ScanResult.WIFI_BAND_24_GHZ, - wifiConfiguration1); + wifiConfiguration1, new int[0]); WifiConfiguration wifiConfiguration2 = new WifiConfiguration(); wifiConfiguration2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); @@ -747,7 +750,7 @@ public class WifiNetworkSpecifierTest { Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), ScanResult.WIFI_BAND_24_GHZ, - wifiConfiguration2); + wifiConfiguration2, new int[0]); assertFalse(specifier2.canBeSatisfiedBy(specifier1)); } @@ -768,15 +771,15 @@ public class WifiNetworkSpecifierTest { new WifiNetworkSpecifier(new PatternMatcher("", PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), - ScanResult.WIFI_BAND_5_GHZ, - wifiConfiguration); + WIFI_BAND_5_GHZ, + wifiConfiguration, new int[0]); WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), - ScanResult.WIFI_BAND_5_GHZ, - wifiConfiguration); + WIFI_BAND_5_GHZ, + wifiConfiguration, new int[0]); assertFalse(specifier2.canBeSatisfiedBy(specifier1)); } @@ -798,14 +801,14 @@ public class WifiNetworkSpecifierTest { Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), ScanResult.WIFI_BAND_24_GHZ, - wifiConfiguration); + wifiConfiguration, new int[0]); WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), ScanResult.WIFI_BAND_24_GHZ, - wifiConfiguration); + wifiConfiguration, new int[0]); assertFalse(specifier2.canBeSatisfiedBy(specifier1)); } @@ -824,14 +827,14 @@ public class WifiNetworkSpecifierTest { Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), ScanResult.WIFI_BAND_24_GHZ, - wifiConfiguration); + wifiConfiguration, new int[0]); WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), ScanResult.WIFI_BAND_24_GHZ, - wifiConfiguration); + wifiConfiguration, new int[0]); // Same band matches. assertTrue(specifier2.canBeSatisfiedBy(specifier1)); @@ -841,8 +844,8 @@ public class WifiNetworkSpecifierTest { new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), - ScanResult.WIFI_BAND_5_GHZ, - wifiConfiguration); + WIFI_BAND_5_GHZ, + wifiConfiguration, new int[0]); // Different band does not match. assertFalse(specifier2.canBeSatisfiedBy(specifier1)); @@ -853,7 +856,7 @@ public class WifiNetworkSpecifierTest { Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), ScanResult.UNSPECIFIED, - wifiConfiguration); + wifiConfiguration, new int[0]); // An UNSPECIFIED band does not match a specified band, because a WifiNetworkSpecifier // satisfies another only if they are equal. @@ -874,16 +877,29 @@ public class WifiNetworkSpecifierTest { new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS), MacAddress.fromString(TEST_BSSID_OUI_MASK)), - ScanResult.WIFI_BAND_5_GHZ, - wifiConfiguration); + WIFI_BAND_5_GHZ, + wifiConfiguration, new int[0]); final NetworkSpecifier redacted = specifier.redact(); if (SdkLevel.isAtLeastS()) { assertEquals( - new WifiNetworkSpecifier.Builder().setBand(ScanResult.WIFI_BAND_5_GHZ).build(), + new WifiNetworkSpecifier.Builder().setBand(WIFI_BAND_5_GHZ).build(), redacted); } else { assertTrue(redacted == specifier); } } + + @Test + public void testSetPreferredChannel() { + WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder() + .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX)); + assertThrows(IllegalArgumentException.class, () -> builder + .setPreferredChannelsFrequenciesMhz(new int[]{0})); + WifiNetworkSpecifier networkSpecifier = builder + .setPreferredChannelsFrequenciesMhz(new int[]{5180}).build(); + assertArrayEquals(new int[]{5180}, networkSpecifier.getPreferredChannelFrequenciesMhz()); + builder.setBand(WIFI_BAND_5_GHZ); + assertThrows(IllegalStateException.class, builder::build); + } } diff --git a/framework/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java b/framework/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java index 93e62b2c14..8eb7c42c5b 100644 --- a/framework/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java +++ b/framework/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java @@ -41,14 +41,12 @@ public class OsuProviderTest { private static final WifiSsid TEST_SSID = WifiSsid.fromBytes("TEST SSID".getBytes(StandardCharsets.UTF_8)); private static final String TEST_FRIENDLY_NAME = "Friendly Name"; - private static final Map<String, String> TEST_FRIENDLY_NAMES = - new HashMap<String, String>() { - { - put("en", TEST_FRIENDLY_NAME); - put("kr", TEST_FRIENDLY_NAME + 2); - put("jp", TEST_FRIENDLY_NAME + 3); - } - }; + private static final Map<String, String> TEST_FRIENDLY_NAMES = new HashMap<>(); + static { + TEST_FRIENDLY_NAMES.put("en", TEST_FRIENDLY_NAME); + TEST_FRIENDLY_NAMES.put("kr", TEST_FRIENDLY_NAME + 2); + TEST_FRIENDLY_NAMES.put("jp", TEST_FRIENDLY_NAME + 3); + } private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service"; private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com"); diff --git a/framework/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/framework/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java index a44df40a8e..511f37a58d 100644 --- a/framework/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java +++ b/framework/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue; import android.net.wifi.EAPConstants; import android.net.wifi.FakeKeys; +import android.net.wifi.WifiEnterpriseConfig; import android.os.Parcel; import androidx.test.filters.SmallTest; @@ -633,4 +634,41 @@ public class CredentialTest { assertNotEquals(certCred1.getUniqueId(), certCred2.getUniqueId()); } + + /** + * Verify setMinimumTlsVersion sunny cases. + */ + @Test + public void testSetMinimumTlsVersionWithValidValues() throws Exception { + Credential cred = new Credential(); + for (int i = WifiEnterpriseConfig.TLS_VERSION_MIN; + i <= WifiEnterpriseConfig.TLS_VERSION_MAX; i++) { + cred.setMinimumTlsVersion(i); + assertEquals(i, cred.getMinimumTlsVersion()); + } + } + + /** + * Verify that setMinimumTlsVersion() raises IllegalArgumentException when + * an invalid TLS version is set. + * + * @throws IllegalArgumentException + */ + @Test (expected = IllegalArgumentException.class) + public void testSetMinimumTlsVersionWithVersionLargerThanMaxVersion() throws Exception { + Credential cred = new Credential(); + cred.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_VERSION_MAX + 1); + } + + /** + * Verify that setMinimumTlsVersion() raises IllegalArgumentException when + * an invalid TLS version is set. + * + * @throws IllegalArgumentException + */ + @Test (expected = IllegalArgumentException.class) + public void testSetMinimumTlsVersionWithVersionSmallerThanMinVersion() throws Exception { + Credential cred = new Credential(); + cred.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_VERSION_MIN - 1); + } } diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java index e5f2431918..bcd8d9556d 100644 --- a/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java +++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java @@ -16,14 +16,20 @@ package android.net.wifi.p2p; +import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP; +import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import android.net.MacAddress; import android.os.Parcel; import androidx.test.filters.SmallTest; +import com.android.modules.utils.build.SdkLevel; + import org.junit.Test; /** @@ -151,6 +157,54 @@ public class WifiP2pConfigTest { assertEquals(WifiP2pGroup.NETWORK_ID_TEMPORARY, c.netId); } + /** Verify that a config by default has group client IP provisioning with DHCP IPv4. */ + @Test + public void testBuildConfigWithGroupClientIpProvisioningModeDefault() throws Exception { + WifiP2pConfig c = new WifiP2pConfig.Builder() + .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS)) + .build(); + assertEquals(c.deviceAddress, DEVICE_ADDRESS); + assertEquals(c.getGroupClientIpProvisioningMode(), + GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP); + } + + /** Verify that a config with group client IP provisioning with IPv4 DHCP can be built. */ + @Test + public void testBuildConfigWithGroupClientIpProvisioningModeIpv4Dhcp() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + WifiP2pConfig c = new WifiP2pConfig.Builder() + .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS)) + .setGroupClientIpProvisioningMode(GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP) + .build(); + assertEquals(c.deviceAddress, DEVICE_ADDRESS); + assertEquals(c.getGroupClientIpProvisioningMode(), + GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP); + } + + /** Verify that a config with group client IP provisioning with IPv6 link-local can be built. */ + @Test + public void testBuildConfigWithGroupClientIpProvisioningModeIpv6LinkLocal() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + WifiP2pConfig c = new WifiP2pConfig.Builder() + .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS)) + .setGroupClientIpProvisioningMode(GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL) + .build(); + assertEquals(c.deviceAddress, DEVICE_ADDRESS); + assertEquals(c.getGroupClientIpProvisioningMode(), + GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL); + } + + /** + * Verify that the builder throws IllegalArgumentException if invalid group client IP + * provisioning mode is set. + */ + @Test(expected = IllegalArgumentException.class) + public void testBuilderWithInvalidGroupClientIpProvisioningMode() + throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + WifiP2pConfig c = new WifiP2pConfig.Builder().setGroupClientIpProvisioningMode(5).build(); + } + /** * Verify that the builder throws IllegalStateException if none of * network name, passphrase, and device address is set. @@ -203,7 +257,6 @@ public class WifiP2pConfigTest { // no equals operator, use toString for comparison. assertEquals(config.toString(), configFromParcel.toString()); - } @Test @@ -216,5 +269,4 @@ public class WifiP2pConfigTest { config.invalidate(); assertEquals("", config.deviceAddress); } - } diff --git a/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java index 8f517980ca..b9e482e448 100644 --- a/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java +++ b/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java @@ -620,4 +620,12 @@ public class WifiRttManagerTest { assertEquals(ResponderConfig.PREAMBLE_HE, config.preamble); } + + @Test + public void testGetRttCharacteristics() throws Exception { + when(mockRttService.getRttCharacteristics()).thenReturn(new Bundle()); + Bundle characteristics = mDut.getRttCharacteristics(); + verify(mockRttService).getRttCharacteristics(); + assertEquals(0, characteristics.size()); + } } diff --git a/service/Android.bp b/service/Android.bp index 2beb972154..f5bc67cf07 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -48,8 +48,6 @@ java_library { installable: false, defaults: ["wifi-service-common"], srcs: [ ":wifi-service-srcs" ], - // java_api_finder must accompany `srcs` - plugins: ["java_api_finder"], sdk_version: "system_server_current", lint: { @@ -67,6 +65,7 @@ java_library { // compile time "framework-wifi-pre-jarjar", "framework-bluetooth", + "framework-configinfrastructure", "framework-connectivity.stubs.module_lib", "framework-connectivity-t.stubs.module_lib", "framework-statsd.stubs.module_lib", @@ -76,6 +75,9 @@ java_library { ], static_libs: [ + // AIDL vendor hal implementation + "android.hardware.wifi-V1-java", + // HIDL vendor hal implementation "android.hardware.wifi-V1.0-java", "android.hardware.wifi-V1.1-java", "android.hardware.wifi-V1.2-java", @@ -91,7 +93,7 @@ java_library { "android.hardware.wifi.hostapd-V1.2-java", "android.hardware.wifi.hostapd-V1.3-java", // AIDL supplicant implementation - "android.hardware.wifi.supplicant-V1-java", + "android.hardware.wifi.supplicant-V2-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-af/strings.xml b/service/ServiceWifiResources/res/values-af/strings.xml index 5d1f8d355d..a40a9ca746 100644 --- a/service/ServiceWifiResources/res/values-af/strings.xml +++ b/service/ServiceWifiResources/res/values-af/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Jy kan wi-fi in Kitsinstellings afskakel"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Laat toe"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Moenie toelaat nie"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑fi is aan in vliegtuigmodus"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"As jy wi-fi aangeskakel hou, sal jou foon onthou om dit aan te hou wanneer jy weer in vliegtuigmodus is"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑fi bly aan"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Jou foon onthou om wi‑fi aan te hou in vliegtuigmodus. Skakel wi-fi af as jy nie wil hê dit moet aan bly nie."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Netwerk is onbeskikbaar"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> is deur jou administrateur gedeaktiveer."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Maak toe"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑fi is aan in vliegtuigmodus"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑fi bly aan"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-am/strings.xml b/service/ServiceWifiResources/res/values-am/strings.xml index df8b970d02..2826bf3685 100644 --- a/service/ServiceWifiResources/res/values-am/strings.xml +++ b/service/ServiceWifiResources/res/values-am/strings.xml @@ -160,13 +160,13 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"በፈጣን ቅንብሮች ውስጥ Wi-Fiን ማጥፋት ይችላሉ"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"ፍቀድ"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"አትፍቀድ"</string> - <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"የማይገኝ አውታረ መረብ"</string> - <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> በእርስዎ አስተዳዳሪ ተሰናክሏል።"</string> - <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ዝጋ"</string> <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"በአውሮፕላን ሁነታ ላይ Wi-Fi በርቷል"</string> <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> <skip /> <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi በርቶ ይቆያል"</string> <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> <skip /> + <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"የማይገኝ አውታረ መረብ"</string> + <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> በእርስዎ አስተዳዳሪ ተሰናክሏል።"</string> + <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ዝጋ"</string> </resources> diff --git a/service/ServiceWifiResources/res/values-ar/strings.xml b/service/ServiceWifiResources/res/values-ar/strings.xml index 213e287182..d7ce4e1271 100644 --- a/service/ServiceWifiResources/res/values-ar/strings.xml +++ b/service/ServiceWifiResources/res/values-ar/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"يمكنك إيقاف Wi-Fi في الإعدادات السريعة."</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"السماح"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"عدم السماح"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"شبكة Wi‑Fi مفعَّلة في \"وضع الطيران\""</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"إذا واصلت تفعيل شبكة Wi‑Fi، سيتذكر هاتفك إبقاءها مفعَّلة في المرة القادمة التي تفعِّل فيها \"وضع الطيران\"."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"تظل شبكة Wi-Fi مفعّلة"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"يتذكر هاتفك إبقاء شبكة Wi‑Fi مفعَّلة في \"وضع الطيران\". يمكنك إيقاف شبكة Wi‑Fi إذا لم تكن تريد مواصلة تفعيلها."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"شبكة غير متوفّرة"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"تم إيقاف معرّف <xliff:g id="SSID">%1$s</xliff:g> من قِبل المشرف."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"إغلاق"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"شبكة Wi‑Fi مفعَّلة في \"وضع الطيران\""</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"تظل شبكة Wi-Fi مفعّلة"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-as/strings.xml b/service/ServiceWifiResources/res/values-as/strings.xml index 6cca27a589..02c50762de 100644 --- a/service/ServiceWifiResources/res/values-as/strings.xml +++ b/service/ServiceWifiResources/res/values-as/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"আপুনি ক্ষিপ্ৰ ছেটিঙত ৱাই-ফাই অফ কৰিব পাৰে"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"অনুমতি দিয়ক"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"অনুমতি নিদিব"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"এয়াৰপ্লেন ম’ডত ৱাই‐ফাই অন হৈ থাকিব"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"আপুনি যদি ৱাই-ফাই অন কৰি ৰাখে, পৰৱৰ্তী সময়ত আপুনি এয়াৰপ্লেন ম’ড ব্যৱহাৰ কৰিলে আপোনাৰ ফ’নটোৱে এয়া অন কৰি ৰাখিবলৈ মনত ৰাখিব"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi অন হৈ থাকিব"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"আপোনাৰ ফ’নটোৱে এয়াৰপ্লেন ম’ডত ৱাই-ফাই অন ৰাখিবলৈ মনত ৰাখে। আপুনি যদি ৱাই-ফাই অন হৈ থকাটো নিবিচাৰে, তেন্তে ইয়াক অফ কৰক।"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"উপলব্ধ নোহোৱা নেটৱৰ্ক"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"আপোনাৰ প্ৰশাসকে <xliff:g id="SSID">%1$s</xliff:g> অক্ষম কৰিছে।"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"বন্ধ কৰক"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"এয়াৰপ্লেন ম’ডত ৱাই‐ফাই অন হৈ থাকিব"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi অন হৈ থাকিব"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-az/strings.xml b/service/ServiceWifiResources/res/values-az/strings.xml index 3938db2f13..279e48205b 100644 --- a/service/ServiceWifiResources/res/values-az/strings.xml +++ b/service/ServiceWifiResources/res/values-az/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Sürətli Ayarlarda Wi‑Fi\'ı deaktiv edə bilərsiniz"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"İcazə verin"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"İcazə verməyin"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Təyyarə rejimində Wi‑Fi aktiv qalsın"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wi‑Fi\'ı aktiv saxlasanız, növbəti dəfə təyyarə rejimində olduqda telefonunuz onu aktiv saxlayacaq"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi aktiv qalacaq"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefonunuz təyyarə rejimində Wi‑Fi\'ı aktiv saxlayacaq. Aktiv qalmasını istəmirsinizsə, Wi‑Fi\'ı deaktiv edin."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Əlçatan Şəbəkə"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> administratorunuz tərəfindən deaktiv edilib."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Bağlayın"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Təyyarə rejimində Wi‑Fi aktiv qalsın"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi aktiv qalacaq"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml b/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml index e77f0c579a..7dcc6a9a14 100644 --- a/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml +++ b/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Možete da isključite WiFi u Brzim podešavanjima"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Dozvoli"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ne dozvoli"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi je uključen u režimu rada u avionu"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ako odlučite da ne isključujete WiFi, telefon će zapamtiti da ga ne isključuje sledeći put kada budete u režimu rada u avionu"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi ostaje uključen"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefon pamti da ne treba da isključuje WiFi u režimu rada u avionu. Isključite WiFi ako ne želite da ostane uključen."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Nedostupna mreža"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administrator je onemogućio <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Zatvori"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi je uključen u režimu rada u avionu"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi ostaje uključen"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-be/strings.xml b/service/ServiceWifiResources/res/values-be/strings.xml index 04758ca32f..874e8a2364 100644 --- a/service/ServiceWifiResources/res/values-be/strings.xml +++ b/service/ServiceWifiResources/res/values-be/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Вы можаце выключыць сетку Wi‑Fi у Хуткіх наладах"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Дазволіць"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Не дазваляць"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"У рэжыме палёту сетка Wi‑Fi застанецца ўключанай"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Калі вы не выключыце сетку Wi‑Fi, падчас наступнага пераходу ў рэжым палёту тэлефон будзе захоўваць яе ўключанай"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Сетка Wi‑Fi застаецца ўключанай"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"На тэлефоне ў рэжыме палёту сетка Wi‑Fi будзе заставацца ўключанай, але вы можаце выключыць яе."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Недаступная сетка"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Сетка \"<xliff:g id="SSID">%1$s</xliff:g>\" адключана вашым адміністратарам."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Закрыць"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"У рэжыме палёту сетка Wi‑Fi застанецца ўключанай"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Сетка Wi‑Fi застаецца ўключанай"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-bg/strings.xml b/service/ServiceWifiResources/res/values-bg/strings.xml index 020583b05a..e4da9d56f2 100644 --- a/service/ServiceWifiResources/res/values-bg/strings.xml +++ b/service/ServiceWifiResources/res/values-bg/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Можете да изключите Wi‑Fi от бързите настройки"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Разрешаване"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Забраняване"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Включване на Wi‑Fi в самолетния режим"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ако не изключите функцията за Wi‑Fi, телефонът ви ще я остави активна следващия път, когато използвате самолетния режим"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi няма да се изключи"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Функцията за Wi‑Fi ще бъде включена, докато телефонът ви е в самолетен режим. Ако не искате това, изключете я."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Няма достъп до мрежата"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Функцията <xliff:g id="SSID">%1$s</xliff:g> е деактивирана от администратора ви."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Затваряне"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Включване на Wi‑Fi в самолетния режим"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi няма да се изключи"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-bn/strings.xml b/service/ServiceWifiResources/res/values-bn/strings.xml index 0d23bf34ba..f79fc4a6e3 100644 --- a/service/ServiceWifiResources/res/values-bn/strings.xml +++ b/service/ServiceWifiResources/res/values-bn/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"\'দ্রুত সেটিংস\' মেনু থেকে আপনি ওয়াই-ফাই বন্ধ করতে পারবেন"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"অনুমতি দিন"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"অনুমতি দেবেন না"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"\'বিমান মোড\'-এ ওয়াই-ফাই চালু থাকে"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"আপনি ওয়াই-ফাই চালু রাখলে, আপনি \'বিমান\' মোডে থাকলে পরবর্তী সময় আপনার ফোন এটি চালু রাখার জন্য মনে রাখবে"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ওয়াই-ফাই চালু থাকে"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"\'বিমান মোড\'-এ থাকাকালীন আপনার ফোন ওয়াই-ফাই চালু রাখে। আপনি এটি চালু না রাখতে চাইলে ওয়াই-ফাই বন্ধ করুন।"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"নেটওয়ার্ক উপলভ্য নয়"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"আপনার অ্যাডমিনিস্ট্রেটর <xliff:g id="SSID">%1$s</xliff:g> বন্ধ করে দিয়েছেন।"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"বন্ধ করুন"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"\'বিমান মোড\'-এ ওয়াই-ফাই চালু থাকে"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ওয়াই-ফাই চালু থাকে"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-bs/strings.xml b/service/ServiceWifiResources/res/values-bs/strings.xml index ac272e8b1b..eb54553f5e 100644 --- a/service/ServiceWifiResources/res/values-bs/strings.xml +++ b/service/ServiceWifiResources/res/values-bs/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"WiFi možete isključiti u Brzim postavkama"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Dozvoli"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Nemoj dozvoliti"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi je uključen u načinu rada u avionu"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ako ostavite WiFi uključen, telefon će zapamtiti da ga ostavi uključenog sljedeći put kada budete u načinu rada u avionu"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi ostaje uključen"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefon pamti da zadrži WiFi u načinu rada u avionu. Isključite WiFi ako ne želite da ostane uključen."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Nedostupna mreža"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administrator je onemogućio <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Zatvori"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi je uključen u načinu rada u avionu"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi ostaje uključen"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ca/strings.xml b/service/ServiceWifiResources/res/values-ca/strings.xml index 0e45b307d1..f877622197 100644 --- a/service/ServiceWifiResources/res/values-ca/strings.xml +++ b/service/ServiceWifiResources/res/values-ca/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Pots desactivar la Wi‑Fi a la configuració ràpida"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permet"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"No permetis"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi activada en mode d\'avió"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Si tens activada la Wi‑Fi, el telèfon recordarà mantenir-la així la pròxima vegada que utilitzis el mode d\'avió"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"La Wi‑Fi es manté activada"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"El telèfon recorda mantenir la Wi‑Fi activada en mode d\'avió. Desactiva la Wi‑Fi si no vols que es quedi activada."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Xarxa no disponible"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"L\'administrador ha desactivat <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Tanca"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi activada en mode d\'avió"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"La Wi‑Fi es manté activada"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-cs/strings.xml b/service/ServiceWifiResources/res/values-cs/strings.xml index 895cbfc7a9..97bdde85a3 100644 --- a/service/ServiceWifiResources/res/values-cs/strings.xml +++ b/service/ServiceWifiResources/res/values-cs/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi‑Fi můžete vypnout v Rychlém nastavení"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Povolit"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Nepovolovat"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Zapnutá Wi-Fi v režimu Letadlo"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Pokud Wi-Fi necháte zapnutou, telefon si zapamatuje, že ji má příště v režimu Letadlo ponechat zapnutou"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi zůstane zapnutá"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefon si pamatuje, že má v režimu Letadlo ponechat zapnutou Wi-Fi. Pokud nechcete, aby Wi-Fi zůstala zapnutá, vypněte ji."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Nedostupná síť"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Funkce <xliff:g id="SSID">%1$s</xliff:g> byla deaktivována administrátorem."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Zavřít"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Zapnutá Wi-Fi v režimu Letadlo"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi zůstane zapnutá"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-da/strings.xml b/service/ServiceWifiResources/res/values-da/strings.xml index 570662b0af..9a598594fc 100644 --- a/service/ServiceWifiResources/res/values-da/strings.xml +++ b/service/ServiceWifiResources/res/values-da/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Du kan deaktivere Wi‑Fi via kvikmenuen"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Tillad"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Tillad ikke"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi aktiveret i flytilstand"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Hvis du holder Wi-Fi aktiveret, sørger din telefon for, at Wi-Fi forbliver aktiveret, næste gang du sætter den til flytilstand"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi forbliver aktiv"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Din telefon holder Wi-Fi aktiveret i flytilstand. Deaktiver Wi-Fi, hvis du ikke vil have, at det forbliver aktiveret."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Utilgængeligt netværk"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> er blevet deaktiveret af din administrator."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Luk"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi aktiveret i flytilstand"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi forbliver aktiv"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-de/strings.xml b/service/ServiceWifiResources/res/values-de/strings.xml index f98966269f..e19de9096a 100644 --- a/service/ServiceWifiResources/res/values-de/strings.xml +++ b/service/ServiceWifiResources/res/values-de/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Das WLAN kannst du in den Schnelleinstellungen deaktivieren"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Zulassen"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Nicht zulassen"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WLAN im Flugzeugmodus"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wenn das WLAN aktiviert bleibt, lässt es dein Smartphone eingeschaltet, wenn du das nächste Mal in den Flugmodus wechselst"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WLAN bleibt eingeschaltet"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Dein Smartphone lässt das WLAN im Flugmodus eingeschaltet. Schalte das WLAN aus, wenn du das nicht möchtest."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Nicht verfügbares Netzwerk"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Die Funktion „<xliff:g id="SSID">%1$s</xliff:g>“ wurde von deinem Administrator deaktiviert."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Schließen"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WLAN im Flugzeugmodus"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WLAN bleibt eingeschaltet"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-el/strings.xml b/service/ServiceWifiResources/res/values-el/strings.xml index 6ff37212db..114f9949fb 100644 --- a/service/ServiceWifiResources/res/values-el/strings.xml +++ b/service/ServiceWifiResources/res/values-el/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Μπορείτε να απενεργοποιήσετε το Wi‑Fi από τις Γρήγορες ρυθμίσεις"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Να επιτρέπεται"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Να μην επιτρέπεται"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ενεργό σε λειτουργία πτήσης"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Αν διατηρήσετε το Wi‑Fi ενεργοποιημένο, το τηλέφωνό σας θα θυμάται να το διατηρήσει ενεργοποιημένο την επόμενη φορά που θα βρεθεί σε λειτουργία πτήσης"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Το Wi‑Fi παραμένει ενεργό"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Το τηλέφωνο θυμάται να διατηρεί ενεργοποιημένο το Wi‑Fi σε λειτουργία πτήσης. Απενεργοποιήστε το Wi‑Fi, αν δεν επιθυμείτε να είναι ενεργοποιημένο."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Μη διαθέσιμο δίκτυο"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Το <xliff:g id="SSID">%1$s</xliff:g> έχει απενεργοποιηθεί από τον διαχειριστή σας."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Κλείσιμο"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ενεργό σε λειτουργία πτήσης"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Το Wi‑Fi παραμένει ενεργό"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-en-rAU/strings.xml b/service/ServiceWifiResources/res/values-en-rAU/strings.xml index 61a990664d..7928067642 100644 --- a/service/ServiceWifiResources/res/values-en-rAU/strings.xml +++ b/service/ServiceWifiResources/res/values-en-rAU/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"You can turn off Wi‑Fi in Quick Settings"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Allow"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Don\'t allow"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in aeroplane mode"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"If you keep Wi‑Fi on, your phone will remember to keep it on the next time that you\'re in aeroplane mode"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Your phone remembers to keep Wi‑Fi on in aeroplane mode. Turn off Wi‑Fi if you don\'t want it to stay on."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Unavailable network"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> is disabled by your administrator."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Close"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in aeroplane mode"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-en-rCA/strings.xml b/service/ServiceWifiResources/res/values-en-rCA/strings.xml index 057cdc7453..2ed55cbe01 100644 --- a/service/ServiceWifiResources/res/values-en-rCA/strings.xml +++ b/service/ServiceWifiResources/res/values-en-rCA/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"You can turn off Wi‑Fi in Quick Settings"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Allow"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Don\'t allow"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in airplane mode"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"If you keep Wi‑Fi on, your phone will remember to keep it on the next time you\'re in airplane mode"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Your phone remembers to keep Wi‑Fi on in airplane mode. Turn off Wi‑Fi if you don\'t want it to stay on."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Unavailable Network"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> is disabled by your administrator."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Close"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in airplane mode"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-en-rGB/strings.xml b/service/ServiceWifiResources/res/values-en-rGB/strings.xml index 61a990664d..7928067642 100644 --- a/service/ServiceWifiResources/res/values-en-rGB/strings.xml +++ b/service/ServiceWifiResources/res/values-en-rGB/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"You can turn off Wi‑Fi in Quick Settings"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Allow"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Don\'t allow"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in aeroplane mode"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"If you keep Wi‑Fi on, your phone will remember to keep it on the next time that you\'re in aeroplane mode"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Your phone remembers to keep Wi‑Fi on in aeroplane mode. Turn off Wi‑Fi if you don\'t want it to stay on."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Unavailable network"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> is disabled by your administrator."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Close"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in aeroplane mode"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-en-rIN/strings.xml b/service/ServiceWifiResources/res/values-en-rIN/strings.xml index 61a990664d..7928067642 100644 --- a/service/ServiceWifiResources/res/values-en-rIN/strings.xml +++ b/service/ServiceWifiResources/res/values-en-rIN/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"You can turn off Wi‑Fi in Quick Settings"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Allow"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Don\'t allow"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in aeroplane mode"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"If you keep Wi‑Fi on, your phone will remember to keep it on the next time that you\'re in aeroplane mode"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Your phone remembers to keep Wi‑Fi on in aeroplane mode. Turn off Wi‑Fi if you don\'t want it to stay on."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Unavailable network"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> is disabled by your administrator."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Close"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in aeroplane mode"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-en-rXC/strings.xml b/service/ServiceWifiResources/res/values-en-rXC/strings.xml index f1a9c7ef06..387326a64a 100644 --- a/service/ServiceWifiResources/res/values-en-rXC/strings.xml +++ b/service/ServiceWifiResources/res/values-en-rXC/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"You can turn off Wi‑Fi in Quick Settings"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Allow"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Don\'t allow"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in airplane mode"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"If you keep Wi‑Fi on, your phone will remember to keep it on the next time you\'re in airplane mode"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Your phone remembers to keep Wi‑Fi on in airplane mode. Turn off Wi‑Fi if you don\'t want it to stay on."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Unavailable Network"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> is disabled by your administrator."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Close"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi on in airplane mode"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi stays on"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-es-rUS/strings.xml b/service/ServiceWifiResources/res/values-es-rUS/strings.xml index f8af29acaa..47d90767ad 100644 --- a/service/ServiceWifiResources/res/values-es-rUS/strings.xml +++ b/service/ServiceWifiResources/res/values-es-rUS/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Puedes desactivar el Wi‑Fi en la Configuración rápida"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permitir"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"No permitir"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi activado en modo de avión"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Si mantienes el Wi-Fi activado, tu teléfono recordará mantenerlo activado la próxima vez que actives el modo de avión"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"El Wi-Fi permanece activado"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"El teléfono dejará activado el Wi-Fi en el modo de avión. Desactiva el Wi-Fi si no quieres permanecer conectado."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Red no disponible"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Tu administrador inhabilitó <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Cerrar"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi activado en modo de avión"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"El Wi-Fi permanece activado"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-es/strings.xml b/service/ServiceWifiResources/res/values-es/strings.xml index 29464d4922..1e3005e397 100644 --- a/service/ServiceWifiResources/res/values-es/strings.xml +++ b/service/ServiceWifiResources/res/values-es/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Puedes desactivar la Wi‑Fi en los ajustes rápidos"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permitir"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"No permitir"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi activado en modo Avión"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Si dejas el Wi-Fi activado, tu teléfono se acordará de dejarlo así la próxima vez que uses el modo Avión"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"El Wi‑Fi se mantiene activado"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Tu teléfono dejará el Wi-Fi activado en modo Avión. Desactiva el Wi-Fi si no quieres que se quede activado."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Red no disponible"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Tu administrador ha inhabilitado <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Cerrar"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi activado en modo Avión"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"El Wi‑Fi se mantiene activado"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-et/strings.xml b/service/ServiceWifiResources/res/values-et/strings.xml index 2a28aa6cd6..5731347c6f 100644 --- a/service/ServiceWifiResources/res/values-et/strings.xml +++ b/service/ServiceWifiResources/res/values-et/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"WiFi saab välja lülitada kiirseadetes"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Luba"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ära luba"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi on lennukirežiimis sisse lülitatud"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Kui hoiate WiFi sisselülitatuna, jätab telefon teie valiku meelde ja kasutab seda järgmisel korral lennukirežiimi aktiveerimisel."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi jääb sisselülitatuks"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Teie telefon hoiab WiFi lennukirežiimis sisselülitatuna. Lülitage WiFi välja, kui te ei soovi, et see oleks sisse lülitatud."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Võrk ei ole saadaval"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administraator on funktsiooni <xliff:g id="SSID">%1$s</xliff:g> keelanud."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Sule"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi on lennukirežiimis sisse lülitatud"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi jääb sisselülitatuks"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-eu/strings.xml b/service/ServiceWifiResources/res/values-eu/strings.xml index 08ca5d0cb4..c069373bc2 100644 --- a/service/ServiceWifiResources/res/values-eu/strings.xml +++ b/service/ServiceWifiResources/res/values-eu/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Ezarpen bizkorrak erabil ditzakezu wifia desaktibatzeko"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Eman baimena"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ez eman baimenik"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifia aktibatuta hegaldi moduan"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wifia aktibatuta utziz gero, hura aktibatuta mantentzeaz gogoratuko da telefonoa hegaldi modua erabiltzen duzun hurrengoan"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifia aktibatuta mantentzen da"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Hegaldi moduan, wifia aktibatuta mantentzeaz gogoratzen da telefonoa. Halakorik nahi ez baduzu, desaktiba ezazu zuk zeuk."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Sarea ez dago erabilgarri"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administratzaileak desgaitu du <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Itxi"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifia aktibatuta hegaldi moduan"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifia aktibatuta mantentzen da"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-fa/strings.xml b/service/ServiceWifiResources/res/values-fa/strings.xml index 1688041b0e..9256b778ed 100644 --- a/service/ServiceWifiResources/res/values-fa/strings.xml +++ b/service/ServiceWifiResources/res/values-fa/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"میتوانید Wi‑Fi را در «تنظیمات فوری» خاموش کنید"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"اجازه دادن"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"اجازه ندادن"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi در «حالت هواپیما» روشن باشد"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"اگر Wi-Fi را روشن نگه دارید، تلفنتان بهیاد خواهد داشت تا دفعه بعدی که در «حالت هواپیما» هستید آن را روشن نگه دارد"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi روشن بماند"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"تلفنتان بهیاد میآورد که Wi-Fi را در حالت هواپیما روشن نگه دارد. اگر نمیخواهید Wi-Fi روشن بماند، آن را خاموش کنید."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"شبکه غیرقابلدسترس"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"سرپرست شما <xliff:g id="SSID">%1$s</xliff:g> را غیرفعال کرده است."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"بستن"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi در «حالت هواپیما» روشن باشد"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi روشن بماند"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-fi/strings.xml b/service/ServiceWifiResources/res/values-fi/strings.xml index 698d951763..754ed048b6 100644 --- a/service/ServiceWifiResources/res/values-fi/strings.xml +++ b/service/ServiceWifiResources/res/values-fi/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Voit laittaa Wi-Fi-yhteyden pois päältä pika-asetuksista"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Salli"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Älä salli"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi päällä lentokonetilassa"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Jos pidät Wi-Fi-yhteyden päällä, puhelin pitää sen päällä, kun seuraavan kerran olet lentokonetilassa"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi pysyy päällä"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Puhelimen Wi-Fi-yhteys pysyy päällä lentokonetilassa. Voit halutessasi laittaa Wi-Fi-yhteyden pois päältä."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Verkko ei ole käytettävissä"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> on järjestelmänvalvojan käytöstä poistama."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Sulje"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi päällä lentokonetilassa"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi pysyy päällä"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-fr-rCA/strings.xml b/service/ServiceWifiResources/res/values-fr-rCA/strings.xml index cc081880f5..18c75c2260 100644 --- a/service/ServiceWifiResources/res/values-fr-rCA/strings.xml +++ b/service/ServiceWifiResources/res/values-fr-rCA/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Vous pouvez désactiver le Wi-Fi dans les Paramètres rapides"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Autoriser"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ne pas autoriser"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi activé en mode Avion"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Si vous laissez le Wi-Fi activé, votre téléphone se rappellera qu\'il doit le laisser activé la prochaine fois que vous serez en mode Avion"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Le Wi‑Fi reste activé"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Votre téléphone se rappelle de garder le Wi-Fi activé en mode Avion. Désactivez le Wi-Fi si vous ne voulez pas qu\'il reste allumé."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Réseau indisponible"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Fonctionnalité <xliff:g id="SSID">%1$s</xliff:g> désactivée par votre administrateur."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Fermer"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi activé en mode Avion"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Le Wi‑Fi reste activé"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-fr/strings.xml b/service/ServiceWifiResources/res/values-fr/strings.xml index 1701a10937..4affffb978 100644 --- a/service/ServiceWifiResources/res/values-fr/strings.xml +++ b/service/ServiceWifiResources/res/values-fr/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Vous pouvez désactiver le Wi‑Fi dans \"Réglages rapides\""</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Autoriser"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ne pas autoriser"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi activé en mode Avion"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Si vous laissez le Wi-Fi activé, votre téléphone s\'en souviendra et le Wi-Fi restera activé la prochaine fois que vous serez en mode Avion"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Le Wi‑Fi reste activé"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Le Wi‑Fi de votre téléphone restera activé en mode Avion. Désactivez le Wi-Fi si ce paramètre ne vous convient pas."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Réseau indisponible"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> est désactivé par votre administrateur."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Fermer"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi activé en mode Avion"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Le Wi‑Fi reste activé"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-gl/strings.xml b/service/ServiceWifiResources/res/values-gl/strings.xml index 6f0f6055e8..802b08b1d3 100644 --- a/service/ServiceWifiResources/res/values-gl/strings.xml +++ b/service/ServiceWifiResources/res/values-gl/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Podes desactivar a wifi en Configuración rápida"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permitir"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Non permitir"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"A wifi está activada no modo avión"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Se mantés a wifi activada, o teléfono lembrará que ten que deixala nese estado a próxima vez que esteas no modo avión"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"A wifi permanece activada"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"O teléfono lembrará manter a wifi activada no modo avión. Desactívaa se non queres que permaneza activada."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rede non dispoñible"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"O teu administrador desactivou a rede <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Pechar"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"A wifi está activada no modo avión"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"A wifi permanece activada"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-gu/strings.xml b/service/ServiceWifiResources/res/values-gu/strings.xml index e662e3f22d..6f54c062e1 100644 --- a/service/ServiceWifiResources/res/values-gu/strings.xml +++ b/service/ServiceWifiResources/res/values-gu/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"તમે ઝડપી સેટિંગમાં જઈને વાઇ-ફાઇ બંધ કરી શકો છો"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"મંજૂરી આપો"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"મંજૂરી આપશો નહીં"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"એરપ્લેન મોડમાં વાઇ-ફાઇ ચાલુ રહેશે"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"જો તમે વાઇ-ફાઇ ચાલુ રાખો, તો તમે જ્યારે આગલી વખતે એરપ્લેન મોડ પર જશો, ત્યારે તમારો ફોન તેને ચાલુ રાખવાનું યાદ રાખશે"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"વાઇ-ફાઇ ચાલુ રહેશે"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"તમારો ફોન વાઇ-ફાઇને એરપ્લેન મોડમાં ચાલુ રાખવાનું યાદ રાખે છે. જો તમે વાઇ-ફાઇ ચાલુ રાખવા માગતા ન હો, તો તેને બંધ કરો."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"નેટવર્ક ઉપલબ્ધ નથી"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g>ને તમારા ઍડમિનિસ્ટ્રેટર દ્વારા બંધ કરવામાં આવ્યું છે."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"બંધ કરો"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"એરપ્લેન મોડમાં વાઇ-ફાઇ ચાલુ રહેશે"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"વાઇ-ફાઇ ચાલુ રહેશે"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-hi/strings.xml b/service/ServiceWifiResources/res/values-hi/strings.xml index dc0411c165..32fca99e29 100644 --- a/service/ServiceWifiResources/res/values-hi/strings.xml +++ b/service/ServiceWifiResources/res/values-hi/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"\'फटाफट सेटिंग\' में जाकर, वाई-फ़ाई बंद किया जा सकता है"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"अनुमति दें"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"अनुमति न दें"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"हवाई जहाज़ मोड में वाई-फ़ाई चालू रहेगा"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"वाई-फ़ाई चालू रखने पर आपका फ़ोन, अगली बार हवाई जहाज़ मोड चालू होने पर भी वाई-फ़ाई चालू रखेगा"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"वाई-फ़ाई चालू रहेगा"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"हवाई जहाज़ मोड में भी आपका फ़ोन वाई-फ़ाई चालू रखता है. अगर वाई-फ़ाई चालू नहीं रखना है, तो उसे बंद कर दें."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"नेटवर्क उपलब्ध नहीं है"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"आपके एडमिन ने <xliff:g id="SSID">%1$s</xliff:g> को बंद किया हुआ है."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"बंद करें"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"हवाई जहाज़ मोड में वाई-फ़ाई चालू रहेगा"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"वाई-फ़ाई चालू रहेगा"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-hr/strings.xml b/service/ServiceWifiResources/res/values-hr/strings.xml index c41836c5d7..efc69d0e94 100644 --- a/service/ServiceWifiResources/res/values-hr/strings.xml +++ b/service/ServiceWifiResources/res/values-hr/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi‑Fi možete isključiti u brzim postavkama"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Dopusti"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Nemoj dopustiti"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi je uključen u načinu rada u zrakoplovu"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ako Wi-Fi ostane uključen, telefon će zapamtiti da treba ostati uključen u načinu rada u zrakoplovu"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ostaje uključen"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefon će zapamtiti da Wi‑Fi treba ostati uključen u načinu rada u zrakoplovu. Isključite Wi-Fi ako ne želite da ostane uključen."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Mreža nije dostupna"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Značajku <xliff:g id="SSID">%1$s</xliff:g> onemogućio je vaš administrator."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Zatvori"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi je uključen u načinu rada u zrakoplovu"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ostaje uključen"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-hu/strings.xml b/service/ServiceWifiResources/res/values-hu/strings.xml index 438c32d3f1..26224decf8 100644 --- a/service/ServiceWifiResources/res/values-hu/strings.xml +++ b/service/ServiceWifiResources/res/values-hu/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"A Wi‑Fi-t a Gyorsbeállításokban kapcsolhatja ki"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Engedélyezés"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Tiltás"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"A Wi‑Fi bekapcsolva marad Repülős üzemmódban"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ha bekapcsolva tartja a Wi-Fi-t, a telefon emlékezni fog arra, hogy a következő alkalommal, amikor Repülős üzemmódban van, bekapcsolva tartsa a funkciót"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"A Wi‑Fi bekapcsolva marad"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"A telefon bekapcsolva tartja a Wi‑Fi-t Repülős üzemmódban. Kapcsolja ki a Wi-Fi-t, ha nem szeretné, hogy bekapcsolva maradjon."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Hozzáférhetetlen hálózat"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> letiltva a rendszergazda által."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Bezárás"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"A Wi‑Fi bekapcsolva marad Repülős üzemmódban"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"A Wi‑Fi bekapcsolva marad"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-hy/strings.xml b/service/ServiceWifiResources/res/values-hy/strings.xml index 8c3d758bd5..282b0f7382 100644 --- a/service/ServiceWifiResources/res/values-hy/strings.xml +++ b/service/ServiceWifiResources/res/values-hy/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi‑Fi-ը կարող եք անջատել Արագ կարգավորումներում"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Թույլատրել"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Չթույլատրել"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Ավիառեժիմում Wi‑Fi-ը միացված կլինի"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Եթե Wi-Fi-ը միացված թողնեք, հաջորդ անգամ այն ավտոմատ միացված կմնա ավիառեժիմում"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi-ը մնում է միացված"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Ավիառեժիմում Wi‑Fi-ը միացված կմնա։ Ցանկության դեպքում կարող եք անջատել Wi-Fi-ը։"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Անհասանելի ցանց"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Ադմինիստրատորն անջատել է <xliff:g id="SSID">%1$s</xliff:g> գործառույթը։"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Փակել"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Ավիառեժիմում Wi‑Fi-ը միացված կլինի"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi-ը մնում է միացված"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-in/strings.xml b/service/ServiceWifiResources/res/values-in/strings.xml index 6ba3e6e5e9..0515dc6ee1 100644 --- a/service/ServiceWifiResources/res/values-in/strings.xml +++ b/service/ServiceWifiResources/res/values-in/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Anda dapat menonaktifkan Wi‑Fi di Setelan Cepat"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Izinkan"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Jangan izinkan"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi aktif dalam mode pesawat"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Jika Wi-Fi tetap diaktifkan, ponsel akan ingat untuk tetap mengaktifkannya saat berikutnya ponsel Anda disetel ke mode pesawat"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi tetap aktif"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Ponsel akan ingat untuk tetap mengaktifkan Wi-Fi dalam mode pesawat. Nonaktifkan jika Anda tidak ingin Wi-Fi terus aktif."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Jaringan Tidak Tersedia"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> dinonaktifkan oleh administrator Anda."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Tutup"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi aktif dalam mode pesawat"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi tetap aktif"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-is/strings.xml b/service/ServiceWifiResources/res/values-is/strings.xml index 575a11580f..f12cee7c04 100644 --- a/service/ServiceWifiResources/res/values-is/strings.xml +++ b/service/ServiceWifiResources/res/values-is/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Þú getur slökkt á WiFi í flýtistillingum"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Leyfa"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ekki leyfa"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Kveikt á Wi‑Fi í flugstillingu"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ef þú hefur kveikt á Wi-Fi mun síminn muna að hafa kveikt á því næst þegar þú stillir á flugstillingu"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Áfram kveikt á Wi‑Fi"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Síminn man að hafa kveikt á Wi-Fi í flugstillingu. Slökktu á Wi-Fi ef þú vilt ekki hafa kveikt á því."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Netkerfi ekki tiltækt"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Stjórnandinn hefur slökkt á <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Loka"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Kveikt á Wi‑Fi í flugstillingu"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Áfram kveikt á Wi‑Fi"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-it/strings.xml b/service/ServiceWifiResources/res/values-it/strings.xml index 651d0e55f5..2ddce7387a 100644 --- a/service/ServiceWifiResources/res/values-it/strings.xml +++ b/service/ServiceWifiResources/res/values-it/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Puoi disattivare il Wi‑Fi nelle Impostazioni rapide"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Consenti"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Non consentire"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi attivo in modalità aereo"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Se tieni attivo il Wi-fi, il telefono ricorderà di mantenerlo attivo la prossima volta che sarai in modalità aereo"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Il Wi-Fi rimane attivo"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Il telefono ricorda di mantenere attivo il Wi‑Fi in modalità aereo. Disattiva il Wi-Fi se non vuoi che resti attivo."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rete non disponibile"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"L\'amministratore ha disattivato la funzionalità <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Chiudi"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi attivo in modalità aereo"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Il Wi-Fi rimane attivo"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-iw/strings.xml b/service/ServiceWifiResources/res/values-iw/strings.xml index 1b6dcc6cb4..12cd714240 100644 --- a/service/ServiceWifiResources/res/values-iw/strings.xml +++ b/service/ServiceWifiResources/res/values-iw/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"אפשר לכבות את ה-Wi-Fi בהגדרות המהירות"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"אישור"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"אין אישור"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi מופעל במצב טיסה"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"אם חיבור ה-Wi‑Fi נשאר מופעל, הטלפון יזכור להשאיר אותו מופעל בפעם הבאה שהוא יועבר למצב טיסה"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"חיבור ה-Wi‑Fi יישאר מופעל"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"חיבור ה-Wi‑Fi בטלפון יישאר מופעל במצב טיסה. אפשר להשבית את ה-Wi-Fi אם לא רוצים שהוא יפעל."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"רשת לא זמינה"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"האדמין השבית את <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"סגירה"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi מופעל במצב טיסה"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"חיבור ה-Wi‑Fi יישאר מופעל"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ja/strings.xml b/service/ServiceWifiResources/res/values-ja/strings.xml index c4054439e9..f3613231f3 100644 --- a/service/ServiceWifiResources/res/values-ja/strings.xml +++ b/service/ServiceWifiResources/res/values-ja/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"クイック設定で Wi‑Fi を OFF にできます"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"許可"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"許可しない"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"機内モードで Wi-Fi を ON"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wi-Fi を ON にしておくと、次に機内モードになったときも ON のままになります"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi を ON のままにする"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"機内モードでも、スマートフォンの Wi-Fi は ON のままになります。Wi-Fi を ON にしたくない場合は OFF にしてください。"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"使用できないネットワーク"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> は管理者によって無効にされています。"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"閉じる"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"機内モードで Wi-Fi を ON"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi を ON のままにする"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ka/strings.xml b/service/ServiceWifiResources/res/values-ka/strings.xml index e643cf6a14..cd6bc0944b 100644 --- a/service/ServiceWifiResources/res/values-ka/strings.xml +++ b/service/ServiceWifiResources/res/values-ka/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"შეგიძლიათ, გამორთოთ Wi-Fi სწრაფი პარამეტრებიდან"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"დაშვება"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"აკრძალვა"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ჩართულია თვითმფრინავის რეჟიმში"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"თუ Wi‑Fi-ს ჩართულს დატოვებთ, თქვენი ტელეფონი დაიმახსოვრებს და ჩართულს დატოვებს, როდესაც შემდგომში თვითმფრინავის რეჟიმში იქნებით"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi კვლავ ჩართულია"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"თქვენს ტელეფონს ემახსოვრება, რომ Wi‑Fi ჩართული უნდა იყოს თვითმფრინავის რეჟიმში. Wi‑Fi if-ის გამორთვა, თუ არ გსურთ ჩართული დატოვოთ."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ქსელი მიუწვდომელია"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> გათიშულია თქვენი ადმინისტრატორის მიერ."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"დახურვა"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ჩართულია თვითმფრინავის რეჟიმში"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi კვლავ ჩართულია"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-kk/strings.xml b/service/ServiceWifiResources/res/values-kk/strings.xml index af1817ef49..e4b82af8cf 100644 --- a/service/ServiceWifiResources/res/values-kk/strings.xml +++ b/service/ServiceWifiResources/res/values-kk/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi‑Fi-ды \"Жылдам параметрлер\" бөлімінде өшіре аласыз."</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Рұқсат беру"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Рұқсат бермеу"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ұшақ режимінде қосулы болады"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wi‑Fi қосулы болса, ол келесіде телефондағы ұшақ режимінде қосулы болады."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi қосулы тұрады"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Телефондағы Wi‑Fi ұшақ режимінде қосулы болады. Wi‑Fi желісінің қосулы тұрғанын қаламасаңыз, оны өшіріңіз."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Қолжетімсіз желі"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> әкімші тарапынан өшірілді."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Жабу"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ұшақ режимінде қосулы болады"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi қосулы тұрады"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-km/strings.xml b/service/ServiceWifiResources/res/values-km/strings.xml index 6e6ea9a651..60236be653 100644 --- a/service/ServiceWifiResources/res/values-km/strings.xml +++ b/service/ServiceWifiResources/res/values-km/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"អ្នកអាចបិទ Wi‑Fi នៅក្នុងការកំណត់រហ័ស"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"អនុញ្ញាត"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"មិនអនុញ្ញាត"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"បើក Wi-Fi នៅក្នុងមុខងារពេលជិះយន្តហោះ"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"ប្រសិនបើអ្នកបន្តបើក Wi‑Fi នោះទូរសព្ទរបស់អ្នកនឹងចាំថាត្រូវបន្តបើកវា នៅលើកក្រោយដែលអ្នកស្ថិតក្នុងមុខងារពេលជិះយន្តហោះ"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi នៅតែបើក"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"ទូរសព្ទរបស់អ្នកចាំថាត្រូវបន្តបើក Wi-Fi នៅក្នុងមុខងារពេលជិះយន្តហោះ។ បិទ Wi‑Fi ប្រសិនបើអ្នកមិនចង់ឱ្យវាបន្តបើក។"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"បណ្ដាញមិនអាចប្រើបាន"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> ត្រូវបានបិទដោយអ្នកគ្រប់គ្រងរបស់អ្នក។"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"បិទ"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"បើក Wi-Fi នៅក្នុងមុខងារពេលជិះយន្តហោះ"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi នៅតែបើក"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-kn/strings.xml b/service/ServiceWifiResources/res/values-kn/strings.xml index 34e8d407c0..bac4a72928 100644 --- a/service/ServiceWifiResources/res/values-kn/strings.xml +++ b/service/ServiceWifiResources/res/values-kn/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನೀವು ವೈ-ಫೈ ಅನ್ನು ಆಫ್ ಮಾಡಬಹುದು"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"ಅನುಮತಿಸಿ"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"ಅನುಮತಿಸಬೇಡಿ"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ಏರ್ಪ್ಲೇನ್ ಮೋಡ್ನಲ್ಲಿ ವೈ-ಫೈ ಆನ್ ಆಗಿದೆ"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"ನೀವು ವೈ-ಫೈ ಆನ್ ಮಾಡಿದರೆ, ಮುಂದಿನ ಬಾರಿ ನೀವು ಏರ್ಪ್ಲೇನ್ ಮೋಡ್ನಲ್ಲಿರುವಾಗ ಅದನ್ನು ಆನ್ ಮಾಡಲು ನಿಮ್ಮ ಫೋನ್ ನೆನಪಿಸಿಕೊಳ್ಳುತ್ತದೆ"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ವೈ-ಫೈ ಆನ್ ಇರುತ್ತದೆ"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"ವೈ-ಫೈ ಅನ್ನು ಏರ್ಪ್ಲೇನ್ ಮೋಡ್ನಲ್ಲಿ ಇರಿಸಿಕೊಳ್ಳಲು ನಿಮ್ಮ ಫೋನ್ ನೆನಪಿನಲ್ಲಿರಿಸಿಕೊಳ್ಳುತ್ತದೆ. ವೈ-ಫೈ ಆನ್ ಆಗಿರಲು ನೀವು ಬಯಸದಿದ್ದರೆ ಅದನ್ನು ಆಫ್ ಮಾಡಿ."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> ಅನ್ನು ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ಮುಚ್ಚಿರಿ"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ಏರ್ಪ್ಲೇನ್ ಮೋಡ್ನಲ್ಲಿ ವೈ-ಫೈ ಆನ್ ಆಗಿದೆ"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ವೈ-ಫೈ ಆನ್ ಇರುತ್ತದೆ"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ko/strings.xml b/service/ServiceWifiResources/res/values-ko/strings.xml index 98b5dc6728..656cf1b5c8 100644 --- a/service/ServiceWifiResources/res/values-ko/strings.xml +++ b/service/ServiceWifiResources/res/values-ko/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"빠른 설정에서 Wi‑Fi를 끌 수 있습니다."</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"허용"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"허용 안함"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"비행기 모드에서 Wi-Fi 사용"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wi-Fi를 켜진 상태로 유지하면 다음에 비행기 모드를 사용할 때도 Wi-Fi 연결이 유지됩니다."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi가 켜진 상태로 유지됨"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"휴대전화가 비행기 모드에서 Wi-Fi를 켜진 상태로 유지합니다. 유지하지 않으려면 Wi-Fi를 사용 중지하세요."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"사용할 수 없는 네트워크"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g>이(가) 관리자에 의해 사용 중지되었습니다."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"닫기"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"비행기 모드에서 Wi-Fi 사용"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi가 켜진 상태로 유지됨"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ky/strings.xml b/service/ServiceWifiResources/res/values-ky/strings.xml index ce19b53812..0f0a12333c 100644 --- a/service/ServiceWifiResources/res/values-ky/strings.xml +++ b/service/ServiceWifiResources/res/values-ky/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi‑Fi\'ды Ыкчам жөндөөлөрдөн өчүрсөңүз болот"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Уруксат берүү"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Тыюу салуу"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi учак режиминде күйгүзүлөт"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Эгер Wi-Fi күйүк бойдон калса, кийинки жолу учак режимине өткөнүңүздө телефонуңуз аны эстеп калат"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi күйгөн бойдон калат"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Телефонуңуз учак режиминде Wi‑Fi\'га туташкан бойдон калат. Кааласаңыз, Wi‑Fi\'ды өчүрүп койсоңуз болот."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Жеткиликсиз тармак"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> администраторуңуз тарабынан өчүрүлдү."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Жабуу"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi учак режиминде күйгүзүлөт"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi күйгөн бойдон калат"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-lo/strings.xml b/service/ServiceWifiResources/res/values-lo/strings.xml index d580e25f51..aa19a5acf9 100644 --- a/service/ServiceWifiResources/res/values-lo/strings.xml +++ b/service/ServiceWifiResources/res/values-lo/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"ທ່ານສາມາດປິດ Wi‑Fi ໄດ້ໃນການຕັ້ງຄ່າດ່ວນ"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"ອະນຸຍາດ"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"ບໍ່ອະນຸຍາດ"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ເປີດຢູ່ໃນໂໝດຢູ່ໃນຍົນ"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"ຫາກທ່ານເປີດ Wi‑Fi ໄວ້, ໂທລະສັບຂອງທ່ານຈະຈື່ວ່າຕ້ອງເປີດ Wi‑Fi ໃນເທື່ອຕໍ່ໄປທີ່ທ່ານຢູ່ໃນໂໝດຢູ່ໃນຍົນ"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ເປີດຢູ່"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"ໂທລະສັບຂອງທ່ານຈື່ວ່າຈະຕ້ອງເປີດ Wi-Fi ໄວ້ໃນໂໝດຢູ່ໃນຍົນ. ປິດ Wi‑Fi ຫາກທ່ານບໍ່ຕ້ອງການໃຫ້ເປີດມັນໄວ້."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ບໍ່ສາມາດໃຊ້ເຄືອຂ່າຍໄດ້"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ປິດ"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ເປີດຢູ່ໃນໂໝດຢູ່ໃນຍົນ"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ເປີດຢູ່"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-lt/strings.xml b/service/ServiceWifiResources/res/values-lt/strings.xml index 36db1ef849..25a48d4937 100644 --- a/service/ServiceWifiResources/res/values-lt/strings.xml +++ b/service/ServiceWifiResources/res/values-lt/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"„Wi‑Fi“ galite išjungti sparčiuosiuose nustatymuose"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Leisti"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Neleisti"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"„Wi‑Fi“ ryšys įjungtas lėktuvo režimu"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Jei paliksite „Wi‑Fi“ ryšį įjungtą, telefonas, prisimins palikti jį įjungtą, kai kitą kartą įjungsite lėktuvo režimą"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"„Wi‑Fi“ lieka įjungtas"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefonas prisimena, kad lėktuvo režimu reikia palikti įjungtą „Wi‑Fi“ ryšį. Išjunkite „Wi‑Fi“, jei nenorite, kad jis liktų įjungtas."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Nepasiekiamas tinklas"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"„<xliff:g id="SSID">%1$s</xliff:g>“ išjungė administratorius."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Uždaryti"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"„Wi‑Fi“ ryšys įjungtas lėktuvo režimu"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"„Wi‑Fi“ lieka įjungtas"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-lv/strings.xml b/service/ServiceWifiResources/res/values-lv/strings.xml index abd4905744..5fcff98237 100644 --- a/service/ServiceWifiResources/res/values-lv/strings.xml +++ b/service/ServiceWifiResources/res/values-lv/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Varat izslēgt Wi-Fi savienojumu ātrajos iestatījumos."</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Atļaut"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Neatļaut"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ieslēgts lidojuma režīmā"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ja Wi‑Fi savienojums paliks ieslēgts, tālrunī tas paliks ieslēgts arī nākamreiz, kad ieslēgsiet lidojuma režīmu."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi joprojām ieslēgts"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Tālrunī joprojām būs ieslēgts Wi-Fi savienojums lidojuma režīmā. Izslēdziet Wi‑Fi savienojumu, ja nevēlaties, lai tas paliktu ieslēgts."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Nepieejams tīkls"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administrators atspējoja tīklu <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Aizvērt"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ieslēgts lidojuma režīmā"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi joprojām ieslēgts"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-mk/strings.xml b/service/ServiceWifiResources/res/values-mk/strings.xml index 8abed0719d..6827cbfdcb 100644 --- a/service/ServiceWifiResources/res/values-mk/strings.xml +++ b/service/ServiceWifiResources/res/values-mk/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Може да го исклучите Wi‑Fi во „Брзи поставки“"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Дозволи"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Не дозволувај"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi е вклучено во авионски режим"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ако го оставите Wi‑Fi вклучено, телефонот ќе запомни да го остави вклучено до следниот пат кога ќе бидете во авионски режим"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi останува вклучено"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Телефонот помни да го остави Wi‑Fi вклучено во авионски режим. Исклучете го Wi‑Fi ако не сакате да остане вклучено."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Недостапна мрежа"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> е оневозможенa од вашиот администратор."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Затвори"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi е вклучено во авионски режим"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi останува вклучено"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ml/strings.xml b/service/ServiceWifiResources/res/values-ml/strings.xml index da1ed6d4aa..b4c84577b7 100644 --- a/service/ServiceWifiResources/res/values-ml/strings.xml +++ b/service/ServiceWifiResources/res/values-ml/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"ദ്രുത ക്രമീകരണത്തിൽ നിങ്ങൾക്ക് വൈഫൈ ഓഫാക്കാൻ കഴിയും"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"അനുവദിക്കുക"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"അനുവദിക്കരുത്"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ഫ്ലൈറ്റ് മോഡിൽ വൈഫൈ ഓണാണ്"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"വൈഫൈ ഓണാക്കി വച്ചാൽ, അടുത്ത തവണ നിങ്ങൾ ഫ്ലൈറ്റ് മോഡിൽ ആയിരിക്കുമ്പോൾ നിങ്ങളുടെ ഫോൺ അത് ഓണാക്കി വയ്ക്കാൻ ഓർക്കും"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"വൈഫൈ ഓണായിരിക്കും"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"ഫ്ലൈറ്റ് മോഡിലായിരിക്കുമ്പോൾ വൈഫൈ ഓണാക്കി വയ്ക്കാൻ നിങ്ങളുടെ ഫോൺ ഓർമ്മിക്കും. വൈഫൈ ഓണാക്കി വയ്ക്കാൻ താൽപ്പര്യമില്ലെങ്കിൽ അത് ഓഫാക്കുക."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ലഭ്യമല്ലാത്ത നെറ്റ്വർക്ക്"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> നിങ്ങളുടെ അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"അടയ്ക്കുക"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ഫ്ലൈറ്റ് മോഡിൽ വൈഫൈ ഓണാണ്"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"വൈഫൈ ഓണായിരിക്കും"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-mn/strings.xml b/service/ServiceWifiResources/res/values-mn/strings.xml index c940864362..2698812cc2 100644 --- a/service/ServiceWifiResources/res/values-mn/strings.xml +++ b/service/ServiceWifiResources/res/values-mn/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Та Wi-Fi-г Шуурхай тохиргоо хэсэгт унтраах боломжтой"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Зөвшөөр"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Бүү зөвшөөр"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi нислэгийн горимд асаалттай"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Хэрэв та Wi-Fi-аа асаалттай байлгавал таныг дараагийн удаа нислэгийн горимд байх үед утас тань үүнийг асаалттай байлгахыг санана"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi асаалттай байна"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Таны утас Wi-Fi-г нислэгийн горимд асаалттай байлгахыг санана. Хэрэв та үүнийг асаалттай байлгахыг хүсэхгүй байвал Wi-Fi-г унтраана уу."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Боломжгүй сүлжээ"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g>-г танай администратор идэвхгүй болгосон."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Хаах"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi нислэгийн горимд асаалттай"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi асаалттай байна"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-mr/strings.xml b/service/ServiceWifiResources/res/values-mr/strings.xml index c285271d66..edfa021713 100644 --- a/service/ServiceWifiResources/res/values-mr/strings.xml +++ b/service/ServiceWifiResources/res/values-mr/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"तुम्ही क्विक सेटिंग्ज मध्ये वाय-फाय बंद करू शकता"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"अनुमती द्या"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"अनुमती देऊ नका"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"विमान मोडमध्ये वाय-फाय सुरू आहे"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"तुम्ही वाय-फाय सुरू ठेवल्यास, पुढील वेळी विमान मोडमध्ये असाल, तेव्हा तुमचा फोन ते सुरू ठेवण्याचे लक्षात ठेवेल"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"वाय-फाय सुरू राहते"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"तुमचा फोन विमान मोडमध्ये वाय-फाय सुरू ठेवण्याचे लक्षात ठेवतो. तुम्हाला सुरू ठेवायचे नसल्यास, वाय-फाय बंद करा."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"उपलब्ध नसलेले नेटवर्क"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"तुमच्या अॅडमिनिस्ट्रेटर ने <xliff:g id="SSID">%1$s</xliff:g> बंद केले आहे."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"बंद करा"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"विमान मोडमध्ये वाय-फाय सुरू आहे"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"वाय-फाय सुरू राहते"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ms/strings.xml b/service/ServiceWifiResources/res/values-ms/strings.xml index 930c49d16b..ed211b1901 100644 --- a/service/ServiceWifiResources/res/values-ms/strings.xml +++ b/service/ServiceWifiResources/res/values-ms/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Anda boleh mematikan Wi‑Fi dalam Tetapan Pantas"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Benarkan"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Jangan benarkan"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi dihidupkan dalam mod pesawat"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Jika anda terus menghidupkan Wi-Fi, telefon anda akan ingat untuk membiarkan Wi-Fi hidup pada kali seterusnya telefon anda berada dalam mod pesawat"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi terus dihidupkan"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefon anda diingatkan untuk terus menghidupkan Wi-Fi dalam mod pesawat. Matikan Wi‑Fi jika anda tidak mahu Wi‑Fi sentiasa hidup."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rangkaian Tidak Tersedia"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> dilumpuhkan oleh pentadbir anda."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Tutup"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi dihidupkan dalam mod pesawat"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi terus dihidupkan"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-my/strings.xml b/service/ServiceWifiResources/res/values-my/strings.xml index 9fc959273c..c31355f88a 100644 --- a/service/ServiceWifiResources/res/values-my/strings.xml +++ b/service/ServiceWifiResources/res/values-my/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"‘အမြန် ဆက်တင်များ’ တွင် Wi‑Fi ပိတ်နိုင်သည်"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"ခွင့်ပြုရန်"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"ခွင့်မပြုပါ"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"လေယာဉ်ပျံမုဒ်တွင် Wi‑Fi ပွင့်နေသည်"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wi‑Fi ဆက်ဖွင့်ထားပါက နောက်တစ်ကြိမ်လေယာဉ်ပျံမုဒ် သုံးချိန်တွင် ၎င်းဆက်ဖွင့်ရန် သင့်ဖုန်းက မှတ်ထားမည်။"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ဆက်ပွင့်နေသည်"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"လေယာဉ်ပျံမုဒ်သုံးစဉ် Wi-Fi ဆက်ဖွင့်ထားရန် သင့်ဖုန်းက မှတ်မိသည်။ Wi‑Fi ဆက်ဖွင့်မထားလိုပါက ပိတ်နိုင်သည်။"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ကွန်ရက်မရနိုင်ပါ"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"သင့်စီမံခန့်ခွဲသူက <xliff:g id="SSID">%1$s</xliff:g> ကို ပိတ်ထားသည်။"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ပိတ်ရန်"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"လေယာဉ်ပျံမုဒ်တွင် Wi‑Fi ပွင့်နေသည်"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ဆက်ပွင့်နေသည်"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-nb/strings.xml b/service/ServiceWifiResources/res/values-nb/strings.xml index b9188a6373..dc7cd5ceb2 100644 --- a/service/ServiceWifiResources/res/values-nb/strings.xml +++ b/service/ServiceWifiResources/res/values-nb/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Du kan slå av Wi‑Fi i hurtiginnstillingene"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Tillat"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ikke tillat"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifi på i flymodus"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Hvis du lar wifi være på, husker telefonen dette til den neste gangen du bruker flymodus"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifi holdes på"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefonen husker å la wifi være påslått i flymodus. Du kan slå av wifi hvis du ikke vil la det være på."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Utilgjengelig nettverk"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administratoren din har deaktivert <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Lukk"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifi på i flymodus"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifi holdes på"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ne/strings.xml b/service/ServiceWifiResources/res/values-ne/strings.xml index b9e72840f5..fedf745227 100644 --- a/service/ServiceWifiResources/res/values-ne/strings.xml +++ b/service/ServiceWifiResources/res/values-ne/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"तपाईं द्रुत सेटिङहरूमा गएर Wi‑Fi अफ गर्न सक्नुहुन्छ"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"अनुमति दिनुहोस्"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"अनुमति नदिनुहोस्"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"हवाइजहाज मोडमा Wi-Fi अन रहन्छ"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"तपाईंले Wi‑Fi अन राख्नुभयो भने तपाईंले फेरि हवाइजहाज मोड सेट गर्दा फोनले Wi-Fi अन राख्नु पर्ने कुरा याद राख्छ"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi अन रहन्छ"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"हवाइजहाज मोडमा पनि तपाईंको फोनमा Wi-Fi अन नै रहने छ। तपाईं Wi‑Fi अन भइनरहोस् भन्ने चाहनुहुन्छ भने अफ गर्नुहोस्।"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"नेटवर्क उपलब्ध छैन"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"तपाईंका एड्मिनले <xliff:g id="SSID">%1$s</xliff:g> अफ गर्नुभएको छ।"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"बन्द गर्नुहोस्"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"हवाइजहाज मोडमा Wi-Fi अन रहन्छ"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi अन रहन्छ"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-nl/strings.xml b/service/ServiceWifiResources/res/values-nl/strings.xml index 53fc90e0e6..3f76368e65 100644 --- a/service/ServiceWifiResources/res/values-nl/strings.xml +++ b/service/ServiceWifiResources/res/values-nl/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Je kunt wifi uitzetten via Snelle instellingen"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Toestaan"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Niet toestaan"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifi aan in vliegtuigmodus"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Als je wifi laat aanstaan, onthoudt je telefoon dit en blijft de wifi aanstaan als je de vliegtuigmodus weer aanzet"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifi blijft aan"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"De wifi op je telefoon blijft aan in de vliegtuigmodus. Zet wifi uit als je niet wilt dat dit aan blijft."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Niet-beschikbaar netwerk"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> is uitgezet door je beheerder."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Sluiten"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifi aan in vliegtuigmodus"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifi blijft aan"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-or/strings.xml b/service/ServiceWifiResources/res/values-or/strings.xml index f210f4c2f6..02e25164a5 100644 --- a/service/ServiceWifiResources/res/values-or/strings.xml +++ b/service/ServiceWifiResources/res/values-or/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"ଆପଣ କ୍ୱିକ ସେଟିଂସରେ ୱାଇ-ଫାଇ ବନ୍ଦ କରିପାରିବେ"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"ଅନୁମତି ଦିଅନ୍ତୁ"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ଏୟାରପ୍ଲେନ ମୋଡରେ ୱାଇ-ଫାଇ ଚାଲୁ ଅଛି"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"ଯଦି ଆପଣ ୱାଇ-ଫାଇ ଚାଲୁ ରଖନ୍ତି, ତେବେ ଆପଣ ପରବର୍ତ୍ତୀ ଥର ଏୟାରପ୍ଲେନ ମୋଡରେ ଥିବା ସମୟରେ ଆପଣଙ୍କ ଫୋନ ଏହାକୁ ଚାଲୁ ରଖିବାକୁ ମନେ ରଖିବ"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ୱାଇ-ଫାଇ ଚାଲୁ ରହିବ"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"ଆପଣଙ୍କ ଫୋନ ଏୟାରପ୍ଲେନ ମୋଡରେ ୱାଇ-ଫାଇ ଚାଲୁ ରଖିବାକୁ ମନେ ରଖେ। ଯଦି ଆପଣ ୱାଇ-ଫାଇ ଚାଲୁ ରଖିବାକୁ ଚାହାଁନ୍ତି ନାହିଁ ତେବେ ୱାଇ-ଫାଇ ବନ୍ଦ କରନ୍ତୁ।"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ଅନୁପଲବ୍ଧ ନେଟୱାର୍କ"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g>କୁ ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟରଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି।"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ବନ୍ଦ କରନ୍ତୁ"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ଏୟାରପ୍ଲେନ ମୋଡରେ ୱାଇ-ଫାଇ ଚାଲୁ ଅଛି"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ୱାଇ-ଫାଇ ଚାଲୁ ରହିବ"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-pa/strings.xml b/service/ServiceWifiResources/res/values-pa/strings.xml index 46b352de09..23fe0f388a 100644 --- a/service/ServiceWifiResources/res/values-pa/strings.xml +++ b/service/ServiceWifiResources/res/values-pa/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"ਤੁਸੀਂ ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਵਾਈ-ਫਾਈ ਨੂੰ ਬੰਦ ਕਰ ਸਕਦੇ ਹੋ"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"ਆਗਿਆ ਦਿਓ"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"ਆਗਿਆ ਨਾ ਦਿਓ"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ ਵਿੱਚ ਵਾਈ-ਫਾਈ ਚਾਲੂ ਹੈ"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"ਜੇ ਤੁਸੀਂ ਵਾਈ-ਫਾਈ ਨੂੰ ਚਾਲੂ ਰੱਖਦੇ ਹੋ, ਤਾਂ ਅਗਲੀ ਵਾਰ ਤੁਹਾਡਾ ਫ਼ੋਨ ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ ਵਿੱਚ ਹੋਣ \'ਤੇ ਤੁਹਾਡਾ ਫ਼ੋਨ ਇਸਨੂੰ ਚਾਲੂ ਰੱਖਣਾ ਯਾਦ ਰੱਖੇਗਾ"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ਵਾਈ-ਫਾਈ ਚਾਲੂ ਰਹੇਗਾ"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ ਵਿੱਚ ਵਾਈ-ਫਾਈ ਨੂੰ ਚਾਲੂ ਰੱਖਣਾ ਯਾਦ ਰੱਖਦਾ ਹੈ। ਜੇ ਤੁਸੀਂ ਇਸਨੂੰ ਚਾਲੂ ਨਹੀਂ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਵਾਈ-ਫਾਈ ਨੂੰ ਬੰਦ ਕਰੋ।"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ <xliff:g id="SSID">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ।"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ਬੰਦ ਕਰੋ"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ ਵਿੱਚ ਵਾਈ-ਫਾਈ ਚਾਲੂ ਹੈ"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"ਵਾਈ-ਫਾਈ ਚਾਲੂ ਰਹੇਗਾ"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-pl/strings.xml b/service/ServiceWifiResources/res/values-pl/strings.xml index 6a13a74fd2..78c38fbc66 100644 --- a/service/ServiceWifiResources/res/values-pl/strings.xml +++ b/service/ServiceWifiResources/res/values-pl/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Możesz wyłączyć Wi‑Fi w Szybkich ustawieniach"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Zezwól"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Nie zezwalaj"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi włączone w trybie samolotowym"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Jeśli pozostawisz funkcję Wi‑Fi włączoną, telefon zachowa się podobnie przy kolejnym przejściu w tryb samolotowy"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi pozostanie włączone"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Wi-Fi na telefonie pozostaje włączone w trybie samolotowym. Wyłącz Wi‑Fi, jeśli nie chcesz, aby ta funkcja pozostała uruchomiona."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Niedostępna sieć"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administrator wyłączył sieć <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Zamknij"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi włączone w trybie samolotowym"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi pozostanie włączone"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-pt-rBR/strings.xml b/service/ServiceWifiResources/res/values-pt-rBR/strings.xml index 6b044eac0e..c5edab3235 100644 --- a/service/ServiceWifiResources/res/values-pt-rBR/strings.xml +++ b/service/ServiceWifiResources/res/values-pt-rBR/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"É possível desativar o Wi-Fi nas Configurações rápidas"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permitir"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Não permitir"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi ativado no modo avião"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Se você escolher manter o Wi‑Fi ligado, na próxima vez que você estiver em modo avião, o Wi-Fi do smartphone vai continuar ativado"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"O Wi-Fi fica ativado"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"O smartphone vai manter o Wi-Fi ligado no modo avião. Desligue o Wi‑Fi se você não quer que ele fique ativado."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rede indisponível"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"O recurso <xliff:g id="SSID">%1$s</xliff:g> foi desativado pelo administrador."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Fechar"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi ativado no modo avião"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"O Wi-Fi fica ativado"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-pt-rPT/strings.xml b/service/ServiceWifiResources/res/values-pt-rPT/strings.xml index 4ee0be601f..7ece8a8688 100644 --- a/service/ServiceWifiResources/res/values-pt-rPT/strings.xml +++ b/service/ServiceWifiResources/res/values-pt-rPT/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Pode desativar o Wi‑Fi nas Definições rápidas"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permitir"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Não permitir"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ativado no modo de avião"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Se mantiver o Wi‑Fi ativado, o telemóvel vai lembrar-se de o manter ativado da próxima vez que estiver no modo de avião"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"O Wi‑Fi mantém-se ativado"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"O seu telemóvel mantém o Wi-Fi ativado no modo de avião. Desative o Wi-Fi se não quiser que fique ativado."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rede indisponível"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"O administrador desativou a funcionalidade <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Fechar"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi ativado no modo de avião"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"O Wi‑Fi mantém-se ativado"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-pt/strings.xml b/service/ServiceWifiResources/res/values-pt/strings.xml index 6b044eac0e..c5edab3235 100644 --- a/service/ServiceWifiResources/res/values-pt/strings.xml +++ b/service/ServiceWifiResources/res/values-pt/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"É possível desativar o Wi-Fi nas Configurações rápidas"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permitir"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Não permitir"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi ativado no modo avião"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Se você escolher manter o Wi‑Fi ligado, na próxima vez que você estiver em modo avião, o Wi-Fi do smartphone vai continuar ativado"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"O Wi-Fi fica ativado"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"O smartphone vai manter o Wi-Fi ligado no modo avião. Desligue o Wi‑Fi se você não quer que ele fique ativado."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rede indisponível"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"O recurso <xliff:g id="SSID">%1$s</xliff:g> foi desativado pelo administrador."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Fechar"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi-Fi ativado no modo avião"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"O Wi-Fi fica ativado"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ro/strings.xml b/service/ServiceWifiResources/res/values-ro/strings.xml index bed936e8b9..8d50f9d424 100644 --- a/service/ServiceWifiResources/res/values-ro/strings.xml +++ b/service/ServiceWifiResources/res/values-ro/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Poți dezactiva conexiunea Wi‑Fi din Setările rapide"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Permite"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Nu permite"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi activat în modul Avion"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Dacă păstrezi Wi‑Fi activat, telefonul tău va reține să-l păstreze activat data viitoare când ești în modul Avion"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Funcția Wi‑Fi rămâne activată"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefonul reține să păstreze funcția Wi-Fi activată în modul Avion. Dezactivează Wi‑Fi dacă nu vrei să rămână activat."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rețea indisponibilă"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Administratorul a dezactivat <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Închide"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi activat în modul Avion"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Funcția Wi‑Fi rămâne activată"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ru/strings.xml b/service/ServiceWifiResources/res/values-ru/strings.xml index 7179dd51ae..0ee529a173 100644 --- a/service/ServiceWifiResources/res/values-ru/strings.xml +++ b/service/ServiceWifiResources/res/values-ru/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Отключить Wi‑Fi можно в быстрых настройках."</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Разрешить"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Не разрешать"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi будет включен в режиме полета"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Если не отключить функцию Wi-Fi, в следующий раз она останется включенной в режиме полета."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Функция Wi‑Fi остается включенной"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Функция Wi‑Fi останется включенной в режиме полета. Вы можете отключить ее, если хотите."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Сеть недоступна"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Администратор отключил функцию \"<xliff:g id="SSID">%1$s</xliff:g>\"."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Закрыть"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi будет включен в режиме полета"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Функция Wi‑Fi остается включенной"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-si/strings.xml b/service/ServiceWifiResources/res/values-si/strings.xml index ea269f6d6b..abcbca427d 100644 --- a/service/ServiceWifiResources/res/values-si/strings.xml +++ b/service/ServiceWifiResources/res/values-si/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"ඔබට ඉක්මන් සැකසීම් තුළ Wi‑Fi ක්රියාවිරහිත කළ හැකිය"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"ඉඩ දෙන්න"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"ඉඩ නොදෙන්න"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ගුවන්යානා ප්රකාරය තුළ Wi‑Fi සක්රීයයි"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"ඔබ Wi‑Fi ක්රියාත්මක කර තබා ගන්නේ නම්, ඔබ අහස්යානා ආකාරයේ සිටින මීළඟ වතාවේ එය ක්රියාත්මක කිරීමට ඔබේ දුරකථනයට මතක තිබෙනු ඇත."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi ක්රියාත්මකව පවතී"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"ඔබේ දුරකථනය අහස්යානා ආකාරයේ දී Wi‑Fi ක්රියාත්මකව තබා ගැනීමට මතක තබා ගනියි. ඔබට Wi‑Fi ක්රියාත්මක වීමට අවශ්ය නොවේ නම් එය ක්රියාවිරහිත කරන්න."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"ලබා ගත නොහැකි ජාලය"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> ඔබේ පරිපාලක විසින් අබල කර ඇත."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"වසන්න"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ගුවන්යානා ප්රකාරය තුළ Wi‑Fi සක්රීයයි"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi ක්රියාත්මකව පවතී"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-sk/strings.xml b/service/ServiceWifiResources/res/values-sk/strings.xml index 8d00f9019c..1f8484ec99 100644 --- a/service/ServiceWifiResources/res/values-sk/strings.xml +++ b/service/ServiceWifiResources/res/values-sk/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi‑Fi môžete vypnúť v rýchlych nastaveniach"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Povoliť"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Nepovoliť"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Sieť Wi‑Fi bude v režime v lietadle zapnutá"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ak ponecháte sieť Wi‑Fi zapnutú, váš telefón si zapamätá, že ju má ponechať zapnutú pri ďalšom aktivovaní režimu v lietadle"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Pripojenie Wi‑Fi zostane zapnuté"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefón si zapamätá, aby v režime v lietadle nevypínal sieť Wi‑Fi. Vypnite ju, ak nechcete, aby zostala zapnutá."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Nedostupná sieť"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Funkcia <xliff:g id="SSID">%1$s</xliff:g> je deaktivovaná správcom."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Zavrieť"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Sieť Wi‑Fi bude v režime v lietadle zapnutá"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Pripojenie Wi‑Fi zostane zapnuté"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-sl/strings.xml b/service/ServiceWifiResources/res/values-sl/strings.xml index ab763ba559..9d3ea17e9a 100644 --- a/service/ServiceWifiResources/res/values-sl/strings.xml +++ b/service/ServiceWifiResources/res/values-sl/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi‑Fi lahko izklopite v hitrih nastavitvah."</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Dovoli"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ne dovoli"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi je vklopljen v načinu za letalo."</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Če pustite Wi-Fi vklopljen, bo telefon ob naslednjem preklopu na način za letalo pustil Wi-Fi vklopljen."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi ostane vklopljen"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefon v načinu za letalo pusti Wi-Fi vklopljen. Če ne želite, da ostane vklopljen, izklopite vmesnik Wi‑Fi."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Omrežje ni na voljo"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Omrežje <xliff:g id="SSID">%1$s</xliff:g> je onemogočil skrbnik."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Zapri"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi je vklopljen v načinu za letalo."</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi ostane vklopljen"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-sq/strings.xml b/service/ServiceWifiResources/res/values-sq/strings.xml index bd22a68f83..11632fe88e 100644 --- a/service/ServiceWifiResources/res/values-sq/strings.xml +++ b/service/ServiceWifiResources/res/values-sq/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Mund ta çaktivizosh Wi-Fi te \"Cilësimet e shpejta\""</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Lejo"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Mos lejo"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi është në modalitetin e aeroplanit"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Nëse e mban Wi-Fi të aktivizuar, telefoni yt do të kujtohet ta mbajë atë të aktivizuar herën tjetër që të jesh në modalitetin e aeroplanit"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi qëndron aktiv"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefoni yt kujtohet që ta mbajë Wi-Fi të aktivizuar në modalitetin e aeroplanit. Çaktivizo Wi‑Fi nëse nuk dëshiron që të qëndrojë e aktivizuar."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Rrjeti i padisponueshëm"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> është çaktivizuar nga administratori yt."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Mbyll"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi është në modalitetin e aeroplanit"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi qëndron aktiv"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-sr/strings.xml b/service/ServiceWifiResources/res/values-sr/strings.xml index 4f514c9612..6bdf104afb 100644 --- a/service/ServiceWifiResources/res/values-sr/strings.xml +++ b/service/ServiceWifiResources/res/values-sr/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Можете да искључите WiFi у Брзим подешавањима"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Дозволи"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Не дозволи"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi је укључен у режиму рада у авиону"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Ако одлучите да не искључујете WiFi, телефон ће запамтити да га не искључује следећи пут када будете у режиму рада у авиону"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi остаје укључен"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Телефон памти да не треба да искључује WiFi у режиму рада у авиону. Искључите WiFi ако не желите да остане укључен."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Недоступна мрежа"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Администратор је онемогућио <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Затвори"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"WiFi је укључен у режиму рада у авиону"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WiFi остаје укључен"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-sv/strings.xml b/service/ServiceWifiResources/res/values-sv/strings.xml index 337363185f..57c31282a6 100644 --- a/service/ServiceWifiResources/res/values-sv/strings.xml +++ b/service/ServiceWifiResources/res/values-sv/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Du kan stänga av wifi i snabbinställningarna"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Tillåt"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Tillåt inte"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifi är aktiverat i flygplansläget"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Om du håller wifi aktiverat kommer telefonen ihåg att hålla det aktiverat nästa gång du använder flygplansläge."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifi inaktiveras inte"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefonen håller wifi aktiverat i flygplansläge. Inaktivera wifi om du inte vill att wifi ska hållas aktiverat."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Otillgängligt nätverk"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> har inaktiverats av administratören."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Stäng"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wifi är aktiverat i flygplansläget"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wifi inaktiveras inte"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-sw/strings.xml b/service/ServiceWifiResources/res/values-sw/strings.xml index 5d4dee3f8c..aa007edafe 100644 --- a/service/ServiceWifiResources/res/values-sw/strings.xml +++ b/service/ServiceWifiResources/res/values-sw/strings.xml @@ -160,13 +160,13 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Unaweza kuzima Wi-Fi kwenye Mipangilio ya Haraka"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Ruhusu"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Usiruhusu"</string> - <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Mtandao Haupatikani"</string> - <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> umezimwa na msimamizi wako."</string> - <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Funga"</string> <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi itawashwa katika hali ya ndegeni"</string> <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> <skip /> <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi itaendelea kuwaka"</string> <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> <skip /> + <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Mtandao Haupatikani"</string> + <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> umezimwa na msimamizi wako."</string> + <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Funga"</string> </resources> diff --git a/service/ServiceWifiResources/res/values-ta/strings.xml b/service/ServiceWifiResources/res/values-ta/strings.xml index d385417da4..e2dc6c6572 100644 --- a/service/ServiceWifiResources/res/values-ta/strings.xml +++ b/service/ServiceWifiResources/res/values-ta/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"விரைவு அமைப்புகளில் நீங்கள் வைஃபையை முடக்கிக்கொள்ளலாம்"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"அனுமதி"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"அனுமதிக்க வேண்டாம்"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"விமானப் பயன்முறையில் வைஃபை இயக்கத்திலேயே இருக்கும்"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"வைஃபையை இயக்கத்தில் வைத்திருந்தால், அடுத்த முறை நீங்கள் விமானப் பயன்முறையைப் பயன்படுத்தும்போது உங்கள் மொபைல் வைஃபையை இயக்கத்தில் வைக்கும்"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"வைஃபை இயக்கத்திலேயே இருக்கும்"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"உங்கள் மொபைல் விமானப் பயன்முறையில் இருக்கும்போது வைஃபையை இயக்கத்திலேயே வைத்திருக்கும். வைஃபையைப் பயன்படுத்த விரும்பவில்லை என்றால் அதை முடக்கவும்."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"நெட்வொர்க் கிடைக்கவில்லை"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> உங்கள் நிர்வாகியால் முடக்கப்பட்டுள்ளது."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"மூடுக"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"விமானப் பயன்முறையில் வைஃபை இயக்கத்திலேயே இருக்கும்"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"வைஃபை இயக்கத்திலேயே இருக்கும்"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-te/strings.xml b/service/ServiceWifiResources/res/values-te/strings.xml index 47f53eda42..3e1a882606 100644 --- a/service/ServiceWifiResources/res/values-te/strings.xml +++ b/service/ServiceWifiResources/res/values-te/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"మీరు క్విక్ సెట్టింగ్లలో Wi‑Fiని ఆఫ్ చేయవచ్చు"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"అనుమతించండి"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"అనుమతించవద్దు"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"విమానం మోడ్లో Wi‑Fi ఆన్ చేయబడింది"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"మీరు Wi‑Fiని ఆన్లో ఉంచినట్లయితే, మీరు తదుపరిసారి విమానం మోడ్లో ఉన్నప్పుడు దాన్ని ఆన్లో ఉంచాలని మీ ఫోన్ గుర్తుంచుకుంటుంది"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ఆన్లోనే ఉంటుంది"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"మీ ఫోన్ విమానం మోడ్లో Wi‑Fiని ఆన్లో ఉంచాలని గుర్తుంచుకుంటుంది. Wi‑Fi ఆన్లో ఉండకూడదనుకుంటే దాన్ని ఆఫ్ చేయండి."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"నెట్వర్క్ అందుబాటులో లేదు"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g>ను మీ అడ్మినిస్ట్రేటర్ డిజేబుల్ చేశారు."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"మూసివేయండి"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"విమానం మోడ్లో Wi‑Fi ఆన్ చేయబడింది"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi ఆన్లోనే ఉంటుంది"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-th/strings.xml b/service/ServiceWifiResources/res/values-th/strings.xml index 38355e7c44..0cdd9c2c42 100644 --- a/service/ServiceWifiResources/res/values-th/strings.xml +++ b/service/ServiceWifiResources/res/values-th/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"คุณปิด Wi‑Fi ได้ในการตั้งค่าด่วน"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"อนุญาต"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"ไม่อนุญาต"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi จะเปิดในโหมดบนเครื่องบิน"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"หากเปิด Wi-Fi ไว้ โทรศัพท์จะจำว่าต้องเปิด Wi-Fi ในครั้งถัดไปที่คุณอยู่ในโหมดบนเครื่องบิน"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi เปิดอยู่"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"โทรศัพท์จำว่าจะต้องเปิด Wi-Fi ในโหมดบนเครื่องบิน ปิด Wi-Fi หากคุณไม่ต้องการให้เปิดไว้"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"เครือข่ายไม่พร้อมใช้งาน"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"ผู้ดูแลระบบปิดใช้ <xliff:g id="SSID">%1$s</xliff:g>"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"ปิด"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi จะเปิดในโหมดบนเครื่องบิน"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi-Fi เปิดอยู่"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-tl/strings.xml b/service/ServiceWifiResources/res/values-tl/strings.xml index 8ab7d880ba..ac0be04d6f 100644 --- a/service/ServiceWifiResources/res/values-tl/strings.xml +++ b/service/ServiceWifiResources/res/values-tl/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Puwede mong i-off ang Wi‑Fi sa Mga Mabilisang Setting"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Payagan"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Huwag payagan"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"I-on ang Wi‑Fi habang nasa airplane mode"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Kung papanatilihin mong naka-on ang Wi‑Fi, tatandaan ng iyong telepono na panatilihin itong naka-on sa susunod na nasa airplane mode ka"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Mananatiling naka-on ang Wi‑Fi"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Tinatandaan ng iyong telepono na panatilihing naka-on ang Wi-Fi habang nasa airplane mode. I-off ang Wi‑Fi kung ayaw mo itong manatiling naka-on."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Hindi Available na Network"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Na-disable ng iyong administrator ang <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Isara"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"I-on ang Wi‑Fi habang nasa airplane mode"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Mananatiling naka-on ang Wi‑Fi"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-tr/strings.xml b/service/ServiceWifiResources/res/values-tr/strings.xml index f8a1b6ae89..8ba171ad0b 100644 --- a/service/ServiceWifiResources/res/values-tr/strings.xml +++ b/service/ServiceWifiResources/res/values-tr/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Kablosuz bağlantıyı Hızlı Ayarlar\'dan kapatabilirsiniz"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"İzin ver"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"İzin verme"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Uçak modundayken kablosuz bağlantı açık"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Kablosuz bağlantıyı açık tutarsanız telefonunuz, daha sonra tekrar uçak modunda olduğunuzda kablosuz bağlantıyı açık tutar"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Kablosuz bağlantı açık kalır"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefonunuz, uçak modundayken kablosuz bağlantıyı açık tutmayı hatırlar. Açık kalmasını istemiyorsanız kablosuz bağlantıyı kapatın."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Kullanılamayan Ağ"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g>, yöneticiniz tarafından devre dışı bırakıldı."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Kapat"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Uçak modundayken kablosuz bağlantı açık"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Kablosuz bağlantı açık kalır"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-uk/strings.xml b/service/ServiceWifiResources/res/values-uk/strings.xml index 2a34dc0621..63f172c1c5 100644 --- a/service/ServiceWifiResources/res/values-uk/strings.xml +++ b/service/ServiceWifiResources/res/values-uk/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Wi-Fi можна вимкнути у швидких налаштуваннях"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Дозволити"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Не дозволяти"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Ви ввімкнули Wi‑Fi у режимі польоту"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Якщо ви не вимкнете Wi‑Fi на телефоні, ця функція залишатиметься ввімкненою під час наступного використання режиму польоту"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi не буде вимкнено"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"У режимі польоту функція Wi‑Fi на телефоні залишатиметься ввімкненою. Якщо захочете вимкнути її, вимкніть Wi‑Fi."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Недоступна мережа"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Адміністратор вимкнув мережу <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Закрити"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Ви ввімкнули Wi‑Fi у режимі польоту"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi не буде вимкнено"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-ur/strings.xml b/service/ServiceWifiResources/res/values-ur/strings.xml index 8f8f6f0ac2..ac5dc2976d 100644 --- a/service/ServiceWifiResources/res/values-ur/strings.xml +++ b/service/ServiceWifiResources/res/values-ur/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"آپ فوری ترتیبات میں Wi-Fi آف کر سکتے ہیں"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"اجازت دیں"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"اجازت نہ دیں"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ہوائی جہاز وضع میں Wi‑Fi آن ہے"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"اگر آپ Wi-Fi کو آن رکھتے ہیں تو آپ کا فون آپ کے اگلی مرتبہ ہوائی جہاز وضع میں ہونے پر اسے آن رکھنا یاد رکھے گا"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi آن رہتا ہے"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"آپ کا فون ہوائی جہاز وضع میں Wi‑Fi کو آن رکھنا یاد رکھتا ہے۔ اگر آپ نہیں چاہتے ہیں کہ Wi-Fi آن رہے تو اسے آف کریں۔"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"غیر دستیاب نیٹ ورک"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> کو آپ کے منتظم کے ذریعے مسدود کر دیا گیا ہے۔"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"بند کریں"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"ہوائی جہاز وضع میں Wi‑Fi آن ہے"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi آن رہتا ہے"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-uz/strings.xml b/service/ServiceWifiResources/res/values-uz/strings.xml index e62ec1e76d..e16b3cc37e 100644 --- a/service/ServiceWifiResources/res/values-uz/strings.xml +++ b/service/ServiceWifiResources/res/values-uz/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Tezkor sozlamalar orqali Wi-Fi aloqani faolsizlantirish mumkin"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Ruxsat berish"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Rad etish"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi parvoz rejimida yoniq"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Wi-Fi yoniq qolsa, telefon keyingi safar parvoz rejimida ham uni yoniq qoldiradi."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi yoniq turadi"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Telefoningiz parvoz rejimida Wi‑Fi yoqilganini eslab qoladi. Yoniq qolmasligi uchun Wi-Fi aloqasini oʻchiring."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Tarmoq mavjud emas"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> administrator tomonidan faolsizlantirilgan."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Yopish"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi parvoz rejimida yoniq"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi yoniq turadi"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-vi/strings.xml b/service/ServiceWifiResources/res/values-vi/strings.xml index 1470d42809..7336092071 100644 --- a/service/ServiceWifiResources/res/values-vi/strings.xml +++ b/service/ServiceWifiResources/res/values-vi/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Bạn có thể tắt Wi-Fi trong phần Cài đặt nhanh"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Cho phép"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Không cho phép"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi bật ở chế độ trên máy bay"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Nếu bạn không tắt Wi‑Fi, điện thoại sẽ luôn bật Wi‑Fi vào lần tiếp theo bạn dùng chế độ trên máy bay"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi ‑ Fi luôn được bật"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Điện thoại của bạn sẽ luôn bật Wi-Fi ở chế độ trên máy bay. Nếu không muốn như vậy thì bạn có thể tắt Wi-Fi."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Không có kết nối mạng"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"Quản trị viên của bạn đã tắt tính năng <xliff:g id="SSID">%1$s</xliff:g>."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Đóng"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"Wi‑Fi bật ở chế độ trên máy bay"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi ‑ Fi luôn được bật"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-zh-rCN/strings.xml b/service/ServiceWifiResources/res/values-zh-rCN/strings.xml index 24f5cb288f..623a33c397 100644 --- a/service/ServiceWifiResources/res/values-zh-rCN/strings.xml +++ b/service/ServiceWifiResources/res/values-zh-rCN/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"您可以在“快捷设置”中关闭 WLAN"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"允许"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"不允许"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"飞行模式时开启 WLAN"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"如果您不关闭 WLAN,那么您下次进入飞行模式时手机将记住保持 WLAN 开启"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WLAN 保持开启状态"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"在飞行模式下手机将记住保持 WLAN 开启。如果您不想让 WLAN 保持开启,请将其关闭。"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"网络无法使用"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"<xliff:g id="SSID">%1$s</xliff:g> 已被您的管理员停用。"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"关闭"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"飞行模式时开启 WLAN"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"WLAN 保持开启状态"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-zh-rHK/strings.xml b/service/ServiceWifiResources/res/values-zh-rHK/strings.xml index f4f56b7f8d..19e43dd644 100644 --- a/service/ServiceWifiResources/res/values-zh-rHK/strings.xml +++ b/service/ServiceWifiResources/res/values-zh-rHK/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"您可以在「快速設定」中關閉 Wi-Fi"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"允許"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"不允許"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"在飛行模式下開啟 Wi-Fi"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"如果您不關閉 Wi-Fi,下次手機進入飛行模式時,Wi-Fi 將保持開啟"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"保持 Wi-Fi 連線"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"手機會記得在飛行模式下保持 Wi-Fi 開啟。如果您不希望保持開啟,請關閉 Wi-Fi。"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"無法使用網絡"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"您的管理員已停用「<xliff:g id="SSID">%1$s</xliff:g>」。"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"關閉"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"在飛行模式下開啟 Wi-Fi"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"保持 Wi-Fi 連線"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-zh-rTW/strings.xml b/service/ServiceWifiResources/res/values-zh-rTW/strings.xml index c941f23239..b579adfe0c 100644 --- a/service/ServiceWifiResources/res/values-zh-rTW/strings.xml +++ b/service/ServiceWifiResources/res/values-zh-rTW/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"你可以透過快速設定關閉 Wi-Fi"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"允許"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"不允許"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"在飛航模式下保持 Wi-Fi 開啟狀態"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"如果你不關閉 Wi-Fi,下次手機進入飛航模式時,Wi-Fi 將保持開啟"</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi 會保持開啟狀態"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"手機會記得在飛航模式下保持 Wi-Fi 開啟。如果不要保持開啟,請關閉 Wi-Fi。"</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"網路無法使用"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"你的系統管理員已停用 <xliff:g id="SSID">%1$s</xliff:g>。"</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"關閉"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"在飛航模式下保持 Wi-Fi 開啟狀態"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"Wi‑Fi 會保持開啟狀態"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values-zu/strings.xml b/service/ServiceWifiResources/res/values-zu/strings.xml index 69f841ce72..7b2596923b 100644 --- a/service/ServiceWifiResources/res/values-zu/strings.xml +++ b/service/ServiceWifiResources/res/values-zu/strings.xml @@ -160,13 +160,11 @@ <string name="wifi_enable_request_dialog_message" msgid="6395169178524938278">"Ungavala i-Wi-Fi Kumasethingi Asheshayo"</string> <string name="wifi_enable_request_dialog_positive_button" msgid="6050832555821470466">"Vumela"</string> <string name="wifi_enable_request_dialog_negative_button" msgid="4754219902374918882">"Ungavumeli"</string> + <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"I-Wi‑Fi ivuliwe kumodi yendiza"</string> + <string name="wifi_enabled_apm_first_time_message" msgid="5443101896157496353">"Uma ugcina i-Wi‑Fi ivuliwe, ifoni yakho izokhumbula ukuyigcina ivuliwe ngesikhathi esilandelayo uma ukumodi yendiza."</string> + <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"I-Wi‑Fi ihlala ivuliwe"</string> + <string name="apm_enabled_first_time_message" msgid="4753441005253327841">"Ifoni yakho ikhumbula ukugcina i-Wi‑Fi ivuliwe kumodi yendiza. Vala i-Wi-Fi uma ungafuni ukuthi ihlale ivuliwe."</string> <string name="wifi_network_disabled_by_admin_title" msgid="9057697656855227293">"Inethiwekhi Engatholakali"</string> <string name="wifi_network_disabled_by_admin_message" msgid="7830360441333155462">"I-<xliff:g id="SSID">%1$s</xliff:g> ikhutshazwe umlawuli wakho."</string> <string name="wifi_network_disabled_by_admin_button" msgid="3350310756265122689">"Vala"</string> - <string name="wifi_enabled_apm_first_time_title" msgid="4814302384637588804">"I-Wi‑Fi ivuliwe kumodi yendiza"</string> - <!-- no translation found for wifi_enabled_apm_first_time_message (5443101896157496353) --> - <skip /> - <string name="apm_enabled_first_time_title" msgid="2534167413190488009">"I-Wi‑Fi ihlala ivuliwe"</string> - <!-- no translation found for apm_enabled_first_time_message (4753441005253327841) --> - <skip /> </resources> diff --git a/service/ServiceWifiResources/res/values/config.xml b/service/ServiceWifiResources/res/values/config.xml index a5dcb90705..d3107151b9 100644 --- a/service/ServiceWifiResources/res/values/config.xml +++ b/service/ServiceWifiResources/res/values/config.xml @@ -134,8 +134,10 @@ config_wifiFrameworkUnmeteredNetworkBonus. --> <integer translatable="false" name="config_wifiScoringBucketStepSize">500</integer> - <!-- The duration in minutes to strongly favor the last-selected network over other options. --> + <!-- The duration in minutes to strongly favor the last-selected non-metered network over other options. --> <integer translatable="false" name="config_wifiFrameworkLastSelectionMinutes">480</integer> + <!-- The duration in minutes to strongly favor the last-selected metered network over other options. --> + <integer translatable="false" name="config_wifiFrameworkLastMeteredSelectionMinutes">120</integer> <!-- Integer specifying the min packet Tx/Rx rates in packets per second to be considered active traffic so that network selection and scan could be skipped--> @@ -550,6 +552,24 @@ <integer translatable="false" name="config_wifiDisableReasonAuthenticationFailureThreshold"> 3 </integer> <integer translatable="false" name="config_wifiDisableReasonDhcpFailureThreshold"> 2 </integer> <integer translatable="false" name="config_wifiDisableReasonNetworkNotFoundThreshold"> 2 </integer> + <integer translatable="false" name="config_wifiDisableReasonNoInternetTemporaryThreshold"> 1 </integer> + <integer translatable="false" name="config_wifiDisableReasonAuthenticationNoCredentialsThreshold"> 3 </integer> + <integer translatable="false" name="config_wifiDisableReasonNoInternetPermanentThreshold"> 1 </integer> + <integer translatable="false" name="config_wifiDisableReasonByWrongPasswordThreshold"> 1 </integer> + <integer translatable="false" name="config_wifiDisableReasonAuthenticationNoSubscriptionThreshold"> 1 </integer> + <integer translatable="false" name="config_wifiDisableReasonConsecutiveFailuresThreshold"> 1 </integer> + + <!-- Base duration to set a network disabled after validation failure happen--> + <integer translatable="false" name="config_wifiDisableReasonAssociationRejectionDurationMs"> 300000 </integer> + <integer translatable="false" name="config_wifiDisableReasonAuthenticationFailureDurationMs"> 300000 </integer> + <integer translatable="false" name="config_wifiDisableReasonDhcpFailureDurationMs"> 300000 </integer> + <integer translatable="false" name="config_wifiDisableReasonNetworkNotFoundDurationMs"> 300000 </integer> + <integer translatable="false" name="config_wifiDisableReasonNoInternetTemporaryDurationMs"> 600000 </integer> + <integer translatable="false" name="config_wifiDisableReasonAuthenticationNoCredentialsDurationMs"> -1 </integer> + <integer translatable="false" name="config_wifiDisableReasonNoInternetPermanentDurationMs"> -1 </integer> + <integer translatable="false" name="config_wifiDisableReasonByWrongPasswordDurationMs"> -1 </integer> + <integer translatable="false" name="config_wifiDisableReasonAuthenticationNoSubscriptionDurationMs"> -1 </integer> + <integer translatable="false" name="config_wifiDisableReasonConsecutiveFailuresDurationMs"> 300000 </integer> <!-- List of constants that indicate the number of consecutive failures per type needed to block a BSSID. A blocked BSSID will not be considered in network selection and firmware roaming.--> @@ -571,6 +591,9 @@ config_wifiBssidBlocklistMonitorFailureStreakCap is set to 7--> <integer translatable="false" name="config_wifiBssidBlocklistMonitorBaseBlockDurationMs"> 300000 </integer> + <!-- Base duration to block a bssid after validation failure happen--> + <integer translatable="false" name="config_wifiBssidBlocklistMonitorValidationFailureBaseBlockDurationMs"> 300000 </integer> + <!-- Base duration to block a BSSID after the external connected scorer sets wifi as unusable. The block duration is increased exponentially if the same BSSID is repeated marked as unusable. ie. 0.5/1/2/4/8/16/32/64 minutes - capped at 64 minutes because the default for @@ -838,6 +861,9 @@ <!-- Indicate the number of networks to restore in a batch. 0 : all networks in a batch --> <integer translatable="false" name="config_wifiConfigurationRestoreNetworksBatchNum">50</integer> + <!-- Enables logging for any tasks running on the Wi-Fi thread which take longer than this threshold (in milliseconds) --> + <integer translatable="false" name="config_wifiConfigurationWifiRunnerThresholdInMs">100</integer> + <!-- OEM privileged WiFi admin package names. Empty by default--> <string-array translatable="false" name="config_oemPrivilegedWifiAdminPackages"> <!-- Add package names here, example: --> @@ -961,4 +987,7 @@ <!-- boolean indicating whether the caller thread needs to wait for destroyed listeners --> <bool translatable="false" name ="config_wifiWaitForDestroyedListeners">false</bool> + + <!-- Indicates the number of channels is allowed to set in a WifiNetworkSpecifier --> + <integer translatable="false" name ="config_wifiNetworkSpecifierMaxPreferredChannels">5</integer> </resources> diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml index 019063b6d2..44fde711c5 100644 --- a/service/ServiceWifiResources/res/values/overlayable.xml +++ b/service/ServiceWifiResources/res/values/overlayable.xml @@ -50,6 +50,7 @@ <item type="integer" name="config_wifiBand6GhzBonus" /> <item type="integer" name="config_wifiScoringBucketStepSize" /> <item type="integer" name="config_wifiFrameworkLastSelectionMinutes" /> + <item type="integer" name="config_wifiFrameworkLastMeteredSelectionMinutes" /> <item type="integer" name="config_wifiFrameworkMinPacketPerSecondActiveTraffic" /> <item type="integer" name="config_wifiFrameworkMinPacketPerSecondHighTraffic" /> <item type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz" /> @@ -144,10 +145,29 @@ <item type="integer" name="config_wifiPnoScanLowRssiNetworkRetryStartDelaySec" /> <item type="integer" name="config_wifiPnoScanLowRssiNetworkRetryMaxDelaySec" /> <item type="integer" name="config_wifiConnectedHighRssiScanMinimumWindowSizeSec" /> + <item type="integer" name="config_wifiDisableReasonAssociationRejectionThreshold" /> <item type="integer" name="config_wifiDisableReasonAuthenticationFailureThreshold" /> <item type="integer" name="config_wifiDisableReasonDhcpFailureThreshold" /> <item type="integer" name="config_wifiDisableReasonNetworkNotFoundThreshold" /> + <item type="integer" name="config_wifiDisableReasonNoInternetTemporaryThreshold" /> + <item type="integer" name="config_wifiDisableReasonAuthenticationNoCredentialsThreshold" /> + <item type="integer" name="config_wifiDisableReasonNoInternetPermanentThreshold" /> + <item type="integer" name="config_wifiDisableReasonByWrongPasswordThreshold" /> + <item type="integer" name="config_wifiDisableReasonAuthenticationNoSubscriptionThreshold" /> + <item type="integer" name="config_wifiDisableReasonConsecutiveFailuresThreshold" /> + + <item type="integer" name="config_wifiDisableReasonAssociationRejectionDurationMs" /> + <item type="integer" name="config_wifiDisableReasonAuthenticationFailureDurationMs" /> + <item type="integer" name="config_wifiDisableReasonDhcpFailureDurationMs" /> + <item type="integer" name="config_wifiDisableReasonNetworkNotFoundDurationMs" /> + <item type="integer" name="config_wifiDisableReasonNoInternetTemporaryDurationMs" /> + <item type="integer" name="config_wifiDisableReasonAuthenticationNoCredentialsDurationMs" /> + <item type="integer" name="config_wifiDisableReasonNoInternetPermanentDurationMs" /> + <item type="integer" name="config_wifiDisableReasonByWrongPasswordDurationMs" /> + <item type="integer" name="config_wifiDisableReasonAuthenticationNoSubscriptionDurationMs" /> + <item type="integer" name="config_wifiDisableReasonConsecutiveFailuresDurationMs" /> + <item type="integer" name="config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold" /> <item type="integer" name="config_wifiBssidBlocklistMonitorNetworkValidationFailureThreshold" /> <item type="integer" name="config_wifiBssidBlocklistMonitorWrongPasswordThreshold" /> @@ -163,6 +183,7 @@ <item type="integer" name="config_wifiBssidBlocklistMonitorFailureStreakCap" /> <item type="integer" name="config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs" /> <item type="integer" name="config_wifiBssidBlocklistMonitorNoResponseThreshold" /> + <item type="integer" name="config_wifiBssidBlocklistMonitorValidationFailureBaseBlockDurationMs" /> <item type="bool" name="config_wifiScanHiddenNetworksScanOnlyMode" /> <item type="integer" name="config_wifiHardwareSoftapMaxClientCount" /> <item type="bool" name="config_wifiIsUnusableEventMetricsEnabled" /> @@ -233,6 +254,7 @@ <item type="string" name="config_wifiCertInstallationHelpLink" /> <item type="string" name="config_wifiApmEnhancementHelpLink" /> <item type="integer" name="config_wifiConfigurationRestoreNetworksBatchNum" /> + <item type="integer" name="config_wifiConfigurationWifiRunnerThresholdInMs" /> <item type="array" name="config_oemPrivilegedWifiAdminPackages" /> <item type="bool" name="config_wifiSoftapOweSupported" /> <item type="bool" name="config_wifiSoftapOweTransitionSupported" /> @@ -257,6 +279,7 @@ <item type="array" name="config_wifiCharsetsForSsidTranslation" /> <item type="string" name="config_wifiBugreportDeepLink" /> <item type="bool" name="config_wifiWaitForDestroyedListeners" /> + <item type="integer" name="config_wifiNetworkSpecifierMaxPreferredChannels" /> <!-- Params from config.xml that can be overlayed --> <!-- Params from strings.xml that can be overlayed --> @@ -381,13 +404,13 @@ <item type="string" name="wifi_tofu_invalid_cert_chain_title" /> <item type="string" name="wifi_tofu_invalid_cert_chain_message" /> <item type="string" name="wifi_tofu_invalid_cert_chain_ok_text" /> - <item type="string" name="wifi_network_disabled_by_admin_title" /> - <item type="string" name="wifi_network_disabled_by_admin_message" /> - <item type="string" name="wifi_network_disabled_by_admin_button" /> <item type="string" name="wifi_enabled_apm_first_time_title" /> <item type="string" name="wifi_enabled_apm_first_time_message" /> <item type="string" name="apm_enabled_first_time_title" /> <item type="string" name="apm_enabled_first_time_message" /> + <item type="string" name="wifi_network_disabled_by_admin_title" /> + <item type="string" name="wifi_network_disabled_by_admin_message" /> + <item type="string" name="wifi_network_disabled_by_admin_button" /> <!-- Params from strings.xml that can be overlayed --> <!-- Params from styles.xml that can be overlayed --> diff --git a/service/ServiceWifiResources/res/values/strings.xml b/service/ServiceWifiResources/res/values/strings.xml index 0c47bae786..4a32500d55 100644 --- a/service/ServiceWifiResources/res/values/strings.xml +++ b/service/ServiceWifiResources/res/values/strings.xml @@ -242,14 +242,14 @@ <string name="wifi_enable_request_dialog_positive_button">Allow</string> <string name="wifi_enable_request_dialog_negative_button">Don\u0027t allow</string> - <!-- Dialog for connecting to a network with only disabled type BSSes. --> - <string name="wifi_network_disabled_by_admin_title">Unavailable Network</string> - <string name="wifi_network_disabled_by_admin_message"><xliff:g id="ssid">%1$s</xliff:g> is disabled by your administrator.</string> - <string name="wifi_network_disabled_by_admin_button">Close</string> - <!-- Notifying the user that the device will remember Wi-Fi state in APM. --> <string name="wifi_enabled_apm_first_time_title">Wi\u2011Fi on in airplane mode</string> <string name="wifi_enabled_apm_first_time_message">If you keep Wi\u2011Fi on, your phone will remember to keep it on the next time you\'re in airplane mode</string> <string name="apm_enabled_first_time_title">Wi\u2011Fi stays on</string> <string name="apm_enabled_first_time_message">Your phone remembers to keep Wi\u2011Fi on in airplane mode. Turn off Wi\u2011Fi if you don\'t want it to stay on.</string> + + <!-- Dialog for connecting to a network with only disabled type BSSes. --> + <string name="wifi_network_disabled_by_admin_title">Unavailable Network</string> + <string name="wifi_network_disabled_by_admin_message"><xliff:g id="ssid">%1$s</xliff:g> is disabled by your administrator.</string> + <string name="wifi_network_disabled_by_admin_button">Close</string> </resources> diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java index ff60ec7a8d..c957dcf9dd 100644 --- a/service/java/com/android/server/wifi/ActiveModeWarden.java +++ b/service/java/com/android/server/wifi/ActiveModeWarden.java @@ -30,6 +30,7 @@ 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.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED; +import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS; import android.annotation.NonNull; import android.annotation.Nullable; @@ -39,12 +40,15 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.location.LocationManager; +import android.net.Network; import android.net.wifi.ISubsystemRestartCallback; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.SoftApCapability; import android.net.wifi.SoftApConfiguration; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiScanner; import android.os.BatteryStatsManager; import android.os.Build; import android.os.Handler; @@ -60,14 +64,15 @@ import android.os.WorkSource; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; +import android.util.LocalLog; import android.util.Log; import android.util.Pair; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IState; import com.android.internal.util.Preconditions; import com.android.internal.util.Protocol; -import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.ActiveModeManager.ClientConnectivityRole; @@ -75,6 +80,7 @@ import com.android.server.wifi.ActiveModeManager.ClientInternetConnectivityRole; import com.android.server.wifi.ActiveModeManager.ClientRole; import com.android.server.wifi.ActiveModeManager.SoftApRole; import com.android.server.wifi.util.ApConfigUtil; +import com.android.server.wifi.util.NativeUtil; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.wifi.resources.R; @@ -149,6 +155,13 @@ public class ActiveModeWarden { @Nullable private WorkSource mLastScanOnlyClientModeManagerRequestorWs = null; private AtomicLong mSupportedFeatureSet = new AtomicLong(0); + private AtomicInteger mBandsSupported = new AtomicInteger(0); + // Mutex lock between service Api binder thread and Wifi main thread + private final Object mServiceApiLock = new Object(); + @GuardedBy("mServiceApiLock") + private Network mCurrentNetwork; + @GuardedBy("mServiceApiLock") + private WifiInfo mCurrentConnectionInfo; /** * One of {@link WifiManager#WIFI_STATE_DISABLED}, @@ -1318,6 +1331,8 @@ public class ActiveModeWarden { } pw.println("STA + AP Concurrency Supported: " + mWifiNative.isStaApConcurrencySupported()); mWifiInjector.getHalDeviceManager().dump(fd, pw, args); + pw.println("Wifi handler thread overruns"); + mWifiInjector.getWifiHandlerLocalLog().dump(fd, pw, args); } @VisibleForTesting @@ -1482,6 +1497,12 @@ public class ActiveModeWarden { getPrimaryClientModeManager().getInterfaceName()), mWifiNative.isStaApConcurrencySupported(), mWifiNative.isStaStaConcurrencySupported()); + if (clientModeManager.getRole() == ROLE_CLIENT_PRIMARY) { + int band = mWifiNative.getSupportedBandsForSta( + clientModeManager.getInterfaceName()); + if (band == WifiScanner.WIFI_BAND_UNSPECIFIED) band = getStaBandsFromConfigStore(); + setBandSupported(band); + } } @Override @@ -1512,6 +1533,7 @@ public class ActiveModeWarden { setSupportedFeatureSet(mWifiNative.getSupportedFeatureSet(null), mWifiNative.isStaApConcurrencySupported(), mWifiNative.isStaStaConcurrencySupported()); + setBandSupported(getStaBandsFromConfigStore()); } // invoke "removed" callbacks after primary changed invokeOnRemovedCallbacks(clientModeManager); @@ -1633,8 +1655,8 @@ public class ActiveModeWarden { static final int CMD_REQUEST_ADDITIONAL_CLIENT_MODE_MANAGER = BASE + 26; static final int CMD_REMOVE_ADDITIONAL_CLIENT_MODE_MANAGER = BASE + 27; - private final EnabledState mEnabledState = new EnabledState(); - private final DisabledState mDisabledState = new DisabledState(); + private final EnabledState mEnabledState; + private final DisabledState mDisabledState; private boolean mIsInEmergencyCall = false; private boolean mIsInEmergencyCallbackMode = false; @@ -1642,8 +1664,11 @@ public class ActiveModeWarden { WifiController() { super(TAG, mLooper); - - DefaultState defaultState = new DefaultState(); + final int threshold = mContext.getResources().getInteger( + R.integer.config_wifiConfigurationWifiRunnerThresholdInMs); + DefaultState defaultState = new DefaultState(threshold); + mEnabledState = new EnabledState(threshold); + mDisabledState = new DisabledState(threshold); addState(defaultState); { addState(mDisabledState, defaultState); addState(mEnabledState, defaultState); @@ -1714,6 +1739,10 @@ public class ActiveModeWarden { return "CMD_UPDATE_AP_CONFIG"; case CMD_WIFI_TOGGLED: return "CMD_WIFI_TOGGLED"; + case RunnerState.STATE_ENTER_CMD: + return "Enter"; + case RunnerState.STATE_EXIT_CMD: + return "Exit"; default: return "what:" + what; } @@ -1762,7 +1791,11 @@ public class ActiveModeWarden { return recoveryDelayMillis; } - abstract class BaseState extends State { + abstract class BaseState extends RunnerState { + BaseState(int threshold, @NonNull LocalLog localLog) { + super(threshold, localLog); + } + @VisibleForTesting boolean isInEmergencyMode() { return mIsInEmergencyCall || mIsInEmergencyCallbackMode; @@ -1887,7 +1920,21 @@ public class ActiveModeWarden { } @Override - public final boolean processMessage(Message msg) { + public void enterImpl() { + } + + @Override + public void exitImpl() { + } + + @Override + String getMessageLogRec(int what) { + return ActiveModeWarden.class.getSimpleName() + "." + + DefaultState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + public final boolean processMessageImpl(Message msg) { // potentially enter emergency mode if (msg.what == CMD_EMERGENCY_CALL_STATE_CHANGED || msg.what == CMD_EMERGENCY_MODE_CHANGED) { @@ -1908,9 +1955,27 @@ public class ActiveModeWarden { protected abstract boolean processMessageFiltered(Message msg); } - class DefaultState extends State { + class DefaultState extends RunnerState { + DefaultState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public boolean processMessage(Message msg) { + String getMessageLogRec(int what) { + return ActiveModeWarden.class.getSimpleName() + "." + + DefaultState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + void enterImpl() { + } + + @Override + void exitImpl() { + } + + @Override + public boolean processMessageImpl(Message msg) { switch (msg.what) { case CMD_SCAN_ALWAYS_MODE_CHANGED: case CMD_EMERGENCY_SCAN_STATE_CHANGED: @@ -2004,19 +2069,23 @@ public class ActiveModeWarden { } class DisabledState extends BaseState { + DisabledState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { log("DisabledState.enter()"); - super.enter(); + super.enterImpl(); if (hasAnyModeManager()) { Log.e(TAG, "Entered DisabledState, but has active mode managers"); } } @Override - public void exit() { + public void exitImpl() { log("DisabledState.exit()"); - super.exit(); + super.exitImpl(); } @Override @@ -2094,10 +2163,14 @@ public class ActiveModeWarden { private boolean mIsDisablingDueToAirplaneMode; + EnabledState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { log("EnabledState.enter()"); - super.enter(); + super.enterImpl(); if (!hasAnyModeManager()) { Log.e(TAG, "Entered EnabledState, but no active mode managers"); } @@ -2105,12 +2178,12 @@ public class ActiveModeWarden { } @Override - public void exit() { + public void exitImpl() { log("EnabledState.exit()"); if (hasAnyModeManager()) { Log.e(TAG, "Exiting EnabledState, but has active mode managers"); } - super.exit(); + super.exitImpl(); } @Nullable @@ -2401,7 +2474,8 @@ public class ActiveModeWarden { ? null : connectedOrConnectingWifiConfiguration.SSID; Log.v(TAG, connectedOrConnectingBssid + " " + connectedOrConnectingSsid); return Objects.equals(ssid, connectedOrConnectingSsid) - && Objects.equals(bssid, connectedOrConnectingBssid); + && (Objects.equals(bssid, connectedOrConnectingBssid) + || clientModeManager.isAffiliatedLinkBssid(NativeUtil.getMacAddressOrNull(bssid))); } /** @@ -2485,4 +2559,80 @@ public class ActiveModeWarden { public long getSupportedFeatureSet() { return mSupportedFeatureSet.get(); } + + /** + * Check if a band is supported as STA + * @param band Wifi band + * @return true if supported + */ + public boolean isBandSupportedForSta(@WifiScanner.WifiBand int band) { + return (mBandsSupported.get() & band) != 0; + } + + private void setBandSupported(@WifiScanner.WifiBand int bands) { + mBandsSupported.set(bands); + saveStaBandsToConfigStoreIfNecessary(bands); + if (mVerboseLoggingEnabled) { + Log.d(TAG, "setBandSupported 0x" + Long.toHexString(mBandsSupported.get())); + } + } + + /** + * Get the current default Wifi network. + * @return the default Wifi network + */ + public Network getCurrentNetwork() { + synchronized (mServiceApiLock) { + return mCurrentNetwork; + } + } + + /** + * Set the current default Wifi network. Called from ClientModeImpl. + * @param network the default Wifi network + */ + protected void setCurrentNetwork(Network network) { + synchronized (mServiceApiLock) { + mCurrentNetwork = network; + } + } + + /** + * Get the current Wifi network connection info. + * @return the default Wifi network connection info + */ + public WifiInfo getConnectionInfo() { + synchronized (mServiceApiLock) { + return mCurrentConnectionInfo; + } + } + + /** + * Update the current connection information. + */ + public void updateCurrentConnectionInfo() { + synchronized (mServiceApiLock) { + mCurrentConnectionInfo = getPrimaryClientModeManager().getConnectionInfo(); + } + } + + /** + * Save the supported bands for STA from WiFi HAL to config store. + * @param bands bands supported + */ + private void saveStaBandsToConfigStoreIfNecessary(int bands) { + if (bands != getStaBandsFromConfigStore()) { + mWifiInjector.getSettingsConfigStore().put(WIFI_NATIVE_SUPPORTED_STA_BANDS, bands); + Log.i(TAG, "Supported STA bands is updated in config store: " + bands); + } + } + + /** + * Get the supported STA bands from cache/config store + * @return bands supported + */ + private int getStaBandsFromConfigStore() { + return mWifiInjector.getSettingsConfigStore().get(WIFI_NATIVE_SUPPORTED_STA_BANDS); + } + } diff --git a/service/java/com/android/server/wifi/ClientMode.java b/service/java/com/android/server/wifi/ClientMode.java index dfef172c61..66dd151a30 100644 --- a/service/java/com/android/server/wifi/ClientMode.java +++ b/service/java/com/android/server/wifi/ClientMode.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.DhcpResultsParcelable; +import android.net.MacAddress; import android.net.Network; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.WifiAnnotations; @@ -91,11 +92,19 @@ public interface ClientMode { */ void onBluetoothConnectionStateChanged(); - WifiInfo syncRequestConnectionInfo(); + /** + * Get current Wifi connection information + * @return Wifi info + */ + WifiInfo getConnectionInfo(); boolean syncQueryPasspointIcon(long bssid, String fileName); - Network syncGetCurrentNetwork(); + /** + * Get the current Wifi network information + * @return network + */ + Network getCurrentNetwork(); DhcpResultsParcelable syncGetDhcpResultsParcelable(); @@ -298,4 +307,11 @@ public interface ClientMode { * update the capabilities */ void updateCapabilities(); + + /** + * Check if BSSID belongs to any of the affiliated link BSSID's. + * @param bssid BSSID of the AP + * @return true if BSSID matches to one of the affiliated link BSSIDs, false otherwise. + */ + boolean isAffiliatedLinkBssid(MacAddress bssid); } diff --git a/service/java/com/android/server/wifi/ClientModeDefaults.java b/service/java/com/android/server/wifi/ClientModeDefaults.java index 33c3b7a0b3..b18fc07439 100644 --- a/service/java/com/android/server/wifi/ClientModeDefaults.java +++ b/service/java/com/android/server/wifi/ClientModeDefaults.java @@ -18,6 +18,7 @@ package com.android.server.wifi; import android.annotation.NonNull; import android.net.DhcpResultsParcelable; +import android.net.MacAddress; import android.net.Network; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.WifiConfiguration; @@ -78,7 +79,7 @@ public interface ClientModeDefaults extends ClientMode { default void onBluetoothConnectionStateChanged() { } - default WifiInfo syncRequestConnectionInfo() { + default WifiInfo getConnectionInfo() { return new WifiInfo(); } @@ -86,7 +87,7 @@ public interface ClientModeDefaults extends ClientMode { return false; } - default Network syncGetCurrentNetwork() { + default Network getCurrentNetwork() { return null; } @@ -227,4 +228,9 @@ public interface ClientModeDefaults extends ClientMode { @Override default void updateCapabilities() { } + + @Override + default boolean isAffiliatedLinkBssid(MacAddress bssid) { + return false; + } } diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 05eb8230a1..8fd71c5fb7 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -25,8 +25,10 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; +import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; 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_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED; @@ -35,6 +37,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AlarmManager; +import android.app.BroadcastOptions; import android.app.admin.SecurityLog; import android.content.BroadcastReceiver; import android.content.Context; @@ -288,7 +291,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { private boolean mCurrentConnectionDetectedCaptivePortal; private String getTag() { - return TAG + "[" + (mInterfaceName == null ? "unknown" : mInterfaceName) + "]"; + return TAG + "[" + mId + ":" + (mInterfaceName == null ? "unknown" : mInterfaceName) + "]"; } private void processRssiThreshold(byte curRssi, int reason, @@ -338,7 +341,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { @NonNull private DhcpResultsParcelable mDhcpResultsParcelable = new DhcpResultsParcelable(); - // NOTE: Do not return to clients - see syncRequestConnectionInfo() + // NOTE: Do not return to clients - see getConnectionInfo() private final ExtendedWifiInfo mWifiInfo; // TODO : remove this member. It should be possible to only call sendNetworkChangeBroadcast when // the state actually changed, and to deduce the state of the agent from the state of the @@ -538,6 +541,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { /* used to indicated RSSI threshold breach in hw */ static final int CMD_RSSI_THRESHOLD_BREACHED = BASE + 164; + /* Used to time out the creation of an IpClient instance. */ + static final int CMD_IPCLIENT_STARTUP_TIMEOUT = BASE + 165; + /** * Used to handle messages bounced between ClientModeImpl and IpClient. */ @@ -573,7 +579,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { /* Start connection to FILS AP*/ static final int CMD_START_FILS_CONNECTION = BASE + 262; - static final int CMD_CONNECTABLE_STATE_SETUP = BASE + 300; + static final int CMD_IPCLIENT_CREATED = BASE + 300; @VisibleForTesting static final int CMD_ACCEPT_EAP_SERVER_CERTIFICATE = BASE + 301; @@ -601,21 +607,23 @@ public class ClientModeImpl extends StateMachine implements ClientMode { int mRunningBeaconCount = 0; /* Parent state where connections are allowed */ - private State mConnectableState = new ConnectableState(); + private State mConnectableState; /* Connecting/Connected to an access point */ - private State mConnectingOrConnectedState = new ConnectingOrConnectedState(); + private State mConnectingOrConnectedState; /* Connecting to an access point */ - private State mL2ConnectingState = new L2ConnectingState(); + private State mL2ConnectingState; /* Connected at 802.11 (L2) level */ - private State mL2ConnectedState = new L2ConnectedState(); + private State mL2ConnectedState; + /* Waiting for IpClient recreation completes */ + private State mWaitBeforeL3ProvisioningState; /* fetching IP after connection to access point (assoc+auth complete) */ - private State mL3ProvisioningState = new L3ProvisioningState(); + private State mL3ProvisioningState; /* Connected with IP addr */ - private State mL3ConnectedState = new L3ConnectedState(); + private State mL3ConnectedState; /* Roaming */ - private State mRoamingState = new RoamingState(); + private State mRoamingState; /* Network is not connected, supplicant assoc+auth is not complete */ - private State mDisconnectedState = new DisconnectedState(); + private State mDisconnectedState; /* * FILS connection related variables. @@ -862,10 +870,23 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mInterfaceName, getHandler()); + final int threshold = mContext.getResources().getInteger( + R.integer.config_wifiConfigurationWifiRunnerThresholdInMs); + mConnectableState = new ConnectableState(threshold); + mConnectingOrConnectedState = new ConnectingOrConnectedState(threshold); + mL2ConnectingState = new L2ConnectingState(threshold); + mL2ConnectedState = new L2ConnectedState(threshold); + mWaitBeforeL3ProvisioningState = new WaitBeforeL3ProvisioningState(threshold); + mL3ProvisioningState = new L3ProvisioningState(threshold); + mL3ConnectedState = new L3ConnectedState(threshold); + mRoamingState = new RoamingState(threshold); + mDisconnectedState = new DisconnectedState(threshold); + addState(mConnectableState); { addState(mConnectingOrConnectedState, mConnectableState); { addState(mL2ConnectingState, mConnectingOrConnectedState); addState(mL2ConnectedState, mConnectingOrConnectedState); { + addState(mWaitBeforeL3ProvisioningState, mL2ConnectedState); addState(mL3ProvisioningState, mL2ConnectedState); addState(mL3ConnectedState, mL2ConnectedState); addState(mRoamingState, mL2ConnectedState); @@ -883,6 +904,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // update with initial role for ConcreteClientModeManager onRoleChanged(); + // Update current connection wifiInfo + updateCurrentConnectionInfo(); } private static final int[] WIFI_MONITOR_EVENTS = { @@ -995,29 +1018,33 @@ public class ClientModeImpl extends StateMachine implements ClientMode { @Override public void onIpClientCreated(IIpClient ipClient) { + if (mIpClientCallbacks != this) return; // IpClient may take a very long time (many minutes) to start at boot time. But after // that IpClient should start pretty quickly (a few seconds). // Blocking wait for 5 seconds first (for when the wait is short) // If IpClient is still not ready after blocking wait, async wait (for when wait is // long). Will drop all connection requests until IpClient is ready. Other requests // will still be processed. - sendMessageAtFrontOfQueue(CMD_CONNECTABLE_STATE_SETUP, + sendMessageAtFrontOfQueue(CMD_IPCLIENT_CREATED, new IpClientManager(ipClient, getName())); mWaitForCreationCv.open(); } @Override public void onPreDhcpAction() { + if (mIpClientCallbacks != this) return; sendMessage(CMD_PRE_DHCP_ACTION); } @Override public void onPostDhcpAction() { + if (mIpClientCallbacks != this) return; sendMessage(CMD_POST_DHCP_ACTION); } @Override public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) { + if (mIpClientCallbacks != this) return; if (dhcpResults != null) { sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults); } else { @@ -1027,6 +1054,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { @Override public void onProvisioningSuccess(LinkProperties newLp) { + if (mIpClientCallbacks != this) return; addPasspointInfoToLinkProperties(newLp); mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL); sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); @@ -1035,54 +1063,64 @@ public class ClientModeImpl extends StateMachine implements ClientMode { @Override public void onProvisioningFailure(LinkProperties newLp) { + if (mIpClientCallbacks != this) return; mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST); sendMessage(CMD_IP_CONFIGURATION_LOST); } @Override public void onLinkPropertiesChange(LinkProperties newLp) { + if (mIpClientCallbacks != this) return; addPasspointInfoToLinkProperties(newLp); sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); } @Override public void onReachabilityLost(String logMsg) { + if (mIpClientCallbacks != this) return; mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_REACHABILITY_LOST); sendMessage(CMD_IP_REACHABILITY_LOST, logMsg); } @Override public void onReachabilityFailure(ReachabilityLossInfoParcelable lossInfo) { + if (mIpClientCallbacks != this) return; sendMessage(CMD_IP_REACHABILITY_FAILURE, lossInfo); } @Override public void installPacketFilter(byte[] filter) { + if (mIpClientCallbacks != this) return; sendMessage(CMD_INSTALL_PACKET_FILTER, filter); } @Override public void startReadPacketFilter() { + if (mIpClientCallbacks != this) return; sendMessage(CMD_READ_PACKET_FILTER); } @Override public void setFallbackMulticastFilter(boolean enabled) { + if (mIpClientCallbacks != this) return; sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled); } @Override public void setNeighborDiscoveryOffload(boolean enabled) { + if (mIpClientCallbacks != this) return; sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0)); } @Override public void onPreconnectionStart(List<Layer2PacketParcelable> packets) { + if (mIpClientCallbacks != this) return; sendMessage(CMD_START_FILS_CONNECTION, 0, 0, packets); } @Override public void onQuit() { + if (mIpClientCallbacks != this) return; mWaitForStopCv.open(); } @@ -1199,6 +1237,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { Log.i(getTag(), "Network marked metered=" + isMetered + " trusted=" + newConfig.trusted + ", triggering capabilities update"); updateCapabilities(newConfig); + updateCurrentConnectionInfo(); } @Override @@ -1533,6 +1572,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate); } mWifiMetrics.incrementWifiLinkLayerUsageStats(mInterfaceName, stats); + updateCurrentConnectionInfo(); return stats; } @@ -1647,7 +1687,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { public boolean isConnecting() { IState state = getCurrentState(); return state == mL2ConnectingState || state == mL2ConnectedState - || state == mL3ProvisioningState; + || state == mWaitBeforeL3ProvisioningState || state == mL3ProvisioningState; } @Override @@ -1691,11 +1731,10 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * thread, will execute synchronously). * * @return a {@link WifiInfo} object containing information about the current connection - * TODO (b/173551144): Change to direct call. Let callers use WifiThreadRunner if necessary. */ @Override - public WifiInfo syncRequestConnectionInfo() { - return mWifiThreadRunner.call(() -> new WifiInfo(mWifiInfo), new WifiInfo()); + public WifiInfo getConnectionInfo() { + return new WifiInfo(mWifiInfo); } /** @@ -1862,30 +1901,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } /** - * Should only be used internally. - * External callers should use {@link #syncGetCurrentNetwork()}. - */ - private Network getCurrentNetwork() { - if (mNetworkAgent != null) { - return mNetworkAgent.getNetwork(); - } else { - return null; - } - } - - /** * Get Network object of currently connected wifi network, or null if not connected. * @return Network object of current wifi network */ - public Network syncGetCurrentNetwork() { - return mWifiThreadRunner.call( - () -> { - if (getCurrentState() == mL3ConnectedState - || getCurrentState() == mRoamingState) { - return getCurrentNetwork(); - } - return null; - }, null); + public Network getCurrentNetwork() { + if (getCurrentState() != mL3ConnectedState + && getCurrentState() != mRoamingState) return null; + return (mNetworkAgent != null) ? mNetworkAgent.getNetwork() : null; } /** @@ -2310,6 +2332,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { return "CMD_IP_REACHABILITY_LOST"; case CMD_IP_REACHABILITY_FAILURE: return "CMD_IP_REACHABILITY_FAILURE"; + case CMD_IPCLIENT_STARTUP_TIMEOUT: + return "CMD_IPCLIENT_STARTUP_TIMEOUT"; case CMD_IPV4_PROVISIONING_FAILURE: return "CMD_IPV4_PROVISIONING_FAILURE"; case CMD_IPV4_PROVISIONING_SUCCESS: @@ -2366,6 +2390,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { return "CMD_UNWANTED_NETWORK"; case CMD_UPDATE_LINKPROPERTIES: return "CMD_UPDATE_LINKPROPERTIES"; + case CMD_IPCLIENT_CREATED: + return "CMD_IPCLIENT_CREATED"; case CMD_ACCEPT_EAP_SERVER_CERTIFICATE: return "CMD_ACCEPT_EAP_SERVER_CERTIFICATE"; case CMD_REJECT_EAP_SERVER_CERTIFICATE: @@ -2420,6 +2446,10 @@ public class ClientModeImpl extends StateMachine implements ClientMode { return "NETWORK_NOT_FOUND_EVENT"; case WifiMonitor.TOFU_ROOT_CA_CERTIFICATE: return "TOFU_ROOT_CA_CERTIFICATE"; + case RunnerState.STATE_ENTER_CMD: + return "Enter"; + case RunnerState.STATE_EXIT_CMD: + return "Exit"; default: return "what:" + what; } @@ -2627,6 +2657,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * Increment various performance metrics */ mWifiMetrics.handlePollResult(mInterfaceName, mWifiInfo); + updateCurrentConnectionInfo(); return stats; } @@ -2668,6 +2699,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.setSuccessfulRxPacketsPerSecond(0); mWifiScoreReport.reset(); mLastLinkLayerStats = null; + updateCurrentConnectionInfo(); } private void updateLinkProperties(LinkProperties newLp) { @@ -2724,10 +2756,18 @@ public class ClientModeImpl extends StateMachine implements ClientMode { Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); + final BroadcastOptions opts; + if (SdkLevel.isAtLeastU()) { + opts = BroadcastOptions.makeBasic(); + opts.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); + } else { + opts = null; + } mBroadcastQueue.queueOrSendBroadcast( mClientModeManager, () -> mContext.sendBroadcastAsUser(intent, UserHandle.ALL, - android.Manifest.permission.ACCESS_WIFI_STATE)); + android.Manifest.permission.ACCESS_WIFI_STATE, + opts == null ? null : opts.toBundle())); } private void sendLinkConfigurationChangedBroadcast() { @@ -2855,6 +2895,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.setApMloLinkId(MloLink.INVALID_MLO_LINK_ID); mWifiInfo.setAffiliatedMloLinks(Collections.emptyList()); } + updateCurrentConnectionInfo(); } private SupplicantState handleSupplicantStateChange(StateChangeResult stateChangeResult) { @@ -2877,6 +2918,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.setInformationElements(findMatchingInfoElements(stateChangeResult.bssid)); } else { // Reset parameters according to WifiInfo.reset() + mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID()); mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); mWifiInfo.setBSSID(null); mWifiInfo.setSSID(null); @@ -2913,9 +2955,34 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } } mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); + updateCurrentConnectionInfo(); return state; } + private void handleNetworkConnectionEventInfo( + WifiConfiguration config, NetworkConnectionEventInfo connectionInfo) { + if (connectionInfo == null) return; + + mWifiInfo.setBSSID(connectionInfo.bssid); + mWifiInfo.setNetworkId(connectionInfo.networkId); + + if (config != null && connectionInfo.keyMgmtMask != null) { + // Besides allowed key management, pmf and wep keys are necessary to + // identify WPA3 Enterprise and WEP, so the original configuration + // is still necessary. + WifiConfiguration tmp = new WifiConfiguration(config); + tmp.setSecurityParams(connectionInfo.keyMgmtMask); + mWifiInfo.setCurrentSecurityType(tmp.getDefaultSecurityParams().getSecurityType()); + // Update the last used security params. + config.getNetworkSelectionStatus().setLastUsedSecurityParams( + tmp.getDefaultSecurityParams()); + mWifiConfigManager.setNetworkLastUsedSecurityParams(config.networkId, + tmp.getDefaultSecurityParams()); + Log.i(getTag(), "Update current security type to " + mWifiInfo.getCurrentSecurityType() + + " from network connection event."); + } + } + private void updateWifiInfoWhenConnected(@NonNull WifiConfiguration config) { mWifiInfo.setEphemeral(config.ephemeral); mWifiInfo.setTrusted(config.trusted); @@ -2932,11 +2999,76 @@ public class ClientModeImpl extends StateMachine implements ClientMode { SecurityParams securityParams = config.getNetworkSelectionStatus() .getLastUsedSecurityParams(); if (securityParams != null) { + Log.i(getTag(), "Update current security type to " + securityParams.getSecurityType()); mWifiInfo.setCurrentSecurityType(securityParams.getSecurityType()); } else { mWifiInfo.clearCurrentSecurityType(); Log.e(TAG, "Network connection candidate with no security parameters"); } + updateCurrentConnectionInfo(); + } + + /** + * Update mapping of affiliated BSSID in blocklist. Called when there is a change in MLO links. + */ + private void updateBlockListAffiliatedBssids() { + /** + * getAffiliatedMloLinks() returns a list of MloLink objects for all the links + * advertised by AP-MLD including the associated link. Update mWifiBlocklistMonitor + * with all affiliated AP link MAC addresses, excluding the associated link, indexed + * with associated AP link MAC address (BSSID). + * For e.g. + * link1_bssid -> affiliated {link2_bssid, link3_bssid} + * Above mapping is used to block list all affiliated links when associated link is + * block listed. + */ + List<String> affiliatedBssids = new ArrayList<>(); + for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) { + if (!Objects.equals(mWifiInfo.getBSSID(), link.getApMacAddress().toString())) { + affiliatedBssids.add(link.getApMacAddress().toString()); + } + } + mWifiBlocklistMonitor.setAffiliatedBssids(mWifiInfo.getBSSID(), affiliatedBssids); + } + + /** + * Clear MLO link states to UNASSOCIATED. + */ + private void clearMloLinkStates() { + for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) { + link.setState(MloLink.MLO_LINK_STATE_UNASSOCIATED); + } + } + + /** + * Update the MLO link states to ACTIVE or IDLE depending on any traffic stream is mapped to the + * link. + * + * @param info MLO link object from HAL. + */ + private void updateMloLinkStates(@Nullable WifiNative.ConnectionMloLinksInfo info) { + if (info == null) return; + for (int i = 0; i < info.links.length; i++) { + mWifiInfo.updateMloLinkState(info.links[i].getLinkId(), + info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE + : MloLink.MLO_LINK_STATE_IDLE); + } + } + /** + * Update the MLO link states to ACTIVE or IDLE depending on any traffic stream is mapped to the + * link. Also, update the link MAC address. + * + * @param info MLO link object from HAL. + */ + private void updateMloLinkAddrAndStates(@Nullable WifiNative.ConnectionMloLinksInfo info) { + if (info == null) return; + for (int i = 0; i < info.links.length; i++) { + mWifiInfo.updateMloLinkStaAddress(info.links[i].getLinkId(), + info.links[i].getMacAddress()); + mWifiInfo.updateMloLinkState(info.links[i].getLinkId(), + info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE + : MloLink.MLO_LINK_STATE_IDLE); + } } private void updateWifiInfoLinkParamsAfterAssociation() { @@ -2951,16 +3083,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(mInterfaceName, maxTxLinkSpeedMbps, maxRxLinkSpeedMbps); if (mLastConnectionCapabilities.wifiStandard == ScanResult.WIFI_STANDARD_11BE) { - WifiNative.ConnectionMloLinksInfo info = - mWifiNative.getConnectionMloLinksInfo(mInterfaceName); - if (info != null) { - for (int i = 0; i < info.links.length; i++) { - mWifiInfo.updateMloLinkStaAddress(info.links[i].linkId, - info.links[i].staMacAddress); - mWifiInfo.updateMloLinkState( - info.links[i].linkId, MloLink.MLO_LINK_STATE_ACTIVE); - } - } + updateMloLinkAddrAndStates(mWifiNative.getConnectionMloLinksInfo(mInterfaceName)); + updateBlockListAffiliatedBssids(); } if (mVerboseLoggingEnabled) { StringBuilder sb = new StringBuilder(); @@ -2969,6 +3093,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { .append(" maxRxSpeed: ").append(maxRxLinkSpeedMbps) .toString()); } + updateCurrentConnectionInfo(); } /** @@ -2978,7 +3103,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (mIpClient != null) { Pair<String, String> p = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo); if (!p.equals(mLastL2KeyAndGroupHint)) { - final MacAddress currentBssid = getMacAddressFromBssidString(mWifiInfo.getBSSID()); + final MacAddress currentBssid = + NativeUtil.getMacAddressOrNull(mWifiInfo.getBSSID()); final Layer2Information l2Information = new Layer2Information( p.first, p.second, currentBssid); // Update current BSSID on IpClient side whenever l2Key and groupHint @@ -3048,6 +3174,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiScoreReport.stopConnectedNetworkScorer(); /* Reset data structures */ mWifiScoreReport.reset(); + mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID()); mWifiInfo.reset(); /* Reset roaming parameters */ mIsAutoRoaming = false; @@ -3076,6 +3203,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (!newConnectionInProgress) { mIsUserSelected = false; } + updateCurrentConnectionInfo(); } void handlePreDhcpSetup() { @@ -3454,6 +3582,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } updateCapabilities(); + updateCurrentConnectionInfo(); } private void handleSuccessfulIpConfiguration() { @@ -3498,6 +3627,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * disconnect thru supplicant, we will let autojoin retry connecting to the network */ mWifiNative.disconnect(mInterfaceName); + updateCurrentConnectionInfo(); } private void handleIpReachabilityLost() { @@ -3507,6 +3637,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // Disconnect via supplicant, and let autojoin retry connecting to the network. mWifiNative.disconnect(mInterfaceName); + updateCurrentConnectionInfo(); } private void handleIpReachabilityFailure(ReachabilityLossInfoParcelable lossInfo) { @@ -3559,10 +3690,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mQosPolicyRequestHandler.setNetworkAgent(mNetworkAgent); } - transitionTo(mL3ProvisioningState); + transitionTo(mWaitBeforeL3ProvisioningState); } else { logd("Invalid failure reason from onIpReachabilityFailure"); } + updateCurrentConnectionInfo(); } private NetworkAgentConfig getNetworkAgentConfigInternal(WifiConfiguration config) { @@ -3694,7 +3826,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { return; } String currentMacString = mWifiNative.getMacAddress(mInterfaceName); - MacAddress currentMac = getMacAddressFromBssidString(currentMacString); + MacAddress currentMac = NativeUtil.getMacAddressOrNull(currentMacString); MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config, isSecondaryInternet() && mClientModeManager.isSecondaryInternetDbsAp()); if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) { @@ -3802,6 +3934,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // Retrieve and store the factory MAC address (on first bootup). retrieveFactoryMacAddressAndStoreIfNecessary(); + updateCurrentConnectionInfo(); } /** @@ -3814,13 +3947,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiDiagnostics.stopLogging(mInterfaceName); mMboOceController.disable(); - if (mIpClient != null && mIpClient.shutdown()) { - // Block to make sure IpClient has really shut down, lest cleanup - // race with, say, bringup code over in tethering. - mIpClientCallbacks.awaitShutdown(); - mIpClientCallbacks = null; - mIpClient = null; - } + maybeShutdownIpclient(); deregisterForWifiMonitorEvents(); // uses mInterfaceName, must call before nulling out // TODO: b/79504296 This broadcast has been deprecated and should be removed sendSupplicantConnectionChangedBroadcast(false); @@ -3830,6 +3957,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * Helper method called when a L3 connection is successfully established to a network. */ void registerConnected() { + if (isPrimary()) { + mWifiInjector.getActiveModeWarden().setCurrentNetwork(getCurrentNetwork()); + } if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { WifiConfiguration config = getConnectedWifiConfigurationInternal(); boolean shouldSetUserConnectChoice = config != null @@ -3849,6 +3979,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } void registerDisconnected() { + // The role of the ClientModeManager may have been changed to scan only before handling + // the network disconnect. + if (isPrimary() || mClientModeManager.getRole() == ROLE_CLIENT_SCAN_ONLY) { + mWifiInjector.getActiveModeWarden().setCurrentNetwork(getCurrentNetwork()); + } if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId); } @@ -3935,17 +4070,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { return scanDetailCache.getScanResult(bssid); } - private MacAddress getMacAddressFromBssidString(@Nullable String bssidStr) { - try { - return (bssidStr != null) ? MacAddress.fromString(bssidStr) : null; - } catch (IllegalArgumentException e) { - Log.e(getTag(), "Invalid BSSID format: " + bssidStr); - return null; - } - } - private MacAddress getCurrentBssidInternalMacAddress() { - return getMacAddressFromBssidString(mLastBssid); + return NativeUtil.getMacAddressOrNull(mLastBssid); } private void connectToNetwork(WifiConfiguration config) { @@ -3968,11 +4094,31 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } } + private void makeIpClient() { + mIpClientCallbacks = new IpClientCallbacksImpl(); + mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks); + mIpClientCallbacks.awaitCreation(); + } + + private void maybeShutdownIpclient() { + if (mIpClient == null) return; + if (!mIpClient.shutdown()) { + logd("Fail to shut down IpClient"); + return; + } + + // Block to make sure IpClient has really shut down, lest cleanup + // race with, say, bringup code over in tethering. + mIpClientCallbacks.awaitShutdown(); + mIpClientCallbacks = null; + mIpClient = null; + } + /******************************************************** * HSM states *******************************************************/ - class ConnectableState extends State { + class ConnectableState extends RunnerState { private boolean mIsScreenStateChangeReceiverRegistered = false; BroadcastReceiver mScreenStateChangeReceiver = new BroadcastReceiver() { @Override @@ -3986,17 +4132,18 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } }; + ConnectableState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { Log.d(getTag(), "entering ConnectableState: ifaceName = " + mInterfaceName); setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); mWifiStateTracker.updateState(mInterfaceName, WifiStateTracker.INVALID); - mIpClientCallbacks = new IpClientCallbacksImpl(); - Log.d(getTag(), "Start makeIpClient ifaceName = " + mInterfaceName); - mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks); - mIpClientCallbacks.awaitCreation(); + makeIpClient(); } private void continueEnterSetup(IpClientManager ipClientManager) { @@ -4026,10 +4173,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_WIFI_ENABLED); mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); + updateCurrentConnectionInfo(); } @Override - public void exit() { + public void exitImpl() { // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISABLED); mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_WIFI_DISABLED); @@ -4047,9 +4195,15 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + ConnectableState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { switch (message.what) { - case CMD_CONNECTABLE_STATE_SETUP: + case CMD_IPCLIENT_CREATED: if (mIpClient != null) { loge("Setup connectable state again when IpClient is ready?"); } else { @@ -4149,6 +4303,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName); mWifiInfo.setMacAddress(currentMacAddress); + updateCurrentConnectionInfo(); Log.i(getTag(), "Connecting with " + currentMacAddress + " as the mac address"); mTargetWifiConfiguration = config; @@ -4555,7 +4710,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (!uids.isEmpty() && !mWifiConnectivityManager.hasMultiInternetConnection()) { // Remove internet capability. - builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + if (!mNetworkFactory.shouldHaveInternetCapabilities()) { + builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + } if (SdkLevel.isAtLeastS()) { builder.setUids(getUidRangeSet(uids)); } else { @@ -4660,6 +4817,22 @@ public class ClientModeImpl extends StateMachine implements ClientMode { updateCapabilities(getConnectedWifiConfigurationInternal()); } + /** + * Check if BSSID belongs to any of the affiliated link BSSID's. + * @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) { + List<MloLink> links = mWifiInfo.getAffiliatedMloLinks(); + for (MloLink link: links) { + if (link.getApMacAddress().equals(bssid)) { + return true; + } + } + return false; + } + + private void updateCapabilities(WifiConfiguration currentWifiConfiguration) { updateCapabilities(getCapabilities(currentWifiConfiguration, getConnectedBssidInternal())); } @@ -4867,15 +5040,19 @@ public class ClientModeImpl extends StateMachine implements ClientMode { sendMessage(CMD_NETWORK_STATUS, status); } - class ConnectingOrConnectedState extends State { + class ConnectingOrConnectedState extends RunnerState { + ConnectingOrConnectedState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { if (mVerboseLoggingEnabled) Log.v(getTag(), "Entering ConnectingOrConnectedState"); mCmiMonitor.onConnectionStart(mClientModeManager); } @Override - public void exit() { + public void exitImpl() { if (mVerboseLoggingEnabled) Log.v(getTag(), "Exiting ConnectingOrConnectedState"); mCmiMonitor.onConnectionEnd(mClientModeManager); @@ -4892,9 +5069,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { Log.e(getTag(), "Failed to set random MAC address on disconnect"); } } + if (mWifiInfo.getBSSID() != null) { + mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID()); + } mWifiInfo.reset(); mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo); + updateCurrentConnectionInfo(); // For secondary client roles, they should stop themselves upon disconnection. // - Primary role shouldn't because it is persistent, and should try connecting to other @@ -4918,7 +5099,14 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + ConnectingOrConnectedState.class.getSimpleName() + "." + getWhatToString( + what); + } + + @Override + public boolean processMessageImpl(Message message) { boolean handleStatus = HANDLED; switch (message.what) { case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: { @@ -5010,8 +5198,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK); break; } - mWifiInfo.setBSSID(mLastBssid); - mWifiInfo.setNetworkId(mLastNetworkId); + handleNetworkConnectionEventInfo(config, connectionInfo); mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); ScanDetailCache scanDetailCache = @@ -5090,6 +5277,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.setNetworkKey(config.getNetworkKeyFromSecurityType( mWifiInfo.getCurrentSecurityType())); updateLayer2Information(); + updateCurrentConnectionInfo(); transitionTo(mL3ProvisioningState); break; } @@ -5250,9 +5438,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } } - class L2ConnectingState extends State { + class L2ConnectingState extends RunnerState { + L2ConnectingState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { if (mVerboseLoggingEnabled) Log.v(getTag(), "Entering L2ConnectingState"); // Make sure we connect: we enter this state prior to connecting to a new // network. In some cases supplicant ignores the connect requests (it might not @@ -5265,7 +5457,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public void exit() { + public void exitImpl() { if (mVerboseLoggingEnabled) Log.v(getTag(), "Exiting L2ConnectingState"); // Cancel any pending CMD_CONNECTING_WATCHDOG_TIMER since this is only valid in // L2ConnectingState anyway. @@ -5273,7 +5465,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + L2ConnectingState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { boolean handleStatus = HANDLED; switch (message.what) { case WifiMonitor.NETWORK_NOT_FOUND_EVENT: @@ -5490,6 +5688,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { config.getNetworkKeyFromSecurityType( mWifiInfo.getCurrentSecurityType())); } + updateCurrentConnectionInfo(); } sendNetworkChangeBroadcast( WifiInfo.getDetailedStateOf(stateChangeResult.state)); @@ -5592,7 +5791,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } } - class L2ConnectedState extends State { + class L2ConnectedState extends RunnerState { + L2ConnectedState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + class RssiEventHandler implements WifiNative.WifiRssiEventHandler { @Override public void onRssiThresholdBreached(byte curRssi) { @@ -5606,7 +5809,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { RssiEventHandler mRssiEventHandler = new RssiEventHandler(); @Override - public void enter() { + public void enterImpl() { mRssiPollToken++; if (mEnableRssiPolling) { if (isPrimary()) { @@ -5651,7 +5854,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public void exit() { + public void exitImpl() { // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectableState // Bug: 15347363 // For paranoia's sake, call handleNetworkDisconnect @@ -5672,7 +5875,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + L2ConnectedState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { boolean handleStatus = HANDLED; switch (message.what) { @@ -5775,11 +5984,12 @@ public class ClientModeImpl extends StateMachine implements ClientMode { case WifiMonitor.NETWORK_CONNECTION_EVENT: { NetworkConnectionEventInfo connectionInfo = (NetworkConnectionEventInfo) message.obj; - mWifiInfo.setBSSID(connectionInfo.bssid); mLastNetworkId = connectionInfo.networkId; - mWifiInfo.setNetworkId(mLastNetworkId); + handleNetworkConnectionEventInfo( + getConnectedWifiConfigurationInternal(), connectionInfo); mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName)); updateLayer2Information(); + updateCurrentConnectionInfo(); if (!Objects.equals(mLastBssid, connectionInfo.bssid)) { mLastBssid = connectionInfo.bssid; sendNetworkChangeBroadcastWithCurrentState(); @@ -5875,6 +6085,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } sendNetworkChangeBroadcastWithCurrentState(); mMultiInternetManager.notifyBssidAssociatedEvent(mClientModeManager); + updateCurrentConnectionInfo(); } break; } @@ -5882,6 +6093,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { case CMD_RSSI_THRESHOLD_BREACHED: { byte currRssi = (byte) message.arg1; processRssiThreshold(currRssi, message.what, mRssiEventHandler); + updateCurrentConnectionInfo(); break; } case CMD_STOP_RSSI_MONITORING_OFFLOAD: { @@ -5962,6 +6174,32 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } break; } + case WifiMonitor.MLO_LINKS_INFO_CHANGED: + WifiMonitor.MloLinkInfoChangeReason reason = + (WifiMonitor.MloLinkInfoChangeReason) message.obj; + WifiNative.ConnectionMloLinksInfo newInfo = + mWifiNative.getConnectionMloLinksInfo(mInterfaceName); + if (reason == WifiMonitor.MloLinkInfoChangeReason.TID_TO_LINK_MAP) { + // Traffic stream mapping changed. Update link states. + updateMloLinkStates(newInfo); + // There is a change in link capabilities. Will trigger android.net + // .ConnectivityManager.NetworkCallback.onCapabilitiesChanged(). + updateCapabilities(); + } else if (reason + == WifiMonitor.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL) { + // Link is removed. Set removed link state to MLO_LINK_STATE_UNASSOCIATED. + // Also update block list mapping, as there is a change in affiliated + // BSSIDs. + clearMloLinkStates(); + updateMloLinkStates(newInfo); + updateBlockListAffiliatedBssids(); + // There is a change in link capabilities. Will trigger android.net + // .ConnectivityManager.NetworkCallback.onCapabilitiesChanged(). + updateCapabilities(); + } else { + logw("MLO_LINKS_INFO_CHANGED with UNKNOWN reason"); + } + break; default: { handleStatus = NOT_HANDLED; break; @@ -6054,9 +6292,82 @@ public class ClientModeImpl extends StateMachine implements ClientMode { return triggerType; } - class L3ProvisioningState extends State { + // Before transition to L3ProvisioningState, always shut down the current IpClient + // instance and recreate a new IpClient and IpClientCallbacks instance, defer received + // messages in this state except CMD_IPCLIENT_CREATED, recreation of a new IpClient + // guarantees the out-of-date callbacks will be ignored, otherwise, it's not easy to + // differentiate callbacks which comes from new IpClient or legacy IpClient. So far + // only transit to this state iff IP reachability gets lost post roam. + class WaitBeforeL3ProvisioningState extends RunnerState { + WaitBeforeL3ProvisioningState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + + @Override + public void enterImpl() { + // Recreate a new IpClient instance. + maybeShutdownIpclient(); + makeIpClient(); + + // Given that {@link IpClientCallbacks#awaitCreation} is invoked when making a + // IpClient instance, which waits for {@link IPCLIENT_STARTUP_TIMEOUT_MS}. + // If await IpClient recreation times out, then send timeout message to proceed + // to Disconnected state, otherwise, we will never exit this state. + sendMessage(CMD_IPCLIENT_STARTUP_TIMEOUT); + } + @Override - public void enter() { + public void exitImpl() { + removeMessages(CMD_IPCLIENT_STARTUP_TIMEOUT); + } + + @Override + public boolean processMessageImpl(Message message) { + switch(message.what) { + case CMD_IPCLIENT_CREATED: { + mIpClient = (IpClientManager) message.obj; + transitionTo(mL3ProvisioningState); + break; + } + + case CMD_IPCLIENT_STARTUP_TIMEOUT: { + Log.e(getTag(), "Fail to create an IpClient instance within " + + IPCLIENT_STARTUP_TIMEOUT_MS + "ms"); + handleNetworkDisconnect(false, + WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__TIMEOUT); + transitionTo(mDisconnectedState); + break; + } + + default: + // Do not process any other messages except CMD_IPCLIENT_CREATED and + // CMD_IPCLIENT_STARTUP_TIMEOUT. This means that this state can be very + // simple because it does not need to worry about messasge ordering. + // Re-creating IpClient should only take a few milliseconds, but in the + // worst case, this will result in the state machine not processing any + // messages for IPCLIENT_STARTUP_TIMEOUT_MS. + deferMessage(message); + } + + logStateAndMessage(message, this); + return HANDLED; + } + + @Override + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + WaitBeforeL3ProvisioningState.class.getSimpleName() + "." + + getWhatToString(what); + } + } + + class L3ProvisioningState extends RunnerState { + L3ProvisioningState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + + @Override + public void enterImpl() { if (mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected)) { return; } @@ -6065,7 +6376,17 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public boolean processMessage(Message message) { + public void exitImpl() { + } + + @Override + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + L3ProvisioningState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { boolean handleStatus = HANDLED; switch(message.what) { @@ -6129,7 +6450,6 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // Get Link layer stats so as we get fresh tx packet counters getWifiLinkLayerStats(); } - } /** @@ -6149,10 +6469,15 @@ public class ClientModeImpl extends StateMachine implements ClientMode { sendNetworkChangeBroadcast(DetailedState.CONNECTED); } - class RoamingState extends State { + class RoamingState extends RunnerState { boolean mAssociated; + + RoamingState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { if (mVerboseLoggingEnabled) { log("RoamingState Enter mScreenOn=" + mScreenOn); } @@ -6164,8 +6489,19 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mRoamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); mAssociated = false; } + + @Override + public void exitImpl() { + } + + @Override + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + RoamingState.class.getSimpleName() + + "." + getWhatToString(what); + } + @Override - public boolean processMessage(Message message) { + public boolean processMessageImpl(Message message) { boolean handleStatus = HANDLED; switch (message.what) { @@ -6239,11 +6575,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode { (NetworkConnectionEventInfo) message.obj; mLastNetworkId = connectionInfo.networkId; mLastBssid = connectionInfo.bssid; - mWifiInfo.setBSSID(mLastBssid); - mWifiInfo.setNetworkId(mLastNetworkId); + handleNetworkConnectionEventInfo( + getConnectedWifiConfigurationInternal(), connectionInfo); updateLayer2Information(); sendNetworkChangeBroadcastWithCurrentState(); - + updateCurrentConnectionInfo(); // Successful framework roam! (probably) mWifiBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, mWifiInfo.getSSID()); @@ -6309,9 +6645,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } } - class L3ConnectedState extends State { + class L3ConnectedState extends RunnerState { + L3ConnectedState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { if (mVerboseLoggingEnabled) { log("Enter ConnectedState mScreenOn=" + mScreenOn); } @@ -6344,9 +6684,17 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // too many places to record L3 failure with too many failure reasons. // So only record success here. mWifiMetrics.noteFirstL3ConnectionAfterBoot(true); + updateCurrentConnectionInfo(); } + @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + L3ConnectedState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { boolean handleStatus = HANDLED; switch (message.what) { @@ -6560,7 +6908,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public void exit() { + public void exitImpl() { logd("ClientModeImpl: Leaving Connected state"); mWifiConnectivityManager.handleConnectionStateChanged( mClientModeManager, @@ -6570,9 +6918,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } } - class DisconnectedState extends State { + class DisconnectedState extends RunnerState { + DisconnectedState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { Log.i(getTag(), "disconnectedstate enter"); // We don't scan frequently if this is a temporary disconnect // due to p2p @@ -6598,7 +6950,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ClientModeImpl.class.getSimpleName() + "." + + DisconnectedState.class.getSimpleName() + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { boolean handleStatus = HANDLED; switch (message.what) { @@ -6632,7 +6990,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } @Override - public void exit() { + public void exitImpl() { mWifiConnectivityManager.handleConnectionStateChanged( mClientModeManager, WifiConnectivityManager.WIFI_STATE_TRANSITIONING); @@ -6807,9 +7165,6 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * a factory MAC address stored in config store, retrieve it now and store it. * * Note: - * <li> This is needed to ensure that we use the same MAC address for connecting to - * networks with MAC randomization disabled regardless of whether the connection is - * occurring on "wlan0" or "wlan1" due to STA + STA. </li> * <li> Retries added to deal with any transient failures when invoking * {@link WifiNative#getStaFactoryMacAddress(String)}. */ @@ -6819,20 +7174,26 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiGlobals.isSaveFactoryMacToConfigStoreEnabled(); if (saveFactoryMacInConfigStore) { // Already present, just return. - String factoryMacAddressStr = mSettingsConfigStore.get(WIFI_STA_FACTORY_MAC_ADDRESS); + String factoryMacAddressStr = mSettingsConfigStore.get(isPrimary() + ? WIFI_STA_FACTORY_MAC_ADDRESS : SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS); if (factoryMacAddressStr != null) return MacAddress.fromString(factoryMacAddressStr); } MacAddress factoryMacAddress = mWifiNative.getStaFactoryMacAddress(mInterfaceName); if (factoryMacAddress == null) { // the device may be running an older HAL (version < 1.3). - Log.w(TAG, "Failed to retrieve factory MAC address"); + Log.w(TAG, (isPrimary() ? "Primary" : "Secondary") + + " failed to retrieve factory MAC address"); return null; } if (saveFactoryMacInConfigStore) { - mSettingsConfigStore.put(WIFI_STA_FACTORY_MAC_ADDRESS, factoryMacAddress.toString()); - Log.i(TAG, "Factory MAC address stored in config store: " + factoryMacAddress); - } - Log.i(TAG, "Factory MAC address retrieved: " + factoryMacAddress); + mSettingsConfigStore.put(isPrimary() + ? WIFI_STA_FACTORY_MAC_ADDRESS : SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS, + factoryMacAddress.toString()); + Log.i(TAG, (isPrimary() ? "Primary" : "Secondary") + + " factory MAC address stored in config store: " + factoryMacAddress); + } + Log.i(TAG, (isPrimary() ? "Primary" : "Secondary") + + " factory MAC address retrieved: " + factoryMacAddress); return factoryMacAddress; } @@ -7217,11 +7578,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode { scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID, scanResult.BSSID, ies); } - + final Network network = (mNetworkAgent != null) ? mNetworkAgent.getNetwork() : null; if (!isUsingStaticIp) { prov = new ProvisioningConfiguration.Builder() .withPreDhcpAction() - .withNetwork(getCurrentNetwork()) + .withNetwork(network) .withDisplayName(config.SSID) .withScanResultInfo(scanResultInfo) .withLayer2Information(layer2Info); @@ -7229,7 +7590,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration(); prov = new ProvisioningConfiguration.Builder() .withStaticConfiguration(staticIpConfig) - .withNetwork(getCurrentNetwork()) + .withNetwork(network) .withDisplayName(config.SSID) .withLayer2Information(layer2Info); } @@ -7596,6 +7957,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { sendNetworkChangeBroadcast(DetailedState.CONNECTING); mWifiInfo.setFrequency(scanResult.frequency); mWifiInfo.setBSSID(associatedBssid); + updateCurrentConnectionInfo(); return true; } @@ -7670,4 +8032,10 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } } } + + private void updateCurrentConnectionInfo() { + if (isPrimary()) { + mWifiInjector.getActiveModeWarden().updateCurrentConnectionInfo(); + } + } } diff --git a/service/java/com/android/server/wifi/ConcreteClientModeManager.java b/service/java/com/android/server/wifi/ConcreteClientModeManager.java index 7f6bbc0b72..5186018dcc 100644 --- a/service/java/com/android/server/wifi/ConcreteClientModeManager.java +++ b/service/java/com/android/server/wifi/ConcreteClientModeManager.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.DhcpResultsParcelable; +import android.net.MacAddress; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; @@ -178,7 +179,8 @@ public class ConcreteClientModeManager implements ClientModeManager { } private String getTag() { - return TAG + "[" + (mClientInterfaceName == null ? "unknown" : mClientInterfaceName) + "]"; + return TAG + "[" + mId + ":" + (mClientInterfaceName == null ? "unknown" + : mClientInterfaceName) + "]"; } /** @@ -714,10 +716,10 @@ public class ConcreteClientModeManager implements ClientModeManager { public static final int CMD_INTERFACE_DESTROYED = 4; public static final int CMD_INTERFACE_DOWN = 5; public static final int CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE = 6; - private final State mIdleState = new IdleState(); - private final State mStartedState = new StartedState(); - private final State mScanOnlyModeState = new ScanOnlyModeState(); - private final State mConnectModeState = new ConnectModeState(); + private final State mIdleState; + private final State mStartedState; + private final State mScanOnlyModeState; + private final State mConnectModeState; // Workaround since we cannot use transitionTo(mScanOnlyModeState, RoleChangeInfo) private RoleChangeInfo mScanRoleChangeInfoToSetOnTransition = null; // Workaround since we cannot use transitionTo(mConnectModeState, RoleChangeInfo) @@ -743,6 +745,8 @@ public class ConcreteClientModeManager implements ClientModeManager { mClientModeImpl.handleIfaceDestroyed(); } + // set it to null since the interface had been destroyed + mClientInterfaceName = null; sendMessage(CMD_INTERFACE_DESTROYED); } } @@ -764,7 +768,12 @@ public class ConcreteClientModeManager implements ClientModeManager { ClientModeStateMachine(Looper looper) { super(TAG, looper); - + final int threshold = mContext.getResources().getInteger( + R.integer.config_wifiConfigurationWifiRunnerThresholdInMs); + mIdleState = new IdleState(threshold); + mStartedState = new StartedState(threshold); + mScanOnlyModeState = new ScanOnlyModeState(threshold); + mConnectModeState = new ConnectModeState(threshold); // CHECKSTYLE:OFF IndentationCheck addState(mIdleState); addState(mStartedState, mIdleState); @@ -834,6 +843,10 @@ public class ConcreteClientModeManager implements ClientModeManager { return "CMD_INTERFACE_DOWN"; case CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE: return "CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE"; + case RunnerState.STATE_ENTER_CMD: + return "Enter"; + case RunnerState.STATE_EXIT_CMD: + return "Exit"; default: return "what:" + what; } @@ -865,11 +878,17 @@ public class ConcreteClientModeManager implements ClientModeManager { private void setRoleInternalAndInvokeCallback(@NonNull RoleChangeInfo roleChangeInfo) { if (roleChangeInfo.role == mRole) return; if (mRole == null) { - Log.v(getTag(), "ClientModeManager started in role: " + roleChangeInfo); + if (mVerboseLoggingEnabled) { + Log.v(getTag(), "CurState:" + getCurrentStateName() + + ", clientModeManager started in role: " + roleChangeInfo); + } setRoleInternal(roleChangeInfo); mModeListener.onStarted(ConcreteClientModeManager.this); } else { - Log.v(getTag(), "ClientModeManager role changed: " + roleChangeInfo); + if (mVerboseLoggingEnabled) { + Log.v(getTag(), "CurState:" + getCurrentStateName() + + ", clientModeManager role changed: " + roleChangeInfo); + } setRoleInternal(roleChangeInfo); reset(); mModeListener.onRoleChanged(ConcreteClientModeManager.this); @@ -879,26 +898,43 @@ public class ConcreteClientModeManager implements ClientModeManager { } } - private class IdleState extends State { + private class IdleState extends RunnerState { + IdleState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { Log.d(getTag(), "entering IdleState"); mClientInterfaceName = null; mIfaceIsUp = false; } @Override - public void exit() { + public void exitImpl() { // Sometimes the wifi handler thread may become blocked that the statemachine // will exit in the IdleState without first entering StartedState. Trigger a // cleanup here in case the above sequence happens. This the statemachine was // started normally this will will not send a duplicate broadcast since mIsStopped // will get set to false the first time the exit happens. cleanupOnQuitIfApplicable(); + Log.d(getTag(), "IdleState.exit()"); } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ConcreteClientModeManager.class.getSimpleName() + "." + + IdleState.class.getSimpleName() + "." + + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { + if (mVerboseLoggingEnabled) { + Log.d(getTag(), + getName() + " cmd = " + getWhatToString(message.what) + " " + + message.toString()); + } switch (message.what) { case CMD_START: // Always start in scan mode first. @@ -923,14 +959,17 @@ public class ConcreteClientModeManager implements ClientModeManager { } break; default: - Log.d(getTag(), "received an invalid message: " + message); + Log.d(getTag(), getName() + ", received an invalid message: " + message); return NOT_HANDLED; } return HANDLED; } } - private class StartedState extends State { + private class StartedState extends RunnerState { + StartedState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } private void onUpChanged(boolean isUp) { if (isUp == mIfaceIsUp) { @@ -939,7 +978,7 @@ public class ConcreteClientModeManager implements ClientModeManager { mIfaceIsUp = isUp; if (!isUp) { // if the interface goes down we should exit and go back to idle state. - Log.d(getTag(), "interface down!"); + Log.d(getTag(), getName() + ", interface down!"); mStateMachine.sendMessage(CMD_INTERFACE_DOWN); } if (mClientModeImpl != null) { @@ -948,7 +987,7 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public void enter() { + public void enterImpl() { Log.d(getTag(), "entering StartedState"); mIfaceIsUp = false; mIsStopped = false; @@ -956,7 +995,19 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ConcreteClientModeManager.class.getSimpleName() + "." + + StartedState.class.getSimpleName() + "." + + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { + if (mVerboseLoggingEnabled) { + Log.d(getTag(), + getName() + " cmd = " + getWhatToString(message.what) + " " + + message.toString()); + } switch (message.what) { case CMD_START: // Already started, ignore this command. @@ -998,8 +1049,9 @@ public class ConcreteClientModeManager implements ClientModeManager { break; } case CMD_INTERFACE_DOWN: - Log.e(getTag(), "Detected an interface down, reporting failure to " - + "SelfRecovery"); + Log.e(getTag(), + getName() + ", detected an interface down, reporting failure to " + + "SelfRecovery"); mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN); // once interface down, nothing else to do... stop the state machine captureObituaryAndQuitNow(); @@ -1009,7 +1061,7 @@ public class ConcreteClientModeManager implements ClientModeManager { onUpChanged(isUp); break; case CMD_INTERFACE_DESTROYED: - Log.e(getTag(), "interface destroyed - client mode stopping"); + Log.e(getTag(), getName() + ", interface destroyed - client mode stopping"); mClientInterfaceName = null; // once interface destroyed, nothing else to do... stop the state machine captureObituaryAndQuitNow(); @@ -1024,22 +1076,26 @@ public class ConcreteClientModeManager implements ClientModeManager { * Clean up state, unregister listeners and update wifi state. */ @Override - public void exit() { + public void exitImpl() { if (mClientInterfaceName != null) { mWifiNative.teardownInterface(mClientInterfaceName); mClientInterfaceName = null; mIfaceIsUp = false; } - Log.i(getTag(), "StartedState#exit(), setting mRole = null"); + Log.i(getTag(), "StartedState.exit(), setting mRole = null"); mIsStopped = true; cleanupOnQuitIfApplicable(); } } - private class ScanOnlyModeState extends State { + private class ScanOnlyModeState extends RunnerState { + ScanOnlyModeState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { Log.d(getTag(), "entering ScanOnlyModeState"); if (mClientInterfaceName != null) { @@ -1066,7 +1122,19 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ConcreteClientModeManager.class.getSimpleName() + "." + + ScanOnlyModeState.class.getSimpleName() + "." + + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { + if (mVerboseLoggingEnabled) { + Log.d(getTag(), + getName() + " cmd = " + getWhatToString(message.what) + " " + + message.toString()); + } switch (message.what) { case CMD_SWITCH_TO_SCAN_ONLY_MODE: // Already in scan only mode, ignore this command. @@ -1078,7 +1146,7 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public void exit() { + public void exitImpl() { mScanOnlyModeImpl = null; mScanRoleChangeInfoToSetOnTransition = null; @@ -1089,9 +1157,13 @@ public class ConcreteClientModeManager implements ClientModeManager { } } - private class ConnectModeState extends State { + private class ConnectModeState extends RunnerState { + ConnectModeState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { Log.d(getTag(), "entering ConnectModeState, starting ClientModeImpl"); if (mClientInterfaceName == null) { Log.e(getTag(), "Supposed to start ClientModeImpl, but iface is null!"); @@ -1122,7 +1194,19 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return ConcreteClientModeManager.class.getSimpleName() + "." + + ConnectModeState.class.getSimpleName() + "." + + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { + if (mVerboseLoggingEnabled) { + Log.d(getTag(), + getName() + " cmd = " + getWhatToString(message.what) + " " + + message.toString()); + } switch (message.what) { case CMD_SWITCH_TO_CONNECT_MODE: RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj; @@ -1136,7 +1220,7 @@ public class ConcreteClientModeManager implements ClientModeManager { // If this call failed, the iface would be torn down. // Thus, simply abort and let the iface down handling take care of the // rest. - Log.e(getTag(), "Failed to switch ClientModeManager=" + Log.e(getTag(), getName() + ", Failed to switch ClientModeManager=" + ConcreteClientModeManager.this + "'s requestorWs"); } break; @@ -1179,14 +1263,14 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public void exit() { + public void exitImpl() { updateConnectModeState(mRole, WifiManager.WIFI_STATE_DISABLED, WifiManager.WIFI_STATE_DISABLING); if (mClientModeImpl == null) { Log.w(getTag(), "ConnectModeState.exit(): mClientModeImpl is already null?!"); } else { - Log.d(getTag(), "Stopping ClientModeImpl"); + Log.d(getTag(), "ConnectModeState.exit(): Stopping ClientModeImpl"); mClientModeImpl.stop(); mGraveyard.inter(mClientModeImpl); mClientModeImpl = null; @@ -1301,8 +1385,8 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public WifiInfo syncRequestConnectionInfo() { - return getClientMode().syncRequestConnectionInfo(); + public WifiInfo getConnectionInfo() { + return getClientMode().getConnectionInfo(); } @Override @@ -1311,8 +1395,8 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public Network syncGetCurrentNetwork() { - return getClientMode().syncGetCurrentNetwork(); + public Network getCurrentNetwork() { + return getClientMode().getCurrentNetwork(); } @Override @@ -1526,4 +1610,9 @@ public class ConcreteClientModeManager implements ClientModeManager { public void updateCapabilities() { getClientMode().updateCapabilities(); } + + @Override + public boolean isAffiliatedLinkBssid(MacAddress bssid) { + return getClientMode().isAffiliatedLinkBssid(bssid); + } } diff --git a/service/java/com/android/server/wifi/HalDeviceManager.java b/service/java/com/android/server/wifi/HalDeviceManager.java index b0fb6883fd..919ecd19c8 100644 --- a/service/java/com/android/server/wifi/HalDeviceManager.java +++ b/service/java/com/android/server/wifi/HalDeviceManager.java @@ -24,33 +24,9 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Resources; -import android.hardware.wifi.V1_0.IWifi; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.IWifiP2pIface; -import android.hardware.wifi.V1_0.IWifiRttController; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_5.WifiBand; -import android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination; -import android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit; -import android.hardware.wifi.V1_6.IfaceConcurrencyType; -import android.hardware.wifi.V1_6.WifiRadioCombination; -import android.hardware.wifi.V1_6.WifiRadioCombinationMatrix; -import android.hardware.wifi.V1_6.WifiRadioConfiguration; -import android.hidl.manager.V1_0.IServiceNotification; -import android.hidl.manager.V1_2.IServiceManager; import android.net.wifi.WifiContext; +import android.net.wifi.WifiScanner; import android.os.Handler; -import android.os.IHwBinder.DeathRecipient; -import android.os.RemoteException; import android.os.WorkSource; import android.text.TextUtils; import android.util.ArrayMap; @@ -63,7 +39,13 @@ import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.HalDeviceManagerUtil.StaticChipInfo; -import com.android.server.wifi.util.GeneralUtil.Mutable; +import com.android.server.wifi.hal.WifiApIface; +import com.android.server.wifi.hal.WifiChip; +import com.android.server.wifi.hal.WifiHal; +import com.android.server.wifi.hal.WifiNanIface; +import com.android.server.wifi.hal.WifiP2pIface; +import com.android.server.wifi.hal.WifiRttController; +import com.android.server.wifi.hal.WifiStaIface; import com.android.server.wifi.util.WorkSourceHelper; import com.android.wifi.resources.R; @@ -83,7 +65,7 @@ import java.util.Map; import java.util.Set; /** - * Handles device management through the HAL (HIDL) interface. + * Handles device management through the HAL interface. */ public class HalDeviceManager { private static final String TAG = "HalDevMgr"; @@ -94,9 +76,9 @@ public class HalDeviceManager { private static final long CHIP_CAPABILITY_UNINITIALIZED = -1L; private static final int DBS_24G_5G_MASK = - (1 << WifiBand.BAND_24GHZ) | (1 << WifiBand.BAND_5GHZ); + WifiScanner.WIFI_BAND_24_GHZ | WifiScanner.WIFI_BAND_5_GHZ; private static final int DBS_5G_6G_MASK = - (1 << WifiBand.BAND_5GHZ) | (1 << WifiBand.BAND_6GHZ); + WifiScanner.WIFI_BAND_5_GHZ | WifiScanner.WIFI_BAND_6_GHZ; private static final int START_HAL_RETRY_INTERVAL_MS = 20; // Number of attempts a start() is re-tried. A value of 0 means no retries after a single @@ -107,20 +89,18 @@ public class HalDeviceManager { private final Clock mClock; private final WifiInjector mWifiInjector; private final Handler mEventHandler; + private WifiHal mWifiHal; private WifiDeathRecipient mIWifiDeathRecipient; - private ServiceManagerDeathRecipient mServiceManagerDeathRecipient; - private boolean mIsBridgedSoftApSupported; - private boolean mIsStaWithBridgedSoftApConcurrencySupported; private boolean mWifiUserApprovalRequiredForD2dInterfacePriority; private boolean mIsConcurrencyComboLoadedFromDriver; private boolean mWaitForDestroyedListeners; - private ArrayMap<IWifiIface, SoftApManager> mSoftApManagers = new ArrayMap<>(); - - // cache the value for supporting vendor HAL or not - private boolean mIsVendorHalSupported = false; + private ArrayMap<WifiHal.WifiInterface, SoftApManager> mSoftApManagers = new ArrayMap<>(); /** * Public API for querying interfaces from the HalDeviceManager. + * + * TODO (b/256648410): Consider replacing these values with WifiChip.IFACE_TYPE_ + * to avoid duplication. */ public static final int HDM_CREATE_IFACE_STA = 0; public static final int HDM_CREATE_IFACE_AP = 1; @@ -138,34 +118,19 @@ public class HalDeviceManager { public @interface HdmIfaceTypeForCreation {}; public static final SparseIntArray HAL_IFACE_MAP = new SparseIntArray() {{ - put(HDM_CREATE_IFACE_STA, IfaceType.STA); - put(HDM_CREATE_IFACE_AP, IfaceType.AP); - put(HDM_CREATE_IFACE_AP_BRIDGE, IfaceType.AP); - put(HDM_CREATE_IFACE_P2P, IfaceType.P2P); - put(HDM_CREATE_IFACE_NAN, IfaceType.NAN); - }}; - - public static final SparseIntArray REVERSE_HAL_IFACE_MAP = new SparseIntArray() {{ - put(IfaceType.STA, HDM_CREATE_IFACE_STA); - put(IfaceType.AP, HDM_CREATE_IFACE_AP); - put(IfaceType.P2P, HDM_CREATE_IFACE_P2P); - put(IfaceType.NAN, HDM_CREATE_IFACE_NAN); + put(HDM_CREATE_IFACE_STA, WifiChip.IFACE_TYPE_STA); + put(HDM_CREATE_IFACE_AP, WifiChip.IFACE_TYPE_AP); + put(HDM_CREATE_IFACE_AP_BRIDGE, WifiChip.IFACE_TYPE_AP); + put(HDM_CREATE_IFACE_P2P, WifiChip.IFACE_TYPE_P2P); + put(HDM_CREATE_IFACE_NAN, WifiChip.IFACE_TYPE_NAN); }}; public static final SparseIntArray CONCURRENCY_TYPE_TO_CREATE_TYPE_MAP = new SparseIntArray() {{ - put(android.hardware.wifi.V1_6.IfaceConcurrencyType.STA, HDM_CREATE_IFACE_STA); - put(android.hardware.wifi.V1_6.IfaceConcurrencyType.AP, HDM_CREATE_IFACE_AP); - put(android.hardware.wifi.V1_6.IfaceConcurrencyType.AP_BRIDGED, - HDM_CREATE_IFACE_AP_BRIDGE); - put(android.hardware.wifi.V1_6.IfaceConcurrencyType.P2P, HDM_CREATE_IFACE_P2P); - put(android.hardware.wifi.V1_6.IfaceConcurrencyType.NAN, HDM_CREATE_IFACE_NAN); - }}; - - public static final SparseIntArray IFACE_TYPE_TO_CONCURRENCY_TYPE_MAP = new SparseIntArray() {{ - put(IfaceType.STA, android.hardware.wifi.V1_6.IfaceConcurrencyType.STA); - put(IfaceType.AP, android.hardware.wifi.V1_6.IfaceConcurrencyType.AP); - put(IfaceType.P2P, android.hardware.wifi.V1_6.IfaceConcurrencyType.P2P); - put(IfaceType.NAN, android.hardware.wifi.V1_6.IfaceConcurrencyType.NAN); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, HDM_CREATE_IFACE_STA); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, HDM_CREATE_IFACE_AP); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED, HDM_CREATE_IFACE_AP_BRIDGE); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, HDM_CREATE_IFACE_P2P); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, HDM_CREATE_IFACE_NAN); }}; @@ -173,9 +138,6 @@ public class HalDeviceManager { public HalDeviceManager(WifiContext context, Clock clock, WifiInjector wifiInjector, Handler handler) { Resources res = context.getResources(); - mIsBridgedSoftApSupported = res.getBoolean(R.bool.config_wifiBridgedSoftApSupported); - mIsStaWithBridgedSoftApConcurrencySupported = - res.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported); mWifiUserApprovalRequiredForD2dInterfacePriority = res.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority); mWaitForDestroyedListeners = res.getBoolean(R.bool.config_wifiWaitForDestroyedListeners); @@ -183,7 +145,12 @@ public class HalDeviceManager { mWifiInjector = wifiInjector; mEventHandler = handler; mIWifiDeathRecipient = new WifiDeathRecipient(); - mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient(); + mWifiHal = getWifiHalMockable(context, wifiInjector); + } + + @VisibleForTesting + protected WifiHal getWifiHalMockable(WifiContext context, WifiInjector wifiInjector) { + return new WifiHal(context, wifiInjector.getSsidTranslator()); } /** @@ -206,6 +173,7 @@ public class HalDeviceManager { */ public void initialize() { initializeInternal(); + registerWifiHalEventCallback(); } /** @@ -234,7 +202,7 @@ public class HalDeviceManager { * Returns whether the vendor HAL is supported on this device or not. */ public boolean isSupported() { - return mIsVendorHalSupported; + return mWifiHal.isSupported(); } /** @@ -243,24 +211,20 @@ public class HalDeviceManager { * the registerStatusListener() to listener for status changes. */ public boolean isReady() { - return mIsReady; + return mWifiHal.isInitializationComplete(); } /** * Returns the current status of Wi-Fi: started (true) or stopped (false). - * - * Note: direct call to HIDL. */ public boolean isStarted() { return isWifiStarted(); } /** - * Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or + * Attempts to start Wi-Fi. Returns the success (true) or failure (false) or * the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on * success. - * - * Note: direct call to HIDL. */ public boolean start() { return startWifi(); @@ -268,14 +232,10 @@ public class HalDeviceManager { /** * Stops Wi-Fi. Will also dispatch any registeredManagerStatusCallback.onStop(). - * - * Note: direct call to HIDL - failure is not-expected. */ public void stop() { - synchronized (mLock) { // prevents race condition - stopWifi(); - mWifi = null; - } + stopWifi(); + mWifiHal.invalidate(); } /** @@ -303,7 +263,7 @@ public class HalDeviceManager { * * @return A set of IfaceTypes constants (possibly empty, e.g. on error). */ - public Set<Integer> getSupportedIfaceTypes(IWifiChip chip) { + public Set<Integer> getSupportedIfaceTypes(WifiChip chip) { return getSupportedIfaceTypesInternal(chip); } @@ -326,11 +286,11 @@ public class HalDeviceManager { * interface using rules based on the requestor app's context. * @return A newly created interface - or null if the interface could not be created. */ - public IWifiStaIface createStaIface( + public WifiStaIface createStaIface( long requiredChipCapabilities, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs) { - return (IWifiStaIface) createIface(HDM_CREATE_IFACE_STA, requiredChipCapabilities, + return (WifiStaIface) createIface(HDM_CREATE_IFACE_STA, requiredChipCapabilities, destroyedListener, handler, requestorWs); } @@ -349,17 +309,16 @@ public class HalDeviceManager { * interface using rules based on the requestor app's context. * @return A newly created interface - or null if the interface could not be created. */ - public IWifiStaIface createStaIface( + public WifiStaIface createStaIface( @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs) { - return (IWifiStaIface) createStaIface(CHIP_CAPABILITY_ANY, - destroyedListener, handler, requestorWs); + return createStaIface(CHIP_CAPABILITY_ANY, destroyedListener, handler, requestorWs); } /** * Create AP interface if possible (see createStaIface doc). */ - public IWifiApIface createApIface( + public WifiApIface createApIface( long requiredChipCapabilities, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs, boolean isBridged, @@ -368,7 +327,7 @@ public class HalDeviceManager { Log.e(TAG, "Cannot create AP Iface with null SoftApManager"); return null; } - IWifiApIface apIface = (IWifiApIface) createIface(isBridged ? HDM_CREATE_IFACE_AP_BRIDGE + WifiApIface apIface = (WifiApIface) createIface(isBridged ? HDM_CREATE_IFACE_AP_BRIDGE : HDM_CREATE_IFACE_AP, requiredChipCapabilities, destroyedListener, handler, requestorWs); if (apIface != null) { @@ -380,29 +339,38 @@ public class HalDeviceManager { /** * Create P2P interface if possible (see createStaIface doc). */ - public IWifiP2pIface createP2pIface( + public String createP2pIface( long requiredChipCapabilities, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs) { - return (IWifiP2pIface) createIface(HDM_CREATE_IFACE_P2P, requiredChipCapabilities, - destroyedListener, handler, requestorWs); + WifiP2pIface iface = (WifiP2pIface) createIface(HDM_CREATE_IFACE_P2P, + requiredChipCapabilities, destroyedListener, handler, requestorWs); + if (iface == null) { + return null; + } + String ifaceName = getName(iface); + if (TextUtils.isEmpty(ifaceName)) { + removeIface(iface); + return null; + } + mWifiP2pIfaces.put(ifaceName, iface); + return ifaceName; } /** * Create P2P interface if possible (see createStaIface doc). */ - public IWifiP2pIface createP2pIface(@Nullable InterfaceDestroyedListener destroyedListener, + public String createP2pIface(@Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs) { - return (IWifiP2pIface) createP2pIface(CHIP_CAPABILITY_ANY, - destroyedListener, handler, requestorWs); + return createP2pIface(CHIP_CAPABILITY_ANY, destroyedListener, handler, requestorWs); } /** * Create NAN interface if possible (see createStaIface doc). */ - public IWifiNanIface createNanIface(@Nullable InterfaceDestroyedListener destroyedListener, + public WifiNanIface createNanIface(@Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs) { - return (IWifiNanIface) createIface(HDM_CREATE_IFACE_NAN, CHIP_CAPABILITY_ANY, + return (WifiNanIface) createIface(HDM_CREATE_IFACE_NAN, CHIP_CAPABILITY_ANY, destroyedListener, handler, requestorWs); } @@ -410,12 +378,26 @@ public class HalDeviceManager { * Removes (releases/destroys) the given interface. Will trigger any registered * InterfaceDestroyedListeners. */ - public boolean removeIface(IWifiIface iface) { + public boolean removeIface(WifiHal.WifiInterface iface) { boolean success = removeIfaceInternal(iface, /* validateRttController */true); return success; } - private InterfaceCacheEntry getInterfaceCacheEntry(IWifiIface iface) { + /** + * Wrapper around {@link #removeIface(WifiHal.WifiInterface)} for P2P ifaces. + */ + public boolean removeP2pIface(String ifaceName) { + WifiP2pIface iface = mWifiP2pIfaces.get(ifaceName); + if (iface == null) return false; + if (!removeIface(iface)) { + Log.e(TAG, "Unable to remove p2p iface " + ifaceName); + return false; + } + mWifiP2pIfaces.remove(ifaceName); + return true; + } + + private InterfaceCacheEntry getInterfaceCacheEntry(WifiHal.WifiInterface iface) { String name = getName(iface); int type = getType(iface); if (VDBG) Log.d(TAG, "getInterfaceCacheEntry: iface(name)=" + name); @@ -432,26 +414,26 @@ public class HalDeviceManager { } /** - * Returns the IWifiChip corresponding to the specified interface (or null on error). + * Returns the WifiChip corresponding to the specified interface (or null on error). * * Note: clients must not perform chip mode changes or interface management (create/delete) - * operations on IWifiChip directly. However, they can use the IWifiChip interface to perform + * operations on WifiChip directly. However, they can use the WifiChip interface to perform * other functions - e.g. calling the debug/trace methods. */ - public IWifiChip getChip(IWifiIface iface) { + public WifiChip getChip(WifiHal.WifiInterface iface) { synchronized (mLock) { InterfaceCacheEntry cacheEntry = getInterfaceCacheEntry(iface); return (cacheEntry == null) ? null : cacheEntry.chip; } } - private WifiChipInfo getChipInfo(IWifiIface iface) { + private WifiChipInfo getChipInfo(WifiHal.WifiInterface iface) { synchronized (mLock) { InterfaceCacheEntry cacheEntry = getInterfaceCacheEntry(iface); - if (null == cacheEntry) return null; + if (cacheEntry == null) return null; WifiChipInfo[] chipInfos = getAllChipInfoCached(); - if (null == chipInfos) return null; + if (chipInfos == null) return null; for (WifiChipInfo info: chipInfos) { if (info.chipId == cacheEntry.chipId) { @@ -462,14 +444,14 @@ public class HalDeviceManager { } } - private boolean isDbsSupported(IWifiIface iface, int dbsMask) { + private boolean isDbsSupported(WifiHal.WifiInterface iface, int dbsMask) { synchronized (mLock) { WifiChipInfo info = getChipInfo(iface); - if (null == info) return false; + if (info == null) return false; // If there is no radio combination information, cache it. - if (null == info.radioCombinationMatrix) { - IWifiChip chip = getChip(iface); - if (null == chip) return false; + if (info.radioCombinationMatrix == null) { + WifiChip chip = getChip(iface); + if (chip == null) return false; info.radioCombinationMatrix = getChipSupportedRadioCombinationsMatrix(chip); info.radioCombinationLookupTable = convertRadioCombinationMatrixToLookupTable( @@ -484,39 +466,57 @@ public class HalDeviceManager { } /** - * Indicate whether or not 2.4GHz/5GHz DBS is supported. + * Indicate whether 2.4GHz/5GHz DBS is supported. * * @param iface The interface on the chip. * @return true if supported; false, otherwise; */ - public boolean is24g5gDbsSupported(IWifiIface iface) { + public boolean is24g5gDbsSupported(WifiHal.WifiInterface iface) { return isDbsSupported(iface, DBS_24G_5G_MASK); } /** - * Indicate whether or not 5GHz/6GHz DBS is supported. + * Wrapper around {@link #is24g5gDbsSupported(WifiHal.WifiInterface)} for P2P ifaces. + */ + public boolean is24g5gDbsSupportedOnP2pIface(String ifaceName) { + WifiP2pIface iface = mWifiP2pIfaces.get(ifaceName); + if (iface == null) return false; + return is24g5gDbsSupported(iface); + } + + /** + * Indicate whether 5GHz/6GHz DBS is supported. * * @param iface The interface on the chip. * @return true if supported; false, otherwise; */ - public boolean is5g6gDbsSupported(IWifiIface iface) { + public boolean is5g6gDbsSupported(WifiHal.WifiInterface iface) { return isDbsSupported(iface, DBS_5G_6G_MASK); } /** + * Wrapper around {@link #is5g6gDbsSupported(WifiHal.WifiInterface)} for P2P ifaces. + */ + public boolean is5g6gDbsSupportedOnP2pIface(String ifaceName) { + WifiP2pIface iface = mWifiP2pIfaces.get(ifaceName); + if (iface == null) return false; + return is5g6gDbsSupported(iface); + } + + /** * Replace the requestorWs info for the associated info. * * When a new iface is requested via - * {@link #createIface(int, InterfaceDestroyedListener, Handler, WorkSource)}, the clients + * {@link #createIface(int, long, InterfaceDestroyedListener, Handler, WorkSource)}, the clients * pass in a worksource which includes all the apps that triggered the iface creation. However, * this list of apps can change during the lifetime of the iface (as new apps request the same * iface or existing apps release their request for the iface). This API can be invoked multiple * times to replace the entire requestor info for the provided iface. * - * Note: This is is wholesale replace of the requestor info. The corresponding client is + * Note: This is a wholesale replacement of the requestor info. The corresponding client is * responsible for individual add/remove of apps in the WorkSource passed in. */ - public boolean replaceRequestorWs(@NonNull IWifiIface iface, + public boolean replaceRequestorWs(@NonNull WifiHal.WifiInterface iface, @NonNull WorkSource newRequestorWs) { String name = getName(iface); int type = getType(iface); @@ -537,6 +537,24 @@ public class HalDeviceManager { } /** + * Wrapper around {@link #replaceRequestorWs(WifiHal.WifiInterface, WorkSource)} for P2P ifaces. + */ + public boolean replaceRequestorWsForP2pIface(String ifaceName, + @NonNull WorkSource newRequestorWs) { + WifiP2pIface iface = mWifiP2pIfaces.get(ifaceName); + if (iface == null) return false; + return replaceRequestorWs(iface, newRequestorWs); + } + + /** + * Wrapper around {@link #replaceRequestorWs(WifiHal.WifiInterface, WorkSource)} for NAN ifaces. + */ + public boolean replaceRequestorWsForNanIface(@NonNull WifiNanIface iface, + @NonNull WorkSource newRequestorWs) { + return replaceRequestorWs(iface, newRequestorWs); + } + + /** * Register a SubsystemRestartListener to listen to the subsystem restart event from HAL. * Use the action() to forward the event to SelfRecovery when receiving the event from HAL. * @@ -564,6 +582,10 @@ public class HalDeviceManager { * an existing RTT controller is destroyed (the previous copies must be discarded by the * recipient). * + * Each listener should maintain a single callback object to register here. The callback can + * be registered upon the listener's initialization, and re-registered on HDM status changes, if + * {@link #isStarted} is true. + * * @param callback InterfaceRttControllerLifecycleCallback object. * @param handler Handler on which to dispatch callback */ @@ -590,11 +612,11 @@ public class HalDeviceManager { return; } - if (mIWifiRttController == null) { - mIWifiRttController = createRttControllerIfPossible(); + if (mWifiRttController == null) { + mWifiRttController = createRttControllerIfPossible(); } - if (mIWifiRttController != null) { - proxy.onNewRttController(mIWifiRttController); + if (mWifiRttController != null) { + proxy.onNewRttController(mWifiRttController); } } } @@ -602,25 +624,11 @@ public class HalDeviceManager { /** * Return the name of the input interface or null on error. */ - public static String getName(IWifiIface iface) { + public String getName(WifiHal.WifiInterface iface) { if (iface == null) { return "<null>"; } - - Mutable<String> nameResp = new Mutable<>(); - try { - iface.getName((WifiStatus status, String name) -> { - if (status.code == WifiStatusCode.SUCCESS) { - nameResp.value = name; - } else { - Log.e(TAG, "Error on getName: " + statusString(status)); - } - }); - } catch (RemoteException e) { - Log.e(TAG, "Exception on getName: " + e); - } - - return nameResp.value; + return iface.getName(); } /** @@ -669,12 +677,12 @@ public class HalDeviceManager { * * @param controller The RTT controller object. */ - void onNewRttController(@NonNull IWifiRttController controller); + void onNewRttController(@NonNull WifiRttController controller); /** * Called when the previously provided RTT controller is destroyed. Clients must discard * their copy. A new copy may be provided later by - * {@link #onNewRttController(IWifiRttController)}. + * {@link #onNewRttController(WifiRttController)}. */ void onRttControllerDestroyed(); } @@ -683,7 +691,7 @@ public class HalDeviceManager { * Returns whether the provided @HdmIfaceTypeForCreation combo can be supported by the device. * Note: This only returns an answer based on the create type combination exposed by the HAL. * The actual iface creation/deletion rules depend on the iface priorities set in - * {@link #allowedToDeleteIfaceTypeForRequestedType(int, WorkSource, int, WifiIfaceInfo[][])} + * {@link #allowedToDelete(int, int, int, int)} * * @param createTypeCombo SparseArray keyed in by @HdmIfaceTypeForCreation to number of ifaces * needed. @@ -732,7 +740,7 @@ public class HalDeviceManager { * * @param createIfaceType Type of iface requested. * @param requiredChipCapabilities The bitmask of Capabilities which are required. - * See IWifiChip.hal for documentation. + * See the HAL for documentation. * @param requestorWs Requestor worksource. This will be used to determine priority of this * interface using rules based on the requestor app's context. * @return true if the device supports the provided combo, false otherwise. @@ -768,7 +776,7 @@ public class HalDeviceManager { * * Return types imply: * - null: interface cannot be created - * - empty list: interface can be crated w/o destroying any other interafces + * - empty list: interface can be crated w/o destroying any other interfaces * - otherwise: a list of interfaces to be destroyed * * @param createIfaceType Type of iface requested. @@ -776,7 +784,7 @@ public class HalDeviceManager { * there's already an interface of the specified type then no need * for further operation. * @param requiredChipCapabilities The bitmask of Capabilities which are required. - * See IWifiChip.hal for documentation. + * See the HAL for documentation. * @param requestorWs Requestor worksource. This will be used to determine priority of this * interface using rules based on the requestor app's context. * @return the list of interfaces that would have to be destroyed and their worksource. The @@ -793,8 +801,8 @@ public class HalDeviceManager { IfaceCreationData creationData; synchronized (mLock) { - if (mWifi == null) { - Log.e(TAG, "reportImpactToCreateIface: null IWifi -- ifaceType=" + createIfaceType); + if (!mWifiHal.isInitializationComplete()) { + Log.e(TAG, "reportImpactToCreateIface: Wifi Hal is not available"); return null; } WifiChipInfo[] chipInfos = getAllChipInfo(); @@ -883,27 +891,24 @@ public class HalDeviceManager { * - Order of dispatch of available for request listeners */ private static final int[] IFACE_TYPES_BY_PRIORITY = - {IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN}; + {WifiChip.IFACE_TYPE_AP, WifiChip.IFACE_TYPE_STA, WifiChip.IFACE_TYPE_P2P, + WifiChip.IFACE_TYPE_NAN}; private static final int[] CREATE_TYPES_BY_PRIORITY = {HDM_CREATE_IFACE_AP, HDM_CREATE_IFACE_AP_BRIDGE, HDM_CREATE_IFACE_STA, HDM_CREATE_IFACE_P2P, HDM_CREATE_IFACE_NAN}; private final Object mLock = new Object(); - private IServiceManager mServiceManager; - private IWifi mWifi; - private IWifiRttController mIWifiRttController; - private final WifiEventCallback mWifiEventCallback = new WifiEventCallback(); - private final WifiEventCallbackV15 mWifiEventCallbackV15 = new WifiEventCallbackV15(); + private WifiRttController mWifiRttController; + private HashMap<String, WifiP2pIface> mWifiP2pIfaces = new HashMap<>(); + private final WifiHal.Callback mWifiEventCallback = new WifiEventCallback(); private final Set<ManagerStatusListenerProxy> mManagerStatusListeners = new HashSet<>(); private final Set<InterfaceRttControllerLifecycleCallbackProxy> mRttControllerLifecycleCallbacks = new HashSet<>(); - private final SparseArray<IWifiChipEventCallback.Stub> mDebugCallbacks = new SparseArray<>(); - private boolean mIsReady; private final Set<SubsystemRestartListenerProxy> mSubsystemRestartListener = new HashSet<>(); /* - * This is the only place where we cache HIDL information in this manager. Necessary since + * This is the only place where we cache HAL information in this manager. Necessary since * we need to keep a list of registered destroyed listeners. Will be validated regularly * in getAllChipInfoAndValidateCache(). */ @@ -911,7 +916,7 @@ public class HalDeviceManager { new HashMap<>(); private class InterfaceCacheEntry { - public IWifiChip chip; + public WifiChip chip; public int chipId; public String name; public int type; @@ -932,7 +937,7 @@ public class HalDeviceManager { private class WifiIfaceInfo { public String name; - public IWifiIface iface; + public WifiHal.WifiInterface iface; public @HdmIfaceTypeForCreation int createType; public WorkSourceHelper requestorWsHelper; @@ -944,16 +949,16 @@ public class HalDeviceManager { } private class WifiChipInfo { - public IWifiChip chip; + public WifiChip chip; public int chipId = -1; - public ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> availableModes; + public ArrayList<WifiChip.ChipMode> availableModes; public boolean currentModeIdValid = false; public int currentModeId = -1; // Arrays of WifiIfaceInfo indexed by @HdmIfaceTypeForCreation, in order of creation as - // returned by IWifiChip.getXxxIfaceNames. + // returned by WifiChip.getXxxIfaceNames. public WifiIfaceInfo[][] ifaces = new WifiIfaceInfo[CREATE_TYPES_BY_PRIORITY.length][]; public long chipCapabilities; - public WifiRadioCombinationMatrix radioCombinationMatrix = null; + public WifiChip.WifiRadioCombinationMatrix radioCombinationMatrix = null; public SparseBooleanArray radioCombinationLookupTable = new SparseBooleanArray(); @Override @@ -971,56 +976,6 @@ public class HalDeviceManager { } } - /** - * Wrapper function to access the HIDL services. Created to be mockable in unit-tests. - */ - protected IWifi getWifiServiceMockable() { - try { - return IWifi.getService(true /* retry */); - } catch (RemoteException e) { - Log.e(TAG, "Exception getting IWifi service: " + e); - return null; - } - } - - protected android.hardware.wifi.V1_5.IWifi getWifiServiceForV1_5Mockable(IWifi iWifi) { - if (null == iWifi) return null; - return android.hardware.wifi.V1_5.IWifi.castFrom(iWifi); - } - - protected IServiceManager getServiceManagerMockable() { - try { - return IServiceManager.getService(); - } catch (RemoteException e) { - Log.e(TAG, "Exception getting IServiceManager: " + e); - return null; - } - } - - protected android.hardware.wifi.V1_5.IWifiChip getWifiChipForV1_5Mockable(IWifiChip chip) { - if (null == chip) return null; - return android.hardware.wifi.V1_5.IWifiChip.castFrom(chip); - } - - protected android.hardware.wifi.V1_6.IWifiChip getWifiChipForV1_6Mockable(IWifiChip chip) { - if (null == chip) return null; - return android.hardware.wifi.V1_6.IWifiChip.castFrom(chip); - } - - protected android.hardware.wifi.V1_5.IWifiApIface getIWifiApIfaceForV1_5Mockable( - IWifiApIface iface) { - if (null == iface) return null; - return android.hardware.wifi.V1_5.IWifiApIface.castFrom(iface); - } - - protected boolean isBridgedSoftApSupportedMockable() { - return mIsBridgedSoftApSupported; - } - - protected boolean isStaWithBridgedSoftApConcurrencySupportedMockable() { - return mIsStaWithBridgedSoftApConcurrencySupported; - } - protected boolean isWaitForDestroyedListenersMockable() { return mWaitForDestroyedListeners; } @@ -1028,122 +983,25 @@ public class HalDeviceManager { // internal implementation private void initializeInternal() { - initIServiceManagerIfNecessary(); - if (mIsVendorHalSupported) { - initIWifiIfNecessary(); - } + mWifiHal.initialize(mIWifiDeathRecipient); } private void teardownInternal() { managerStatusListenerDispatch(); dispatchAllDestroyedListeners(); - mIWifiRttController = null; + mWifiRttController = null; dispatchRttControllerLifecycleOnDestroyed(); mRttControllerLifecycleCallbacks.clear(); + mWifiP2pIfaces.clear(); } - private class ServiceManagerDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - Log.wtf(TAG, "IServiceManager died: cookie=" + cookie); - synchronized (mLock) { - mServiceManager = null; - // theoretically can call initServiceManager again here - but - // there's no point since most likely system is going to reboot - } - }); - } - } - - private final IServiceNotification mServiceNotificationCallback = - new IServiceNotification.Stub() { - @Override - public void onRegistration(String fqName, String name, - boolean preexisting) { - Log.d(TAG, "IWifi registration notification: fqName=" + fqName - + ", name=" + name + ", preexisting=" + preexisting); - synchronized (mLock) { - initIWifiIfNecessary(); - } - } - }; - - /** - * Failures of IServiceManager are most likely system breaking in any case. Behavior here - * will be to WTF and continue. - */ - private void initIServiceManagerIfNecessary() { - if (mDbg) Log.d(TAG, "initIServiceManagerIfNecessary"); - - synchronized (mLock) { - if (mServiceManager != null) { - return; - } - - mServiceManager = getServiceManagerMockable(); - if (mServiceManager == null) { - Log.wtf(TAG, "Failed to get IServiceManager instance"); - } else { - try { - if (!mServiceManager.linkToDeath( - mServiceManagerDeathRecipient, /* don't care */ 0)) { - Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); - mServiceManager = null; - return; - } - - if (!mServiceManager.registerForNotifications(IWifi.kInterfaceName, "", - mServiceNotificationCallback)) { - Log.wtf(TAG, "Failed to register a listener for IWifi service"); - mServiceManager = null; - } - } catch (RemoteException e) { - Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); - mServiceManager = null; - } - - // Cache the result for the supporting vendor hal or not - mIsVendorHalSupported = isSupportedInternal(); - } - } - } - - /** - * Uses the IServiceManager to query if the vendor HAL is present in the VINTF for the device - * or not. - * @return true if supported, false otherwise. - */ - private boolean isSupportedInternal() { - if (VDBG) Log.d(TAG, "isSupportedInternal"); - - synchronized (mLock) { - if (mServiceManager == null) { - Log.e(TAG, "isSupported: called but mServiceManager is null!?"); - return false; - } - try { - List<String> wifiServices = - mServiceManager.listManifestByInterface(IWifi.kInterfaceName); - return !wifiServices.isEmpty(); - } catch (RemoteException e) { - Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); - return false; - } - } - } - - private class WifiDeathRecipient implements DeathRecipient { + private class WifiDeathRecipient implements WifiHal.DeathRecipient { @Override - public void serviceDied(long cookie) { + public void onDeath() { mEventHandler.post(() -> { - Log.e(TAG, "IWifi HAL service died! Have a listener for it ... cookie=" + cookie); synchronized (mLock) { // prevents race condition with surrounding method - mWifi = null; - mIsReady = false; teardownInternal(); - // don't restart: wait for registration notification } }); } @@ -1154,192 +1012,7 @@ public class HalDeviceManager { * @return true if success. */ private boolean registerWifiHalEventCallback() { - try { - if (mWifi == null) { - Log.e(TAG, "registerWifiHalEventCallback called but mWifi is null!?"); - return false; - } - WifiStatus status; - android.hardware.wifi.V1_5.IWifi iWifiV15 = getWifiServiceForV1_5Mockable(mWifi); - if (iWifiV15 != null) { - status = iWifiV15.registerEventCallback_1_5(mWifiEventCallbackV15); - } else { - status = mWifi.registerEventCallback(mWifiEventCallback); - } - - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "IWifi.registerEventCallback failed: " + statusString(status)); - mWifi = null; - } - return status.code == WifiStatusCode.SUCCESS; - } catch (RemoteException e) { - Log.e(TAG, "Exception while operating on IWifi: " + e); - } - return false; - } - - /** - * Initialize IWifi and register death listener and event callback. - * - * - It is possible that IWifi is not ready - we have a listener on IServiceManager for it. - * - It is not expected that any of the registrations will fail. Possible indication that - * service died after we obtained a handle to it. - * - * Here and elsewhere we assume that death listener will do the right thing! - */ - private void initIWifiIfNecessary() { - if (mDbg) Log.d(TAG, "initIWifiIfNecessary"); - - synchronized (mLock) { - if (mWifi != null) { - return; - } - - try { - mWifi = getWifiServiceMockable(); - if (mWifi == null) { - Log.e(TAG, "IWifi not (yet) available - but have a listener for it ..."); - return; - } - - if (!mWifi.linkToDeath(mIWifiDeathRecipient, /* don't care */ 0)) { - Log.e(TAG, "Error on linkToDeath on IWifi - will retry later"); - return; - } - - // Stopping wifi just in case. This would also trigger the status callback. - // Stopping wifi invalidated the registered the event callback, register after the - // wifi stop. - stopWifi(); - if (!registerWifiHalEventCallback()) { - return; - } - mIsReady = true; - } catch (RemoteException e) { - Log.e(TAG, "Exception while operating on IWifi: " + e); - } - } - } - - /** - * Registers event listeners on all IWifiChips after a successful start: DEBUG only! - * - * We don't need the listeners since any callbacks are just confirmation of status codes we - * obtain directly from mode changes or interface creation/deletion. - * - * Relies (to the degree we care) on the service removing all listeners when Wi-Fi is stopped. - */ - private void initIWifiChipDebugListeners() { - if (VDBG) Log.d(TAG, "initIWifiChipDebugListeners"); - - if (!VDBG) { - return; - } - - synchronized (mLock) { - try { - Mutable<Boolean> statusOk = new Mutable<>(false); - Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>(); - - // get all chip IDs - mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> { - statusOk.value = false; - if (status.code == WifiStatusCode.SUCCESS) { - if (chipIds == null) { - Log.wtf(TAG, "getChipIds failed, chipIds is null"); - return; - } - statusOk.value = true; - } - if (statusOk.value) { - chipIdsResp.value = chipIds; - } else { - Log.e(TAG, "getChipIds failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return; - } - - Log.d(TAG, "getChipIds=" + chipIdsResp.value); - if (chipIdsResp.value.size() == 0) { - Log.e(TAG, "Should have at least 1 chip!"); - return; - } - - // register a callback for each chip - Mutable<IWifiChip> chipResp = new Mutable<>(); - for (Integer chipId: chipIdsResp.value) { - mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> { - statusOk.value = false; - if (status.code == WifiStatusCode.SUCCESS) { - if (chip == null) { - Log.wtf(TAG, "getChip failed, chip " + chipId + " is null"); - } - statusOk.value = true; - } - if (statusOk.value) { - chipResp.value = chip; - } else { - Log.e(TAG, "getChip failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - continue; // still try next one? - } - - IWifiChipEventCallback.Stub callback = - new IWifiChipEventCallback.Stub() { - @Override - public void onChipReconfigured(int modeId) throws RemoteException { - Log.d(TAG, "onChipReconfigured: modeId=" + modeId); - } - - @Override - public void onChipReconfigureFailure(WifiStatus status) - throws RemoteException { - Log.e(TAG, "onChipReconfigureFailure: status=" + statusString( - status)); - } - - @Override - public void onIfaceAdded(int type, String name) - throws RemoteException { - Log.d(TAG, "onIfaceAdded: type=" + type + ", name=" + name); - } - - @Override - public void onIfaceRemoved(int type, String name) - throws RemoteException { - Log.d(TAG, "onIfaceRemoved: type=" + type + ", name=" + name); - } - - @Override - public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, - ArrayList<Byte> data) throws RemoteException { - Log.d(TAG, "onDebugRingBufferDataAvailable"); - } - - @Override - public void onDebugErrorAlert(int errorCode, - ArrayList<Byte> debugData) - throws RemoteException { - Log.d(TAG, "onDebugErrorAlert"); - } - }; - mDebugCallbacks.put(chipId, callback); // store to prevent GC: needed by HIDL - WifiStatus status = chipResp.value.registerEventCallback(callback); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "registerEventCallback failed: " + statusString(status)); - continue; // still try next one? - } - } - } catch (RemoteException e) { - Log.e(TAG, "initIWifiChipDebugListeners: exception: " + e); - return; - } - } + return mWifiHal.registerEventCallback(mWifiEventCallback); } @Nullable @@ -1374,373 +1047,171 @@ public class HalDeviceManager { return null; } - try { - Mutable<Boolean> statusOk = new Mutable<>(false); - Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>(); + // get all chip IDs + List<Integer> chipIds = mWifiHal.getChipIds(); + if (chipIds == null) { + return null; + } - // get all chip IDs - mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - chipIdsResp.value = chipIds; - } else { - Log.e(TAG, "getChipIds failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } + if (VDBG) Log.d(TAG, "getChipIds=" + Arrays.toString(chipIds.toArray())); + if (chipIds.size() == 0) { + Log.e(TAG, "Should have at least 1 chip!"); + return null; + } - if (VDBG) Log.d(TAG, "getChipIds=" + chipIdsResp.value); - if (chipIdsResp.value.size() == 0) { - Log.e(TAG, "Should have at least 1 chip!"); - return null; - } + SparseArray<StaticChipInfo> staticChipInfoPerId = new SparseArray<>(); + for (StaticChipInfo staticChipInfo : getStaticChipInfos()) { + staticChipInfoPerId.put(staticChipInfo.getChipId(), staticChipInfo); + } + + int chipInfoIndex = 0; + WifiChipInfo[] chipsInfo = new WifiChipInfo[chipIds.size()]; - SparseArray<StaticChipInfo> staticChipInfoPerId = new SparseArray<>(); - for (StaticChipInfo staticChipInfo : getStaticChipInfos()) { - staticChipInfoPerId.put(staticChipInfo.getChipId(), staticChipInfo); + for (Integer chipId : chipIds) { + WifiChip chip = mWifiHal.getChip(chipId); + if (chip == null) { + return null; } - int chipInfoIndex = 0; - WifiChipInfo[] chipsInfo = new WifiChipInfo[chipIdsResp.value.size()]; - - Mutable<IWifiChip> chipResp = new Mutable<>(); - for (Integer chipId: chipIdsResp.value) { - mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - chipResp.value = chip; - } else { - Log.e(TAG, "getChip failed: " + statusString(status)); - } - }); - if (!statusOk.value) { + StaticChipInfo staticChipInfo = staticChipInfoPerId.get(chipId); + List<WifiChip.ChipMode> chipModes = null; + if (staticChipInfo == null) { + chipModes = chip.getAvailableModes(); + if (chipModes == null) { return null; } + } - StaticChipInfo staticChipInfo = staticChipInfoPerId.get(chipId); - Mutable<ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode>> - availableModesResp = new Mutable<>(); - if (staticChipInfo == null) { - android.hardware.wifi.V1_6.IWifiChip chipV16 = - getWifiChipForV1_6Mockable(chipResp.value); - if (chipV16 != null) { - chipV16.getAvailableModes_1_6((WifiStatus status, - ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> modes) - -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - availableModesResp.value = modes; - } else { - Log.e(TAG, "getAvailableModes_1_6 failed: " - + statusString(status)); - } - }); - } else { - chipResp.value.getAvailableModes((WifiStatus status, - ArrayList<IWifiChip.ChipMode> modes) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - availableModesResp.value = upgradeV1_0ChipModesToV1_6(modes); - } else { - Log.e(TAG, "getAvailableModes failed: " - + statusString(status)); - } - }); - } - if (!statusOk.value) { - return null; - } - } - - Mutable<Boolean> currentModeValidResp = new Mutable<>(false); - Mutable<Integer> currentModeResp = new Mutable<>(0); - chipResp.value.getMode((WifiStatus status, int modeId) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - currentModeValidResp.value = true; - currentModeResp.value = modeId; - } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) { - statusOk.value = true; // valid response - } else { - Log.e(TAG, "getMode failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } + WifiChip.Response<Integer> currentMode = chip.getMode(); + if (currentMode.getStatusCode() != WifiHal.WIFI_STATUS_SUCCESS + && currentMode.getStatusCode() != WifiHal.WIFI_STATUS_ERROR_NOT_AVAILABLE) { + return null; + } - Mutable<Long> chipCapabilities = new Mutable<>(0L); - chipCapabilities.value = getChipCapabilities(chipResp.value); + long chipCapabilities = getChipCapabilities(chip); - Mutable<ArrayList<String>> ifaceNamesResp = new Mutable<>(); - Mutable<Integer> ifaceIndex = new Mutable<>(0); + List<String> ifaceNames = chip.getStaIfaceNames(); + if (ifaceNames == null) { + return null; + } - chipResp.value.getStaIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getStaIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { + int ifaceIndex = 0; + WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNames.size()]; + for (String ifaceName: ifaceNames) { + WifiHal.WifiInterface iface = chip.getStaIface(ifaceName); + if (iface == null) { return null; } + WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); + ifaceInfo.name = ifaceName; + ifaceInfo.iface = iface; + ifaceInfo.createType = HDM_CREATE_IFACE_STA; + staIfaces[ifaceIndex++] = ifaceInfo; + } - WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getStaIface(ifaceName, - (WifiStatus status, IWifiStaIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - ifaceInfo.createType = HDM_CREATE_IFACE_STA; - staIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getStaIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } + ifaceIndex = 0; + ifaceNames = chip.getApIfaceNames(); + if (ifaceNames == null) { + return null; + } - ifaceIndex.value = 0; - chipResp.value.getApIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getApIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { + WifiIfaceInfo[] apIfaces = new WifiIfaceInfo[ifaceNames.size()]; + for (String ifaceName : ifaceNames) { + WifiHal.WifiInterface iface = chip.getApIface(ifaceName); + if (iface == null) { return null; } + WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); + ifaceInfo.name = ifaceName; + ifaceInfo.iface = iface; + ifaceInfo.createType = HDM_CREATE_IFACE_AP; + apIfaces[ifaceIndex++] = ifaceInfo; + } - WifiIfaceInfo[] apIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getApIface(ifaceName, - (WifiStatus status, IWifiApIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - ifaceInfo.createType = HDM_CREATE_IFACE_AP; - apIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getApIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } - Mutable<Integer> numBridgedAps = new Mutable<>(0); - for (WifiIfaceInfo apIfaceInfo : apIfaces) { - android.hardware.wifi.V1_5.IWifiApIface wifiApIfaceV15 = - getIWifiApIfaceForV1_5Mockable((IWifiApIface) apIfaceInfo.iface); - if (wifiApIfaceV15 == null) { - continue; - } - try { - wifiApIfaceV15.getBridgedInstances((status, instances) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - // Only count bridged APs with more than 1 instance as a bridged - // AP; 1 instance bridged APs will be counted as single AP. - if (instances != null && instances.size() > 1) { - apIfaceInfo.createType = HDM_CREATE_IFACE_AP_BRIDGE; - numBridgedAps.value++; - } - } else { - Log.e(TAG, "getBridgedInstances failed: " - + statusString(status)); - } - }); - } catch (RemoteException e) { - Log.e(TAG, "IWifiApIface.getBridgedInstances exception: " + e); - } - } - WifiIfaceInfo[] singleApIfaces = - new WifiIfaceInfo[apIfaces.length - numBridgedAps.value]; - WifiIfaceInfo[] bridgedApIfaces = new WifiIfaceInfo[numBridgedAps.value]; - int singleApIndex = 0; - int bridgedApIndex = 0; - for (WifiIfaceInfo apIfaceInfo : apIfaces) { - if (apIfaceInfo.createType == HDM_CREATE_IFACE_AP_BRIDGE) { - bridgedApIfaces[bridgedApIndex++] = apIfaceInfo; - } else { - singleApIfaces[singleApIndex++] = apIfaceInfo; - } + int numBridgedAps = 0; + for (WifiIfaceInfo apIfaceInfo : apIfaces) { + List<String> bridgedInstances = ((WifiApIface) apIfaceInfo.iface) + .getBridgedInstances(); + // Only count bridged APs with more than 1 instance as a bridged + // AP; 1 instance bridged APs will be counted as single AP. + if (bridgedInstances != null && bridgedInstances.size() > 1) { + apIfaceInfo.createType = HDM_CREATE_IFACE_AP_BRIDGE; + numBridgedAps++; } + } - ifaceIndex.value = 0; - chipResp.value.getP2pIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getP2pIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; + WifiIfaceInfo[] singleApIfaces = new WifiIfaceInfo[apIfaces.length - numBridgedAps]; + WifiIfaceInfo[] bridgedApIfaces = new WifiIfaceInfo[numBridgedAps]; + int singleApIndex = 0; + int bridgedApIndex = 0; + for (WifiIfaceInfo apIfaceInfo : apIfaces) { + if (apIfaceInfo.createType == HDM_CREATE_IFACE_AP_BRIDGE) { + bridgedApIfaces[bridgedApIndex++] = apIfaceInfo; + } else { + singleApIfaces[singleApIndex++] = apIfaceInfo; } + } - WifiIfaceInfo[] p2pIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getP2pIface(ifaceName, - (WifiStatus status, IWifiP2pIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - ifaceInfo.createType = HDM_CREATE_IFACE_P2P; - p2pIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getP2pIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } + ifaceIndex = 0; + ifaceNames = chip.getP2pIfaceNames(); + if (ifaceNames == null) { + return null; + } - ifaceIndex.value = 0; - chipResp.value.getNanIfaceNames( - (WifiStatus status, ArrayList<String> ifnames) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - ifaceNamesResp.value = ifnames; - } else { - Log.e(TAG, "getNanIfaceNames failed: " + statusString(status)); - } - }); - if (!statusOk.value) { + WifiIfaceInfo[] p2pIfaces = new WifiIfaceInfo[ifaceNames.size()]; + for (String ifaceName : ifaceNames) { + WifiHal.WifiInterface iface = chip.getP2pIface(ifaceName); + if (iface == null) { return null; } + WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); + ifaceInfo.name = ifaceName; + ifaceInfo.iface = iface; + ifaceInfo.createType = HDM_CREATE_IFACE_P2P; + p2pIfaces[ifaceIndex++] = ifaceInfo; + } - WifiIfaceInfo[] nanIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; - for (String ifaceName: ifaceNamesResp.value) { - chipResp.value.getNanIface(ifaceName, - (WifiStatus status, IWifiNanIface iface) -> { - statusOk.value = status.code == WifiStatusCode.SUCCESS; - if (statusOk.value) { - WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); - ifaceInfo.name = ifaceName; - ifaceInfo.iface = iface; - ifaceInfo.createType = HDM_CREATE_IFACE_NAN; - nanIfaces[ifaceIndex.value++] = ifaceInfo; - } else { - Log.e(TAG, "getNanIface failed: " + statusString(status)); - } - }); - if (!statusOk.value) { - return null; - } - } - - WifiChipInfo chipInfo = new WifiChipInfo(); - chipsInfo[chipInfoIndex++] = chipInfo; + ifaceIndex = 0; + ifaceNames = chip.getNanIfaceNames(); + if (ifaceNames == null) { + return null; + } - chipInfo.chip = chipResp.value; - chipInfo.chipId = chipId; - if (staticChipInfo != null) { - chipInfo.availableModes = staticChipInfo.getAvailableModes(); - } else { - chipInfo.availableModes = availableModesResp.value; + WifiIfaceInfo[] nanIfaces = new WifiIfaceInfo[ifaceNames.size()]; + for (String ifaceName : ifaceNames) { + WifiHal.WifiInterface iface = chip.getNanIface(ifaceName); + if (iface == null) { + return null; } - chipInfo.currentModeIdValid = currentModeValidResp.value; - chipInfo.currentModeId = currentModeResp.value; - chipInfo.chipCapabilities = chipCapabilities.value; - chipInfo.ifaces[HDM_CREATE_IFACE_STA] = staIfaces; - chipInfo.ifaces[HDM_CREATE_IFACE_AP] = singleApIfaces; - chipInfo.ifaces[HDM_CREATE_IFACE_AP_BRIDGE] = bridgedApIfaces; - chipInfo.ifaces[HDM_CREATE_IFACE_P2P] = p2pIfaces; - chipInfo.ifaces[HDM_CREATE_IFACE_NAN] = nanIfaces; + WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); + ifaceInfo.name = ifaceName; + ifaceInfo.iface = iface; + ifaceInfo.createType = HDM_CREATE_IFACE_NAN; + nanIfaces[ifaceIndex++] = ifaceInfo; } - return chipsInfo; - } catch (RemoteException e) { - Log.e(TAG, "getAllChipInfoAndValidateCache exception: " + e); - } - } - return null; - } + WifiChipInfo chipInfo = new WifiChipInfo(); + chipsInfo[chipInfoIndex++] = chipInfo; - private ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> - upgradeV1_0ChipModesToV1_6(ArrayList<IWifiChip.ChipMode> oldChipModes) { - ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> newChipModes = new ArrayList<>(); - for (IWifiChip.ChipMode oldChipMode : oldChipModes) { - android.hardware.wifi.V1_6.IWifiChip.ChipMode newChipMode = - new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - newChipMode.id = oldChipMode.id; - newChipMode.availableCombinations = new ArrayList<>(); - for (IWifiChip.ChipIfaceCombination oldCombo : oldChipMode.availableCombinations) { - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination - newCombo = new ChipConcurrencyCombination(); - newCombo.limits = new ArrayList<>(); - // Define a duplicate combination list with AP converted to AP_BRIDGED - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination - newComboWithBridgedAp = new ChipConcurrencyCombination(); - newComboWithBridgedAp.limits = new ArrayList<>(); - ChipConcurrencyCombinationLimit bridgedApLimit = - new ChipConcurrencyCombinationLimit(); - bridgedApLimit.maxIfaces = 1; - bridgedApLimit.types = new ArrayList<>(); - bridgedApLimit.types.add(IfaceConcurrencyType.AP_BRIDGED); - newComboWithBridgedAp.limits.add(bridgedApLimit); - - boolean apInCombo = false; - // Populate both the combo with AP_BRIDGED and the combo without AP_BRIDGED - for (IWifiChip.ChipIfaceCombinationLimit oldLimit : oldCombo.limits) { - ChipConcurrencyCombinationLimit newLimit = - new ChipConcurrencyCombinationLimit(); - newLimit.types = new ArrayList<>(); - newLimit.maxIfaces = oldLimit.maxIfaces; - for (int oldType : oldLimit.types) { - newLimit.types.add(IFACE_TYPE_TO_CONCURRENCY_TYPE_MAP.get(oldType)); - } - newCombo.limits.add(newLimit); - - ChipConcurrencyCombinationLimit newLimitForBridgedApCombo = - new ChipConcurrencyCombinationLimit(); - newLimitForBridgedApCombo.types = new ArrayList<>(newLimit.types); - newLimitForBridgedApCombo.maxIfaces = newLimit.maxIfaces; - if (newLimitForBridgedApCombo.types.contains(IfaceConcurrencyType.AP)) { - // Skip the limit if it contains AP, since this corresponds to the - // AP_BRIDGED in the duplicate AP_BRIDGED combo. - apInCombo = true; - } else if (!isStaWithBridgedSoftApConcurrencySupportedMockable() - && newLimitForBridgedApCombo.types.contains(IfaceConcurrencyType.STA)) { - // Don't include STA in the AP_BRIDGED combo if STA + AP_BRIDGED is not - // supported. - newLimitForBridgedApCombo.types.remove((Integer) IfaceConcurrencyType.STA); - if (!newLimitForBridgedApCombo.types.isEmpty()) { - newComboWithBridgedAp.limits.add(newLimitForBridgedApCombo); - } - } else { - newComboWithBridgedAp.limits.add(newLimitForBridgedApCombo); - } - } - newChipMode.availableCombinations.add(newCombo); - if (isBridgedSoftApSupportedMockable() && apInCombo) { - newChipMode.availableCombinations.add(newComboWithBridgedAp); + chipInfo.chip = chip; + chipInfo.chipId = chipId; + if (staticChipInfo != null) { + chipInfo.availableModes = staticChipInfo.getAvailableModes(); + } else { + chipInfo.availableModes = new ArrayList<>(chipModes); } + chipInfo.currentModeIdValid = + currentMode.getStatusCode() == WifiHal.WIFI_STATUS_SUCCESS; + chipInfo.currentModeId = currentMode.getValue(); + chipInfo.chipCapabilities = chipCapabilities; + chipInfo.ifaces[HDM_CREATE_IFACE_STA] = staIfaces; + chipInfo.ifaces[HDM_CREATE_IFACE_AP] = singleApIfaces; + chipInfo.ifaces[HDM_CREATE_IFACE_AP_BRIDGE] = bridgedApIfaces; + chipInfo.ifaces[HDM_CREATE_IFACE_P2P] = p2pIfaces; + chipInfo.ifaces[HDM_CREATE_IFACE_NAN] = nanIfaces; } - newChipModes.add(newChipMode); + return chipsInfo; } - return newChipModes; } @Nullable @@ -1858,95 +1329,69 @@ public class HalDeviceManager { private boolean isWifiStarted() { if (VDBG) Log.d(TAG, "isWifiStart"); - synchronized (mLock) { - try { - if (mWifi == null) { - return false; - } else { - return mWifi.isStarted(); - } - } catch (RemoteException e) { - Log.e(TAG, "isWifiStarted exception: " + e); - return false; - } + return mWifiHal.isStarted(); } } private boolean startWifi() { if (VDBG) Log.d(TAG, "startWifi"); - initIWifiIfNecessary(); + initializeInternal(); synchronized (mLock) { - try { - if (mWifi == null) { - Log.w(TAG, "startWifi called but mWifi is null!?"); - return false; - } else { - int triedCount = 0; - while (triedCount <= START_HAL_RETRY_TIMES) { - WifiStatus status = mWifi.start(); - if (status.code == WifiStatusCode.SUCCESS) { - initIWifiChipDebugListeners(); - managerStatusListenerDispatch(); - if (triedCount != 0) { - Log.d(TAG, "start IWifi succeeded after trying " - + triedCount + " times"); - } - WifiChipInfo[] wifiChipInfos = getAllChipInfo(); - if (wifiChipInfos == null) { - Log.e(TAG, "Started wifi but could not get current chip info."); - } - return true; - } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) { - // Should retry. Hal might still be stopping. the registered event - // callback will not be cleared. - Log.e(TAG, "Cannot start IWifi: " + statusString(status) - + ", Retrying..."); - try { - Thread.sleep(START_HAL_RETRY_INTERVAL_MS); - } catch (InterruptedException ignore) { - // no-op - } - triedCount++; - } else { - // Should not retry on other failures. - // Will be handled in the onFailure event. - Log.e(TAG, "Cannot start IWifi: " + statusString(status)); - return false; - } + int triedCount = 0; + while (triedCount <= START_HAL_RETRY_TIMES) { + int status = mWifiHal.start(); + if (status == WifiHal.WIFI_STATUS_SUCCESS) { + managerStatusListenerDispatch(); + if (triedCount != 0) { + Log.d(TAG, "start IWifi succeeded after trying " + + triedCount + " times"); } - Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times"); + WifiChipInfo[] wifiChipInfos = getAllChipInfo(); + if (wifiChipInfos == null) { + Log.e(TAG, "Started wifi but could not get current chip info."); + } + return true; + } else if (status == WifiHal.WIFI_STATUS_ERROR_NOT_AVAILABLE) { + // Should retry. Hal might still be stopping. the registered event + // callback will not be cleared. + Log.e(TAG, "Cannot start wifi because unavailable. Retrying..."); + try { + Thread.sleep(START_HAL_RETRY_INTERVAL_MS); + } catch (InterruptedException ignore) { + // no-op + } + triedCount++; + } else { + // Should not retry on other failures. + // Will be handled in the onFailure event. + Log.e(TAG, "Cannot start IWifi. Status: " + status); return false; } - } catch (RemoteException e) { - Log.e(TAG, "startWifi exception: " + e); - return false; } + Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times"); + return false; } } private void stopWifi() { if (VDBG) Log.d(TAG, "stopWifi"); - - try { - if (mWifi == null) { - Log.w(TAG, "stopWifi called but mWifi is null!?"); - } else { - WifiStatus status = mWifi.stop(); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "Cannot stop IWifi: " + statusString(status)); - } - // even on failure since WTF?? - teardownInternal(); + synchronized (mLock) { + if (!mWifiHal.isInitializationComplete()) { + Log.w(TAG, "stopWifi was called, but Wifi Hal is not initialized"); + return; + } + if (!mWifiHal.stop()) { + Log.e(TAG, "Cannot stop IWifi"); } - } catch (RemoteException e) { - Log.e(TAG, "stopWifi exception: " + e); + // even on failure since WTF?? + teardownInternal(); } } - private class WifiEventCallback extends IWifiEventCallback.Stub { + private class WifiEventCallback implements WifiHal.Callback { @Override - public void onStart() throws RemoteException { + public void onStart() { mEventHandler.post(() -> { if (VDBG) Log.d(TAG, "IWifiEventCallback.onStart"); // NOP: only happens in reaction to my calls - will handle directly @@ -1954,7 +1399,7 @@ public class HalDeviceManager { } @Override - public void onStop() throws RemoteException { + public void onStop() { mEventHandler.post(() -> { if (VDBG) Log.d(TAG, "IWifiEventCallback.onStop"); // NOP: only happens in reaction to my calls - will handle directly @@ -1962,41 +1407,20 @@ public class HalDeviceManager { } @Override - public void onFailure(WifiStatus status) throws RemoteException { + public void onFailure(int status) { mEventHandler.post(() -> { - Log.e(TAG, "IWifiEventCallback.onFailure: " + statusString(status)); + Log.e(TAG, "IWifiEventCallback.onFailure. Status: " + status); synchronized (mLock) { - mWifi = null; - mIsReady = false; teardownInternal(); } }); } - } - - private class WifiEventCallbackV15 extends - android.hardware.wifi.V1_5.IWifiEventCallback.Stub { - private final WifiEventCallback mWifiEventCallback = new WifiEventCallback(); - @Override - public void onStart() throws RemoteException { - mWifiEventCallback.onStart(); - } @Override - public void onStop() throws RemoteException { - mWifiEventCallback.onStop(); - } - - @Override - public void onFailure(WifiStatus status) throws RemoteException { - mWifiEventCallback.onFailure(status); - } - - @Override - public void onSubsystemRestart(WifiStatus status) throws RemoteException { + public void onSubsystemRestart(int status) { Log.i(TAG, "onSubsystemRestart"); mEventHandler.post(() -> { - Log.i(TAG, "IWifiEventCallback.onSubsystemRestart: " + statusString(status)); + Log.i(TAG, "IWifiEventCallback.onSubsystemRestart. Status: " + status); synchronized (mLock) { Log.i(TAG, "Attempting to invoke mSubsystemRestartListener"); for (SubsystemRestartListenerProxy cb : mSubsystemRestartListener) { @@ -2028,7 +1452,7 @@ public class HalDeviceManager { } } - private Set<Integer> getSupportedIfaceTypesInternal(IWifiChip chip) { + private Set<Integer> getSupportedIfaceTypesInternal(WifiChip chip) { Set<Integer> results = new HashSet<>(); WifiChipInfo[] chipInfos = getAllChipInfoCached(); @@ -2037,37 +1461,22 @@ public class HalDeviceManager { return results; } - Mutable<Integer> chipIdIfProvided = new Mutable<>(0); // NOT using 0 as a magic value + int chipIdIfProvided = 0; // NOT using 0 as a magic value if (chip != null) { - Mutable<Boolean> statusOk = new Mutable<>(false); - try { - chip.getId((WifiStatus status, int id) -> { - if (status.code == WifiStatusCode.SUCCESS) { - chipIdIfProvided.value = id; - statusOk.value = true; - } else { - Log.e(TAG, "getSupportedIfaceTypesInternal: IWifiChip.getId() error: " - + statusString(status)); - statusOk.value = false; - } - }); - } catch (RemoteException e) { - Log.e(TAG, "getSupportedIfaceTypesInternal IWifiChip.getId() exception: " + e); - return results; - } - if (!statusOk.value) { + chipIdIfProvided = chip.getId(); + if (chipIdIfProvided == -1) { return results; } } for (WifiChipInfo wci: chipInfos) { - if (chip != null && wci.chipId != chipIdIfProvided.value) { + if (chip != null && wci.chipId != chipIdIfProvided) { continue; } - // Map the V1_6 IfaceConcurrencyTypes to the corresponding IfaceType. - for (android.hardware.wifi.V1_6.IWifiChip.ChipMode cm: wci.availableModes) { - for (ChipConcurrencyCombination cic : cm.availableCombinations) { - for (ChipConcurrencyCombinationLimit cicl : cic.limits) { + // Map the IfaceConcurrencyTypes to the corresponding IfaceType. + for (WifiChip.ChipMode cm : wci.availableModes) { + for (WifiChip.ChipConcurrencyCombination cic : cm.availableCombinations) { + for (WifiChip.ChipConcurrencyCombinationLimit cicl : cic.limits) { for (int concurrencyType: cicl.types) { results.add(HAL_IFACE_MAP.get( CONCURRENCY_TYPE_TO_CREATE_TYPE_MAP.get(concurrencyType))); @@ -2076,11 +1485,10 @@ public class HalDeviceManager { } } } - return results; } - private IWifiIface createIface(@HdmIfaceTypeForCreation int createIfaceType, + private WifiHal.WifiInterface createIface(@HdmIfaceTypeForCreation int createIfaceType, long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, Handler handler, WorkSource requestorWs) { if (mDbg) { @@ -2175,11 +1583,11 @@ public class HalDeviceManager { * supported by that id. */ private SparseArray<List<int[][]>> getExpandedCreateTypeCombosPerChipModeId( - ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> chipModes) { + ArrayList<WifiChip.ChipMode> chipModes) { SparseArray<List<int[][]>> combosPerChipModeId = new SparseArray<>(); - for (android.hardware.wifi.V1_6.IWifiChip.ChipMode chipMode : chipModes) { + for (WifiChip.ChipMode chipMode : chipModes) { List<int[][]> expandedCreateTypeCombos = new ArrayList<>(); - for (ChipConcurrencyCombination chipConcurrencyCombo + for (WifiChip.ChipConcurrencyCombination chipConcurrencyCombo : chipMode.availableCombinations) { expandedCreateTypeCombos.add(expandCreateTypeCombo(chipConcurrencyCombo)); } @@ -2188,7 +1596,7 @@ public class HalDeviceManager { return combosPerChipModeId; } - private IWifiIface createIfaceIfPossible( + private WifiHal.WifiInterface createIfaceIfPossible( WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType, long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, Handler handler, WorkSource requestorWs) { @@ -2205,13 +1613,12 @@ public class HalDeviceManager { createIfaceType, requiredChipCapabilities, requestorWs); if (bestIfaceCreationProposal != null) { - IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, + WifiHal.WifiInterface iface = executeChipReconfiguration(bestIfaceCreationProposal, createIfaceType); if (iface == null) { // If the chip reconfiguration failed, we'll need to clean up internal state. Log.e(TAG, "Teardown Wifi internal state"); - mWifi = null; - mIsReady = false; + mWifiHal.invalidate(); teardownInternal(); } else { InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry(); @@ -2251,9 +1658,10 @@ public class HalDeviceManager { * TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to * provide correct hashes. */ - private int[][] expandCreateTypeCombo(ChipConcurrencyCombination chipConcurrencyCombo) { + private int[][] expandCreateTypeCombo( + WifiChip.ChipConcurrencyCombination chipConcurrencyCombo) { int numOfCombos = 1; - for (ChipConcurrencyCombinationLimit limit : chipConcurrencyCombo.limits) { + for (WifiChip.ChipConcurrencyCombinationLimit limit : chipConcurrencyCombo.limits) { for (int i = 0; i < limit.maxIfaces; ++i) { numOfCombos *= limit.types.size(); } @@ -2263,7 +1671,7 @@ public class HalDeviceManager { new int[numOfCombos][CREATE_TYPES_BY_PRIORITY.length]; int span = numOfCombos; // span of an individual type (or sub-tree size) - for (ChipConcurrencyCombinationLimit limit : chipConcurrencyCombo.limits) { + for (WifiChip.ChipConcurrencyCombinationLimit limit : chipConcurrencyCombo.limits) { for (int i = 0; i < limit.maxIfaces; ++i) { span /= limit.types.size(); for (int k = 0; k < numOfCombos; ++k) { @@ -2468,52 +1876,6 @@ public class HalDeviceManager { } /** - * Returns true if the requested iface can delete an existing iface only after user approval. - */ - public boolean needsUserApprovalToDelete( - int requestedCreateType, @NonNull WorkSourceHelper newRequestorWsHelper, - int existingCreateType, @NonNull WorkSourceHelper existingRequestorWsHelper) { - @WorkSourceHelper.RequestorWsPriority int newRequestorWsPriority = - newRequestorWsHelper.getRequestorWsPriority(); - @WorkSourceHelper.RequestorWsPriority int existingRequestorWsPriority = - existingRequestorWsHelper.getRequestorWsPriority(); - - if (!mWifiUserApprovalRequiredForD2dInterfacePriority - || newRequestorWsPriority <= WorkSourceHelper.PRIORITY_BG - || existingRequestorWsPriority == WorkSourceHelper.PRIORITY_INTERNAL) { - return false; - } - - // Allow LOHS to beat Settings STA if there's no STA+AP concurrency (legacy behavior) - if (allowedToDeleteForNoStaApConcurrencyLohs( - requestedCreateType, newRequestorWsPriority, - existingCreateType, existingRequestorWsPriority)) { - return false; - } - - if (requestedCreateType == HDM_CREATE_IFACE_AP - || requestedCreateType == HDM_CREATE_IFACE_AP_BRIDGE) { - if (existingCreateType == HDM_CREATE_IFACE_P2P - || existingCreateType == HDM_CREATE_IFACE_NAN) { - return true; - } - } else if (requestedCreateType == HDM_CREATE_IFACE_P2P) { - if (existingCreateType == HDM_CREATE_IFACE_AP - || existingCreateType == HDM_CREATE_IFACE_AP_BRIDGE - || existingCreateType == HDM_CREATE_IFACE_NAN) { - return true; - } - } else if (requestedCreateType == HDM_CREATE_IFACE_NAN) { - if (existingCreateType == HDM_CREATE_IFACE_AP - || existingCreateType == HDM_CREATE_IFACE_AP_BRIDGE - || existingCreateType == HDM_CREATE_IFACE_P2P) { - return true; - } - } - return false; - } - - /** * Returns whether interface request from |newRequestorWsPriority| is allowed to delete an * interface request from |existingRequestorWsPriority|. * @@ -2536,8 +1898,9 @@ public class HalDeviceManager { } // Defer deletion decision to the InterfaceConflictManager dialog. - if (needsUserApprovalToDelete(requestedCreateType, newRequestorWs, - existingCreateType, existingRequestorWs)) { + if (mWifiInjector.getInterfaceConflictManager().needsUserApprovalToDelete( + requestedCreateType, newRequestorWs, + existingCreateType, existingRequestorWs)) { return true; } @@ -2591,8 +1954,8 @@ public class HalDeviceManager { @WorkSourceHelper.RequestorWsPriority int existingRequestorWsPriority) { return !canDeviceSupportCreateTypeCombo( new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP, 1); + put(HDM_CREATE_IFACE_STA, 1); + put(HDM_CREATE_IFACE_AP, 1); }}) && (requestedCreateType == HDM_CREATE_IFACE_AP || requestedCreateType == HDM_CREATE_IFACE_AP_BRIDGE) @@ -2812,131 +2175,98 @@ public class HalDeviceManager { * * Returns the newly created interface or a null on any error. */ - private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData, + private WifiHal.WifiInterface executeChipReconfiguration(IfaceCreationData ifaceCreationData, @HdmIfaceTypeForCreation int createIfaceType) { if (mDbg) { Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData + ", createIfaceType=" + createIfaceType); } synchronized (mLock) { - try { - // is this a mode change? - boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid - || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId; - if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded); - - // first delete interfaces/change modes - if (isModeConfigNeeded) { - // remove all interfaces pre mode-change - // TODO: is this necessary? note that even if we don't want to explicitly - // remove the interfaces we do need to call the onDeleted callbacks - which - // this does - for (WifiIfaceInfo[] ifaceInfos : ifaceCreationData.chipInfo.ifaces) { - for (WifiIfaceInfo ifaceInfo : ifaceInfos) { - removeIfaceInternal(ifaceInfo.iface, - /* validateRttController */false); // ignore return value - } - } - - WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip( - ifaceCreationData.chipModeId); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "executeChipReconfiguration: configureChip error: " - + statusString(status)); - return null; - } - if (!mIsConcurrencyComboLoadedFromDriver) { - WifiChipInfo[] wifiChipInfos = getAllChipInfo(); - if (wifiChipInfos != null) { - mCachedStaticChipInfos = - convertWifiChipInfoToStaticChipInfos(getAllChipInfo()); - saveStaticChipInfoToStore(mCachedStaticChipInfos); - mIsConcurrencyComboLoadedFromDriver = true; - } else { - Log.e(TAG, "Configured chip but could not get current chip info."); - } - } - } else { - // remove all interfaces on the delete list - for (WifiIfaceInfo ifaceInfo : ifaceCreationData.interfacesToBeRemovedFirst) { + // is this a mode change? + boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid + || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId; + if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded); + Log.i(TAG, "currentModeId=" + ifaceCreationData.chipInfo.currentModeId + + ", requestModeId=" + ifaceCreationData.chipModeId + + ", currentModeIdValid=" + ifaceCreationData.chipInfo.currentModeIdValid); + + // first delete interfaces/change modes + if (isModeConfigNeeded) { + // remove all interfaces pre mode-change + // TODO: is this necessary? note that even if we don't want to explicitly + // remove the interfaces we do need to call the onDeleted callbacks - which + // this does + for (WifiIfaceInfo[] ifaceInfos : ifaceCreationData.chipInfo.ifaces) { + for (WifiIfaceInfo ifaceInfo : ifaceInfos) { removeIfaceInternal(ifaceInfo.iface, /* validateRttController */false); // ignore return value } - // downgrade all interfaces on the downgrade list - for (WifiIfaceInfo ifaceInfo : ifaceCreationData.interfacesToBeDowngraded) { - if (ifaceInfo.createType == HDM_CREATE_IFACE_AP_BRIDGE) { - if (!downgradeBridgedApIface(ifaceInfo)) { - Log.e(TAG, "executeChipReconfiguration: failed to downgrade bridged" - + " AP: " + ifaceInfo); - return null; - } - } - } } - // create new interface - Mutable<WifiStatus> statusResp = new Mutable<>(); - Mutable<IWifiIface> ifaceResp = new Mutable<>(); - switch (createIfaceType) { - case HDM_CREATE_IFACE_STA: - ifaceCreationData.chipInfo.chip.createStaIface( - (WifiStatus status, IWifiStaIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; - case HDM_CREATE_IFACE_AP_BRIDGE: - android.hardware.wifi.V1_5.IWifiChip chip15 = - getWifiChipForV1_5Mockable(ifaceCreationData.chipInfo.chip); - if (chip15 != null) { - chip15.createBridgedApIface( - (WifiStatus status, - android.hardware.wifi.V1_5.IWifiApIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - } else { - Log.e(TAG, "Hal doesn't support to create AP bridge mode"); + boolean success = ifaceCreationData.chipInfo.chip.configureChip( + ifaceCreationData.chipModeId); + if (!success) { + Log.e(TAG, "executeChipReconfiguration: configureChip error"); + return null; + } + if (!mIsConcurrencyComboLoadedFromDriver) { + WifiChipInfo[] wifiChipInfos = getAllChipInfo(); + if (wifiChipInfos != null) { + mCachedStaticChipInfos = + convertWifiChipInfoToStaticChipInfos(getAllChipInfo()); + saveStaticChipInfoToStore(mCachedStaticChipInfos); + mIsConcurrencyComboLoadedFromDriver = true; + } else { + Log.e(TAG, "Configured chip but could not get current chip info."); + } + } + } else { + // remove all interfaces on the delete list + for (WifiIfaceInfo ifaceInfo : ifaceCreationData.interfacesToBeRemovedFirst) { + removeIfaceInternal(ifaceInfo.iface, + /* validateRttController */false); // ignore return value + } + // downgrade all interfaces on the downgrade list + for (WifiIfaceInfo ifaceInfo : ifaceCreationData.interfacesToBeDowngraded) { + if (ifaceInfo.createType == HDM_CREATE_IFACE_AP_BRIDGE) { + if (!downgradeBridgedApIface(ifaceInfo)) { + Log.e(TAG, "executeChipReconfiguration: failed to downgrade bridged" + + " AP: " + ifaceInfo); return null; } - break; - case HDM_CREATE_IFACE_AP: - ifaceCreationData.chipInfo.chip.createApIface( - (WifiStatus status, IWifiApIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; - case HDM_CREATE_IFACE_P2P: - ifaceCreationData.chipInfo.chip.createP2pIface( - (WifiStatus status, IWifiP2pIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; - case HDM_CREATE_IFACE_NAN: - ifaceCreationData.chipInfo.chip.createNanIface( - (WifiStatus status, IWifiNanIface iface) -> { - statusResp.value = status; - ifaceResp.value = iface; - }); - break; + } } + } - updateRttControllerWhenInterfaceChanges(); + // create new interface + WifiHal.WifiInterface iface = null; + switch (createIfaceType) { + case HDM_CREATE_IFACE_STA: + iface = ifaceCreationData.chipInfo.chip.createStaIface(); + break; + case HDM_CREATE_IFACE_AP_BRIDGE: + iface = ifaceCreationData.chipInfo.chip.createBridgedApIface(); + break; + case HDM_CREATE_IFACE_AP: + iface = ifaceCreationData.chipInfo.chip.createApIface(); + break; + case HDM_CREATE_IFACE_P2P: + iface = ifaceCreationData.chipInfo.chip.createP2pIface(); + break; + case HDM_CREATE_IFACE_NAN: + iface = ifaceCreationData.chipInfo.chip.createNanIface(); + break; + } - if (statusResp.value.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "executeChipReconfiguration: failed to create interface" - + " createIfaceType=" + createIfaceType + ": " - + statusString(statusResp.value)); - return null; - } + updateRttControllerWhenInterfaceChanges(); - return ifaceResp.value; - } catch (RemoteException e) { - Log.e(TAG, "executeChipReconfiguration exception: " + e); + if (iface == null) { + Log.e(TAG, "executeChipReconfiguration: failed to create interface" + + " createIfaceType=" + createIfaceType); return null; } + + return iface; } } @@ -2948,7 +2278,8 @@ public class HalDeviceManager { * this must be true. * @return True if removal succeed, otherwise false. */ - private boolean removeIfaceInternal(IWifiIface iface, boolean validateRttController) { + private boolean removeIfaceInternal(WifiHal.WifiInterface iface, + boolean validateRttController) { String name = getName(iface); int type = getType(iface); if (mDbg) Log.d(TAG, "removeIfaceInternal: iface(name)=" + name + ", type=" + type); @@ -2959,12 +2290,7 @@ public class HalDeviceManager { } synchronized (mLock) { - if (mWifi == null) { - Log.e(TAG, "removeIfaceInternal: null IWifi -- iface(name)=" + name); - return false; - } - - IWifiChip chip = getChip(iface); + WifiChip chip = getChip(iface); if (chip == null) { Log.e(TAG, "removeIfaceInternal: null IWifiChip -- iface(name)=" + name); return false; @@ -2980,27 +2306,23 @@ public class HalDeviceManager { // status. dispatchDestroyedListeners(name, type, true); - WifiStatus status = null; - try { - switch (type) { - case IfaceType.STA: - status = chip.removeStaIface(name); - break; - case IfaceType.AP: - status = chip.removeApIface(name); - break; - case IfaceType.P2P: - status = chip.removeP2pIface(name); - break; - case IfaceType.NAN: - status = chip.removeNanIface(name); - break; - default: - Log.wtf(TAG, "removeIfaceInternal: invalid type=" + type); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IWifiChip.removeXxxIface exception: " + e); + boolean success = false; + switch (type) { + case WifiChip.IFACE_TYPE_STA: + success = chip.removeStaIface(name); + break; + case WifiChip.IFACE_TYPE_AP: + success = chip.removeApIface(name); + break; + case WifiChip.IFACE_TYPE_P2P: + success = chip.removeP2pIface(name); + break; + case WifiChip.IFACE_TYPE_NAN: + success = chip.removeNanIface(name); + break; + default: + Log.wtf(TAG, "removeIfaceInternal: invalid type=" + type); + return false; } // dispatch listeners no matter what status @@ -3010,10 +2332,10 @@ public class HalDeviceManager { updateRttControllerWhenInterfaceChanges(); } - if (status != null && status.code == WifiStatusCode.SUCCESS) { + if (success) { return true; } else { - Log.e(TAG, "IWifiChip.removeXxxIface failed: " + statusString(status)); + Log.e(TAG, "IWifiChip.removeXxxIface failed, name=" + name + ", type=" + type); return false; } } @@ -3084,24 +2406,13 @@ public class HalDeviceManager { if (name == null) { return false; } - IWifiChip chip = getChip(bridgedApIfaceInfo.iface); + WifiChip chip = getChip(bridgedApIfaceInfo.iface); if (chip == null) { return false; } - android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipForV1_5Mockable(chip); - if (chip15 == null) { - return false; - } String instanceForRemoval = bridgedSoftApManager.getBridgedApDowngradeIfaceInstanceForRemoval(); - try { - chip15.removeIfaceInstanceFromBridgedApIface(name, instanceForRemoval); - } catch (RemoteException e) { - Log.e(TAG, - "IWifiChip.removeIfaceInstanceFromBridgedApIface exception: " + e); - return false; - } - return true; + return chip.removeIfaceInstanceFromBridgedApIface(name, instanceForRemoval); } private abstract class ListenerProxy<LISTENER> { @@ -3147,9 +2458,12 @@ public class HalDeviceManager { } else { // Current thread is not the thread the listener should be invoked on. // Post action to the intended thread. - mHandler.postAtFrontOfQueue(() -> { - action(); - }); + if (mHandler instanceof RunnerHandler) { + RunnerHandler rh = (RunnerHandler) mHandler; + rh.postToFront(() -> action()); + } else { + mHandler.postAtFrontOfQueue(() -> action()); + } } } @@ -3214,7 +2528,7 @@ public class HalDeviceManager { } @Override - public void onNewRttController(IWifiRttController controller) { + public void onNewRttController(WifiRttController controller) { mHandler.post(() -> mCallback.onNewRttController(controller)); } @@ -3230,7 +2544,7 @@ public class HalDeviceManager { + mRttControllerLifecycleCallbacks.size()); } for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { - cbp.onNewRttController(mIWifiRttController); + cbp.onNewRttController(mWifiRttController); } } @@ -3240,7 +2554,6 @@ public class HalDeviceManager { } } - /** * Updates the RttController when the interface changes: * - Handles callbacks to registered listeners @@ -3248,55 +2561,37 @@ public class HalDeviceManager { */ private void updateRttControllerWhenInterfaceChanges() { synchronized (mLock) { - if (validateRttController()) { + if (mWifiRttController != null && mWifiRttController.validate()) { if (mDbg) { Log.d(TAG, "Current RttController is valid, Don't try to create a new one"); } return; } - boolean controllerDestroyed = mIWifiRttController != null; - mIWifiRttController = null; + boolean controllerDestroyed = mWifiRttController != null; + mWifiRttController = null; if (mRttControllerLifecycleCallbacks.size() == 0) { Log.d(TAG, "updateRttController: no one is interested in RTT controllers"); return; } - IWifiRttController newRttController = createRttControllerIfPossible(); + WifiRttController newRttController = createRttControllerIfPossible(); if (newRttController == null) { if (controllerDestroyed) { dispatchRttControllerLifecycleOnDestroyed(); } } else { - mIWifiRttController = newRttController; + mWifiRttController = newRttController; dispatchRttControllerLifecycleOnNew(); } } } - private boolean validateRttController() { - if (mIWifiRttController == null) { - return false; - } - Mutable<Boolean> isRttControllerValid = new Mutable<>(false); - try { - mIWifiRttController.getBoundIface( - (status, iface) -> { - if (status.code == WifiStatusCode.SUCCESS) { - isRttControllerValid.value = true; - } - }); - } catch (RemoteException e) { - Log.e(TAG, "RttController: exception getBoundIface" + e); - } - return isRttControllerValid.value; - } - /** - * Try to create a new RttController. + * Try to create and set up a new RttController. * * @return The new RttController - or null on failure. */ - private IWifiRttController createRttControllerIfPossible() { + private WifiRttController createRttControllerIfPossible() { synchronized (mLock) { if (!isWifiStarted()) { Log.d(TAG, "createRttControllerIfPossible: Wifi is not started"); @@ -3319,51 +2614,13 @@ public class HalDeviceManager { continue; } - Mutable<IWifiRttController> rttResp = new Mutable<>(); - try { - android.hardware.wifi.V1_6.IWifiChip chip16 = - android.hardware.wifi.V1_6.IWifiChip.castFrom(chipInfo.chip); - android.hardware.wifi.V1_4.IWifiChip chip14 = - android.hardware.wifi.V1_4.IWifiChip.castFrom(chipInfo.chip); - - if (chip16 != null) { - chip16.createRttController_1_6(null, - (WifiStatus status, - android.hardware.wifi.V1_6.IWifiRttController rtt) -> { - if (status.code == WifiStatusCode.SUCCESS) { - rttResp.value = rtt; - } else { - Log.e(TAG, "IWifiChip.createRttController_1_6 failed: " - + statusString(status)); - } - }); - } else if (chip14 != null) { - chip14.createRttController_1_4(null, - (WifiStatus status, - android.hardware.wifi.V1_4.IWifiRttController rtt) -> { - if (status.code == WifiStatusCode.SUCCESS) { - rttResp.value = rtt; - } else { - Log.e(TAG, "IWifiChip.createRttController_1_4 failed: " - + statusString(status)); - } - }); - } else { - chipInfo.chip.createRttController(null, - (WifiStatus status, IWifiRttController rtt) -> { - if (status.code == WifiStatusCode.SUCCESS) { - rttResp.value = rtt; - } else { - Log.e(TAG, "IWifiChip.createRttController failed: " - + statusString(status)); - } - }); + WifiRttController rttController = chipInfo.chip.createRttController(); + if (rttController != null) { + if (!rttController.setup()) { + return null; } - } catch (RemoteException e) { - Log.e(TAG, "IWifiChip.createRttController exception: " + e); - } - if (rttResp.value != null) { - return rttResp.value; + rttController.enableVerboseLogging(mDbg); + return rttController; } } } @@ -3374,57 +2631,30 @@ public class HalDeviceManager { // general utilities - private static String statusString(WifiStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.code).append(" (").append(status.description).append(")"); - return sb.toString(); - } - // Will return -1 for invalid results! Otherwise will return one of the 4 valid values. - private static int getType(IWifiIface iface) { - Mutable<Integer> typeResp = new Mutable<>(-1); - try { - iface.getType((WifiStatus status, int type) -> { - if (status.code == WifiStatusCode.SUCCESS) { - typeResp.value = type; - } else { - Log.e(TAG, "Error on getType: " + statusString(status)); - } - }); - } catch (RemoteException e) { - Log.e(TAG, "Exception on getType: " + e); + @VisibleForTesting + protected static int getType(WifiHal.WifiInterface iface) { + if (iface instanceof WifiStaIface) { + return WifiChip.IFACE_TYPE_STA; + } else if (iface instanceof WifiApIface) { + return WifiChip.IFACE_TYPE_AP; + } else if (iface instanceof WifiP2pIface) { + return WifiChip.IFACE_TYPE_P2P; + } else if (iface instanceof WifiNanIface) { + return WifiChip.IFACE_TYPE_NAN; } - - return typeResp.value; - } - - /** - * Checks for a successful status result. - * - * Failures are logged to mLog. - * - * @param status is the WifiStatus generated by a hal call - * @return true for success, false for failure - */ - private boolean ok(String method, WifiStatus status) { - if (status.code == WifiStatusCode.SUCCESS) return true; - - Log.e(TAG, "Error on " + method + ": " + statusString(status)); - return false; + return -1; } private static SparseBooleanArray convertRadioCombinationMatrixToLookupTable( - WifiRadioCombinationMatrix matrix) { + WifiChip.WifiRadioCombinationMatrix matrix) { SparseBooleanArray lookupTable = new SparseBooleanArray(); - if (null == matrix) return lookupTable; + if (matrix == null) return lookupTable; - for (WifiRadioCombination combination: matrix.radioCombinations) { + for (WifiChip.WifiRadioCombination combination : matrix.radioCombinations) { int bandMask = 0; - for (WifiRadioConfiguration config: combination.radioConfigurations) { - bandMask |= 1 << config.bandInfo; + for (WifiChip.WifiRadioConfiguration config : combination.radioConfigurations) { + bandMask |= config.bandInfo; } if ((bandMask & DBS_24G_5G_MASK) == DBS_24G_5G_MASK) { lookupTable.put(DBS_24G_5G_MASK, true); @@ -3436,36 +2666,24 @@ public class HalDeviceManager { } /** - * Get the chip capabilities - * - * This is called before creating an interface and needs at least v1.5 HAL. + * Get the chip capabilities. * - * @param wifiChip WifiChip - * @return bitmask defined by HAL interface + * @param wifiChip WifiChip to get the features for. + * @return Bitset of WifiManager.WIFI_FEATURE_* values. */ - public long getChipCapabilities(@NonNull IWifiChip wifiChip) { - long featureSet = 0; - if (wifiChip == null) return featureSet; - - try { - final Mutable<Long> feat = new Mutable<>(CHIP_CAPABILITY_UNINITIALIZED); - synchronized (mLock) { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = - getWifiChipForV1_5Mockable(wifiChip); - // HAL newer than v1.5 support getting capabilities before creating an interface. - if (iWifiChipV15 != null) { - iWifiChipV15.getCapabilities_1_5((status, capabilities) -> { - if (!ok("getCapabilities_1_5", status)) return; - feat.value = (long) capabilities; - }); - } - } - featureSet = feat.value; - } catch (RemoteException e) { - Log.e(TAG, "Exception on getCapabilities: " + e); + public long getChipCapabilities(@NonNull WifiChip wifiChip) { + if (wifiChip == null) return 0; + + WifiChip.Response<Long> capsResp = wifiChip.getCapabilitiesBeforeIfacesExist(); + if (capsResp.getStatusCode() == WifiHal.WIFI_STATUS_SUCCESS) { + return 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. + return CHIP_CAPABILITY_UNINITIALIZED; + } else { // remote exception return 0; } - return featureSet; } /** @@ -3476,35 +2694,11 @@ public class HalDeviceManager { * @param wifiChip WifiChip * @return Wifi radio combinmation matrix */ - private WifiRadioCombinationMatrix getChipSupportedRadioCombinationsMatrix( - @NonNull IWifiChip wifiChip) { + private WifiChip.WifiRadioCombinationMatrix getChipSupportedRadioCombinationsMatrix( + @NonNull WifiChip wifiChip) { synchronized (mLock) { - if (null == wifiChip) return null; - android.hardware.wifi.V1_6.IWifiChip chipV16 = - getWifiChipForV1_6Mockable(wifiChip); - if (null == chipV16) return null; - - Mutable<WifiRadioCombinationMatrix> radioCombinationMatrixResp = - new Mutable<>(); - radioCombinationMatrixResp.value = null; - try { - chipV16.getSupportedRadioCombinationsMatrix((WifiStatus status, - WifiRadioCombinationMatrix matrix) -> { - if (status.code == WifiStatusCode.SUCCESS) { - radioCombinationMatrixResp.value = matrix; - if (mDbg) { - Log.d(TAG, "radioCombinationMatrix=" + matrix); - } - } else { - Log.e(TAG, "getSupportedRadioCombinationsMatrix failed: " - + statusString(status)); - } - }); - } catch (RemoteException e) { - Log.e(TAG, "Exception on getSupportedRadioCombinationsMatrix: " + e); - radioCombinationMatrixResp.value = null; - } - return radioCombinationMatrixResp.value; + if (wifiChip == null) return null; + return wifiChip.getSupportedRadioCombinationsMatrix(); } } @@ -3513,8 +2707,6 @@ public class HalDeviceManager { */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Dump of HalDeviceManager:"); - pw.println(" mServiceManager: " + mServiceManager); - pw.println(" mWifi: " + mWifi); pw.println(" mManagerStatusListeners: " + mManagerStatusListeners); pw.println(" mInterfaceInfoCache: " + mInterfaceInfoCache); pw.println(" mDebugChipsInfo: " + Arrays.toString(getAllChipInfo())); diff --git a/service/java/com/android/server/wifi/HalDeviceManagerUtil.java b/service/java/com/android/server/wifi/HalDeviceManagerUtil.java index 08a4727924..5897307522 100644 --- a/service/java/com/android/server/wifi/HalDeviceManagerUtil.java +++ b/service/java/com/android/server/wifi/HalDeviceManagerUtil.java @@ -17,13 +17,15 @@ package com.android.server.wifi; import android.annotation.NonNull; -import android.hardware.wifi.V1_6.IWifiChip; + +import com.android.server.wifi.hal.WifiChip; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; +import java.util.List; /** * Utility methods for HalDeviceManager. @@ -32,13 +34,12 @@ public class HalDeviceManagerUtil { static class StaticChipInfo { private int mChipId; private long mChipCapabilities; - private @NonNull ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> mAvailableModes = - new ArrayList<>(); + private @NonNull ArrayList<WifiChip.ChipMode> mAvailableModes = new ArrayList<>(); StaticChipInfo( int chipId, long chipCapabilities, - @NonNull ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> availableModes) { + @NonNull ArrayList<WifiChip.ChipMode> availableModes) { mChipId = chipId; mChipCapabilities = chipCapabilities; if (availableModes != null) { @@ -54,7 +55,7 @@ public class HalDeviceManagerUtil { return mChipCapabilities; } - ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> getAvailableModes() { + ArrayList<WifiChip.ChipMode> getAvailableModes() { return mAvailableModes; } } @@ -69,8 +70,7 @@ public class HalDeviceManagerUtil { jsonObject.put(KEY_CHIP_ID, staticChipInfo.getChipId()); jsonObject.put(KEY_CHIP_CAPABILITIES, staticChipInfo.getChipCapabilities()); JSONArray availableModesJson = new JSONArray(); - for (android.hardware.wifi.V1_6.IWifiChip.ChipMode mode - : staticChipInfo.getAvailableModes()) { + for (WifiChip.ChipMode mode : staticChipInfo.getAvailableModes()) { availableModesJson.put(chipModeToJson(mode)); } jsonObject.put(KEY_AVAILABLE_MODES, availableModesJson); @@ -78,8 +78,7 @@ public class HalDeviceManagerUtil { } static StaticChipInfo jsonToStaticChipInfo(JSONObject jsonObject) throws JSONException { - ArrayList<IWifiChip.ChipMode> availableModes = - new ArrayList<>(); + ArrayList<WifiChip.ChipMode> availableModes = new ArrayList<>(); int chipId = jsonObject.getInt(KEY_CHIP_ID); long chipCapabilities = jsonObject.getLong(KEY_CHIP_CAPABILITIES); JSONArray modesJson = jsonObject.getJSONArray(KEY_AVAILABLE_MODES); @@ -92,80 +91,72 @@ public class HalDeviceManagerUtil { private static final String KEY_ID = "id"; private static final String KEY_AVAILABLE_COMBINATIONS = "availableCombinations"; - private static JSONObject chipModeToJson(android.hardware.wifi.V1_6.IWifiChip.ChipMode chipMode) + private static JSONObject chipModeToJson(WifiChip.ChipMode chipMode) throws JSONException { JSONObject jsonObject = new JSONObject(); jsonObject.put(KEY_ID, chipMode.id); JSONArray availableCombinationsJson = new JSONArray(); - for (IWifiChip.ChipConcurrencyCombination combo - : chipMode.availableCombinations) { + for (WifiChip.ChipConcurrencyCombination combo : chipMode.availableCombinations) { availableCombinationsJson.put(chipConcurrencyCombinationToJson(combo)); } jsonObject.put(KEY_AVAILABLE_COMBINATIONS, availableCombinationsJson); return jsonObject; } - private static android.hardware.wifi.V1_6.IWifiChip.ChipMode jsonToChipMode( - JSONObject jsonObject) throws JSONException { - android.hardware.wifi.V1_6.IWifiChip.ChipMode chipMode = - new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - chipMode.id = jsonObject.getInt(KEY_ID); + private static WifiChip.ChipMode jsonToChipMode(JSONObject jsonObject) throws JSONException { + List<WifiChip.ChipConcurrencyCombination> availableCombinations = new ArrayList<>(); JSONArray availableCombinationsJson = jsonObject.getJSONArray(KEY_AVAILABLE_COMBINATIONS); for (int i = 0; i < availableCombinationsJson.length(); i++) { - chipMode.availableCombinations.add(jsonToChipConcurrencyCombination( + availableCombinations.add(jsonToChipConcurrencyCombination( availableCombinationsJson.getJSONObject(i))); } - return chipMode; + return new WifiChip.ChipMode(jsonObject.getInt(KEY_ID), availableCombinations); } private static final String KEY_CONCURRENCY_LIMITS = "limits"; private static JSONObject chipConcurrencyCombinationToJson( - IWifiChip.ChipConcurrencyCombination combo) throws JSONException { + WifiChip.ChipConcurrencyCombination combo) throws JSONException { JSONObject jsonObject = new JSONObject(); JSONArray limitsJson = new JSONArray(); - for (IWifiChip.ChipConcurrencyCombinationLimit limit : combo.limits) { + for (WifiChip.ChipConcurrencyCombinationLimit limit : combo.limits) { limitsJson.put(chipConcurrencyCombinationLimitToJson(limit)); } jsonObject.put(KEY_CONCURRENCY_LIMITS, limitsJson); return jsonObject; } - private static IWifiChip.ChipConcurrencyCombination jsonToChipConcurrencyCombination( + private static WifiChip.ChipConcurrencyCombination jsonToChipConcurrencyCombination( JSONObject jsonObject) throws JSONException { - IWifiChip.ChipConcurrencyCombination combo = new IWifiChip.ChipConcurrencyCombination(); - combo.limits = new ArrayList<>(); + List<WifiChip.ChipConcurrencyCombinationLimit> limits = new ArrayList<>(); JSONArray limitsJson = jsonObject.getJSONArray(KEY_CONCURRENCY_LIMITS); for (int i = 0; i < limitsJson.length(); i++) { - combo.limits.add( + limits.add( jsonToChipConcurrencyCombinationLimit(limitsJson.getJSONObject(i))); } - return combo; + return new WifiChip.ChipConcurrencyCombination(limits); } private static final String KEY_MAX_IFACES = "maxIfaces"; private static final String KEY_TYPES = "types"; private static JSONObject chipConcurrencyCombinationLimitToJson( - IWifiChip.ChipConcurrencyCombinationLimit limit) throws JSONException { + WifiChip.ChipConcurrencyCombinationLimit limit) throws JSONException { JSONObject jsonObject = new JSONObject(); jsonObject.put(KEY_MAX_IFACES, limit.maxIfaces); jsonObject.put(KEY_TYPES, new JSONArray(limit.types)); return jsonObject; } - private static IWifiChip.ChipConcurrencyCombinationLimit jsonToChipConcurrencyCombinationLimit( + private static WifiChip.ChipConcurrencyCombinationLimit jsonToChipConcurrencyCombinationLimit( JSONObject jsonObject) throws JSONException { - IWifiChip.ChipConcurrencyCombinationLimit - limit = new IWifiChip.ChipConcurrencyCombinationLimit(); - limit.maxIfaces = jsonObject.getInt(KEY_MAX_IFACES); - limit.types = new ArrayList<>(); + List<Integer> types = new ArrayList<>(); JSONArray limitsJson = jsonObject.getJSONArray(KEY_TYPES); for (int i = 0; i < limitsJson.length(); i++) { - limit.types.add(limitsJson.getInt(i)); + types.add(limitsJson.getInt(i)); } - return limit; + return new WifiChip.ChipConcurrencyCombinationLimit( + jsonObject.getInt(KEY_MAX_IFACES), types); } } - diff --git a/service/java/com/android/server/wifi/InterfaceConflictManager.java b/service/java/com/android/server/wifi/InterfaceConflictManager.java index 8faba11d32..bb2cf2114e 100644 --- a/service/java/com/android/server/wifi/InterfaceConflictManager.java +++ b/service/java/com/android/server/wifi/InterfaceConflictManager.java @@ -44,6 +44,7 @@ import androidx.annotation.NonNull; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.wifi.util.WaitingState; +import com.android.server.wifi.util.WorkSourceHelper; import com.android.wifi.resources.R; import java.io.FileDescriptor; @@ -129,30 +130,67 @@ public class InterfaceConflictManager { } /** - * Returns an indication as to whether user approval is needed for this specific request. User - * approval is controlled by: + * Returns whether user approval is needed to delete an existing interface for a new one. + * User approval is controlled by: * - A global overlay `config_wifiUserApprovalRequiredForD2dInterfacePriority` * - An exemption list overlay `config_wifiExcludedFromUserApprovalForD2dInterfacePriority` * which is a list of packages which are *exempted* from user approval * - A shell command which can be used to override * - * @param requestorWs The WorkSource of the requestor - used to determine whether it is exempted - * from user approval. All requesting packages must be exempted for the - * dialog to NOT be displayed. + * @param requestedCreateType Requested interface type + * @param newRequestorWsHelper WorkSourceHelper of the new interface + * @param existingCreateType Existing interface type + * @param existingRequestorWsHelper WorkSourceHelper of the existing interface + * @return true if the new interface needs user approval to delete the existing one. */ - private boolean isUserApprovalNeeded(WorkSource requestorWs) { - if (mUserApprovalNeededOverride) return mUserApprovalNeededOverrideValue; - if (!mUserApprovalNeeded || mUserApprovalExemptedPackages.isEmpty()) { - return mUserApprovalNeeded; + public boolean needsUserApprovalToDelete( + int requestedCreateType, @NonNull WorkSourceHelper newRequestorWsHelper, + int existingCreateType, @NonNull WorkSourceHelper existingRequestorWsHelper) { + if (!isUserApprovalEnabled()) { + return false; } - for (int i = 0; i < requestorWs.size(); ++i) { - if (!mUserApprovalExemptedPackages.contains(requestorWs.getPackageName(i))) { + // Check if every package in the WorkSource are exempt from user approval. + if (!mUserApprovalExemptedPackages.isEmpty()) { + boolean exemptFromUserApproval = true; + WorkSource requestorWs = newRequestorWsHelper.getWorkSource(); + for (int i = 0; i < requestorWs.size(); i++) { + if (!mUserApprovalExemptedPackages.contains(requestorWs.getPackageName(i))) { + exemptFromUserApproval = false; + break; + } + } + if (exemptFromUserApproval) { + return false; + } + } + // Check if priority level can get user approval. + if (newRequestorWsHelper.getRequestorWsPriority() <= WorkSourceHelper.PRIORITY_BG + || existingRequestorWsHelper.getRequestorWsPriority() + == WorkSourceHelper.PRIORITY_INTERNAL) { + return false; + } + // Check if the conflicting interface types can get user approval. + if (requestedCreateType == HDM_CREATE_IFACE_AP + || requestedCreateType == HDM_CREATE_IFACE_AP_BRIDGE) { + if (existingCreateType == HDM_CREATE_IFACE_P2P + || existingCreateType == HDM_CREATE_IFACE_NAN) { + return true; + } + } else if (requestedCreateType == HDM_CREATE_IFACE_P2P) { + if (existingCreateType == HDM_CREATE_IFACE_AP + || existingCreateType == HDM_CREATE_IFACE_AP_BRIDGE + || existingCreateType == HDM_CREATE_IFACE_NAN) { + return true; + } + } else if (requestedCreateType == HDM_CREATE_IFACE_NAN) { + if (existingCreateType == HDM_CREATE_IFACE_AP + || existingCreateType == HDM_CREATE_IFACE_AP_BRIDGE + || existingCreateType == HDM_CREATE_IFACE_P2P) { return true; } } - - return false; // all packages of the requestor are excluded + return false; } /** @@ -169,6 +207,13 @@ public class InterfaceConflictManager { mUserApprovalNeededOverrideValue = overrideValue; } + private boolean isUserApprovalEnabled() { + if (mUserApprovalNeededOverride) { + return mUserApprovalNeededOverrideValue; + } + return mUserApprovalNeeded; + } + /** * Return values for {@link #manageInterfaceConflictForStateMachine} */ @@ -240,6 +285,7 @@ public class InterfaceConflictManager { @HalDeviceManager.HdmIfaceTypeForCreation int createIfaceType, WorkSource requestorWs, boolean bypassDialog) { synchronized (mLock) { + // Check if we're waiting for user approval for a different caller. if (mUserApprovalPending && !TextUtils.equals(tag, mUserApprovalPendingTag)) { Log.w(TAG, tag + ": rejected since there's a pending user approval for " + mUserApprovalPendingTag); @@ -261,6 +307,7 @@ public class InterfaceConflictManager { return mUserJustApproved ? ICM_EXECUTE_COMMAND : ICM_ABORT_COMMAND; } + // Check if we're already waiting for user approval for this caller. if (mUserApprovalPending) { Log.w(TAG, tag + ": trying for another potentially waiting operation - but should be" @@ -269,8 +316,13 @@ public class InterfaceConflictManager { return ICM_SKIP_COMMAND_WAIT_FOR_USER; // same effect } - if (bypassDialog || !isUserApprovalNeeded(requestorWs)) return ICM_EXECUTE_COMMAND; + // Execute the command if the dialogs aren't enabled. + if (!isUserApprovalEnabled()) return ICM_EXECUTE_COMMAND; + + // Auto-approve dialog if bypass is specified. + if (bypassDialog) return ICM_EXECUTE_COMMAND; + // Check if we need to show the dialog. List<Pair<Integer, WorkSource>> impact = mHdm.reportImpactToCreateIface(createIfaceType, false, requestorWs); localLog(tag + ": Asking user about creating the interface, impact=" + impact); @@ -280,6 +332,7 @@ public class InterfaceConflictManager { return ICM_EXECUTE_COMMAND; } + // Auto-approve dialog if we only need to delete a disconnected P2P. if (mUserApprovalNotRequireForDisconnectedP2p && !mIsP2pConnected && impact.size() == 1 && impact.get(0).first == HDM_CREATE_IFACE_P2P) { localLog(tag @@ -289,7 +342,7 @@ public class InterfaceConflictManager { boolean shouldShowDialogToDelete = false; for (Pair<Integer, WorkSource> ifaceToDelete : impact) { - if (mHdm.needsUserApprovalToDelete( + if (needsUserApprovalToDelete( createIfaceType, mWifiInjector.makeWsHelper(requestorWs), ifaceToDelete.first, mWifiInjector.makeWsHelper(ifaceToDelete.second))) { shouldShowDialogToDelete = true; diff --git a/service/java/com/android/server/wifi/MultiInternetManager.java b/service/java/com/android/server/wifi/MultiInternetManager.java index ed1212d048..6afdde7ad5 100644 --- a/service/java/com/android/server/wifi/MultiInternetManager.java +++ b/service/java/com/android/server/wifi/MultiInternetManager.java @@ -28,6 +28,8 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.WorkSource; +import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; @@ -38,6 +40,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Map; /** * Manages STA + STA for multi internet networks. @@ -84,6 +87,7 @@ public class MultiInternetManager { public long connectionStartTimeMillis; // The WorkSource of the connection requestor. public WorkSource requestorWorkSource; + public String bssid; NetworkConnectionState(WorkSource workSource) { this(workSource, -1L); @@ -95,6 +99,7 @@ public class MultiInternetManager { mConnected = false; mValidated = false; + bssid = null; } public NetworkConnectionState setConnected(boolean connected) { @@ -173,7 +178,9 @@ public class MultiInternetManager { } final ConcreteClientModeManager ccm = (ConcreteClientModeManager) activeModeManager; // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET - if (ccm.getRole() != ROLE_CLIENT_SECONDARY_LONG_LIVED || !ccm.isSecondaryInternet()) { + // Needs to call getPreviousRole here since the role is set to null after a CMM stops + if (ccm.getPreviousRole() != ROLE_CLIENT_SECONDARY_LONG_LIVED + || !ccm.isSecondaryInternet()) { return; } if (mVerboseLoggingEnabled) { @@ -213,7 +220,7 @@ public class MultiInternetManager { || !isStaConcurrencyForMultiInternetEnabled()) { return; } - final WifiInfo info = clientModeManager.syncRequestConnectionInfo(); + final WifiInfo info = clientModeManager.getConnectionInfo(); if (info != null) { final int band = ScanResult.toBand(info.getFrequency()); if (mNetworkConnectionStates.contains(band)) { @@ -367,6 +374,7 @@ public class MultiInternetManager { if (mode == mStaConcurrencyMultiInternetMode) { return true; } + mStaConcurrencyMultiInternetMode = mode; // If the STA+STA multi internet feature was disabled, disconnect the secondary cmm. // TODO: b/197670907 : Add client role ROLE_CLIENT_SECONDARY_INTERNET if (!enabled) { @@ -376,10 +384,6 @@ public class MultiInternetManager { cmm.disconnect(); } } - for (int i = 0; i < mNetworkConnectionStates.size(); i++) { - // Clear the connection state for all bands. - mNetworkConnectionStates.setValueAt(i, new NetworkConnectionState(null)); - } handleConnectionStateChange(MULTI_INTERNET_STATE_NONE, null); } else { updateNetworkConnectionStates(); @@ -389,7 +393,7 @@ public class MultiInternetManager { getRequestorWorkSource(band)); } } - mStaConcurrencyMultiInternetMode = mode; + mSettingsStore.handleWifiMultiInternetMode(mode); // Check if there is already multi internet request then start scan for connection. if (hasPendingConnectionRequests()) { @@ -422,14 +426,14 @@ public class MultiInternetManager { } // If primary CMM has associated to a new BSSID, need to check if it is in a different band // of secondary CMM. - final WifiInfo info = clientModeManager.syncRequestConnectionInfo(); + final WifiInfo info = clientModeManager.getConnectionInfo(); final ConcreteClientModeManager secondaryCcmm = mActiveModeWarden.getClientModeManagerInRole(ROLE_CLIENT_SECONDARY_LONG_LIVED); // If no secondary client mode manager then it's ok if (secondaryCcmm == null) return; // If secondary client mode manager is not connected or not for secondary internet if (!secondaryCcmm.isConnected() || !secondaryCcmm.isSecondaryInternet()) return; - final WifiInfo info2 = secondaryCcmm.syncRequestConnectionInfo(); + final WifiInfo info2 = secondaryCcmm.getConnectionInfo(); // If secondary network is in same band as primary now if (ScanResult.toBand(info.getFrequency()) == ScanResult.toBand(info2.getFrequency())) { // Need to disconnect secondary network @@ -450,20 +454,13 @@ public class MultiInternetManager { } /** - * Check if there is connection request on a specific band. - * @param band The band for the connection request. - * @return true if there is connection request on specific band. - */ - public boolean hasConnectionRequest(int band) { - return mNetworkConnectionStates.contains(band) - ? (getRequestorWorkSource(band) != null) : false; - } - - /** * Check if there is unconnected network connection request. * @return the band of the connection request that is still not connected. */ public int findUnconnectedRequestBand() { + if (mStaConcurrencyMultiInternetMode == WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED) { + return ScanResult.UNSPECIFIED; + } for (int i = 0; i < mNetworkConnectionStates.size(); i++) { if (!mNetworkConnectionStates.valueAt(i).isConnected()) { return mNetworkConnectionStates.keyAt(i); @@ -473,6 +470,22 @@ public class MultiInternetManager { } /** + * Return the mapping from band (one of ScanResult.WIFI_BAND_*) to the specified BSSID for that + * band. + */ + public Map<Integer, String> getSpecifiedBssids() { + Map<Integer, String> result = new ArrayMap<>(); + for (int i = 0; i < mNetworkConnectionStates.size(); i++) { + int band = mNetworkConnectionStates.keyAt(i); + String bssid = mNetworkConnectionStates.valueAt(i).bssid; + if (bssid != null) { + result.put(band, bssid); + } + } + return result; + } + + /** * Traverse the client mode managers and update the internal connection states. */ private void updateNetworkConnectionStates() { @@ -492,7 +505,7 @@ public class MultiInternetManager { && !ccmm.isSecondaryInternet()) { continue; } - WifiInfo info = clientModeManager.syncRequestConnectionInfo(); + WifiInfo info = clientModeManager.getConnectionInfo(); // Exclude the network that is not connected or restricted. if (info == null || !clientModeManager.isConnected() || info.isRestricted()) continue; @@ -534,14 +547,15 @@ public class MultiInternetManager { * @param requestorWs The requestor's WorkSource. Null to clear a network request for a * a band. */ - public void setMultiInternetConnectionWorksource(int band, WorkSource requestorWs) { + public void setMultiInternetConnectionWorksource(int band, String targetBssid, + WorkSource requestorWs) { if (!isStaConcurrencyForMultiInternetEnabled()) { Log.w(TAG, "MultInternet is not enabled."); return; } if (mVerboseLoggingEnabled) { - Log.v(TAG, "setMultiInternetConnectionWorksource: band=" + band + ", requestorWs=" - + requestorWs); + Log.v(TAG, "setMultiInternetConnectionWorksource: band=" + band + ", bssid=" + + targetBssid + ", requestorWs=" + requestorWs); } if (requestorWs == null) { // Disconnect secondary network if the request is removed. @@ -559,12 +573,48 @@ public class MultiInternetManager { } if (mNetworkConnectionStates.contains(band)) { Log.w(TAG, "band " + band + " already requested."); + if (TextUtils.equals(mNetworkConnectionStates.get(band).bssid, targetBssid)) { + // No change in BSSID field, so early return to avoid unnecessary scanning. + return; + } + disconnectSecondaryIfNeeded(band, targetBssid); } - mNetworkConnectionStates.put(band, new NetworkConnectionState(requestorWs, - mClock.getElapsedSinceBootMillis())); + NetworkConnectionState connectionState = new NetworkConnectionState(requestorWs, + mClock.getElapsedSinceBootMillis()); + connectionState.bssid = targetBssid; + mNetworkConnectionStates.put(band, connectionState); startConnectivityScan(); } + /** + * Disconnect the secondary that's connected to the same band but different bssid. + */ + private void disconnectSecondaryIfNeeded(int band, String targetBssid) { + if (targetBssid == null) { + return; + } + for (ConcreteClientModeManager cmm : mActiveModeWarden.getClientModeManagersInRoles( + ROLE_CLIENT_SECONDARY_LONG_LIVED)) { + if (cmm.isSecondaryInternet()) { + WifiInfo wifiInfo = cmm.getConnectionInfo(); + if (band != ScanResult.toBand(wifiInfo.getFrequency())) { + continue; + } + String connectingBssid = cmm.getConnectingBssid(); + String connectedBssid = cmm.getConnectedBssid(); + if ((connectingBssid != null && !connectingBssid.equals(targetBssid)) + || (connectedBssid != null && !connectedBssid.equals(targetBssid))) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Disconnect secondary client mode manager due to specified" + + " BSSID in the same band"); + } + cmm.disconnect(); + break; + } + } + } + } + /** Returns the band of the secondary network connected. */ private int getSecondaryConnectedNetworkBand() { final ConcreteClientModeManager secondaryCcmm = @@ -572,7 +622,7 @@ public class MultiInternetManager { if (secondaryCcmm == null) { return ScanResult.UNSPECIFIED; } - final WifiInfo info = secondaryCcmm.syncRequestConnectionInfo(); + final WifiInfo info = secondaryCcmm.getConnectionInfo(); // Make sure secondary network is connected. if (info == null || !secondaryCcmm.isConnected() || !secondaryCcmm.isSecondaryInternet()) { return ScanResult.UNSPECIFIED; @@ -624,7 +674,8 @@ public class MultiInternetManager { pw.println(TAG + ": mStaConcurrencyMultiInternetMode " + mStaConcurrencyMultiInternetMode); for (int i = 0; i < mNetworkConnectionStates.size(); i++) { - pw.println("band " + mNetworkConnectionStates.keyAt(i) + " connected " + pw.println("band " + mNetworkConnectionStates.keyAt(i) + " bssid " + + mNetworkConnectionStates.valueAt(i).bssid + " connected " + mNetworkConnectionStates.valueAt(i).isConnected() + " validated " + mNetworkConnectionStates.valueAt(i).isValidated()); } diff --git a/service/java/com/android/server/wifi/MultiInternetWifiNetworkFactory.java b/service/java/com/android/server/wifi/MultiInternetWifiNetworkFactory.java index 1cdcda74f8..543fae46b5 100644 --- a/service/java/com/android/server/wifi/MultiInternetWifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/MultiInternetWifiNetworkFactory.java @@ -91,7 +91,8 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { * @param networkRequest the network requested by connectivity service * @return true if the request if for multi internet Wifi network, false if not. */ - public static boolean isWifiMultiInternetRequest(NetworkRequest networkRequest) { + public static boolean isWifiMultiInternetRequest(NetworkRequest networkRequest, + boolean isFromSettings) { if (networkRequest.getNetworkSpecifier() == null || !(networkRequest.getNetworkSpecifier() instanceof WifiNetworkSpecifier)) { return false; @@ -101,7 +102,7 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { // and must not have SSID/BSSID pattern matcher. if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && wns.getBand() != ScanResult.UNSPECIFIED - && WifiConfigurationUtil.isMatchAllNetworkSpecifier(wns)) { + && (isFromSettings || WifiConfigurationUtil.isMatchAllNetworkSpecifier(wns))) { return true; } return false; @@ -137,13 +138,13 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { */ @Override public boolean acceptRequest(NetworkRequest networkRequest) { - if (!mMultiInternetManager.isStaConcurrencyForMultiInternetEnabled() - || !isWifiMultiInternetRequest(networkRequest)) { - return false; - } final int uid = networkRequest.getRequestorUid(); boolean isFromSetting = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid); + if (!mMultiInternetManager.isStaConcurrencyForMultiInternetEnabled() + || !isWifiMultiInternetRequest(networkRequest, isFromSetting)) { + return false; + } boolean isFromNetworkStack = mWifiPermissionsUtil.checkNetworkStackPermission(uid) || mWifiPermissionsUtil.checkMainlineNetworkStackPermission(uid); // Only allow specific wifi network request with band from apps or services with settings @@ -164,14 +165,14 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { @Override protected void needNetworkFor(NetworkRequest networkRequest) { + boolean isFromSetting = mWifiPermissionsUtil.checkNetworkSettingsPermission( + networkRequest.getRequestorUid()); if (!mMultiInternetManager.isStaConcurrencyForMultiInternetEnabled() - || !isWifiMultiInternetRequest(networkRequest)) { + || !isWifiMultiInternetRequest(networkRequest, isFromSetting)) { return; } WifiNetworkSpecifier wns = (WifiNetworkSpecifier) networkRequest.getNetworkSpecifier(); final int band = wns.getBand(); - boolean isFromSetting = mWifiPermissionsUtil.checkNetworkSettingsPermission( - networkRequest.getRequestorUid()); boolean isFromForegroundApp = mFacade.isRequestFromForegroundApp(mContext, networkRequest.getRequestorPackageName()); boolean isFromForegroundAppOrService = @@ -180,7 +181,7 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { NetworkRequestState nrs = new NetworkRequestState(networkRequest, new WifiNetworkSpecifier( wns.ssidPatternMatcher, wns.bssidPatternMatcher, wns.getBand(), - wns.wifiConfiguration), + wns.wifiConfiguration, wns.getPreferredChannelFrequenciesMhz()), isFromSetting, isFromForegroundApp, isFromForegroundAppOrService); @@ -193,13 +194,14 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { if (mConnectionReqCount.contains(band)) { reqCount = mConnectionReqCount.get(band); } - if (reqCount == 0) { + if (reqCount == 0 || isFromSetting) { localLog("Need network : Uid " + networkRequest.getRequestorUid() + " PackageName " + networkRequest.getRequestorPackageName() + " for band " + band + " is rom Setting " + isFromSetting + " ForegroundApp " + isFromForegroundApp + " ForegroundAppOrService " + isFromForegroundApp); mMultiInternetManager.setMultiInternetConnectionWorksource( - band, new WorkSource(networkRequest.getRequestorUid(), + band, wns.wifiConfiguration.BSSID, + new WorkSource(networkRequest.getRequestorUid(), networkRequest.getRequestorPackageName())); } mConnectionReqCount.put(band, reqCount + 1); @@ -207,7 +209,9 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { @Override protected void releaseNetworkFor(NetworkRequest networkRequest) { - if (!isWifiMultiInternetRequest(networkRequest)) { + boolean isFromSetting = mWifiPermissionsUtil.checkNetworkSettingsPermission( + networkRequest.getRequestorUid()); + if (!isWifiMultiInternetRequest(networkRequest, isFromSetting)) { return; } localLog("releaseNetworkFor " + networkRequest); @@ -219,7 +223,7 @@ public class MultiInternetWifiNetworkFactory extends NetworkFactory { return; } if (reqCount == 1) { - mMultiInternetManager.setMultiInternetConnectionWorksource(band, null); + mMultiInternetManager.setMultiInternetConnectionWorksource(band, null, null); } mConnectionReqCount.put(band, reqCount - 1); } diff --git a/service/java/com/android/server/wifi/NetworkConnectionEventInfo.java b/service/java/com/android/server/wifi/NetworkConnectionEventInfo.java index c73e7dafe2..55f6bbaf3c 100644 --- a/service/java/com/android/server/wifi/NetworkConnectionEventInfo.java +++ b/service/java/com/android/server/wifi/NetworkConnectionEventInfo.java @@ -19,6 +19,8 @@ package com.android.server.wifi; import android.annotation.NonNull; import android.net.wifi.WifiSsid; +import java.util.BitSet; + /** Data class to hold information for a {@link WifiMonitor#NETWORK_CONNECTION_EVENT}. */ public class NetworkConnectionEventInfo { public final int networkId; @@ -27,13 +29,15 @@ public class NetworkConnectionEventInfo { @NonNull public final String bssid; public final boolean isFilsConnection; + public final BitSet keyMgmtMask; public NetworkConnectionEventInfo(int networkId, WifiSsid wifiSsid, String bssid, - boolean isFilsConnection) { + boolean isFilsConnection, BitSet keyMgmtMask) { this.networkId = networkId; this.wifiSsid = wifiSsid; this.bssid = bssid; this.isFilsConnection = isFilsConnection; + this.keyMgmtMask = keyMgmtMask; } @Override @@ -43,6 +47,7 @@ public class NetworkConnectionEventInfo { + ", wifiSsid=" + wifiSsid + ", bssid='" + bssid + '\'' + ", isFilsConnection=" + isFilsConnection + + ", keyMgmtMask=" + keyMgmtMask + '}'; } } diff --git a/service/java/com/android/server/wifi/RunnerHandler.java b/service/java/com/android/server/wifi/RunnerHandler.java new file mode 100644 index 0000000000..19e756a8b4 --- /dev/null +++ b/service/java/com/android/server/wifi/RunnerHandler.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2022 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.annotation.NonNull; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; +import android.os.Trace; +import android.util.LocalLog; + +import com.android.modules.utils.HandlerExecutor; + +import java.util.HashSet; +import java.util.Set; + +/** + * RunnerHandler tracks all the Runnable jobs posted to the handler for the running time and + * monitor if the running time exceeds the expected threshold. + * + */ +public class RunnerHandler extends Handler { + private static final String TAG = "WifiThreadRunner"; + + private static final String KEY_SIGNATURE = "KEY_RUNNER_HANDLER_SIGNATURE"; + private static final String KEY_WHEN = "KEY_RUNNER_HANDLER_WHEN"; + + private final int mRunningTimeThresholdInMilliseconds; + + private Set<String> mIgnoredClasses = new HashSet<>(); + private Set<String> mIgnoredMethods = new HashSet<>(); + + // TODO: b/246623192 Add Wifi metric for Runner state overruns. + private final LocalLog mLocalLog; + + /** + * The Runner handler Constructor + * @param looper looper for the handler + * @param threshold the running time threshold in milliseconds + */ + public RunnerHandler(Looper looper, int threshold, @NonNull LocalLog localLog) { + super(looper); + mRunningTimeThresholdInMilliseconds = threshold; + mLocalLog = localLog; + mIgnoredClasses.add(WifiThreadRunner.class.getName()); + mIgnoredClasses.add(WifiThreadRunner.class.getName() + "$BlockingRunnable"); + mIgnoredClasses.add(RunnerHandler.class.getName()); + mIgnoredClasses.add(HandlerExecutor.class.getName()); + mIgnoredClasses.add(Handler.class.getName()); + mIgnoredClasses.add(HandlerThread.class.getName()); + mIgnoredClasses.add(Looper.class.getName()); + mIgnoredMethods.add("handleMessage"); + } + + private String getSignature(StackTraceElement[] elements, Runnable callback) { + StringBuilder sb = new StringBuilder(); + for (StackTraceElement e : elements) { + // Go through the stack elements to find out the caller who schedule the job. + // Ignore the stack frames generated with ignored classes and methods, until the stack + // frame where the runnable job is posted to the handler. + if (!mIgnoredClasses.contains(e.getClassName()) && !mIgnoredMethods.contains( + e.getMethodName())) { + String[] nameArr = e.getClassName().split("\\.", 5); + final int len = nameArr.length; + if (len > 0) { + sb.append(nameArr[len - 1]).append("#").append(e.getMethodName()); + break; + } + } + // The callback is the lambada function posted as Runnable#run function. + // If we can't identify the caller from the stack trace, then we will use the symbol + // of the lambada function as the signature of the caller. + if (HandlerThread.class.getName().equals(e.getClassName())) { + sb.append(callback); + break; + } + } + return sb.length() == 0 ? "<UNKNOWN>" : sb.toString(); + } + + @Override + public boolean sendMessageAtTime(Message msg, long uptimeMillis) { + String signature = getSignature(new Throwable("RunnerHandler:").getStackTrace(), + msg.getCallback()); + Bundle bundle = msg.getData(); + bundle.putString(KEY_SIGNATURE, signature); + return super.sendMessageAtTime(msg, uptimeMillis); + } + + @Override + public void dispatchMessage(@NonNull Message msg) { + final Bundle bundle = msg.getData(); + final String signature = bundle.getString(KEY_SIGNATURE); + if (signature != null) { + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signature); + } + // The message sent to front of the queue has when=0, get from the bundle in that case. + final long when = msg.getWhen() != 0 ? msg.getWhen() : bundle.getLong(KEY_WHEN); + final long start = SystemClock.uptimeMillis(); + final long scheduleLatency = start - when; + super.dispatchMessage(msg); + if (signature != null) { + Trace.traceEnd(Trace.TRACE_TAG_NETWORK); + } + final long runTime = SystemClock.uptimeMillis() - start; + final String signatureToLog = signature != null ? signature : "<EMPTY>"; + if (runTime > mRunningTimeThresholdInMilliseconds) { + mLocalLog.log(signatureToLog + " was running for " + runTime); + } + if (scheduleLatency > WifiThreadRunner.getScissorsTimeoutThreshold()) { + mLocalLog.log(signatureToLog + " schedule latency " + scheduleLatency + " ms"); + } + } + + /** + * Use this helper function rather than directly calling Handler#postAtFrontOfQueue, which does + * not call sendMessageAtTime and set the signature. This function will set the signature + * before enqueueing the message to front of the queue. + * @param r runnable to be queued to the front + * @return true when success + */ + public final boolean postToFront(@NonNull Runnable r) { + Message msg = Message.obtain(this, r); + String signature = getSignature(new Throwable("RunnerHandler:").getStackTrace(), + msg.getCallback()); + Bundle bundle = msg.getData(); + bundle.putString(KEY_SIGNATURE, signature); + bundle.putLong(KEY_WHEN, SystemClock.uptimeMillis()); + return sendMessageAtFrontOfQueue(msg); + } +} diff --git a/service/java/com/android/server/wifi/RunnerState.java b/service/java/com/android/server/wifi/RunnerState.java new file mode 100644 index 0000000000..d219ee91f8 --- /dev/null +++ b/service/java/com/android/server/wifi/RunnerState.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2022 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.annotation.NonNull; +import android.os.Message; +import android.os.Trace; +import android.util.LocalLog; + +import com.android.internal.util.State; + +/** + * RunnerState class is a wrapper based on State class to monitor and track the State enter/exit + * and message handler execution for taking longer time than the expected threshold. + * User must extend the RunnerState class instead of State, and provide the implementation of: + * { @link RunnerState#enterImpl() } { @link RunnerState#exitImpl() } + * { @link RunnerState#processMessageImpl() } + * { @link RunnerState#getMessageLogRec() } + * + */ +public abstract class RunnerState extends State { + private static final String TAG = "RunnerState"; + + /** Message.what value when entering */ + public static final int STATE_ENTER_CMD = -3; + + /** Message.what value when exiting */ + public static final int STATE_EXIT_CMD = -4; + + private final int mRunningTimeThresholdInMilliseconds; + // TODO: b/246623192 Add Wifi metric for Runner state overruns. + private final LocalLog mLocalLog; + + /** + * The Runner state Constructor + * @param threshold the running time threshold in milliseconds + */ + RunnerState(int threshold, @NonNull LocalLog localLog) { + mRunningTimeThresholdInMilliseconds = threshold; + mLocalLog = localLog; + } + + @Override + public boolean processMessage(Message message) { + Long startTime = System.currentTimeMillis(); + + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, getMessageLogRec(message.what)); + boolean ret = processMessageImpl(message); + Trace.traceEnd(Trace.TRACE_TAG_NETWORK); + Long runTime = System.currentTimeMillis() - startTime; + if (runTime > mRunningTimeThresholdInMilliseconds) { + mLocalLog.log(getMessageLogRec(message.what) + " was running for " + runTime + " ms"); + } + return ret; + } + + @Override + public void enter() { + Long startTime = System.currentTimeMillis(); + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, getMessageLogRec(STATE_ENTER_CMD)); + enterImpl(); + Trace.traceEnd(Trace.TRACE_TAG_NETWORK); + Long runTime = System.currentTimeMillis() - startTime; + if (runTime > mRunningTimeThresholdInMilliseconds) { + mLocalLog.log( + getMessageLogRec(STATE_ENTER_CMD) + " was running for " + runTime + " ms"); + } + } + + @Override + public void exit() { + Long startTime = System.currentTimeMillis(); + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, getMessageLogRec(STATE_EXIT_CMD)); + exitImpl(); + Trace.traceEnd(Trace.TRACE_TAG_NETWORK); + Long runTime = System.currentTimeMillis() - startTime; + if (runTime > mRunningTimeThresholdInMilliseconds) { + mLocalLog.log(getMessageLogRec(STATE_EXIT_CMD) + " was running for " + runTime + " ms"); + } + } + + /** + * Implement this method for State enter process, instead of enter() + */ + abstract void enterImpl(); + + /** + * Implement this method for State exit process, instead of exit() + */ + abstract void exitImpl(); + + /** + * Implement this method for State message processing, instead of processMessage() + */ + abstract boolean processMessageImpl(Message message); + + /** + * Implement this to translate a message `what` into a readable String + * @param what message 'what' field + * @return Readable string + */ + abstract String getMessageLogRec(int what); +} diff --git a/service/java/com/android/server/wifi/ScanRequestProxy.java b/service/java/com/android/server/wifi/ScanRequestProxy.java index f82da29170..abec2ebd52 100644 --- a/service/java/com/android/server/wifi/ScanRequestProxy.java +++ b/service/java/com/android/server/wifi/ScanRequestProxy.java @@ -39,9 +39,10 @@ import android.util.ArrayMap; import android.util.Log; import android.util.Pair; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.build.SdkLevel; +import com.android.server.wifi.scanner.WifiScannerInternal; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.wifi.resources.R; @@ -97,10 +98,12 @@ public class ScanRequestProxy { private final WifiMetrics mWifiMetrics; private final Clock mClock; private final WifiSettingsConfigStore mSettingsConfigStore; - private WifiScanner mWifiScanner; + private WifiScannerInternal mWifiScanner; // Verbose logging flag. private boolean mVerboseLoggingEnabled = false; + private final Object mThrottleEnabledLock = new Object(); + @GuardedBy("mThrottleEnabledLock") private boolean mThrottleEnabled = true; // Flag to decide if we need to scan or not. private boolean mScanningEnabled = false; @@ -119,7 +122,6 @@ public class ScanRequestProxy { private final Map<String, ScanResult> mLastScanResultsMap = new HashMap<>(); // external ScanResultCallback tracker private final RemoteCallbackList<IScanResultsCallback> mRegisteredScanResultsCallbacks; - // Global scan listener for listening to all scan requests. private class GlobalScanListener implements WifiScanner.ScanListener { @Override public void onSuccess() { @@ -233,22 +235,28 @@ public class ScanRequestProxy { mVerboseLoggingEnabled = verboseEnabled; } + private void updateThrottleEnabled() { + synchronized (mThrottleEnabledLock) { + // Start listening for throttle settings change after we retrieve scanner instance. + mThrottleEnabled = mSettingsConfigStore.get(WIFI_SCAN_THROTTLE_ENABLED); + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Scan throttle enabled " + mThrottleEnabled); + } + } + } + /** * Helper method to populate WifiScanner handle. This is done lazily because * WifiScanningService is started after WifiService. */ private boolean retrieveWifiScannerIfNecessary() { if (mWifiScanner == null) { - mWifiScanner = mWifiInjector.getWifiScanner(); - // Start listening for throttle settings change after we retrieve scanner instance. - mThrottleEnabled = mSettingsConfigStore.get(WIFI_SCAN_THROTTLE_ENABLED); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Scan throttle enabled " + mThrottleEnabled); - } + mWifiScanner = WifiLocalServices.getService(WifiScannerInternal.class); + updateThrottleEnabled(); // Register the global scan listener. if (mWifiScanner != null) { mWifiScanner.registerScanListener( - new HandlerExecutor(mHandler), new GlobalScanListener()); + new WifiScannerInternal.ScanListener(new GlobalScanListener(), mHandler)); } } return mWifiScanner != null; @@ -338,13 +346,15 @@ public class ScanRequestProxy { private LinkedList<Long> getOrCreateScanRequestTimestampsForForegroundApp( int callingUid, String packageName) { Pair<Integer, String> uidAndPackageNamePair = Pair.create(callingUid, packageName); - LinkedList<Long> scanRequestTimestamps = - mLastScanTimestampsForFgApps.get(uidAndPackageNamePair); - if (scanRequestTimestamps == null) { - scanRequestTimestamps = new LinkedList<>(); - mLastScanTimestampsForFgApps.put(uidAndPackageNamePair, scanRequestTimestamps); + synchronized (mThrottleEnabledLock) { + LinkedList<Long> scanRequestTimestamps = + mLastScanTimestampsForFgApps.get(uidAndPackageNamePair); + if (scanRequestTimestamps == null) { + scanRequestTimestamps = new LinkedList<>(); + mLastScanTimestampsForFgApps.put(uidAndPackageNamePair, scanRequestTimestamps); + } + return scanRequestTimestamps; } - return scanRequestTimestamps; } /** @@ -396,15 +406,17 @@ public class ScanRequestProxy { if (isPackageNameInExceptionList(packageName, false)) { return false; } - long lastScanMs = mLastScanTimestampForBgApps; - long elapsedRealtime = mClock.getElapsedSinceBootMillis(); - if (lastScanMs != 0 - && (elapsedRealtime - lastScanMs) < SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS) { - return true; + synchronized (mThrottleEnabledLock) { + long lastScanMs = mLastScanTimestampForBgApps; + long elapsedRealtime = mClock.getElapsedSinceBootMillis(); + if (lastScanMs != 0 + && (elapsedRealtime - lastScanMs) < SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS) { + return true; + } + // Proceed with the scan request and record the time. + mLastScanTimestampForBgApps = elapsedRealtime; + return false; } - // Proceed with the scan request and record the time. - mLastScanTimestampForBgApps = elapsedRealtime; - return false; } /** @@ -470,8 +482,9 @@ public class ScanRequestProxy { // a) App has either NETWORK_SETTINGS or NETWORK_SETUP_WIZARD permission. // b) Throttling has been disabled by user. int packageImportance = getPackageImportance(callingUid, packageName); - if (!fromSettingsOrSetupWizard && mThrottleEnabled - && shouldScanRequestBeThrottledForApp(callingUid, packageName, packageImportance)) { + if (!fromSettingsOrSetupWizard && isScanThrottleEnabled() + && shouldScanRequestBeThrottledForApp(callingUid, packageName, + packageImportance)) { Log.i(TAG, "Scan request from " + packageName + " throttled"); sendScanResultFailureBroadcastToPackage(packageName); return false; @@ -497,15 +510,15 @@ public class ScanRequestProxy { | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; if (mScanningForHiddenNetworksEnabled) { settings.hiddenNetworks.clear(); - // retrieve the list of hidden network SSIDs from saved network to scan for, if enabled. + // retrieve the list of hidden network SSIDs from saved network to scan if enabled. settings.hiddenNetworks.addAll(mWifiConfigManager.retrieveHiddenNetworkList(false)); // retrieve the list of hidden network SSIDs from Network suggestion to scan for. - settings.hiddenNetworks.addAll( - mWifiInjector.getWifiNetworkSuggestionsManager() + settings.hiddenNetworks.addAll(mWifiInjector.getWifiNetworkSuggestionsManager() .retrieveHiddenNetworkList(false)); } - mWifiScanner.startScan(settings, new HandlerExecutor(mHandler), - new ScanRequestProxyScanListener(), workSource); + mWifiScanner.startScan(settings, + new WifiScannerInternal.ScanListener(new ScanRequestProxyScanListener(), mHandler), + workSource); return true; } @@ -537,9 +550,11 @@ public class ScanRequestProxy { * Clear the stored scan results. */ private void clearScanResults() { - mLastScanResultsMap.clear(); - mLastScanTimestampForBgApps = 0; - mLastScanTimestampsForFgApps.clear(); + synchronized (mThrottleEnabledLock) { + mLastScanResultsMap.clear(); + mLastScanTimestampForBgApps = 0; + mLastScanTimestampsForFgApps.clear(); + } } /** @@ -549,11 +564,13 @@ public class ScanRequestProxy { * @param packageName Name of the package. */ public void clearScanRequestTimestampsForApp(@NonNull String packageName, int uid) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "Clearing scan request timestamps for uid=" + uid + ", packageName=" - + packageName); + synchronized (mThrottleEnabledLock) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Clearing scan request timestamps for uid=" + uid + ", packageName=" + + packageName); + } + mLastScanTimestampsForFgApps.remove(Pair.create(uid, packageName)); } - mLastScanTimestampsForFgApps.remove(Pair.create(uid, packageName)); } private void sendScanResultsAvailableToCallbacks() { @@ -589,13 +606,16 @@ public class ScanRequestProxy { * Enable/disable wifi scan throttling from 3rd party apps. */ public void setScanThrottleEnabled(boolean enable) { - mThrottleEnabled = enable; - mSettingsConfigStore.put(WIFI_SCAN_THROTTLE_ENABLED, enable); - - // reset internal counters when enabling/disabling throttling - mLastScanTimestampsForFgApps.clear(); - mLastScanTimestampForBgApps = 0; - Log.i(TAG, "Scan throttle enabled " + mThrottleEnabled); + synchronized (mThrottleEnabledLock) { + mThrottleEnabled = enable; + mSettingsConfigStore.put(WIFI_SCAN_THROTTLE_ENABLED, enable); + if (mVerboseLoggingEnabled) { + Log.i(TAG, "Scan throttle enabled " + mThrottleEnabled); + } + // reset internal counters when enabling/disabling throttling + mLastScanTimestampsForFgApps.clear(); + mLastScanTimestampForBgApps = 0; + } } /** @@ -603,55 +623,57 @@ public class ScanRequestProxy { * {@link #setScanThrottleEnabled(boolean)}. */ public boolean isScanThrottleEnabled() { - return mThrottleEnabled; + synchronized (mThrottleEnabledLock) { + return mThrottleEnabled; + } } /** Indicate whether there are WPA2 personal only networks. */ public boolean isWpa2PersonalOnlyNetworkInRange(String ssid) { return mLastScanResultsMap.values().stream().anyMatch(r -> TextUtils.equals(ssid, r.getWifiSsid().toString()) - && ScanResultUtil.isScanResultForPskOnlyNetwork(r)); + && ScanResultUtil.isScanResultForPskOnlyNetwork(r)); } /** Indicate whether there are WPA3 only networks. */ public boolean isWpa3PersonalOnlyNetworkInRange(String ssid) { return mLastScanResultsMap.values().stream().anyMatch(r -> TextUtils.equals(ssid, r.getWifiSsid().toString()) - && ScanResultUtil.isScanResultForSaeOnlyNetwork(r)); + && ScanResultUtil.isScanResultForSaeOnlyNetwork(r)); } /** Indicate whether there are WPA2/WPA3 transition mode networks. */ public boolean isWpa2Wpa3PersonalTransitionNetworkInRange(String ssid) { return mLastScanResultsMap.values().stream().anyMatch(r -> TextUtils.equals(ssid, ScanResultUtil.createQuotedSsid(r.SSID)) - && ScanResultUtil.isScanResultForPskSaeTransitionNetwork(r)); + && ScanResultUtil.isScanResultForPskSaeTransitionNetwork(r)); } /** Indicate whether there are OPEN only networks. */ public boolean isOpenOnlyNetworkInRange(String ssid) { return mLastScanResultsMap.values().stream().anyMatch(r -> TextUtils.equals(ssid, r.getWifiSsid().toString()) - && ScanResultUtil.isScanResultForOpenOnlyNetwork(r)); + && ScanResultUtil.isScanResultForOpenOnlyNetwork(r)); } /** Indicate whether there are OWE only networks. */ public boolean isOweOnlyNetworkInRange(String ssid) { return mLastScanResultsMap.values().stream().anyMatch(r -> TextUtils.equals(ssid, r.getWifiSsid().toString()) - && ScanResultUtil.isScanResultForOweOnlyNetwork(r)); + && ScanResultUtil.isScanResultForOweOnlyNetwork(r)); } /** Indicate whether there are WPA2 Enterprise only networks. */ public boolean isWpa2EnterpriseOnlyNetworkInRange(String ssid) { return mLastScanResultsMap.values().stream().anyMatch(r -> TextUtils.equals(ssid, r.getWifiSsid().toString()) - && ScanResultUtil.isScanResultForWpa2EnterpriseOnlyNetwork(r)); + && ScanResultUtil.isScanResultForWpa2EnterpriseOnlyNetwork(r)); } /** Indicate whether there are WPA3 Enterprise only networks. */ public boolean isWpa3EnterpriseOnlyNetworkInRange(String ssid) { return mLastScanResultsMap.values().stream().anyMatch(r -> TextUtils.equals(ssid, r.getWifiSsid().toString()) - && ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(r)); + && ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(r)); } } diff --git a/service/java/com/android/server/wifi/ScoringParams.java b/service/java/com/android/server/wifi/ScoringParams.java index 0f42f16129..edc0971ab8 100644 --- a/service/java/com/android/server/wifi/ScoringParams.java +++ b/service/java/com/android/server/wifi/ScoringParams.java @@ -98,7 +98,8 @@ public class ScoringParams { public int secureNetworkBonus = 40; public int band6GhzBonus = 0; public int scoringBucketStepSize = 500; - public int lastSelectionMinutes = 480; + public int lastUnmeteredSelectionMinutes = 480; + public int lastMeteredSelectionMinutes = 120; public int estimateRssiErrorMargin = 5; public static final int MIN_MINUTES = 1; public static final int MAX_MINUTES = Integer.MAX_VALUE / (60 * 1000); @@ -132,7 +133,8 @@ public class ScoringParams { validateRange(horizon, MIN_HORIZON, MAX_HORIZON); validateRange(nud, MIN_NUD, MAX_NUD); validateRange(expid, MIN_EXPID, MAX_EXPID); - validateRange(lastSelectionMinutes, MIN_MINUTES, MAX_MINUTES); + validateRange(lastUnmeteredSelectionMinutes, MIN_MINUTES, MAX_MINUTES); + validateRange(lastMeteredSelectionMinutes, MIN_MINUTES, MAX_MINUTES); } private void validateRssiArray(int[] rssi) throws IllegalArgumentException { @@ -295,8 +297,10 @@ public class ScoringParams { mVal.band6GhzBonus = context.getResources().getInteger(R.integer.config_wifiBand6GhzBonus); mVal.scoringBucketStepSize = context.getResources().getInteger( R.integer.config_wifiScoringBucketStepSize); - mVal.lastSelectionMinutes = context.getResources().getInteger( + mVal.lastUnmeteredSelectionMinutes = context.getResources().getInteger( R.integer.config_wifiFrameworkLastSelectionMinutes); + mVal.lastMeteredSelectionMinutes = context.getResources().getInteger( + R.integer.config_wifiFrameworkLastMeteredSelectionMinutes); mVal.estimateRssiErrorMargin = context.getResources().getInteger( R.integer.config_wifiEstimateRssiErrorMarginDb); mVal.pps[ACTIVE_TRAFFIC] = context.getResources().getInteger( @@ -532,11 +536,19 @@ public class ScoringParams { } /* - * Returns the duration in minutes for a recently selected network + * Returns the duration in minutes for a recently selected non-metered network * to be strongly favored. */ - public int getLastSelectionMinutes() { - return mVal.lastSelectionMinutes; + public int getLastUnmeteredSelectionMinutes() { + return mVal.lastUnmeteredSelectionMinutes; + } + + /* + * Returns the duration in minutes for a recently selected metered network + * to be strongly favored. + */ + public int getLastMeteredSelectionMinutes() { + return mVal.lastMeteredSelectionMinutes; } /** diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java index 1dfb3d1f62..dde875f324 100644 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ b/service/java/com/android/server/wifi/SoftApManager.java @@ -100,6 +100,7 @@ public class SoftApManager implements ActiveModeManager { private final SoftApNotifier mSoftApNotifier; private final BatteryManager mBatteryManager; private final InterfaceConflictManager mInterfaceConflictManager; + private final WifiInjector mWifiInjector; @VisibleForTesting static final long SOFT_AP_PENDING_DISCONNECTION_CHECK_DELAY_MS = 1000; @@ -331,6 +332,7 @@ public class SoftApManager implements ActiveModeManager { @NonNull Looper looper, @NonNull FrameworkFacade framework, @NonNull WifiNative wifiNative, + @NonNull WifiInjector wifiInjector, @NonNull CoexManager coexManager, @NonNull BatteryManager batteryManager, @NonNull InterfaceConflictManager interfaceConflictManager, @@ -352,6 +354,7 @@ public class SoftApManager implements ActiveModeManager { mFrameworkFacade = framework; mSoftApNotifier = softApNotifier; mWifiNative = wifiNative; + mWifiInjector = wifiInjector; mCoexManager = coexManager; mBatteryManager = batteryManager; mInterfaceConflictManager = interfaceConflictManager; @@ -606,7 +609,7 @@ public class SoftApManager implements ActiveModeManager { private void onL2Connected(@NonNull ConcreteClientModeManager clientModeManager) { Log.d(getTag(), "onL2Connected called"); mStateMachine.sendMessage(SoftApStateMachine.CMD_HANDLE_WIFI_CONNECTED, - clientModeManager.syncRequestConnectionInfo()); + clientModeManager.getConnectionInfo()); } @@ -894,9 +897,9 @@ public class SoftApManager implements ActiveModeManager { public static final int CMD_CHARGING_STATE_CHANGED = 17; private final State mActiveState = new ActiveState(); - private final State mIdleState = new IdleState(); + private final State mIdleState; private final WaitingState mWaitingState = new WaitingState(this); - private final State mStartedState = new StartedState(); + private final State mStartedState; private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() { @Override @@ -924,6 +927,10 @@ public class SoftApManager implements ActiveModeManager { SoftApStateMachine(Looper looper) { super(TAG, looper); + final int threshold = mContext.getResources().getInteger( + R.integer.config_wifiConfigurationWifiRunnerThresholdInMs); + mIdleState = new IdleState(threshold); + mStartedState = new StartedState(threshold); // CHECKSTYLE:OFF IndentationCheck addState(mActiveState); addState(mIdleState, mActiveState); @@ -935,6 +942,7 @@ public class SoftApManager implements ActiveModeManager { start(); } + private class ActiveState extends State { @Override public void exit() { @@ -942,16 +950,76 @@ public class SoftApManager implements ActiveModeManager { } } - private class IdleState extends State { + @Override + protected String getWhatToString(int what) { + switch (what) { + case CMD_START: + return "CMD_START"; + case CMD_STOP: + return "CMD_STOP"; + case CMD_FAILURE: + return "CMD_FAILURE"; + case CMD_INTERFACE_STATUS_CHANGED: + return "CMD_INTERFACE_STATUS_CHANGED"; + case CMD_ASSOCIATED_STATIONS_CHANGED: + return "CMD_ASSOCIATED_STATIONS_CHANGED"; + case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: + return "CMD_NO_ASSOCIATED_STATIONS_TIMEOUT"; + case CMD_INTERFACE_DESTROYED: + return "CMD_INTERFACE_DESTROYED"; + case CMD_INTERFACE_DOWN: + return "CMD_INTERFACE_DOWN"; + case CMD_AP_INFO_CHANGED: + return "CMD_AP_INFO_CHANGED"; + case CMD_UPDATE_CAPABILITY: + return "CMD_UPDATE_CAPABILITY"; + case CMD_UPDATE_CONFIG: + return "CMD_UPDATE_CONFIG"; + case CMD_FORCE_DISCONNECT_PENDING_CLIENTS: + return "CMD_FORCE_DISCONNECT_PENDING_CLIENTS"; + case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT_ON_ONE_INSTANCE: + return "CMD_NO_ASSOCIATED_STATIONS_TIMEOUT_ON_ONE_INSTANCE"; + case CMD_SAFE_CHANNEL_FREQUENCY_CHANGED: + return "CMD_SAFE_CHANNEL_FREQUENCY_CHANGED"; + case CMD_HANDLE_WIFI_CONNECTED: + return "CMD_HANDLE_WIFI_CONNECTED"; + case CMD_UPDATE_COUNTRY_CODE: + return "CMD_UPDATE_COUNTRY_CODE"; + case CMD_CHARGING_STATE_CHANGED: + return "CMD_CHARGING_STATE_CHANGED"; + case RunnerState.STATE_ENTER_CMD: + return "Enter"; + case RunnerState.STATE_EXIT_CMD: + return "Exit"; + default: + return "what:" + what; + } + } + + private class IdleState extends RunnerState { + IdleState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + @Override - public void enter() { + public void enterImpl() { mApInterfaceName = null; mIfaceIsUp = false; mIfaceIsDestroyed = false; } @Override - public boolean processMessage(Message message) { + public void exitImpl() { + } + + @Override + String getMessageLogRec(int what) { + return SoftApManager.class.getSimpleName() + "." + IdleState.class.getSimpleName() + + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { switch (message.what) { case CMD_STOP: quitNow(); @@ -981,8 +1049,7 @@ public class SoftApManager implements ActiveModeManager { if (ApConfigUtil.isStaWithBridgedModeSupported(mContext)) { for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { - WifiInfo wifiConnectedInfo = - cmm.syncRequestConnectionInfo(); + WifiInfo wifiConnectedInfo = cmm.getConnectionInfo(); int wifiFrequency = wifiConnectedInfo.getFrequency(); if (wifiFrequency > 0 && !mSafeChannelFrequencyList.contains( @@ -1132,7 +1199,11 @@ public class SoftApManager implements ActiveModeManager { } } - private class StartedState extends State { + private class StartedState extends RunnerState { + StartedState(int threshold) { + super(threshold, mWifiInjector.getWifiHandlerLocalLog()); + } + BroadcastReceiver mBatteryChargingReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1480,7 +1551,7 @@ public class SoftApManager implements ActiveModeManager { } @Override - public void enter() { + public void enterImpl() { mIfaceIsUp = false; mIfaceIsDestroyed = false; onUpChanged(mWifiNative.isInterfaceUp(mApInterfaceName)); @@ -1504,7 +1575,7 @@ public class SoftApManager implements ActiveModeManager { } @Override - public void exit() { + public void exitImpl() { if (!mIfaceIsDestroyed) { stopSoftAp(); } @@ -1575,7 +1646,13 @@ public class SoftApManager implements ActiveModeManager { } @Override - public boolean processMessage(Message message) { + String getMessageLogRec(int what) { + return SoftApManager.class.getSimpleName() + "." + RunnerState.class.getSimpleName() + + "." + getWhatToString(what); + } + + @Override + public boolean processMessageImpl(Message message) { switch (message.what) { case CMD_ASSOCIATED_STATIONS_CHANGED: if (!(message.obj instanceof WifiClient)) { diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java index 2ee2edaf7b..09a37c9473 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java @@ -70,6 +70,7 @@ import com.android.server.wifi.hotspot2.WnmData; import com.android.server.wifi.hotspot2.anqp.ANQPElement; import com.android.server.wifi.hotspot2.anqp.ANQPParser; import com.android.server.wifi.hotspot2.anqp.Constants; +import com.android.server.wifi.util.HalAidlUtil; import com.android.server.wifi.util.NativeUtil; import java.io.IOException; @@ -77,6 +78,7 @@ import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -156,12 +158,33 @@ class SupplicantStaIfaceCallbackAidlImpl extends ISupplicantStaIfaceCallback.Stu @Override public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, byte[] ssid, boolean filsHlpSent) { + onStateChangedWithAkm(newState, bssid, id, ssid, filsHlpSent, 0); + } + + @Override + public void onStateChangedWithAkm(int newState, byte[/* 6 */] bssid, int id, + byte[] ssid, boolean filsHlpSent, int supplicantKeyMgmtMask) { synchronized (mLock) { - mStaIfaceHal.logCallback("onStateChanged"); SupplicantState newSupplicantState = supplicantAidlStateToFrameworkState(newState); WifiSsid wifiSsid = mSsidTranslator.getTranslatedSsid(WifiSsid.fromBytes(ssid)); String bssidStr = NativeUtil.macAddressFromByteArray(bssid); + BitSet keyMgmtMask = null; + if (supplicantKeyMgmtMask != 0) { + try { + keyMgmtMask = HalAidlUtil.supplicantToWifiConfigurationKeyMgmtMask( + supplicantKeyMgmtMask); + } catch (IllegalArgumentException ex) { + Log.w(TAG, "Failed convert supplicant key management mask to" + + " the framework value: " + ex.toString()); + keyMgmtMask = null; + } + } + mStaIfaceHal.logCallback("onStateChanged: newState=" + newSupplicantState + + ", bssid=" + bssidStr + ", ssid=" + wifiSsid.toString() + + ", filsHlpSent=" + filsHlpSent + ", supplicantKeyMgmtMask=" + + String.format("0x%08X", supplicantKeyMgmtMask) + + ", frameworkKeyMgmtMask=" + keyMgmtMask); if (newState != StaIfaceCallbackState.DISCONNECTED) { // onStateChanged(DISCONNECTED) may come before onDisconnected(), so add this // cache to track the state before the disconnect. @@ -177,7 +200,7 @@ class SupplicantStaIfaceCallbackAidlImpl extends ISupplicantStaIfaceCallback.Stu if (newState == StaIfaceCallbackState.COMPLETED) { mWifiMonitor.broadcastNetworkConnectionEvent( mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), filsHlpSent, - wifiSsid, bssidStr); + wifiSsid, bssidStr, keyMgmtMask); } else if (newState == StaIfaceCallbackState.ASSOCIATING) { mCurrentSsid = wifiSsid.toString(); } @@ -1198,4 +1221,38 @@ class SupplicantStaIfaceCallbackAidlImpl extends ISupplicantStaIfaceCallback.Stu public int getInterfaceVersion() { return ISupplicantStaIfaceCallback.VERSION; } + + private String getMloLinksInfoChangedReasonStr(int reason) { + switch (reason) { + case ISupplicantStaIfaceCallback.MloLinkInfoChangeReason.TID_TO_LINK_MAP: + return "TID_TO_LINK_MAP"; + case ISupplicantStaIfaceCallback.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL: + return "MULTI_LINK_RECONFIG_AP_REMOVAL"; + default: + return "UNKNOWN"; + } + } + + private WifiMonitor.MloLinkInfoChangeReason convertMloLinkInfoChangedReason(int reason) { + switch (reason) { + case ISupplicantStaIfaceCallback.MloLinkInfoChangeReason.TID_TO_LINK_MAP: + return WifiMonitor.MloLinkInfoChangeReason.TID_TO_LINK_MAP; + case ISupplicantStaIfaceCallback.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL: + return WifiMonitor.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL; + default: + return WifiMonitor.MloLinkInfoChangeReason.UNKNOWN; + } + } + + @Override + public void onMloLinksInfoChanged(int reason) + throws android.os.RemoteException { + synchronized (mLock) { + mStaIfaceHal.logCallback( + "onMloLinksInfoChanged: reason " + Integer.toString(reason) + " (" + + getMloLinksInfoChangedReasonStr(reason) + ")"); + mWifiMonitor.broadcastMloLinksInfoChanged(mIfaceName, + convertMloLinkInfoChangedReason(reason)); + } + } } diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_2Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_2Impl.java index efff6089f7..c4de2e0e8a 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_2Impl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_2Impl.java @@ -29,6 +29,7 @@ import android.util.Log; import com.android.server.wifi.util.NativeUtil; import java.util.ArrayList; +import java.util.Arrays; abstract class SupplicantStaIfaceCallbackHidlV1_2Impl extends android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback.Stub { @@ -182,7 +183,7 @@ abstract class SupplicantStaIfaceCallbackHidlV1_2Impl extends if (password != null) { newWifiConfiguration.preSharedKey = "\"" + password + "\""; } else if (psk != null) { - newWifiConfiguration.preSharedKey = psk.toString(); + newWifiConfiguration.preSharedKey = Arrays.toString(psk); } // Set up key management: SAE or PSK diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java index 07a2c3d48c..02a62cbff9 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java @@ -26,6 +26,8 @@ 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_SAE_PK; +import static android.net.wifi.WifiManager.WIFI_FEATURE_SET_TLS_MINIMUM_VERSION; +import static android.net.wifi.WifiManager.WIFI_FEATURE_TLS_V1_3; 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_WFD_R2; @@ -120,6 +122,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { private boolean mVerboseLoggingEnabled = false; private boolean mVerboseHalLoggingEnabled = false; private boolean mServiceDeclared = false; + private int mServiceVersion; // Supplicant HAL interface objects private ISupplicant mISupplicant = null; @@ -135,6 +138,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { @VisibleForTesting PmkCacheManager mPmkCacheManager; private WifiNative.SupplicantDeathEventHandler mDeathEventHandler; + private SupplicantDeathRecipient mSupplicantDeathRecipient; private final Context mContext; private final WifiMonitor mWifiMonitor; private final Handler mEventHandler; @@ -146,25 +150,24 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { private CountDownLatch mWaitForDeathLatch; private class SupplicantDeathRecipient implements DeathRecipient { - private final IBinder mWho; @Override public void binderDied() { + } + + @Override + public void binderDied(@NonNull IBinder who) { synchronized (mLock) { - Log.w(TAG, "ISupplicant binder died. who=" + mWho + ", service=" + Log.w(TAG, "ISupplicant binder died. who=" + who + ", service=" + getServiceBinderMockable()); - if (mWho == getServiceBinderMockable()) { + if (who == getServiceBinderMockable()) { if (mWaitForDeathLatch != null) { mWaitForDeathLatch.countDown(); } Log.w(TAG, "Handle supplicant death"); - supplicantServiceDiedHandler(mWho); + supplicantServiceDiedHandler(who); } } } - - SupplicantDeathRecipient(IBinder who) { - mWho = who; - } } public SupplicantStaIfaceHalAidlImpl(Context context, WifiMonitor monitor, Handler handler, @@ -177,6 +180,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { mWifiMetrics = wifiMetrics; mWifiGlobals = wifiGlobals; mSsidTranslator = ssidTranslator; + mSupplicantDeathRecipient = new SupplicantDeathRecipient(); mPmkCacheManager = new PmkCacheManager(mClock, mEventHandler); } @@ -379,6 +383,15 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { return ServiceManager.isDeclared(HAL_INSTANCE_NAME); } + /** + * Check that the service is running at least the expected version. + * Use to avoid the case where the framework is using a newer + * interface version than the service. + */ + private boolean isServiceVersionIsAtLeast(int expectedVersion) { + return expectedVersion <= mServiceVersion; + } + private void clearState() { synchronized (mLock) { Log.i(TAG, "Clearing internal state"); @@ -426,14 +439,14 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { Log.i(TAG, "Local Version: " + ISupplicant.VERSION); try { - Log.i(TAG, "Remote Version: " + mISupplicant.getInterfaceVersion()); + mServiceVersion = mISupplicant.getInterfaceVersion(); + Log.i(TAG, "Remote Version: " + mServiceVersion); IBinder serviceBinder = getServiceBinderMockable(); if (serviceBinder == null) { return false; } mWaitForDeathLatch = null; - serviceBinder.linkToDeath( - new SupplicantDeathRecipient(serviceBinder), /* flags= */ 0); + serviceBinder.linkToDeath(mSupplicantDeathRecipient, /* flags= */ 0); setLogLevel(mVerboseHalLoggingEnabled); return true; } catch (RemoteException e) { @@ -1056,9 +1069,11 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { @NonNull String ifaceName, ISupplicantStaNetwork network) { synchronized (mLock) { SupplicantStaNetworkHalAidlImpl networkWrapper = - new SupplicantStaNetworkHalAidlImpl(network, ifaceName, mContext, + new SupplicantStaNetworkHalAidlImpl(mServiceVersion, + network, ifaceName, mContext, mWifiMonitor, mWifiGlobals, - getAdvancedCapabilities(ifaceName)); + getAdvancedCapabilities(ifaceName), + getWpaDriverCapabilities(ifaceName)); if (networkWrapper != null) { networkWrapper.enableVerboseLogging( mVerboseLoggingEnabled, mVerboseHalLoggingEnabled); @@ -2572,6 +2587,28 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } } + private long aidlWpaDrvFeatureSetToFrameworkV2(int drvCapabilitiesMask) { + if (!isServiceVersionIsAtLeast(2)) return 0; + + final String methodStr = "getWpaDriverFeatureSetV2"; + long featureSet = 0; + + if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.SET_TLS_MINIMUM_VERSION) != 0) { + featureSet |= 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; + if (mVerboseLoggingEnabled) { + Log.v(TAG, methodStr + ": EAP-TLS v1.3 supported"); + } + } + return featureSet; + } + /** * Get the driver supported features through supplicant. * @@ -2619,6 +2656,8 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } } + featureSet |= aidlWpaDrvFeatureSetToFrameworkV2(drvCapabilitiesMask); + return featureSet; } } @@ -2859,10 +2898,10 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { nativeInfo.links = new WifiNative.ConnectionMloLink[halInfo.links.length]; for (int i = 0; i < halInfo.links.length; i++) { - nativeInfo.links[i] = new WifiNative.ConnectionMloLink(); - nativeInfo.links[i].linkId = halInfo.links[i].linkId; - nativeInfo.links[i].staMacAddress = MacAddress.fromBytes( - halInfo.links[i].staLinkMacAddress); + nativeInfo.links[i] = new WifiNative.ConnectionMloLink( + halInfo.links[i].linkId, + MacAddress.fromBytes(halInfo.links[i].staLinkMacAddress), + halInfo.links[i].tidsUplinkMap, halInfo.links[i].tidsDownlinkMap); } return nativeInfo; } catch (RemoteException e) { diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java index 47b76b1795..9c2d177663 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java @@ -79,7 +79,6 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; -import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; @@ -95,7 +94,7 @@ import javax.annotation.concurrent.ThreadSafe; */ @ThreadSafe public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { - private static final String TAG = "SupplicantStaIfaceHalHidlImp"; + private static final String TAG = "SupplicantStaIfaceHalHidlImpl"; @VisibleForTesting public static final String HAL_INSTANCE_NAME = "default"; @VisibleForTesting @@ -130,6 +129,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { private SupplicantDeathRecipient mSupplicantDeathRecipient; // Death recipient cookie registered for current supplicant instance. private long mDeathRecipientCookie = 0; + private CountDownLatch mWaitForDeathLatch; private final Context mContext; private final WifiMonitor mWifiMonitor; private final FrameworkFacade mFrameworkFacade; @@ -176,6 +176,12 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { private class SupplicantDeathRecipient implements DeathRecipient { @Override public void serviceDied(long cookie) { + synchronized (mLock) { + if (mWaitForDeathLatch != null) { + mWaitForDeathLatch.countDown(); + } + } + mEventHandler.post(() -> { synchronized (mLock) { Log.w(TAG, "ISupplicant died: cookie=" + cookie); @@ -640,6 +646,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { Log.i(TAG, "Ignoring stale death recipient notification"); return; } + Log.i(TAG, "Handling service death"); clearState(); if (mDeathEventHandler != null) { mDeathEventHandler.onDeath(); @@ -715,18 +722,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { */ public void terminate() { synchronized (mLock) { - // Register for a new death listener to block until supplicant is dead. - final long waitForDeathCookie = new Random().nextLong(); - final CountDownLatch waitForDeathLatch = new CountDownLatch(1); - linkToSupplicantDeath((cookie) -> { - mEventHandler.post(() -> { - Log.d(TAG, "ISupplicant died: cookie=" + cookie); - if (cookie != waitForDeathCookie) return; - supplicantServiceDiedHandler(mDeathRecipientCookie); - waitForDeathLatch.countDown(); - }); - }, waitForDeathCookie); - + mWaitForDeathLatch = new CountDownLatch(1); if (isV1_1()) { Log.i(TAG, "Terminating supplicant using HIDL"); terminate_V1_1(); @@ -734,15 +730,15 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { Log.i(TAG, "Terminating supplicant using init"); mFrameworkFacade.stopSupplicant(); } + } - // Now wait for death listener callback to confirm that it's dead. - try { - if (!waitForDeathLatch.await(WAIT_FOR_DEATH_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { - Log.w(TAG, "Timed out waiting for confirmation of supplicant death"); - } - } catch (InterruptedException e) { - Log.w(TAG, "Failed to wait for supplicant death"); + // Now wait for death listener callback to confirm that it's dead. + try { + if (!mWaitForDeathLatch.await(WAIT_FOR_DEATH_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { + Log.w(TAG, "Timed out waiting for confirmation of supplicant death"); } + } catch (InterruptedException e) { + Log.w(TAG, "Failed to wait for supplicant death"); } } diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java index 4e0af8dff1..db332769a2 100644 --- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java @@ -32,6 +32,7 @@ import android.hardware.wifi.supplicant.OcspType; import android.hardware.wifi.supplicant.PairwiseCipherMask; import android.hardware.wifi.supplicant.ProtoMask; import android.hardware.wifi.supplicant.SaeH2eMode; +import android.hardware.wifi.supplicant.TlsVersion; import android.net.wifi.SecurityParams; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; @@ -44,6 +45,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wifi.util.ArrayUtils; +import com.android.server.wifi.util.HalAidlUtil; import com.android.server.wifi.util.NativeUtil; import com.android.wifi.resources.R; @@ -107,6 +109,7 @@ public class SupplicantStaNetworkHalAidlImpl { private final WifiGlobals mWifiGlobals; private ISupplicantStaNetwork mISupplicantStaNetwork; private ISupplicantStaNetworkCallback mISupplicantStaNetworkCallback; + private int mServiceVersion; private boolean mVerboseLoggingEnabled = false; // Network variables read from wpa_supplicant. @@ -145,16 +148,29 @@ public class SupplicantStaNetworkHalAidlImpl { private @WifiEnterpriseConfig.Ocsp int mOcsp; private String mWapiCertSuite; private long mAdvanceKeyMgmtFeatures; + private long mWpaDriverFeatures; - SupplicantStaNetworkHalAidlImpl(ISupplicantStaNetwork staNetwork, String ifaceName, + SupplicantStaNetworkHalAidlImpl(int serviceVersion, + ISupplicantStaNetwork staNetwork, String ifaceName, Context context, WifiMonitor monitor, WifiGlobals wifiGlobals, - long advanceKeyMgmtFeature) { + long advanceKeyMgmtFeature, long wpaDriverFeatures) { + mServiceVersion = serviceVersion; mISupplicantStaNetwork = staNetwork; mContext = context; mIfaceName = ifaceName; mWifiMonitor = monitor; mWifiGlobals = wifiGlobals; mAdvanceKeyMgmtFeatures = advanceKeyMgmtFeature; + mWpaDriverFeatures = wpaDriverFeatures; + } + + /** + * Check that the service is running at least the expected version. + * Use to avoid the case where the framework is using a newer + * interface version than the service. + */ + private boolean isServiceVersionIsAtLeast(int expectedVersion) { + return expectedVersion <= mServiceVersion; } /** @@ -229,7 +245,8 @@ public class SupplicantStaNetworkHalAidlImpl { /** allowedKeyManagement */ if (getKeyMgmt()) { - BitSet keyMgmtMask = supplicantToWifiConfigurationKeyMgmtMask(mKeyMgmtMask); + BitSet keyMgmtMask = HalAidlUtil.supplicantToWifiConfigurationKeyMgmtMask( + mKeyMgmtMask); keyMgmtMask = removeFastTransitionFlags(keyMgmtMask); keyMgmtMask = removeSha256KeyMgmtFlags(keyMgmtMask); keyMgmtMask = removePskSaeUpgradableTypeFlags(keyMgmtMask); @@ -323,8 +340,8 @@ public class SupplicantStaNetworkHalAidlImpl { } Log.d(TAG, "The target security params: " + securityParams); - boolean isRequirePmf = getOptimalPmfSettingForConfig(config, - securityParams.isRequirePmf()); + boolean isRequirePmf = NativeUtil.getOptimalPmfSettingForConfig(config, + securityParams.isRequirePmf(), mWifiGlobals); /** RequirePMF */ if (!setRequirePmf(isRequirePmf)) { Log.e(TAG, config.SSID + ": failed to set requirePMF: " + config.requirePmf); @@ -373,7 +390,8 @@ public class SupplicantStaNetworkHalAidlImpl { return false; } /** Group Cipher */ - BitSet allowedGroupCiphers = securityParams.getAllowedGroupCiphers(); + BitSet allowedGroupCiphers = NativeUtil.getOptimalGroupCiphersForConfig( + config, securityParams.getAllowedGroupCiphers(), mWifiGlobals); if (allowedGroupCiphers.cardinality() != 0 && (!setGroupCipher(wifiConfigurationToSupplicantGroupCipherMask( allowedGroupCiphers)))) { @@ -381,7 +399,8 @@ public class SupplicantStaNetworkHalAidlImpl { return false; } /** Pairwise Cipher*/ - BitSet allowedPairwiseCiphers = securityParams.getAllowedPairwiseCiphers(); + BitSet allowedPairwiseCiphers = NativeUtil.getOptimalPairwiseCiphersForConfig( + config, securityParams.getAllowedPairwiseCiphers(), mWifiGlobals); if (allowedPairwiseCiphers.cardinality() != 0 && !setPairwiseCipher(wifiConfigurationToSupplicantPairwiseCipherMask( allowedPairwiseCiphers))) { @@ -825,10 +844,32 @@ public class SupplicantStaNetworkHalAidlImpl { return false; } } + if (isServiceVersionIsAtLeast(2)) { + if (!setMinimumTlsVersionEapPhase1Param(getOptimalMinimumTlsVersion(eapConfig))) { + Log.e(TAG, "Failed to set the minimum TLS version"); + return false; + } + } return true; } } + private int getOptimalMinimumTlsVersion(WifiEnterpriseConfig enterpriseConfig) { + int maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_2; + if ((mWpaDriverFeatures & WifiManager.WIFI_FEATURE_TLS_V1_3) != 0) { + maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_3; + } + + int requiredMinimumTlsVersion = enterpriseConfig.getMinimumTlsVersion(); + if (requiredMinimumTlsVersion > maxTlsVersionSupported) { + Log.w(TAG, "The required minimum TLS version " + requiredMinimumTlsVersion + + " exceeds the maximum supported TLS version " + maxTlsVersionSupported + + ", fallback to the maximum supported TLS version."); + return maxTlsVersionSupported; + } + return requiredMinimumTlsVersion; + } + /** * Maps WifiConfiguration Key Management BitSet to Supplicant AIDL bitmask int * @@ -1105,70 +1146,6 @@ public class SupplicantStaNetworkHalAidlImpl { } } - private static int supplicantMaskValueToWifiConfigurationBitSet(int supplicantMask, - int supplicantValue, BitSet bitset, int bitSetPosition) { - bitset.set(bitSetPosition, (supplicantMask & supplicantValue) == supplicantValue); - int modifiedSupplicantMask = supplicantMask & ~supplicantValue; - return modifiedSupplicantMask; - } - - private static BitSet supplicantToWifiConfigurationKeyMgmtMask(int mask) { - BitSet bitset = new BitSet(); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.NONE, bitset, - WifiConfiguration.KeyMgmt.NONE); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.WPA_PSK, bitset, - WifiConfiguration.KeyMgmt.WPA_PSK); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.WPA_EAP, bitset, - WifiConfiguration.KeyMgmt.WPA_EAP); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.IEEE8021X, bitset, - WifiConfiguration.KeyMgmt.IEEE8021X); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.OSEN, bitset, - WifiConfiguration.KeyMgmt.OSEN); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.FT_PSK, bitset, - WifiConfiguration.KeyMgmt.FT_PSK); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.FT_EAP, bitset, - WifiConfiguration.KeyMgmt.FT_EAP); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.SAE, - bitset, WifiConfiguration.KeyMgmt.SAE); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.OWE, - bitset, WifiConfiguration.KeyMgmt.OWE); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.SUITE_B_192, - bitset, WifiConfiguration.KeyMgmt.SUITE_B_192); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.WPA_PSK_SHA256, - bitset, WifiConfiguration.KeyMgmt.WPA_PSK_SHA256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.WPA_EAP_SHA256, - bitset, WifiConfiguration.KeyMgmt.WPA_EAP_SHA256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.WAPI_PSK, - bitset, WifiConfiguration.KeyMgmt.WAPI_PSK); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.WAPI_CERT, - bitset, WifiConfiguration.KeyMgmt.WAPI_CERT); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.FILS_SHA256, - bitset, WifiConfiguration.KeyMgmt.FILS_SHA256); - mask = supplicantMaskValueToWifiConfigurationBitSet( - mask, KeyMgmtMask.FILS_SHA384, - bitset, WifiConfiguration.KeyMgmt.FILS_SHA384); - if (mask != 0) { - throw new IllegalArgumentException( - "invalid key mgmt mask from supplicant: " + mask); - } - return bitset; - } - private static int wifiConfigurationToSupplicantEapMethod(int value) { switch (value) { case WifiEnterpriseConfig.Eap.PEAP: @@ -1461,6 +1438,9 @@ public class SupplicantStaNetworkHalAidlImpl { if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } + if (mVerboseLoggingEnabled) { + Log.d(TAG, String.format("setGroupCipher: 0x%x", groupCipherMask)); + } try { mISupplicantStaNetwork.setGroupCipher(groupCipherMask); return true; @@ -1533,6 +1513,9 @@ public class SupplicantStaNetworkHalAidlImpl { if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } + if (mVerboseLoggingEnabled) { + Log.d(TAG, String.format("setPairwiseCipher: 0x%x", pairwiseCipherMask)); + } try { mISupplicantStaNetwork.setPairwiseCipher(pairwiseCipherMask); return true; @@ -1690,6 +1673,9 @@ public class SupplicantStaNetworkHalAidlImpl { if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } + if (mVerboseLoggingEnabled) { + Log.d(TAG, "setRequirePmf: " + enable); + } try { mISupplicantStaNetwork.setRequirePmf(enable); return true; @@ -3547,29 +3533,6 @@ public class SupplicantStaNetworkHalAidlImpl { } /** - * Update PMF requirement if auto-upgrade offload is supported. - * - * If SAE auto-upgrade offload is supported and this config enables - * both PSK and SAE, do not set PMF requirement to - * mandatory to allow the device to roam between PSK and SAE BSSes. - * wpa_supplicant will set PMF requirement to optional by default. - */ - private boolean getOptimalPmfSettingForConfig(WifiConfiguration config, - boolean isPmfRequiredFromSelectedSecurityParams) { - if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK) - && config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK).isEnabled() - && config.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE) - && config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE).isEnabled() - && mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Keep optional PMF for SAE auto-upgrade offload."); - } - return false; - } - return isPmfRequiredFromSelectedSecurityParams; - } - - /** * Adds both PSK and SAE AKM if auto-upgrade offload is supported. */ private BitSet addPskSaeUpgradableTypeFlagsIfSupported( @@ -3703,4 +3666,49 @@ public class SupplicantStaNetworkHalAidlImpl { return false; } } + + private int frameworkToAidlTlsVersion(@WifiEnterpriseConfig.TlsVersion int tlsVersion) { + switch (tlsVersion) { + case WifiEnterpriseConfig.TLS_V1_3: + return TlsVersion.TLS_V1_3; + case WifiEnterpriseConfig.TLS_V1_2: + return TlsVersion.TLS_V1_2; + case WifiEnterpriseConfig.TLS_V1_1: + return TlsVersion.TLS_V1_1; + case WifiEnterpriseConfig.TLS_V1_0: + return TlsVersion.TLS_V1_0; + default: + Log.e(TAG, "Invalid TLS version: " + tlsVersion); + return -1; + } + } + + /** + * Enable TLS V1.3 in EAP Phase1 + * + * @param tlsVersion the TLS version + * @return true if successful, false otherwise + */ + private boolean setMinimumTlsVersionEapPhase1Param( + @WifiEnterpriseConfig.TlsVersion int tlsVersion) { + synchronized (mLock) { + final String methodStr = "setMinimumTlsVersionEapPhase1Param"; + if (!checkStaNetworkAndLogFailure(methodStr)) { + return false; + } + int aidlTlsVersion = frameworkToAidlTlsVersion(tlsVersion); + if (aidlTlsVersion < 0) { + return false; + } + try { + mISupplicantStaNetwork.setMinimumTlsVersionEapPhase1Param(aidlTlsVersion); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } } diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java index 251340ee63..faf9aa501d 100644 --- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java @@ -309,8 +309,8 @@ public class SupplicantStaNetworkHalHidlImpl { } Log.d(TAG, "The target security params: " + securityParams); - boolean isRequirePmf = getOptimalPmfSettingForConfig(config, - securityParams.isRequirePmf()); + boolean isRequirePmf = NativeUtil.getOptimalPmfSettingForConfig(config, + securityParams.isRequirePmf(), mWifiGlobals); /** RequirePMF */ if (!setRequirePmf(isRequirePmf)) { Log.e(TAG, config.SSID + ": failed to set requirePMF: " + config.requirePmf); @@ -353,7 +353,8 @@ public class SupplicantStaNetworkHalHidlImpl { return false; } /** Group Cipher */ - BitSet allowedGroupCiphers = securityParams.getAllowedGroupCiphers(); + BitSet allowedGroupCiphers = NativeUtil.getOptimalGroupCiphersForConfig( + config, securityParams.getAllowedGroupCiphers(), mWifiGlobals); if (allowedGroupCiphers.cardinality() != 0 && (!setGroupCipher(wifiConfigurationToSupplicantGroupCipherMask( allowedGroupCiphers)))) { @@ -361,7 +362,8 @@ public class SupplicantStaNetworkHalHidlImpl { return false; } /** Pairwise Cipher*/ - BitSet allowedPairwiseCiphers = securityParams.getAllowedPairwiseCiphers(); + BitSet allowedPairwiseCiphers = NativeUtil.getOptimalPairwiseCiphersForConfig( + config, securityParams.getAllowedPairwiseCiphers(), mWifiGlobals); if (allowedPairwiseCiphers.cardinality() != 0 && !setPairwiseCipher(wifiConfigurationToSupplicantPairwiseCipherMask( allowedPairwiseCiphers))) { @@ -1613,6 +1615,9 @@ public class SupplicantStaNetworkHalHidlImpl { synchronized (mLock) { final String methodStr = "setGroupCipher"; if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; + if (mVerboseLoggingEnabled) { + Log.d(TAG, String.format("setGroupCipher: 0x%x", groupCipherMask)); + } try { SupplicantStatus status; android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork @@ -1721,6 +1726,9 @@ public class SupplicantStaNetworkHalHidlImpl { synchronized (mLock) { final String methodStr = "setPairwiseCipher"; if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; + if (mVerboseLoggingEnabled) { + Log.d(TAG, String.format("setPairwiseCipher: 0x%x", pairwiseCipherMask)); + } try { SupplicantStatus status; android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork @@ -1845,6 +1853,9 @@ public class SupplicantStaNetworkHalHidlImpl { synchronized (mLock) { final String methodStr = "setRequirePmf"; if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false; + if (mVerboseLoggingEnabled) { + Log.d(TAG, "setRequirePmf: " + enable); + } try { SupplicantStatus status = mISupplicantStaNetwork.setRequirePmf(enable); return checkStatusAndLogFailure(status, methodStr); @@ -3829,29 +3840,6 @@ public class SupplicantStaNetworkHalHidlImpl { } /** - * Update PMF requirement if auto-upgrade offload is supported. - * - * If SAE auto-upgrade offload is supported and this config enables - * both PSK and SAE, do not set PMF requirement to - * mandatory to allow the device to roam between PSK and SAE BSSes. - * wpa_supplicant will set PMF requirement to optional by default. - */ - private boolean getOptimalPmfSettingForConfig(WifiConfiguration config, - boolean isPmfRequiredFromSelectedSecurityParams) { - if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK) - && config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK).isEnabled() - && config.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE) - && config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE).isEnabled() - && mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "Keep optional PMF for SAE auto-upgrade offload."); - } - return false; - } - return isPmfRequiredFromSelectedSecurityParams; - } - - /** * Adds both PSK and SAE AKM if auto-upgrade offload is supported. */ private BitSet addPskSaeUpgradableTypeFlagsIfSupported( diff --git a/service/java/com/android/server/wifi/ThroughputScorer.java b/service/java/com/android/server/wifi/ThroughputScorer.java index ab2511f8de..30acce38ab 100644 --- a/service/java/com/android/server/wifi/ThroughputScorer.java +++ b/service/java/com/android/server/wifi/ThroughputScorer.java @@ -105,6 +105,10 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { ? mScoringParams.getBand6GhzBonus() : 0; int currentNetworkBoost = (candidate.isCurrentNetwork() && !unExpectedNoInternet) ? currentNetworkBonus : 0; + int rssiBoost = (candidate.isCurrentNetwork() && unExpectedNoInternet) + ? 0 : rssiBaseScore; + int throughputBoost = (candidate.isCurrentNetwork() && unExpectedNoInternet) + ? 0 : throughputBonusScore; int securityAward = candidate.isOpenNetwork() ? 0 @@ -157,7 +161,7 @@ final class ThroughputScorer implements WifiCandidates.CandidateScorer { + notOemPaidAward + notOemPrivateAward + securityAward; // Within the same scoring bucket, ties are broken by the following bonus scores. The sum // of these scores should be capped to the buket step size to prevent overlapping bucket. - int scoreWithinBucket = rssiBaseScore + throughputBonusScore + currentNetworkBoost + int scoreWithinBucket = rssiBoost + throughputBoost + currentNetworkBoost + bandSpecificBonus; int score = scoreToDetermineBucket + Math.min(mScoringParams.getScoringBucketStepSize(), scoreWithinBucket); diff --git a/service/java/com/android/server/wifi/WakeupController.java b/service/java/com/android/server/wifi/WakeupController.java index d1d0cab94c..7d87b0c9a6 100644 --- a/service/java/com/android/server/wifi/WakeupController.java +++ b/service/java/com/android/server/wifi/WakeupController.java @@ -27,6 +27,7 @@ import android.os.Process; import android.provider.Settings; import android.util.Log; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.HandlerExecutor; @@ -67,6 +68,7 @@ public class WakeupController { private final WifiWakeMetrics mWifiWakeMetrics; private final Clock mClock; private final ActiveModeWarden mActiveModeWarden; + private final Object mLock = new Object(); private final WifiScanner.ScanListener mScanListener = new WifiScanner.ScanListener() { @Override @@ -100,6 +102,7 @@ public class WakeupController { }; /** Whether this feature is enabled in Settings. */ + @GuardedBy("mLock") private boolean mWifiWakeupEnabled; /** Whether the WakeupController is currently active. */ @@ -186,9 +189,11 @@ public class WakeupController { } private void readWifiWakeupEnabledFromSettings() { - mWifiWakeupEnabled = mFrameworkFacade.getIntegerSetting( - mContext, Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1; - Log.d(TAG, "WifiWake " + (mWifiWakeupEnabled ? "enabled" : "disabled")); + synchronized (mLock) { + mWifiWakeupEnabled = mFrameworkFacade.getIntegerSetting( + mContext, Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1; + Log.d(TAG, "WifiWake " + (mWifiWakeupEnabled ? "enabled" : "disabled")); + } } private void setActive(boolean isActive) { @@ -203,15 +208,19 @@ public class WakeupController { * Enable/Disable the feature. */ public void setEnabled(boolean enable) { - mFrameworkFacade.setIntegerSetting( - mContext, Settings.Global.WIFI_WAKEUP_ENABLED, enable ? 1 : 0); + synchronized (mLock) { + mFrameworkFacade.setIntegerSetting( + mContext, Settings.Global.WIFI_WAKEUP_ENABLED, enable ? 1 : 0); + } } /** * Whether the feature is currently enabled. */ public boolean isEnabled() { - return mWifiWakeupEnabled; + synchronized (mLock) { + return mWifiWakeupEnabled; + } } /** @@ -461,7 +470,9 @@ public class WakeupController { */ @VisibleForTesting boolean isEnabledAndReady() { - return mWifiWakeupEnabled && mWakeupConfigStoreData.hasBeenRead(); + synchronized (mLock) { + return mWifiWakeupEnabled && mWakeupConfigStoreData.hasBeenRead(); + } } /** Dumps wakeup controller state. */ diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java index 490c27a3f6..063737f831 100644 --- a/service/java/com/android/server/wifi/WifiApConfigStore.java +++ b/service/java/com/android/server/wifi/WifiApConfigStore.java @@ -188,7 +188,8 @@ public class WifiApConfigStore { * Returns SoftApConfiguration in which some parameters might be upgrade to supported default * configuration. */ - public SoftApConfiguration upgradeSoftApConfiguration(@NonNull SoftApConfiguration config) { + public synchronized SoftApConfiguration upgradeSoftApConfiguration( + @NonNull SoftApConfiguration config) { SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config); if (SdkLevel.isAtLeastS() && ApConfigUtil.isBridgedModeSupported(mContext) && config.getBands().length == 1 && mContext.getResources().getBoolean( @@ -221,7 +222,7 @@ public class WifiApConfigStore { * - If previous bands configuration is bridged mode. Reset to 2.4G when device doesn't support * it. */ - public SoftApConfiguration resetToDefaultForUnsupportedConfig( + public synchronized SoftApConfiguration resetToDefaultForUnsupportedConfig( @NonNull SoftApConfiguration config) { SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config); if ((!ApConfigUtil.isClientForceDisconnectSupported(mContext) @@ -443,15 +444,17 @@ public class WifiApConfigStore { configBuilder.setPassphrase(generatePassword(), SECURITY_TYPE_WPA2_PSK); } - // Update default MAC randomization setting to NONE when feature doesn't support it or - // It was disabled in tethered mode. - if (!ApConfigUtil.isApMacRandomizationSupported(context) - || (mPersistentWifiApConfig != null - && mPersistentWifiApConfig.getMacRandomizationSettingInternal() - == SoftApConfiguration.RANDOMIZATION_NONE)) { - if (SdkLevel.isAtLeastS()) { - configBuilder.setMacRandomizationSetting( - SoftApConfiguration.RANDOMIZATION_NONE); + synchronized (this) { + // Update default MAC randomization setting to NONE when feature doesn't support + // it, or it was disabled in tethered mode. + if (!ApConfigUtil.isApMacRandomizationSupported(context) + || (mPersistentWifiApConfig != null + && mPersistentWifiApConfig.getMacRandomizationSettingInternal() + == SoftApConfiguration.RANDOMIZATION_NONE)) { + if (SdkLevel.isAtLeastS()) { + configBuilder.setMacRandomizationSetting( + SoftApConfiguration.RANDOMIZATION_NONE); + } } } } @@ -516,6 +519,7 @@ public class WifiApConfigStore { * Verify provided preSharedKey in ap config for WPA2_PSK/WPA3_SAE (Transition) network * meets requirements. */ + @SuppressWarnings("ReturnValueIgnored") private static boolean validateApConfigAsciiPreSharedKey( @SoftApConfiguration.SecurityType int securityType, String preSharedKey) { final int sharedKeyLen = preSharedKey.length(); @@ -680,7 +684,8 @@ public class WifiApConfigStore { * @param forcedApBand The forced band. * @param forcedApChannel The forced IEEE channel number or 0 when forced AP band only. */ - public void enableForceSoftApBandOrChannel(@BandType int forcedApBand, int forcedApChannel) { + public synchronized void enableForceSoftApBandOrChannel(@BandType int forcedApBand, + int forcedApChannel) { mForceApChannel = true; mForcedApChannel = forcedApChannel; mForcedApBand = forcedApBand; @@ -689,7 +694,7 @@ public class WifiApConfigStore { /** * Disable force-soft-AP-channel mode which take effect when soft AP starts next time */ - public void disableForceSoftApBandOrChannel() { + public synchronized void disableForceSoftApBandOrChannel() { mForceApChannel = false; } diff --git a/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java b/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java index b99d987273..2d9f91e43d 100644 --- a/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java +++ b/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java @@ -96,65 +96,77 @@ class WifiBackupDataV1Parser implements WifiBackupDataParser { private static final int HIGHEST_SUPPORTED_MINOR_VERSION = 3; // List of tags supported for <WifiConfiguration> section in minor version 0 - private static final Set<String> WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS = - new HashSet<String>(Arrays.asList(new String[] { - WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY, - WifiConfigurationXmlUtil.XML_TAG_SSID, - WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY, - WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS, - WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX, - WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID, - WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS, - WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS, - WifiConfigurationXmlUtil.XML_TAG_SHARED, - })); + private static final Set<String> WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS = Set.of( + WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY, + WifiConfigurationXmlUtil.XML_TAG_SSID, + WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY, + WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS, + WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX, + WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID, + WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF, + WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT, + WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS, + WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS, + WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS, + WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS, + WifiConfigurationXmlUtil.XML_TAG_SHARED); // List of tags supported for <WifiConfiguration> section in minor version 1 private static final Set<String> WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS = - new HashSet<String>() {{ - addAll(WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS); - add(WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE); - }}; + new HashSet<String>(); + static { + WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS.addAll( + WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS); + WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_METERED_OVERRIDE); + } // List of tags supported for <WifiConfiguration> section in minor version 2 private static final Set<String> WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS = - new HashSet<String>() {{ - addAll(WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS); - add(WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN); - }}; + new HashSet<String>(); + static { + WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS.addAll( + WIFI_CONFIGURATION_MINOR_V1_SUPPORTED_TAGS); + WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_IS_AUTO_JOIN); + } // List of tags supported for <WifiConfiguration> section in minor version 3 private static final Set<String> WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS = - new HashSet<String>() {{ - addAll(WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS); - add(WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS_LIST); - add(WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS); - add(WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE); - add(WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE); - add(WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE); - add(WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE); - add(WifiConfigurationXmlUtil.XML_TAG_DELETION_PRIORITY); - add(WifiConfigurationXmlUtil.XML_TAG_NUM_REBOOTS_SINCE_LAST_USE); - }}; + new HashSet<String>(); + static { + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.addAll( + WIFI_CONFIGURATION_MINOR_V2_SUPPORTED_TAGS); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS_LIST); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_SECURITY_PARAMS); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_SECURITY_TYPE); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_SAE_IS_H2E_ONLY_MODE); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_SAE_IS_PK_ONLY_MODE); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_IS_ADDED_BY_AUTO_UPGRADE); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_DELETION_PRIORITY); + WIFI_CONFIGURATION_MINOR_V3_SUPPORTED_TAGS.add( + WifiConfigurationXmlUtil.XML_TAG_NUM_REBOOTS_SINCE_LAST_USE); + } // List of tags supported for <IpConfiguration> section in minor version 0 to 3 - private static final Set<String> IP_CONFIGURATION_MINOR_V0_V1_V2_V3_SUPPORTED_TAGS = - new HashSet<String>(Arrays.asList(new String[] { - IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT, - IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS, - IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH, - IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS, - IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES, - IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS, - IpConfigurationXmlUtil.XML_TAG_PROXY_HOST, - IpConfigurationXmlUtil.XML_TAG_PROXY_PORT, - IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST, - IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE, - })); + private static final Set<String> IP_CONFIGURATION_MINOR_V0_V1_V2_V3_SUPPORTED_TAGS = Set.of( + IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT, + IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS, + IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH, + IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS, + IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES, + IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS, + IpConfigurationXmlUtil.XML_TAG_PROXY_HOST, + IpConfigurationXmlUtil.XML_TAG_PROXY_PORT, + IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST, + IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE); @Override public List<WifiConfiguration> parseNetworkConfigurationsFromXml(XmlPullParser in, diff --git a/service/java/com/android/server/wifi/WifiBackupRestore.java b/service/java/com/android/server/wifi/WifiBackupRestore.java index 564a9021f0..1c2883635a 100644 --- a/service/java/com/android/server/wifi/WifiBackupRestore.java +++ b/service/java/com/android/server/wifi/WifiBackupRestore.java @@ -46,6 +46,7 @@ import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -459,7 +460,7 @@ public class WifiBackupRestore { } if (mDebugLastIpConfigBackupDataRestored != null) { pw.println("Last old ipconfig backup data restored: " - + mDebugLastIpConfigBackupDataRestored); + + Arrays.toString(mDebugLastIpConfigBackupDataRestored)); } } @@ -640,9 +641,8 @@ public class WifiBackupRestore { } if (mParsedKeyMgmtLine == null) { // no key_mgmt line specified; this is defined as equivalent to - // "WPA-PSK WPA-EAP". + // "WPA-PSK". configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); } else { // Need to parse the mParsedKeyMgmtLine line final String bareKeyMgmt = diff --git a/service/java/com/android/server/wifi/WifiBlocklistMonitor.java b/service/java/com/android/server/wifi/WifiBlocklistMonitor.java index 14cd162f59..0c362a636f 100644 --- a/service/java/com/android/server/wifi/WifiBlocklistMonitor.java +++ b/service/java/com/android/server/wifi/WifiBlocklistMonitor.java @@ -131,6 +131,7 @@ public class WifiBlocklistMonitor { private final ScoringParams mScoringParams; private final WifiMetrics mWifiMetrics; private final WifiPermissionsUtil mWifiPermissionsUtil; + private ScanRequestProxy mScanRequestProxy; private final Map<Integer, BssidDisableReason> mBssidDisableReasons = buildBssidDisableReasons(); private final SparseArray<DisableReasonInfo> mDisableReasonInfo; @@ -201,6 +202,49 @@ public class WifiBlocklistMonitor { } } + /** Map of BSSID to affiliated BSSIDs. */ + private Map<String, List<String>> mAffiliatedBssidMap = new ArrayMap<>(); + + /** + * Set the mapping of BSSID to affiliated BSSIDs. + * + * @param bssid A unique identifier of the AP. + * @param bssids List of affiliated BSSIDs. + */ + public void setAffiliatedBssids(@NonNull String bssid, @NonNull List<String> bssids) { + mAffiliatedBssidMap.put(bssid, bssids); + } + + /** + * Get affiliated BSSIDs mapped to a BSSID. + * + * @param bssid A unique identifier of the AP. + * @return List of affiliated BSSIDs or an empty list. + */ + public List<String> getAffiliatedBssids(@NonNull String bssid) { + List<String> affiliatedBssids = mAffiliatedBssidMap.get(bssid); + return affiliatedBssids == null ? Collections.EMPTY_LIST : affiliatedBssids; + } + + /** + * Remove affiliated BSSIDs mapped to a BSSID. + * + * @param bssid A unique identifier of the AP. + */ + public void removeAffiliatedBssids(@NonNull String bssid) { + mAffiliatedBssidMap.remove(bssid); + } + + /** Clear affiliated BSSID mapping table. */ + public void clearAffiliatedBssids() { + mAffiliatedBssidMap.clear(); + } + + /** Sets the ScanRequestProxy **/ + public void setScanRequestProxy(ScanRequestProxy scanRequestProxy) { + mScanRequestProxy = scanRequestProxy; + } + /** * Create a new instance of WifiBlocklistMonitor */ @@ -252,6 +296,8 @@ public class WifiBlocklistMonitor { pw.println("WifiBlocklistMonitor - Bssid blocklist begin ----"); mBssidStatusMap.values().stream().forEach(entry -> pw.println(entry)); pw.println("WifiBlocklistMonitor - Bssid blocklist end ----"); + pw.println("Dump of BSSID to Affiliated BSSID mapping"); + mAffiliatedBssidMap.forEach((bssid, aList) -> pw.println(bssid + " -> " + aList)); mBssidBlocklistMonitorLogger.dump(pw); } @@ -365,6 +411,14 @@ public class WifiBlocklistMonitor { return; } addToBlocklist(status, durationMs, blockReason, rssi); + /** + * Add affiliated BSSIDs also into the block list with the same parameters as connected + * BSSID. + */ + for (String affiliatedBssid : getAffiliatedBssids(bssid)) { + status = getOrCreateBssidStatus(affiliatedBssid, config.SSID); + addToBlocklist(status, durationMs, blockReason, rssi); + } } private String getFailureReasonString(@FailureReason int reasonCode) { @@ -431,11 +485,37 @@ public class WifiBlocklistMonitor { localLog("Ignoring failure to wait for watchdog to trigger first."); return false; } + // rssi may be unavailable for the first ever connection to a newly added network + // because it hasn't been cached inside the ScanDetailsCache yet. In this case, try to + // read the RSSI from the latest scan results. + if (rssi == WifiConfiguration.INVALID_RSSI && bssid != null) { + if (mScanRequestProxy != null) { + ScanResult scanResult = mScanRequestProxy.getScanResult(bssid); + if (scanResult != null) { + rssi = scanResult.level; + } + } else { + localLog("mScanRequestProxy is null"); + Log.w(TAG, "mScanRequestProxy is null"); + } + } int baseBlockDurationMs = getBaseBlockDurationForReason(reasonCode); - addToBlocklist(entry, - getBlocklistDurationWithExponentialBackoff(currentStreak, baseBlockDurationMs), - reasonCode, rssi); + long expBackoff = getBlocklistDurationWithExponentialBackoff(currentStreak, + baseBlockDurationMs); + addToBlocklist(entry, expBackoff, reasonCode, rssi); mWifiScoreCard.incrementBssidBlocklistStreak(ssid, bssid, reasonCode); + + /** + * Block list affiliated BSSID with same parameters, e.g. reason code, rssi ..etc. + * as connected BSSID. + */ + for (String affiliatedBssid : getAffiliatedBssids(bssid)) { + BssidStatus affEntry = getOrCreateBssidStatus(affiliatedBssid, ssid); + affEntry.failureCount[reasonCode] = entry.failureCount[reasonCode]; + addToBlocklist(affEntry, expBackoff, reasonCode, rssi); + mWifiScoreCard.incrementBssidBlocklistStreak(ssid, affiliatedBssid, reasonCode); + } + return true; } return false; @@ -446,9 +526,12 @@ public class WifiBlocklistMonitor { case REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE: return mContext.getResources().getInteger(R.integer .config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs); + case REASON_NETWORK_VALIDATION_FAILURE: + return mContext.getResources().getInteger( + R.integer.config_wifiBssidBlocklistMonitorValidationFailureBaseBlockDurationMs); default: return mContext.getResources().getInteger( - R.integer.config_wifiBssidBlocklistMonitorBaseBlockDurationMs); + R.integer.config_wifiBssidBlocklistMonitorBaseBlockDurationMs); } } @@ -499,6 +582,20 @@ public class WifiBlocklistMonitor { */ public void handleBssidConnectionSuccess(@NonNull String bssid, @NonNull String ssid) { mDisabledSsids.remove(ssid); + resetFailuresAfterConnection(bssid, ssid); + for (String affiliatedBssid : getAffiliatedBssids(bssid)) { + resetFailuresAfterConnection(affiliatedBssid, ssid); + } + } + + /** + * Reset all failure counters related to a connection. + * + * @param bssid A unique identifier of the AP. + * @param ssid Network name. + */ + private void resetFailuresAfterConnection(@NonNull String bssid, @NonNull String ssid) { + /** * First reset the blocklist streak. * This needs to be done even if a BssidStatus is not found, since the BssidStatus may @@ -546,27 +643,67 @@ public class WifiBlocklistMonitor { * And then remove the BSSID from blocklist. */ public void handleNetworkValidationSuccess(@NonNull String bssid, @NonNull String ssid) { + resetNetworkValidationFailures(bssid, ssid); + /** + * Network validation may take more than 1 tries to succeed. + * remove the BSSID from blocklist to make sure we are not accidentally blocking good + * BSSIDs. + **/ + removeFromBlocklist(bssid, "Network validation success"); + + for (String affiliatedBssid : getAffiliatedBssids(bssid)) { + resetNetworkValidationFailures(affiliatedBssid, ssid); + removeFromBlocklist(affiliatedBssid, "Network validation success"); + } + } + + /** + * Clear failure counters related to network validation. + * + * @param bssid A unique identifier of the AP. + * @param ssid Network name. + */ + private void resetNetworkValidationFailures(@NonNull String bssid, @NonNull String ssid) { mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_NETWORK_VALIDATION_FAILURE); BssidStatus status = mBssidStatusMap.get(bssid); if (status == null) { return; } status.failureCount[REASON_NETWORK_VALIDATION_FAILURE] = 0; - /** - * Network validation may take more than 1 tries to succeed. - * remove the BSSID from blocklist to make sure we are not accidentally blocking good - * BSSIDs. - **/ + } + + /** + * Remove BSSID from block list. + * + * @param bssid A unique identifier of the AP. + * @param reasonString A string to be logged while removing the entry from the block list. + */ + private void removeFromBlocklist(@NonNull String bssid, final String reasonString) { + BssidStatus status = mBssidStatusMap.get(bssid); + if (status == null) { + return; + } + if (status.isInBlocklist) { - mBssidBlocklistMonitorLogger.logBssidUnblocked(status, "Network validation success"); + mBssidBlocklistMonitorLogger.logBssidUnblocked(status, reasonString); mBssidStatusMap.remove(bssid); } } /** - * Note a successful DHCP provisioning and clear appropriate faliure counters. + * Note a successful DHCP provisioning and clear appropriate failure counters. */ public void handleDhcpProvisioningSuccess(@NonNull String bssid, @NonNull String ssid) { + resetDhcpFailures(bssid, ssid); + for (String affiliatedBssid : getAffiliatedBssids(bssid)) { + resetDhcpFailures(affiliatedBssid, ssid); + } + } + + /** + * Reset failure counters related to DHCP. + */ + private void resetDhcpFailures(@NonNull String bssid, @NonNull String ssid) { mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_DHCP_FAILURE); BssidStatus status = mBssidStatusMap.get(bssid); if (status == null) { @@ -712,9 +849,10 @@ public class WifiBlocklistMonitor { status.lastRssi < sufficientRssi && scanResult.level >= sufficientRssi; boolean goodRssiBreached = status.lastRssi < goodRssi && scanResult.level >= goodRssi; if (rssiMinDiffAchieved && (sufficientRssiBreached || goodRssiBreached)) { - mBssidBlocklistMonitorLogger.logBssidUnblocked( - status, "rssi significantly improved"); - mBssidStatusMap.remove(status.bssid); + removeFromBlocklist(status.bssid, "rssi significantly improved"); + for (String affiliatedBssid : getAffiliatedBssids(status.bssid)) { + removeFromBlocklist(affiliatedBssid, "rssi significantly improved"); + } results.add(scanDetail); } } @@ -961,28 +1099,80 @@ public class WifiBlocklistMonitor { "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ", mContext.getResources().getInteger(R.integer .config_wifiDisableReasonAssociationRejectionThreshold), - 5 * 60 * 1000)); + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonAssociationRejectionDurationMs))); mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE, new DisableReasonInfo( "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE", mContext.getResources().getInteger(R.integer .config_wifiDisableReasonAuthenticationFailureThreshold), - 5 * 60 * 1000)); + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonAuthenticationFailureDurationMs))); mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_DHCP_FAILURE, new DisableReasonInfo( "NETWORK_SELECTION_DISABLED_DHCP_FAILURE", mContext.getResources().getInteger(R.integer .config_wifiDisableReasonDhcpFailureThreshold), - 5 * 60 * 1000)); + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonDhcpFailureDurationMs))); mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_NETWORK_NOT_FOUND, new DisableReasonInfo( "NETWORK_SELECTION_DISABLED_NETWORK_NOT_FOUND", mContext.getResources().getInteger(R.integer .config_wifiDisableReasonNetworkNotFoundThreshold), - 5 * 60 * 1000)); + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonNetworkNotFoundDurationMs))); + + mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY", + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonNoInternetTemporaryThreshold), + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonNoInternetTemporaryDurationMs))); + + mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS", + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonAuthenticationNoCredentialsThreshold), + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonAuthenticationNoCredentialsDurationMs))); + + mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT", + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonNoInternetPermanentThreshold), + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonNoInternetPermanentDurationMs))); + + mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD", + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonByWrongPasswordThreshold), + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonByWrongPasswordDurationMs))); + + mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_SUBSCRIPTION", + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonAuthenticationNoSubscriptionThreshold), + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonAuthenticationNoSubscriptionDurationMs))); + + mDisableReasonInfo.put(NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_CONSECUTIVE_FAILURES", + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonConsecutiveFailuresThreshold), + mContext.getResources().getInteger(R.integer + .config_wifiDisableReasonConsecutiveFailuresDurationMs))); } /** diff --git a/service/java/com/android/server/wifi/WifiCandidates.java b/service/java/com/android/server/wifi/WifiCandidates.java index f32d3a2704..0eb6032492 100644 --- a/service/java/com/android/server/wifi/WifiCandidates.java +++ b/service/java/com/android/server/wifi/WifiCandidates.java @@ -99,10 +99,7 @@ public class WifiCandidates { * Returns true for a oem private network. */ boolean isOemPrivate(); - /** - * Returns true for a secondary network with internet. - */ - boolean isSecondaryInternet(); + /** * Returns true if suggestion came from a carrier or privileged app. */ @@ -200,7 +197,6 @@ public class WifiCandidates { private final boolean mRestricted; private final boolean mOemPaid; private final boolean mOemPrivate; - private final boolean mSecondaryInternet; private final boolean mCarrierOrPrivileged; private final int mPredictedThroughputMbps; private final int mEstimatedPercentInternetAvailability; @@ -235,7 +231,6 @@ public class WifiCandidates { this.mTrusted = config.trusted; this.mOemPaid = config.oemPaid; this.mOemPrivate = config.oemPrivate; - this.mSecondaryInternet = config.dbsSecondaryInternet; this.mCarrierOrPrivileged = isCarrierOrPrivileged; this.mPredictedThroughputMbps = predictedThroughputMbps; this.mEstimatedPercentInternetAvailability = perBssid == null ? 50 : @@ -289,11 +284,6 @@ public class WifiCandidates { } @Override - public boolean isSecondaryInternet() { - return mSecondaryInternet; - } - - @Override public boolean isCarrierOrPrivileged() { return mCarrierOrPrivileged; } @@ -396,7 +386,6 @@ public class WifiCandidates { + (isRestricted() ? "restricted, " : "") + (isOemPaid() ? "oemPaid, " : "") + (isOemPrivate() ? "oemPrivate, " : "") - + (isSecondaryInternet() ? "secondaryInternet, " : "") + (isCarrierOrPrivileged() ? "priv, " : "") + (isMetered() ? "metered, " : "") + (hasNoInternetAccess() ? "noInternet, " : "") diff --git a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java index 59d9ae602f..cebd07119a 100644 --- a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java +++ b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java @@ -58,6 +58,7 @@ import android.util.SparseBooleanArray; import androidx.annotation.RequiresApi; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.modules.utils.HandlerExecutor; @@ -190,8 +191,11 @@ public class WifiCarrierInfoManager { private boolean mVerboseLogEnabled = false; private SparseBooleanArray mImsiEncryptionInfoAvailable = new SparseBooleanArray(); private final Map<Integer, Boolean> mImsiPrivacyProtectionExemptionMap = new HashMap<>(); - private final Map<Integer, Boolean> mMergedCarrierNetworkOffloadMap = new HashMap<>(); - private final Map<Integer, Boolean> mUnmergedCarrierNetworkOffloadMap = new HashMap<>(); + private final Object mCarrierNetworkOffloadMapLock = new Object(); + @GuardedBy("mCarrierNetworkOffloadMapLock") + private SparseBooleanArray mMergedCarrierNetworkOffloadMap = new SparseBooleanArray(); + @GuardedBy("mCarrierNetworkOffloadMapLock") + private SparseBooleanArray mUnmergedCarrierNetworkOffloadMap = new SparseBooleanArray(); private final List<OnUserApproveCarrierListener> mOnUserApproveCarrierListeners = new ArrayList<>(); private final SparseBooleanArray mUserDataEnabled = new SparseBooleanArray(); @@ -317,13 +321,11 @@ public class WifiCarrierInfoManager { WifiCarrierInfoStoreManagerData.DataSource { @Override - public Map<Integer, Boolean> toSerializeMergedCarrierNetworkOffloadMap() { - return mMergedCarrierNetworkOffloadMap; - } - - @Override - public Map<Integer, Boolean> toSerializeUnmergedCarrierNetworkOffloadMap() { - return mUnmergedCarrierNetworkOffloadMap; + public SparseBooleanArray getCarrierNetworkOffloadMap(boolean isMerged) { + synchronized (mCarrierNetworkOffloadMapLock) { + return isMerged ? mMergedCarrierNetworkOffloadMap + : mUnmergedCarrierNetworkOffloadMap; + } } @Override @@ -331,25 +333,24 @@ public class WifiCarrierInfoManager { mHasNewSharedDataToSerialize = false; } - @Override - public void fromMergedCarrierNetworkOffloadMapDeserialized( - Map<Integer, Boolean> carrierOffloadMap) { - mMergedCarrierNetworkOffloadMap.clear(); - mMergedCarrierNetworkOffloadMap.putAll(carrierOffloadMap); - } - - @Override - public void fromUnmergedCarrierNetworkOffloadMapDeserialized( - Map<Integer, Boolean> subscriptionOffloadMap) { - mUnmergedCarrierNetworkOffloadMap.clear(); - mUnmergedCarrierNetworkOffloadMap.putAll(subscriptionOffloadMap); + public void setCarrierNetworkOffloadMap(SparseBooleanArray carrierOffloadMap, + boolean isMerged) { + synchronized (mCarrierNetworkOffloadMapLock) { + if (isMerged) { + mMergedCarrierNetworkOffloadMap = carrierOffloadMap; + } else { + mUnmergedCarrierNetworkOffloadMap = carrierOffloadMap; + } + } } @Override public void reset() { - mMergedCarrierNetworkOffloadMap.clear(); - mUnmergedCarrierNetworkOffloadMap.clear(); + synchronized (mCarrierNetworkOffloadMapLock) { + mMergedCarrierNetworkOffloadMap.clear(); + mUnmergedCarrierNetworkOffloadMap.clear(); + } } @Override @@ -1915,17 +1916,22 @@ public class WifiCarrierInfoManager { */ public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled) { - if (merged) { - mMergedCarrierNetworkOffloadMap.put(subscriptionId, enabled); - } else { - mUnmergedCarrierNetworkOffloadMap.put(subscriptionId, enabled); - } - if (!enabled) { - for (OnCarrierOffloadDisabledListener listener : mOnCarrierOffloadDisabledListeners) { - listener.onCarrierOffloadDisabled(subscriptionId, merged); + synchronized (mCarrierNetworkOffloadMapLock) { + if (merged) { + mMergedCarrierNetworkOffloadMap.put(subscriptionId, enabled); + } else { + mUnmergedCarrierNetworkOffloadMap.put(subscriptionId, enabled); } } - saveToStore(); + mHandler.post(() -> { + if (!enabled) { + for (OnCarrierOffloadDisabledListener listener : + mOnCarrierOffloadDisabledListeners) { + listener.onCarrierOffloadDisabled(subscriptionId, merged); + } + } + saveToStore(); + }); } /** @@ -1935,11 +1941,13 @@ public class WifiCarrierInfoManager { * @return True to indicate carrier offload is enabled, false otherwise. */ public boolean isCarrierNetworkOffloadEnabled(int subId, boolean merged) { - if (merged) { - return mMergedCarrierNetworkOffloadMap.getOrDefault(subId, true) - && isMobileDataEnabled(subId); - } else { - return mUnmergedCarrierNetworkOffloadMap.getOrDefault(subId, true); + synchronized (mCarrierNetworkOffloadMapLock) { + if (merged) { + return mMergedCarrierNetworkOffloadMap.get(subId, true) + && isMobileDataEnabled(subId); + } else { + return mUnmergedCarrierNetworkOffloadMap.get(subId, true); + } } } @@ -1976,9 +1984,11 @@ public class WifiCarrierInfoManager { * Helper method for user factory reset network setting. */ public void clear() { + synchronized (mCarrierNetworkOffloadMapLock) { + mMergedCarrierNetworkOffloadMap.clear(); + mUnmergedCarrierNetworkOffloadMap.clear(); + } mImsiPrivacyProtectionExemptionMap.clear(); - mMergedCarrierNetworkOffloadMap.clear(); - mUnmergedCarrierNetworkOffloadMap.clear(); mUserDataEnabled.clear(); mCarrierPrivilegedPackagesBySimSlot.clear(); if (SdkLevel.isAtLeastS()) { diff --git a/service/java/com/android/server/wifi/WifiCarrierInfoStoreManagerData.java b/service/java/com/android/server/wifi/WifiCarrierInfoStoreManagerData.java index 29e7a6ac6f..bf2b4ce33e 100644 --- a/service/java/com/android/server/wifi/WifiCarrierInfoStoreManagerData.java +++ b/service/java/com/android/server/wifi/WifiCarrierInfoStoreManagerData.java @@ -18,6 +18,7 @@ package com.android.server.wifi; import android.annotation.NonNull; import android.util.Log; +import android.util.SparseBooleanArray; import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; @@ -51,14 +52,10 @@ public class WifiCarrierInfoStoreManagerData implements WifiConfigStore.StoreDat /** * Retrieve the merged carrier network offload map from the data source to serialize to * disk. + * + * @param isMerged true for merged map, false for unmerged map. */ - Map<Integer, Boolean> toSerializeMergedCarrierNetworkOffloadMap(); - - /** - * Retrieve the unmerged carrier network offload map from the data source to serialize to - * disk. - */ - Map<Integer, Boolean> toSerializeUnmergedCarrierNetworkOffloadMap(); + SparseBooleanArray getCarrierNetworkOffloadMap(boolean isMerged); /** * Should be called when serialize is completed. @@ -69,16 +66,9 @@ public class WifiCarrierInfoStoreManagerData implements WifiConfigStore.StoreDat /** * Set the merged carrier network offload map in the data source after deserialize them * from disk. + * @param isMerged true for merged map, false for unmerged map. */ - void fromMergedCarrierNetworkOffloadMapDeserialized( - Map<Integer, Boolean> carrierOffloadMap); - - /** - * Set the unmerged carrier network offload map in the data source after serializing them - * from disk. - */ - void fromUnmergedCarrierNetworkOffloadMapDeserialized( - Map<Integer, Boolean> subscriptionOffloadMap); + void setCarrierNetworkOffloadMap(SparseBooleanArray carrierOffloadMap, boolean isMerged); /** * Clear internal data structure in preparation for user switch or initial store read. @@ -104,9 +94,9 @@ public class WifiCarrierInfoStoreManagerData implements WifiConfigStore.StoreDat public void serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { XmlUtil.writeNextValue(out, XML_TAG_MERGED_CARRIER_NETWORK_OFFLOAD_MAP, - integerMapToStringMap(mDataSource.toSerializeMergedCarrierNetworkOffloadMap())); + sparseArrayToStringMap(mDataSource.getCarrierNetworkOffloadMap(true))); XmlUtil.writeNextValue(out, XML_TAG_UNMERGED_CARRIER_NETWORK_OFFLOAD_MAP, - integerMapToStringMap(mDataSource.toSerializeUnmergedCarrierNetworkOffloadMap())); + sparseArrayToStringMap(mDataSource.getCarrierNetworkOffloadMap(false))); mDataSource.serializeComplete(); } @@ -132,14 +122,14 @@ public class WifiCarrierInfoStoreManagerData implements WifiConfigStore.StoreDat switch (valueName[0]) { case XML_TAG_MERGED_CARRIER_NETWORK_OFFLOAD_MAP: if (value instanceof Map) { - mDataSource.fromMergedCarrierNetworkOffloadMapDeserialized( - stringMapToIntegerMap((Map<String, Boolean>) value)); + mDataSource.setCarrierNetworkOffloadMap( + stringMapToSparseArray((Map<String, Boolean>) value), true); } break; case XML_TAG_UNMERGED_CARRIER_NETWORK_OFFLOAD_MAP: if (value instanceof Map) { - mDataSource.fromUnmergedCarrierNetworkOffloadMapDeserialized( - stringMapToIntegerMap((Map<String, Boolean>) value)); + mDataSource.setCarrierNetworkOffloadMap( + stringMapToSparseArray((Map<String, Boolean>) value), false); } break; default: @@ -151,19 +141,19 @@ public class WifiCarrierInfoStoreManagerData implements WifiConfigStore.StoreDat } } - private Map<String, Boolean> integerMapToStringMap(Map<Integer, Boolean> input) { + private Map<String, Boolean> sparseArrayToStringMap(SparseBooleanArray input) { Map<String, Boolean> output = new HashMap<>(); if (input == null) { return output; } - for (Map.Entry<Integer, Boolean> entry : input.entrySet()) { - output.put(Integer.toString(entry.getKey()), entry.getValue()); + for (int i = 0; i < input.size(); i++) { + output.put(Integer.toString(input.keyAt(i)), input.valueAt(i)); } return output; } - private Map<Integer, Boolean> stringMapToIntegerMap(Map<String, Boolean> input) { - Map<Integer, Boolean> output = new HashMap<>(); + private SparseBooleanArray stringMapToSparseArray(Map<String, Boolean> input) { + SparseBooleanArray output = new SparseBooleanArray(); if (input == null) { return output; } diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index f0512e98f5..cd1b0881dd 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -1020,7 +1020,8 @@ public class WifiConfigManager { // modify the network. return isCreator || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid); + || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid) + || mWifiPermissionsUtil.checkConfigOverridePermission(uid); } final ContentResolver resolver = mContext.getContentResolver(); @@ -1029,7 +1030,8 @@ public class WifiConfigManager { return !isLockdownFeatureEnabled // If not locked down, settings app (i.e user) has permission to modify the network. && (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) - || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)); + || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid) + || mWifiPermissionsUtil.checkConfigOverridePermission(uid)); } private void mergeSecurityParamsListWithInternalWifiConfiguration( @@ -1183,7 +1185,6 @@ public class WifiConfigManager { internalConfig.trusted = externalConfig.trusted; internalConfig.oemPaid = externalConfig.oemPaid; internalConfig.oemPrivate = externalConfig.oemPrivate; - internalConfig.dbsSecondaryInternet = externalConfig.dbsSecondaryInternet; internalConfig.carrierMerged = externalConfig.carrierMerged; internalConfig.restricted = externalConfig.restricted; @@ -1408,7 +1409,8 @@ public class WifiConfigManager { // Only allow changes in Repeater Enabled flag if the user has permission to if (WifiConfigurationUtil.hasRepeaterEnabledChanged( existingInternalConfig, newInternalConfig) - && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { + && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) + && !mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { Log.e(TAG, "UID " + uid + " does not have permission to modify Repeater Enabled Settings " + " , or add a network with Repeater Enabled set to true " @@ -1421,6 +1423,7 @@ public class WifiConfigManager { if (WifiConfigurationUtil.hasMacRandomizationSettingsChanged(existingInternalConfig, newInternalConfig) && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) && !mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid) + && !mWifiPermissionsUtil.checkConfigOverridePermission(uid) && !(newInternalConfig.isPasspoint() && uid == newInternalConfig.creatorUid) && !config.fromWifiNetworkSuggestion && !mWifiPermissionsUtil.isDeviceInDemoMode(mContext) @@ -3575,7 +3578,7 @@ public class WifiConfigManager { * @param forceWrite Whether the write needs to be forced or not. * @return Whether the write was successful or not, this is applicable only for force writes. */ - public boolean saveToStore(boolean forceWrite) { + public synchronized boolean saveToStore(boolean forceWrite) { if (mPendingStoreRead) { Log.e(TAG, "Cannot save to store before store is read!"); return false; @@ -3692,7 +3695,8 @@ public class WifiConfigManager { mWifiPermissionsUtil.checkNetworkManagedProvisioningPermission(uid); // If |uid| corresponds to the admin, allow all modifications. if (isAdmin || hasNetworkSettingsPermission - || hasNetworkSetupWizardPermission || hasNetworkManagedProvisioningPermission) { + || hasNetworkSetupWizardPermission || hasNetworkManagedProvisioningPermission + || mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { return true; } if (mVerboseLoggingEnabled) { diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index 74952014a4..958cb1e538 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -1026,9 +1026,8 @@ public class WifiConfigStore { * sections (for migration purposes), then override this method. * @return a set of section headers */ - default HashSet<String> getSectionsToParse() { - // - return new HashSet<String>() {{ add(getName()); }}; + default Set<String> getSectionsToParse() { + return Set.of(getName()); } /** diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java index 95db4d75aa..aafe7f79b4 100644 --- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java +++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java @@ -616,9 +616,8 @@ public class WifiConfigurationUtil { Log.e(TAG, "validateKeyMgmt failed: not WPA_EAP"); return false; } - if (!keyMgmnt.get(WifiConfiguration.KeyMgmt.IEEE8021X) - && !keyMgmnt.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - Log.e(TAG, "validateKeyMgmt failed: not PSK or 8021X"); + if (!keyMgmnt.get(WifiConfiguration.KeyMgmt.IEEE8021X)) { + Log.e(TAG, "validateKeyMgmt failed: not 8021X"); return false; } // SUITE-B keymgmt must be WPA_EAP + IEEE8021X + SUITE_B_192. @@ -630,6 +629,11 @@ public class WifiConfigurationUtil { return false; } } + // There should be at least one keymgmt. + if (keyMgmnt.cardinality() == 0) { + Log.e(TAG, "validateKeyMgmt failed: cardinality = 0"); + return false; + } return true; } @@ -814,9 +818,11 @@ public class WifiConfigurationUtil { * 12. {@link WifiConfiguration#getIpConfiguration()} * * @param specifier Instance of {@link WifiNetworkSpecifier}. + * @param maxChannelsAllowed The max number allowed to set in a WifiNetworkSpecifier * @return true if the parameters are valid, false otherwise. */ - public static boolean validateNetworkSpecifier(WifiNetworkSpecifier specifier) { + public static boolean validateNetworkSpecifier(WifiNetworkSpecifier specifier, + int maxChannelsAllowed) { if (!isValidNetworkSpecifier(specifier)) { Log.e(TAG, "validateNetworkSpecifier failed : invalid network specifier"); return false; @@ -832,6 +838,9 @@ public class WifiConfigurationUtil { if (!WifiNetworkSpecifier.validateBand(getBand(specifier))) { return false; } + if (specifier.getPreferredChannelFrequenciesMhz().length > maxChannelsAllowed) { + return false; + } WifiConfiguration config = specifier.wifiConfiguration; if (specifier.ssidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) { // For literal SSID matches, the value should satisfy SSID requirements. diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index 1d2a188b9c..b147be6592 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -32,6 +32,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.net.IpConfiguration; import android.net.MacAddress; import android.net.wifi.IPnoScanResultsCallback; import android.net.wifi.ScanResult; @@ -48,11 +49,11 @@ import android.net.wifi.WifiScanner.ScanSettings; import android.net.wifi.WifiSsid; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.util.ScanResultUtil; -import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.os.Process; import android.os.WorkSource; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -60,9 +61,10 @@ import android.util.LocalLog; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; -import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.hotspot2.PasspointManager; +import com.android.server.wifi.scanner.WifiScannerInternal; +import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.wifi.resources.R; import java.io.FileDescriptor; @@ -148,6 +150,7 @@ public class WifiConnectivityManager { private final WifiContext mContext; private final WifiConfigManager mConfigManager; + private final WifiCarrierInfoManager mWifiCarrierInfoManager; private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; private final WifiConnectivityHelper mConnectivityHelper; private final WifiNetworkSelector mNetworkSelector; @@ -155,7 +158,7 @@ public class WifiConnectivityManager { private final OpenNetworkNotifier mOpenNetworkNotifier; private final WifiMetrics mWifiMetrics; private final AlarmManager mAlarmManager; - private final Handler mEventHandler; + private final RunnerHandler mEventHandler; private final ExternalPnoScanRequestManager mExternalPnoScanRequestManager; private final @NonNull SsidTranslator mSsidTranslator; private final Clock mClock; @@ -175,8 +178,9 @@ public class WifiConnectivityManager { private final DeviceConfigFacade mDeviceConfigFacade; private final ActiveModeWarden mActiveModeWarden; private final FrameworkFacade mFrameworkFacade; + private final WifiPermissionsUtil mWifiPermissionsUtil; - private WifiScanner mScanner; + private WifiScannerInternal mScanner; private final MultiInternetManager mMultiInternetManager; private boolean mDbg = false; private boolean mVerboseLoggingEnabled = false; @@ -320,8 +324,9 @@ public class WifiConnectivityManager { settings.channels[index++] = new WifiScanner.ChannelSpec(freq); } SingleScanListener singleScanListener = new SingleScanListener(false); - mScanner.startScan(settings, new HandlerExecutor(mEventHandler), - singleScanListener, WIFI_WORK_SOURCE); + mScanner.startScan(settings, + new WifiScannerInternal.ScanListener(singleScanListener, + mEventHandler)); mWifiMetrics.incrementConnectivityOneshotScanCount(); } }; @@ -375,7 +380,7 @@ public class WifiConnectivityManager { // a different band with the primary. return false; } - final WifiInfo primaryInfo = primaryCcm.syncRequestConnectionInfo(); + final WifiInfo primaryInfo = primaryCcm.getConnectionInfo(); final int primaryBand = ScanResult.toBand(primaryInfo.getFrequency()); List<WifiCandidates.Candidate> secondaryCmmCandidates; @@ -394,11 +399,20 @@ public class WifiConnectivityManager { && c.getKey().securityType == primaryInfo.getCurrentSecurityType(); }).collect(Collectors.toList()); } + // Filter by specified BSSIDs + Map<Integer, String> specifiedBssids = mMultiInternetManager.getSpecifiedBssids(); + List<WifiCandidates.Candidate> preferredSecondaryCandidates = + secondaryCmmCandidates.stream().filter(c -> { + final int band = ScanResult.toBand(c.getFrequency()); + return specifiedBssids.containsKey(band) && specifiedBssids.get(band).equals( + c.getKey().bssid.toString()); + }).collect(Collectors.toList()); // Perform network selection among secondary candidates. Create a new copy. Do not allow // user choice override. final WifiConfiguration secondaryCmmCandidate = - mNetworkSelector.selectNetwork(secondaryCmmCandidates, - false /* overrideEnabled */); + mNetworkSelector.selectNetwork(preferredSecondaryCandidates.isEmpty() + ? secondaryCmmCandidates : preferredSecondaryCandidates, + false /* overrideEnabled */); // No secondary cmm for internet selected, fallback to legacy flow. if (secondaryCmmCandidate == null @@ -411,6 +425,16 @@ public class WifiConnectivityManager { localLog(listenerName + ":secondaryCmmCandidate " + secondaryCmmCandidate.getNetworkSelectionStatus().getCandidate().SSID + " / " + secondaryCmmCandidate.getNetworkSelectionStatus().getCandidate().BSSID); + // Check if secondary candidate is the same SSID and network id with primary. + final boolean isDbsAp = TextUtils.equals(primaryInfo.getSSID(), + secondaryCmmCandidate.SSID) && (primaryInfo.getNetworkId() + == secondaryCmmCandidate.networkId); + final boolean isUsingStaticIp = + (secondaryCmmCandidate.getIpAssignment() == IpConfiguration.IpAssignment.STATIC); + if (isDbsAp && isUsingStaticIp) { + localLog(listenerName + ": Can't connect to DBS AP with Static IP."); + return false; + } // At this point secondaryCmmCandidate must be multi internet. final WorkSource secondaryRequestorWs = mMultiInternetConnectionRequestorWs; @@ -459,10 +483,6 @@ public class WifiConnectivityManager { // Set the concrete client mode manager to secondary internet usage. ConcreteClientModeManager ccm = (ConcreteClientModeManager) cm; ccm.setSecondaryInternet(true); - // Check if secondary candidate is the same SSID and network Id with primary. - final boolean isDbsAp = TextUtils.equals(primaryInfo.getSSID(), - secondaryCmmCandidate.SSID) && (primaryInfo.getNetworkId() - == secondaryCmmCandidate.networkId); ccm.setSecondaryInternetDbsAp(isDbsAp); localLog(listenerName + ": WNS candidate(secondary)-" + secondaryCmmCandidate.SSID + " / " @@ -471,7 +491,6 @@ public class WifiConnectivityManager { // Secondary candidate cannot be null (otherwise we would have switched to // legacy flow above). Use the explicit bssid for network connection. WifiConfiguration targetNetwork = new WifiConfiguration(secondaryCmmCandidate); - targetNetwork.dbsSecondaryInternet = isDbsAp; targetNetwork.ephemeral = true; targetNetwork.BSSID = targetBssid2; // specify the BSSID to disable roaming. connectToNetworkUsingCmmWithoutMbb(cm, targetNetwork); @@ -503,7 +522,7 @@ public class WifiConnectivityManager { mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization( clientModeManager.getWifiLinkLayerStats(), WifiChannelUtilization.UNKNOWN_FREQ); - WifiInfo wifiInfo = clientModeManager.syncRequestConnectionInfo(); + WifiInfo wifiInfo = clientModeManager.getConnectionInfo(); if (clientModeManager.isConnected()) { connectedSsids.add(wifiInfo.getSSID()); } @@ -722,6 +741,16 @@ public class WifiConnectivityManager { WifiConfiguration candidate = mNetworkSelector.selectNetwork(candidates); if (candidate != null) { localLog(listenerName + ": WNS candidate-" + candidate.SSID); + if (hasMultiInternetConnection()) { + // Disconnect secondary cmm first before connecting the primary. + final ConcreteClientModeManager secondaryCcm = mActiveModeWarden + .getClientModeManagerInRole(ROLE_CLIENT_SECONDARY_LONG_LIVED); + if (secondaryCcm != null && isClientModeManagerConnectedOrConnectingToCandidate( + secondaryCcm, candidate)) { + localLog("Disconnect secondary first."); + secondaryCcm.disconnect(); + } + } connectToNetworkForPrimaryCmmUsingMbbIfAvailable(candidate); handleScanResultsWithCandidate(handleScanResultsListener); } else { @@ -843,7 +872,7 @@ public class WifiConnectivityManager { @Override public void onFailure(int reason, String description) { localLog("registerScanListener onFailure:" - + " reason: " + reason + " description: " + description); + + " reason: " + reason + " description: " + description); } @Override @@ -958,7 +987,8 @@ public class WifiConnectivityManager { } } - private final AllSingleScanListener mAllSingleScanListener = new AllSingleScanListener(); + private final AllSingleScanListener mAllSingleScanListener; + private final WifiScannerInternal.ScanListener mInternalAllSingleScanListener; // Single scan results listener. A single scan is initiated when // DisconnectedPNO scan found a valid network and woke up @@ -1112,7 +1142,8 @@ public class WifiConnectivityManager { } } - private final PnoScanListener mPnoScanListener = new PnoScanListener(); + private final PnoScanListener mPnoScanListener; + private final WifiScannerInternal.ScanListener mInternalPnoScanListener; private class OnNetworkUpdateListener implements WifiConfigManager.OnNetworkUpdateListener { @@ -1219,7 +1250,7 @@ public class WifiConnectivityManager { WifiLastResortWatchdog wifiLastResortWatchdog, OpenNetworkNotifier openNetworkNotifier, WifiMetrics wifiMetrics, - Handler handler, + RunnerHandler handler, Clock clock, LocalLog localLog, WifiScoreCard scoreCard, @@ -1232,7 +1263,9 @@ public class WifiConnectivityManager { FrameworkFacade frameworkFacade, WifiGlobals wifiGlobals, ExternalPnoScanRequestManager externalPnoScanRequestManager, - @NonNull SsidTranslator ssidTranslator) { + @NonNull SsidTranslator ssidTranslator, + WifiPermissionsUtil wifiPermissionsUtil, + WifiCarrierInfoManager wifiCarrierInfoManager) { mContext = context; mScoringParams = scoringParams; mConfigManager = configManager; @@ -1259,6 +1292,8 @@ public class WifiConnectivityManager { mPowerManager = mContext.getSystemService(PowerManager.class); mExternalPnoScanRequestManager = externalPnoScanRequestManager; mSsidTranslator = ssidTranslator; + mWifiPermissionsUtil = wifiPermissionsUtil; + mWifiCarrierInfoManager = wifiCarrierInfoManager; // Listen for screen state change events. // TODO: We should probably add a shared broadcast receiver in the wifi stack which @@ -1282,7 +1317,7 @@ public class WifiConnectivityManager { handleScreenStateChanged(mPowerManager.isInteractive()); // Listen to WifiConfigManager network update events - mEventHandler.postAtFrontOfQueue(() -> + mEventHandler.postToFront(() -> mConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener())); // Listen to WifiNetworkSuggestionsManager suggestion update events mWifiNetworkSuggestionsManager.addOnSuggestionUpdateListener( @@ -1290,11 +1325,17 @@ public class WifiConnectivityManager { mActiveModeWarden.registerModeChangeCallback(new ModeChangeCallback()); mMultiInternetManager.setConnectionStatusListener( new InternalMultiInternetConnectionStatusListener()); + mAllSingleScanListener = new AllSingleScanListener(); + mInternalAllSingleScanListener = new WifiScannerInternal.ScanListener( + mAllSingleScanListener, mEventHandler); + mPnoScanListener = new PnoScanListener(); + mInternalPnoScanListener = new WifiScannerInternal.ScanListener(mPnoScanListener, + mEventHandler); } @NonNull private WifiInfo getPrimaryWifiInfo() { - return getPrimaryClientModeManager().syncRequestConnectionInfo(); + return getPrimaryClientModeManager().getConnectionInfo(); } private ClientModeManager getPrimaryClientModeManager() { @@ -2046,8 +2087,8 @@ public class WifiConnectivityManager { SingleScanListener singleScanListener = new SingleScanListener(isFullBandScan); - mScanner.startScan( - settings, new HandlerExecutor(mEventHandler), singleScanListener, workSource); + mScanner.startScan(settings, + new WifiScannerInternal.ScanListener(singleScanListener, mEventHandler)); mWifiMetrics.incrementConnectivityOneshotScanCount(); } @@ -2101,6 +2142,10 @@ public class WifiConnectivityManager { mNetworkSelector.setSufficiencyCheckEnabled( nsConfig.isSufficiencyCheckEnabledWhenScreenOff(), nsConfig.isSufficiencyCheckEnabledWhenScreenOn()); + mNetworkSelector.setUserConnectChoiceOverrideEnabled( + nsConfig.isUserConnectChoiceOverrideEnabled()); + mNetworkSelector.setLastSelectionWeightEnabled( + nsConfig.isLastSelectionWeightEnabled()); } /** @@ -2187,8 +2232,8 @@ public class WifiConnectivityManager { scanSettings.numBssidsPerScan = 0; scanSettings.periodInMs = deviceMobilityStateToPnoScanIntervalMs(mDeviceMobilityState); - mScanner.startDisconnectedPnoScan( - scanSettings, pnoSettings, new HandlerExecutor(mEventHandler), mPnoScanListener); + pnoSettings.isConnected = false; + mScanner.startPnoScan(scanSettings, pnoSettings, mInternalPnoScanListener); mPnoScanStarted = true; mWifiMetrics.logPnoScanStart(); } @@ -2202,7 +2247,12 @@ public class WifiConnectivityManager { || (!config.ephemeral && !config.getNetworkSelectionStatus().hasEverConnected()) || !config.getNetworkSelectionStatus().isNetworkEnabled() || mConfigManager.isNetworkTemporarilyDisabledByUser( - config.isPasspoint() ? config.FQDN : config.SSID)); + config.isPasspoint() ? config.FQDN : config.SSID) + || (config.enterpriseConfig != null + && config.enterpriseConfig.isAuthenticationSimBased() + && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) + && !mWifiCarrierInfoManager.isSimReady( + mWifiCarrierInfoManager.getBestMatchSubscriptionId(config))); return networks; } @@ -2309,7 +2359,7 @@ public class WifiConnectivityManager { private void stopPnoScan() { if (!mPnoScanStarted) return; - mScanner.stopPnoScan(mPnoScanListener); + mScanner.stopPnoScan(mInternalPnoScanListener); mPnoScanStarted = false; mWifiMetrics.logPnoScanStop(); } @@ -2775,7 +2825,8 @@ public class WifiConnectivityManager { mOpenNetworkNotifier.handleConnectionFailure(); // 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) { + if (clientModeManager.getRole() == ROLE_CLIENT_PRIMARY + && !mWifiPermissionsUtil.isAdminRestrictedNetwork(config)) { retryConnectionOnLatestCandidates(clientModeManager, bssid, config, failureCode == FAILURE_AUTHENTICATION_FAILURE && failureReason == AUTH_FAILURE_EAP_FAILURE); @@ -2987,10 +3038,10 @@ public class WifiConnectivityManager { */ private void retrieveWifiScanner() { if (mScanner != null) return; - mScanner = Objects.requireNonNull(mContext.getSystemService(WifiScanner.class), + mScanner = Objects.requireNonNull(WifiLocalServices.getService(WifiScannerInternal.class), "Got a null instance of WifiScanner!"); // Register for all single scan results - mScanner.registerScanListener(new HandlerExecutor(mEventHandler), mAllSingleScanListener); + mScanner.registerScanListener(mInternalAllSingleScanListener); } /** diff --git a/service/java/com/android/server/wifi/WifiCountryCode.java b/service/java/com/android/server/wifi/WifiCountryCode.java index d9aed9bc67..b64066d7b6 100644 --- a/service/java/com/android/server/wifi/WifiCountryCode.java +++ b/service/java/com/android/server/wifi/WifiCountryCode.java @@ -461,7 +461,7 @@ public class WifiCountryCode { if (!cmm.isConnected()) { continue; } - WifiInfo wifiInfo = cmm.syncRequestConnectionInfo(); + WifiInfo wifiInfo = cmm.getConnectionInfo(); if (wifiInfo.getSuccessfulTxPacketsPerSecond() < PKT_COUNT_HIGH_PKT_PER_SEC && wifiInfo.getSuccessfulRxPacketsPerSecond() < PKT_COUNT_HIGH_PKT_PER_SEC) { return true; diff --git a/service/java/com/android/server/wifi/WifiDialogManager.java b/service/java/com/android/server/wifi/WifiDialogManager.java index 1048570aba..73e5c5c39e 100644 --- a/service/java/com/android/server/wifi/WifiDialogManager.java +++ b/service/java/com/android/server/wifi/WifiDialogManager.java @@ -16,6 +16,7 @@ package com.android.server.wifi; +import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AlertDialog; import android.content.BroadcastReceiver; @@ -331,7 +332,8 @@ public class WifiDialogManager { mActiveDialogIds.add(mDialogId); mActiveDialogHandles.put(mDialogId, this); if (mVerboseLoggingEnabled) { - Log.v(TAG, "Registered dialog with id=" + mDialogId); + Log.v(TAG, "Registered dialog with id=" + mDialogId + + ". Active dialogs ids: " + mActiveDialogIds); } } @@ -347,15 +349,28 @@ public class WifiDialogManager { mActiveDialogIds.remove(mDialogId); mActiveDialogHandles.remove(mDialogId); if (mVerboseLoggingEnabled) { - Log.v(TAG, "Unregistered dialog with id=" + mDialogId); + Log.v(TAG, "Unregistered dialog with id=" + mDialogId + + ". Active dialogs ids: " + mActiveDialogIds); } mDialogId = WifiManager.INVALID_DIALOG_ID; + if (mActiveDialogIds.isEmpty()) { + String wifiDialogApkPkgName = mContext.getWifiDialogApkPkgName(); + if (wifiDialogApkPkgName == null) { + Log.wtf(TAG, "Could not get WifiDialog APK package name to force stop!"); + return; + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Force stopping WifiDialog app"); + } + mContext.getSystemService(ActivityManager.class) + .forceStopPackage(wifiDialogApkPkgName); + } } } private class SimpleDialogHandle extends DialogHandleInternal { - private @NonNull SimpleDialogCallback mCallback; - private @NonNull WifiThreadRunner mCallbackThreadRunner; + @Nullable private final SimpleDialogCallback mCallback; + @Nullable private final WifiThreadRunner mCallbackThreadRunner; SimpleDialogHandle( final String title, @@ -366,8 +381,8 @@ public class WifiDialogManager { final String positiveButtonText, final String negativeButtonText, final String neutralButtonText, - @NonNull SimpleDialogCallback callback, - @NonNull WifiThreadRunner callbackThreadRunner) throws IllegalArgumentException { + @Nullable final SimpleDialogCallback callback, + @Nullable final WifiThreadRunner callbackThreadRunner) { Intent intent = getBaseLaunchIntent(WifiManager.DIALOG_TYPE_SIMPLE); if (intent != null) { intent.putExtra(WifiManager.EXTRA_DIALOG_TITLE, title) @@ -381,45 +396,35 @@ public class WifiDialogManager { setIntent(intent); } setDisplayId(Display.DEFAULT_DISPLAY); - if (messageUrl != null) { - if (message == null) { - throw new IllegalArgumentException("Cannot set span for null message!"); - } - if (messageUrlStart < 0) { - throw new IllegalArgumentException("Span start cannot be less than 0!"); - } - if (messageUrlEnd > message.length()) { - throw new IllegalArgumentException("Span end index " + messageUrlEnd - + " cannot be greater than message length " + message.length() + "!"); - } - } - if (callback == null) { - throw new IllegalArgumentException("Callback cannot be null!"); - } - if (callbackThreadRunner == null) { - throw new IllegalArgumentException("Callback thread runner cannot be null!"); - } mCallback = callback; mCallbackThreadRunner = callbackThreadRunner; } void notifyOnPositiveButtonClicked() { - mCallbackThreadRunner.post(() -> mCallback.onPositiveButtonClicked()); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onPositiveButtonClicked); + } unregisterDialog(); } void notifyOnNegativeButtonClicked() { - mCallbackThreadRunner.post(() -> mCallback.onNegativeButtonClicked()); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onNegativeButtonClicked); + } unregisterDialog(); } void notifyOnNeutralButtonClicked() { - mCallbackThreadRunner.post(() -> mCallback.onNeutralButtonClicked()); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onNeutralButtonClicked); + } unregisterDialog(); } void notifyOnCancelled() { - mCallbackThreadRunner.post(() -> mCallback.onCancelled()); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onCancelled); + } unregisterDialog(); } } @@ -433,8 +438,8 @@ public class WifiDialogManager { final String mPositiveButtonText; final String mNegativeButtonText; final String mNeutralButtonText; - @NonNull SimpleDialogCallback mCallback; - @NonNull WifiThreadRunner mCallbackThreadRunner; + @Nullable final SimpleDialogCallback mCallback; + @Nullable final WifiThreadRunner mCallbackThreadRunner; private Runnable mTimeoutRunnable; private AlertDialog mAlertDialog; int mWindowType = WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; @@ -449,42 +454,32 @@ public class WifiDialogManager { final String positiveButtonText, final String negativeButtonText, final String neutralButtonText, - @NonNull SimpleDialogCallback callback, - @NonNull WifiThreadRunner callbackThreadRunner) throws IllegalArgumentException { - if (messageUrl != null) { - if (message == null) { - throw new IllegalArgumentException("Cannot set span for null message!"); - } - if (messageUrlStart < 0) { - throw new IllegalArgumentException("Span start cannot be less than 0!"); - } - if (messageUrlEnd > message.length()) { - throw new IllegalArgumentException("Span end index " + messageUrlEnd - + " cannot be greater than message length " + message.length() + "!"); - } - } - if (callback == null) { - throw new IllegalArgumentException("Callback cannot be null!"); - } - if (callbackThreadRunner == null) { - throw new IllegalArgumentException("Callback thread runner cannot be null!"); - } + @Nullable final SimpleDialogCallback callback, + @Nullable final WifiThreadRunner callbackThreadRunner) { mTitle = title; if (message != null) { mMessage = new SpannableString(message); - if (messageUrlStart >= 0 && messageUrlEnd <= message.length() - && messageUrlStart < messageUrlEnd) { - mMessage.setSpan(new URLSpan(messageUrl) { - @Override - public void onClick(@NonNull View widget) { - Context c = widget.getContext(); - Intent openLinkIntent = new Intent(Intent.ACTION_VIEW) - .setData(Uri.parse(messageUrl)) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .putExtra(Browser.EXTRA_APPLICATION_ID, c.getPackageName()); - c.startActivity(openLinkIntent); - LegacySimpleDialogHandle.this.dismissDialog(); - }}, messageUrlStart, messageUrlEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (messageUrl != null) { + if (messageUrlStart < 0) { + Log.w(TAG, "Span start cannot be less than 0!"); + } else if (messageUrlEnd > message.length()) { + Log.w(TAG, "Span end index " + messageUrlEnd + " cannot be greater than " + + "message length " + message.length() + "!"); + } else if (messageUrlStart > messageUrlEnd) { + Log.w(TAG, "Span start index cannot be greater than end index!"); + } else { + mMessage.setSpan(new URLSpan(messageUrl) { + @Override + public void onClick(@NonNull View widget) { + Context c = widget.getContext(); + Intent openLinkIntent = new Intent(Intent.ACTION_VIEW) + .setData(Uri.parse(messageUrl)) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(Browser.EXTRA_APPLICATION_ID, c.getPackageName()); + c.startActivity(openLinkIntent); + LegacySimpleDialogHandle.this.dismissDialog(); + }}, messageUrlStart, messageUrlEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } } } else { mMessage = null; @@ -516,25 +511,33 @@ public class WifiDialogManager { if (mVerboseLoggingEnabled) { Log.v(TAG, "Positive button pressed for legacy simple dialog"); } - mCallbackThreadRunner.post(mCallback::onPositiveButtonClicked); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onPositiveButtonClicked); + } }) .setNegativeButton(mNegativeButtonText, (dialogNegative, which) -> { if (mVerboseLoggingEnabled) { Log.v(TAG, "Negative button pressed for legacy simple dialog"); } - mCallbackThreadRunner.post(mCallback::onNegativeButtonClicked); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onNegativeButtonClicked); + } }) .setNeutralButton(mNeutralButtonText, (dialogNeutral, which) -> { if (mVerboseLoggingEnabled) { Log.v(TAG, "Neutral button pressed for legacy simple dialog"); } - mCallbackThreadRunner.post(mCallback::onNeutralButtonClicked); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onNeutralButtonClicked); + } }) .setOnCancelListener((dialogCancel) -> { if (mVerboseLoggingEnabled) { Log.v(TAG, "Legacy simple dialog cancelled."); } - mCallbackThreadRunner.post(mCallback::onCancelled); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onCancelled); + } }) .setOnDismissListener((dialogDismiss) -> { mWifiThreadRunner.post(() -> { @@ -634,7 +637,7 @@ public class WifiDialogManager { * be created. */ @AnyThread - @Nullable + @NonNull public DialogHandle createSimpleDialog( @Nullable String title, @Nullable String message, @@ -644,16 +647,16 @@ public class WifiDialogManager { @NonNull SimpleDialogCallback callback, @NonNull WifiThreadRunner callbackThreadRunner) { return createSimpleDialogWithUrl( - title, - message, - null /* messageUrl */, - 0 /* messageUrlStart */, - 0 /* messageUrlEnd */, - positiveButtonText, - negativeButtonText, - neutralButtonText, - callback, - callbackThreadRunner); + title, + message, + null /* messageUrl */, + 0 /* messageUrlStart */, + 0 /* messageUrlEnd */, + positiveButtonText, + negativeButtonText, + neutralButtonText, + callback, + callbackThreadRunner); } /** @@ -676,7 +679,7 @@ public class WifiDialogManager { * be created. */ @AnyThread - @Nullable + @NonNull public DialogHandle createSimpleDialogWithUrl( @Nullable String title, @Nullable String message, @@ -688,41 +691,36 @@ public class WifiDialogManager { @Nullable String neutralButtonText, @NonNull SimpleDialogCallback callback, @NonNull WifiThreadRunner callbackThreadRunner) { - try { - if (SdkLevel.isAtLeastT()) { - return new DialogHandle( - new SimpleDialogHandle( - title, - message, - messageUrl, - messageUrlStart, - messageUrlEnd, - positiveButtonText, - negativeButtonText, - neutralButtonText, - callback, - callbackThreadRunner) - ); - } else { - // TODO(b/238353074): Remove this fallback to the legacy implementation once the - // AlertDialog style on pre-T platform is fixed. - return new DialogHandle( - new LegacySimpleDialogHandle( - title, - message, - messageUrl, - messageUrlStart, - messageUrlEnd, - positiveButtonText, - negativeButtonText, - neutralButtonText, - callback, - callbackThreadRunner) - ); - } - } catch (IllegalArgumentException e) { - Log.e(TAG, "Could not create DialogHandle for simple dialog: " + e); - return null; + if (SdkLevel.isAtLeastT()) { + return new DialogHandle( + new SimpleDialogHandle( + title, + message, + messageUrl, + messageUrlStart, + messageUrlEnd, + positiveButtonText, + negativeButtonText, + neutralButtonText, + callback, + callbackThreadRunner) + ); + } else { + // TODO(b/238353074): Remove this fallback to the legacy implementation once the + // AlertDialog style on pre-T platform is fixed. + return new DialogHandle( + new LegacySimpleDialogHandle( + title, + message, + messageUrl, + messageUrlStart, + messageUrlEnd, + positiveButtonText, + negativeButtonText, + neutralButtonText, + callback, + callbackThreadRunner) + ); } } @@ -741,7 +739,7 @@ public class WifiDialogManager { * be created. */ @AnyThread - @Nullable + @NonNull public DialogHandle createLegacySimpleDialog( @Nullable String title, @Nullable String message, @@ -783,7 +781,7 @@ public class WifiDialogManager { * be created. */ @AnyThread - @Nullable + @NonNull public DialogHandle createLegacySimpleDialogWithUrl( @Nullable String title, @Nullable String message, @@ -793,26 +791,21 @@ public class WifiDialogManager { @Nullable String positiveButtonText, @Nullable String negativeButtonText, @Nullable String neutralButtonText, - @NonNull SimpleDialogCallback callback, - @NonNull WifiThreadRunner callbackThreadRunner) { - try { - return new DialogHandle( - new LegacySimpleDialogHandle( - title, - message, - messageUrl, - messageUrlStart, - messageUrlEnd, - positiveButtonText, - negativeButtonText, - neutralButtonText, - callback, - callbackThreadRunner) - ); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Could not create DialogHandle for simple dialog: " + e); - return null; - } + @Nullable SimpleDialogCallback callback, + @Nullable WifiThreadRunner callbackThreadRunner) { + return new DialogHandle( + new LegacySimpleDialogHandle( + title, + message, + messageUrl, + messageUrlStart, + messageUrlEnd, + positiveButtonText, + negativeButtonText, + neutralButtonText, + callback, + callbackThreadRunner) + ); } /** @@ -858,16 +851,16 @@ public class WifiDialogManager { } private class P2pInvitationReceivedDialogHandle extends DialogHandleInternal { - private @NonNull P2pInvitationReceivedDialogCallback mCallback; - private @NonNull WifiThreadRunner mCallbackThreadRunner; + @Nullable private final P2pInvitationReceivedDialogCallback mCallback; + @Nullable private final WifiThreadRunner mCallbackThreadRunner; P2pInvitationReceivedDialogHandle( - final @NonNull String deviceName, + final @Nullable String deviceName, final boolean isPinRequested, @Nullable String displayPin, int displayId, - @NonNull P2pInvitationReceivedDialogCallback callback, - @NonNull WifiThreadRunner callbackThreadRunner) throws IllegalArgumentException { + @Nullable P2pInvitationReceivedDialogCallback callback, + @Nullable WifiThreadRunner callbackThreadRunner) { Intent intent = getBaseLaunchIntent(WifiManager.DIALOG_TYPE_P2P_INVITATION_RECEIVED); if (intent != null) { intent.putExtra(WifiManager.EXTRA_P2P_DEVICE_NAME, deviceName) @@ -876,26 +869,21 @@ public class WifiDialogManager { setIntent(intent); } setDisplayId(displayId); - if (deviceName == null) { - throw new IllegalArgumentException("Device name cannot be null!"); - } - if (callback == null) { - throw new IllegalArgumentException("Callback cannot be null!"); - } - if (callbackThreadRunner == null) { - throw new IllegalArgumentException("Callback thread runner cannot be null!"); - } mCallback = callback; mCallbackThreadRunner = callbackThreadRunner; } void notifyOnAccepted(@Nullable String optionalPin) { - mCallbackThreadRunner.post(() -> mCallback.onAccepted(optionalPin)); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(() -> mCallback.onAccepted(optionalPin)); + } unregisterDialog(); } void notifyOnDeclined() { - mCallbackThreadRunner.post(() -> mCallback.onDeclined()); + if (mCallbackThreadRunner != null && mCallback != null) { + mCallbackThreadRunner.post(mCallback::onDeclined); + } unregisterDialog(); } } @@ -932,27 +920,23 @@ public class WifiDialogManager { * be created. */ @AnyThread + @NonNull public DialogHandle createP2pInvitationReceivedDialog( - @NonNull String deviceName, + @Nullable String deviceName, boolean isPinRequested, @Nullable String displayPin, int displayId, - @NonNull P2pInvitationReceivedDialogCallback callback, - @NonNull WifiThreadRunner callbackThreadRunner) { - try { - return new DialogHandle( - new P2pInvitationReceivedDialogHandle( - deviceName, - isPinRequested, - displayPin, - displayId, - callback, - callbackThreadRunner) - ); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Could not create DialogHandle for P2P Invitation Received dialog: " + e); - return null; - } + @Nullable P2pInvitationReceivedDialogCallback callback, + @Nullable WifiThreadRunner callbackThreadRunner) { + return new DialogHandle( + new P2pInvitationReceivedDialogHandle( + deviceName, + isPinRequested, + displayPin, + displayId, + callback, + callbackThreadRunner) + ); } /** @@ -997,9 +981,9 @@ public class WifiDialogManager { private class P2pInvitationSentDialogHandle extends DialogHandleInternal { P2pInvitationSentDialogHandle( - final @NonNull String deviceName, - final @Nullable String displayPin, - int displayId) throws IllegalArgumentException { + @Nullable final String deviceName, + @Nullable final String displayPin, + int displayId) { Intent intent = getBaseLaunchIntent(WifiManager.DIALOG_TYPE_P2P_INVITATION_SENT); if (intent != null) { intent.putExtra(WifiManager.EXTRA_P2P_DEVICE_NAME, deviceName) @@ -1007,9 +991,6 @@ public class WifiDialogManager { setIntent(intent); } setDisplayId(displayId); - if (deviceName == null) { - throw new IllegalArgumentException("Device name cannot be null!"); - } } } @@ -1023,16 +1004,12 @@ public class WifiDialogManager { * be created. */ @AnyThread + @NonNull public DialogHandle createP2pInvitationSentDialog( - @NonNull String deviceName, + @Nullable String deviceName, @Nullable String displayPin, int displayId) { - try { - return new DialogHandle(new P2pInvitationSentDialogHandle(deviceName, displayPin, - displayId)); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Could not create DialogHandle for P2P Invitation Sent dialog: " + e); - return null; - } + return new DialogHandle(new P2pInvitationSentDialogHandle(deviceName, displayPin, + displayId)); } } diff --git a/service/java/com/android/server/wifi/WifiHealthMonitor.java b/service/java/com/android/server/wifi/WifiHealthMonitor.java index 8c56b12915..7c26902f00 100644 --- a/service/java/com/android/server/wifi/WifiHealthMonitor.java +++ b/service/java/com/android/server/wifi/WifiHealthMonitor.java @@ -33,7 +33,6 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.DeviceMobilityState; import android.net.wifi.WifiScanner; import android.os.Build; -import android.os.Handler; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -45,6 +44,7 @@ import com.android.server.wifi.proto.WifiScoreCardProto.SystemInfoStats; import com.android.server.wifi.proto.WifiStatsLog; import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorFailureStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics; +import com.android.server.wifi.scanner.WifiScannerInternal; import com.google.protobuf.InvalidProtocolBufferException; @@ -106,12 +106,12 @@ public class WifiHealthMonitor { private final WifiScoreCard mWifiScoreCard; private final Clock mClock; private final AlarmManager mAlarmManager; - private final Handler mHandler; + private final RunnerHandler mHandler; private final WifiNative mWifiNative; private final WifiInjector mWifiInjector; private final DeviceConfigFacade mDeviceConfigFacade; private final ActiveModeWarden mActiveModeWarden; - private WifiScanner mScanner; + private WifiScannerInternal mScanner; private MemoryStore mMemoryStore; private boolean mWifiEnabled; private WifiSystemInfoStats mWifiSystemInfoStats; @@ -149,7 +149,7 @@ public class WifiHealthMonitor { } WifiHealthMonitor(Context context, WifiInjector wifiInjector, Clock clock, - WifiConfigManager wifiConfigManager, WifiScoreCard wifiScoreCard, Handler handler, + WifiConfigManager wifiConfigManager, WifiScoreCard wifiScoreCard, RunnerHandler handler, WifiNative wifiNative, String l2KeySeed, DeviceConfigFacade deviceConfigFacade, ActiveModeWarden activeModeWarden) { mContext = context; @@ -164,7 +164,7 @@ public class WifiHealthMonitor { mActiveModeWarden = activeModeWarden; mWifiSystemInfoStats = new WifiSystemInfoStats(l2KeySeed); mActiveModeWarden.registerModeChangeCallback(new ModeChangeCallback()); - mHandler.postAtFrontOfQueue(() -> mWifiConfigManager + mHandler.postToFront(() -> mWifiConfigManager .addOnNetworkUpdateListener(new OnNetworkUpdateListener())); } @@ -267,10 +267,11 @@ public class WifiHealthMonitor { */ private void retrieveWifiScanner() { if (mScanner != null) return; - mScanner = mWifiInjector.getWifiScanner(); + mScanner = WifiLocalServices.getService(WifiScannerInternal.class); if (mScanner == null) return; // Register for all single scan results - mScanner.registerScanListener(new ScanListener()); + mScanner.registerScanListener( + new WifiScannerInternal.ScanListener(new ScanListener(), mHandler)); } /** diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index bf8f2ef061..c2afbd9cdd 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -183,6 +183,7 @@ public class WifiInjector { private final WifiConnectivityHelper mWifiConnectivityHelper; private final LocalLog mConnectivityLocalLog; private final LocalLog mWifiAwareLocalLog; + private final LocalLog mWifiHandlerLocalLog; private final ThroughputScorer mThroughputScorer; private final WifiNetworkSelector mWifiNetworkSelector; private final SavedNetworkNominator mSavedNetworkNominator; @@ -266,7 +267,10 @@ public class WifiInjector { mWifiHandlerThread = new HandlerThread("WifiHandlerThread"); mWifiHandlerThread.start(); Looper wifiLooper = mWifiHandlerThread.getLooper(); - Handler wifiHandler = new Handler(wifiLooper); + mWifiHandlerLocalLog = new LocalLog(128); + RunnerHandler wifiHandler = new RunnerHandler(wifiLooper, context.getResources().getInteger( + R.integer.config_wifiConfigurationWifiRunnerThresholdInMs), + mWifiHandlerLocalLog); mWifiDiagnosticsHandlerThread = new HandlerThread("WifiDiagnostics"); mWifiDiagnosticsHandlerThread.start(); @@ -403,6 +407,7 @@ public class WifiInjector { mContext.getSystemService(ActivityManager.class), this, mWifiConfigManager, mWifiPermissionsUtil, mWifiMetrics, mClock, wifiHandler, mSettingsConfigStore); + mWifiBlocklistMonitor.setScanRequestProxy(mScanRequestProxy); mSarManager = new SarManager(mContext, makeTelephonyManager(), wifiLooper, mWifiNative); mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiScoreCard, mScoringParams, @@ -482,7 +487,8 @@ public class WifiInjector { mClock, mConnectivityLocalLog, mWifiScoreCard, mWifiBlocklistMonitor, mWifiChannelUtilizationScan, mPasspointManager, mMultiInternetManager, mDeviceConfigFacade, mActiveModeWarden, mFrameworkFacade, mWifiGlobals, - mExternalPnoScanRequestManager, mSsidTranslator); + mExternalPnoScanRequestManager, mSsidTranslator, mWifiPermissionsUtil, + mWifiCarrierInfoManager); mMboOceController = new MboOceController(makeTelephonyManager(), mActiveModeWarden); mCountryCode = new WifiCountryCode(mContext, mActiveModeWarden, mCmiMonitor, mWifiNative, mSettingsConfigStore); @@ -760,7 +766,8 @@ public class WifiInjector { @NonNull ActiveModeManager.SoftApRole role, boolean verboseLoggingEnabled) { return new SoftApManager(mContext, mWifiHandlerThread.getLooper(), mFrameworkFacade, - mWifiNative, mCoexManager, makeBatteryManager(), mInterfaceConflictManager, + mWifiNative, this, + mCoexManager, makeBatteryManager(), mInterfaceConflictManager, listener, callback, mWifiApConfigStore, config, mWifiMetrics, mSarManager, mWifiDiagnostics, new SoftApNotifier(mContext, mFrameworkFacade, mWifiNotificationManager), @@ -1169,6 +1176,11 @@ public class WifiInjector { } @NonNull + public LocalLog getWifiHandlerLocalLog() { + return mWifiHandlerLocalLog; + } + + @NonNull public WifiKeyStore getWifiKeyStore() { return mWifiKeyStore; } diff --git a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java index 5a27899170..86228edded 100644 --- a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java +++ b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java @@ -184,7 +184,7 @@ public class WifiLastResortWatchdog { if (activeModeWarden == null) return new WifiInfo(); // Cannot be null. ClientModeManager primaryCmm = activeModeWarden.getPrimaryClientModeManager(); - return primaryCmm.syncRequestConnectionInfo(); + return primaryCmm.getConnectionInfo(); } /** diff --git a/service/java/com/android/server/wifi/WifiLocalServices.java b/service/java/com/android/server/wifi/WifiLocalServices.java new file mode 100644 index 0000000000..6702269904 --- /dev/null +++ b/service/java/com/android/server/wifi/WifiLocalServices.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 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.util.ArrayMap; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * This class is used in a similar way as ServiceManager, except the services registered here + * are not Binder objects and are only available in the same process. + * + * Once all services are converted to the SystemService interface, this class can be absorbed + * into SystemServiceManager. + * + */ +public final class WifiLocalServices { + private WifiLocalServices() {} + + private static final ArrayMap<Class<?>, Object> sLocalServiceObjects = + new ArrayMap<Class<?>, Object>(); + + /** + * Returns a local service instance that implements the specified interface. + * + * @param type The type of service. + * @return The service object. + */ + @SuppressWarnings("unchecked") + public static <T> T getService(Class<T> type) { + synchronized (sLocalServiceObjects) { + return (T) sLocalServiceObjects.get(type); + } + } + + /** + * Adds a service instance of the specified interface to the global registry of local services. + */ + public static <T> void addService(Class<T> type, T service) { + synchronized (sLocalServiceObjects) { + if (sLocalServiceObjects.containsKey(type)) { + throw new IllegalStateException("Overriding service registration"); + } + sLocalServiceObjects.put(type, service); + } + } + + /** + * Remove a service instance, must be only used in tests. + */ + @VisibleForTesting + public static <T> void removeServiceForTest(Class<T> type) { + synchronized (sLocalServiceObjects) { + sLocalServiceObjects.remove(type); + } + } +} diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java index 0fdb69b899..63b1eeb27a 100644 --- a/service/java/com/android/server/wifi/WifiMonitor.java +++ b/service/java/com/android/server/wifi/WifiMonitor.java @@ -41,6 +41,7 @@ import com.android.server.wifi.hotspot2.WnmData; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.cert.X509Certificate; +import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -119,6 +120,9 @@ public class WifiMonitor { public static final int QOS_POLICY_RESET_EVENT = BASE + 75; public static final int QOS_POLICY_REQUEST_EVENT = BASE + 76; + /* MLO links change event */ + public static final int MLO_LINKS_INFO_CHANGED = BASE + 77; + /* WPS config errrors */ private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12; private static final int CONFIG_AUTH_FAILURE = 18; @@ -142,6 +146,13 @@ public class WifiMonitor { @Retention(RetentionPolicy.SOURCE) @interface TransitionDisableIndication{} + /* MLO links change event reason codes */ + public enum MloLinkInfoChangeReason { + UNKNOWN, + TID_TO_LINK_MAP, + MULTI_LINK_RECONFIG_AP_REMOVAL, + } + /** * Use this key to get the interface name of the message sent by WifiMonitor, * or null if not available. @@ -558,8 +569,22 @@ public class WifiMonitor { */ public void broadcastNetworkConnectionEvent(String iface, int networkId, boolean filsHlpSent, WifiSsid ssid, String bssid) { + broadcastNetworkConnectionEvent(iface, networkId, filsHlpSent, ssid, bssid, null); + } + + /** + * Broadcast the network connection event to all the handlers registered for this event. + * + * @param iface Name of iface on which this occurred. + * @param networkId ID of the network in wpa_supplicant. + * @param filsHlpSent Whether the connection used FILS. + * @param bssid BSSID of the access point. + * @param keyMgmtMask Current used key management mask. + */ + public void broadcastNetworkConnectionEvent(String iface, int networkId, boolean filsHlpSent, + WifiSsid ssid, String bssid, BitSet keyMgmtMask) { sendMessage(iface, NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(networkId, ssid, bssid, filsHlpSent)); + new NetworkConnectionEventInfo(networkId, ssid, bssid, filsHlpSent, keyMgmtMask)); } /** @@ -663,4 +688,15 @@ public class WifiMonitor { List<QosPolicyRequest> qosPolicyData) { sendMessage(iface, QOS_POLICY_REQUEST_EVENT, qosPolicyRequestId, 0, qosPolicyData); } + + /** + * Broadcast the MLO link changes with reason code to all handlers registered for this event. + * + * @param iface Name of the iface on which this occurred. + * @param reason Reason code for the MLO link info change. + */ + public void broadcastMloLinksInfoChanged(String iface, + WifiMonitor.MloLinkInfoChangeReason reason) { + sendMessage(iface, MLO_LINKS_INFO_CHANGED, reason); + } } diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index 1063f04f5e..cbaa2f2337 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -47,6 +47,7 @@ import android.net.wifi.nl80211.RadioChainInfo; import android.net.wifi.nl80211.WifiNl80211Manager; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.SystemClock; import android.os.WorkSource; import android.text.TextUtils; @@ -56,10 +57,12 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.Immutable; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.SupplicantStaIfaceHal.QosPolicyStatus; import com.android.server.wifi.hotspot2.NetworkDetail; +import com.android.server.wifi.mockwifi.MockWifiServiceUtil; import com.android.server.wifi.util.FrameParser; import com.android.server.wifi.util.InformationElementUtil; import com.android.server.wifi.util.NativeUtil; @@ -76,6 +79,7 @@ import java.nio.ByteOrder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -119,6 +123,7 @@ public class WifiNative { private long mCachedFeatureSet; private boolean mQosPolicyFeatureEnabled = false; private final Map<String, String> mWifiCondIfacesForBridgedAp = new ArrayMap<>(); + private MockWifiServiceUtil mMockWifiModem = null; public WifiNative(WifiVendorHal vendorHal, SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal, @@ -278,6 +283,7 @@ public class WifiNative { public NetworkObserverInternal networkObserver; /** Interface feature set / capabilities */ public long featureSet; + public int bandsSupported; public DeviceWiphyCapabilities phyCapabilities; Iface(int id, @Iface.IfaceType int type) { @@ -1158,27 +1164,6 @@ public class WifiNative { void onDown(String ifaceName); } - private void initializeNwParamsForClientInterface(@NonNull String ifaceName) { - try { - // A runtime crash or shutting down AP mode can leave - // IP addresses configured, and this affects - // connectivity when supplicant starts up. - // Ensure we have no IP addresses before a supplicant start. - mNetdWrapper.clearInterfaceAddresses(ifaceName); - - // Set privacy extensions - mNetdWrapper.setInterfaceIpv6PrivacyExtensions(ifaceName, true); - - // IPv6 is enabled only as long as access point is connected since: - // - IPv6 addresses and routes stick around after disconnection - // - kernel is unaware when connected and fails to start IPv6 negotiation - // - kernel can start autoconfiguration when 802.1x is not complete - mNetdWrapper.disableIpv6(ifaceName); - } catch (IllegalStateException e) { - Log.e(TAG, "Unable to change interface settings", e); - } - } - private void takeBugReportInterfaceFailureIfNeeded(String bugTitle, String bugDetail) { if (mWifiInjector.getDeviceConfigFacade().isInterfaceFailureBugreportEnabled()) { mWifiInjector.getWifiDiagnostics().takeBugReport(bugTitle, bugDetail); @@ -1186,85 +1171,6 @@ public class WifiNative { } /** - * Setup an interface for client mode (for connectivity) operations. - * - * This method configures an interface in STA mode in all the native daemons - * (wificond, wpa_supplicant & vendor HAL). - * - * @param interfaceCallback Associated callback for notifying status changes for the iface. - * @param requestorWs Requestor worksource. - * @return Returns the name of the allocated interface, will be null on failure. - */ - public String setupInterfaceForClientInConnectivityMode( - @NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs) { - synchronized (mLock) { - if (!startHal()) { - Log.e(TAG, "Failed to start Hal"); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); - return null; - } - if (!startSupplicant()) { - Log.e(TAG, "Failed to start supplicant"); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); - return null; - } - Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); - if (iface == null) { - Log.e(TAG, "Failed to allocate new STA iface"); - return null; - } - iface.externalListener = interfaceCallback; - iface.name = createStaIface(iface, requestorWs); - if (TextUtils.isEmpty(iface.name)) { - Log.e(TAG, "Failed to create STA iface in vendor HAL"); - mIfaceMgr.removeIface(iface.id); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); - return null; - } - if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run, - new NormalScanEventCallback(iface.name), - new PnoScanEventCallback(iface.name))) { - Log.e(TAG, "Failed to setup iface in wificond on " + iface); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); - return null; - } - if (!mSupplicantStaIfaceHal.setupIface(iface.name)) { - Log.e(TAG, "Failed to setup iface in supplicant on " + iface); - teardownInterface(iface.name); - mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); - return null; - } - if (mContext.getResources().getBoolean( - R.bool.config_wifiNetworkCentricQosPolicyFeatureEnabled)) { - mQosPolicyFeatureEnabled = mSupplicantStaIfaceHal - .setNetworkCentricQosPolicyFeatureEnabled(iface.name, true); - if (!mQosPolicyFeatureEnabled) { - Log.e(TAG, "Failed to enable QoS policy feature for iface " + iface.name); - } - } - iface.networkObserver = new NetworkObserverInternal(iface.id); - if (!registerNetworkObserver(iface.networkObserver)) { - Log.e(TAG, "Failed to register network observer on " + iface); - teardownInterface(iface.name); - return null; - } - mWifiMonitor.startMonitoring(iface.name); - // Just to avoid any race conditions with interface state change callbacks, - // update the interface state before we exit. - onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); - mWifiVendorHal.enableLinkLayerStats(iface.name); - initializeNwParamsForClientInterface(iface.name); - Log.i(TAG, "Successfully setup " + iface); - - iface.featureSet = getSupportedFeatureSetInternal(iface.name); - saveCompleteFeatureSetInConfigStoreIfNecessary(iface.featureSet); - mIsEnhancedOpenSupported = (iface.featureSet & WIFI_FEATURE_OWE) != 0; - return iface.name; - } - } - - /** * Setup an interface for client mode (for scan) operations. * * This method configures an interface in STA mode in the native daemons @@ -1317,6 +1223,7 @@ public class WifiNative { Log.i(TAG, "Successfully setup " + iface); iface.featureSet = getSupportedFeatureSetInternal(iface.name); + updateSupportedBandForStaInternal(iface); return iface.name; } } @@ -1404,6 +1311,7 @@ public class WifiNative { Log.i(TAG, "Successfully setup " + iface); iface.featureSet = getSupportedFeatureSetInternal(iface.name); + updateSupportedBandForStaInternal(iface); return iface.name; } } @@ -1444,6 +1352,7 @@ public class WifiNative { iface.type = Iface.IFACE_TYPE_STA_FOR_SCAN; stopSupplicantIfNecessary(); iface.featureSet = getSupportedFeatureSetInternal(iface.name); + updateSupportedBandForStaInternal(iface); iface.phyCapabilities = null; Log.i(TAG, "Successfully switched to scan mode on iface=" + iface); return true; @@ -1502,6 +1411,7 @@ public class WifiNative { iface.type = Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY; iface.featureSet = getSupportedFeatureSetInternal(iface.name); saveCompleteFeatureSetInConfigStoreIfNecessary(iface.featureSet); + updateSupportedBandForStaInternal(iface); mIsEnhancedOpenSupported = (iface.featureSet & WIFI_FEATURE_OWE) != 0; Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface); return true; @@ -2124,15 +2034,6 @@ public class WifiNative { * * @param interfaceName Name of the interface */ - public boolean isStaSetMacAddressSupported(@NonNull String interfaceName) { - return mWifiVendorHal.isStaSetMacAddressSupported(interfaceName); - } - - /** - * Returns true if Hal version supports setMacAddress, otherwise false. - * - * @param interfaceName Name of the interface - */ public boolean isApSetMacAddressSupported(@NonNull String interfaceName) { return mWifiVendorHal.isApSetMacAddressSupported(interfaceName); } @@ -3203,7 +3104,7 @@ public class WifiNative { @Override public int hashCode() { - return Objects.hash(ssid, flags, auth_bit_field, frequencies); + return Objects.hash(ssid, flags, auth_bit_field, Arrays.hashCode(frequencies)); } android.net.wifi.nl80211.PnoNetwork toNativePnoNetwork() { @@ -3524,6 +3425,22 @@ public class WifiNative { } /** + * Get the supported bands for STA mode. + * @return supported bands + */ + public @WifiScanner.WifiBand int getSupportedBandsForSta(String ifaceName) { + synchronized (mLock) { + if (ifaceName != null) { + Iface iface = mIfaceMgr.getIface(ifaceName); + if (iface != null) { + return iface.bandsSupported; + } + } + return WifiScanner.WIFI_BAND_UNSPECIFIED; + } + } + + /** * Get the supported features * * @param ifaceName Name of the interface. @@ -3544,6 +3461,47 @@ public class WifiNative { return featureSet; } + private void updateSupportedBandForStaInternal(Iface iface) { + List<WifiAvailableChannel> usableChannelList = + mWifiVendorHal.getUsableChannels(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ, + WifiAvailableChannel.OP_MODE_STA, + WifiAvailableChannel.FILTER_REGULATORY); + int bands = 0; + if (usableChannelList == null) { + // If HAL doesn't support getUsableChannels then check wificond + if (getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ).length > 0) { + bands |= WifiScanner.WIFI_BAND_24_GHZ; + } + if (getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ).length > 0) { + bands |= WifiScanner.WIFI_BAND_5_GHZ; + } + if (getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ).length > 0) { + bands |= WifiScanner.WIFI_BAND_6_GHZ; + } + if (getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ).length > 0) { + bands |= WifiScanner.WIFI_BAND_60_GHZ; + } + } else { + for (int i = 0; i < usableChannelList.size(); i++) { + int frequency = usableChannelList.get(i).getFrequencyMhz(); + if (ScanResult.is24GHz(frequency)) { + bands |= WifiScanner.WIFI_BAND_24_GHZ; + } else if (ScanResult.is5GHz(frequency)) { + bands |= WifiScanner.WIFI_BAND_5_GHZ; + } else if (ScanResult.is6GHz(frequency)) { + bands |= WifiScanner.WIFI_BAND_6_GHZ; + } else if (ScanResult.is60GHz(frequency)) { + bands |= WifiScanner.WIFI_BAND_60_GHZ; + } + } + } + if (mVerboseLoggingEnabled) { + Log.i(TAG, "updateSupportedBandForStaInternal " + iface.name + " : 0x" + + Integer.toHexString(bands)); + } + iface.bandsSupported = bands; + } + /** * Class to retrieve connection capability parameters after association */ @@ -3576,12 +3534,73 @@ public class WifiNative { * Class to represent a connection MLO Link */ public static class ConnectionMloLink { - public int linkId; - public MacAddress staMacAddress; - - ConnectionMloLink() { - // Nothing for now + private int mLinkId; + private MacAddress mStaMacAddress; + private BitSet mTidsUplinkMap; + private BitSet mTidsDownlinkMap; + + ConnectionMloLink(int id, MacAddress mac, byte tidsUplink, byte tidsDownlink) { + mLinkId = id; + mStaMacAddress = mac; + mTidsDownlinkMap = BitSet.valueOf(new byte[] { tidsDownlink }); + mTidsUplinkMap = BitSet.valueOf(new byte[] { tidsUplink }); }; + + /** + * Check if there is any TID mapped to this link in uplink of downlink direction. + * + * @return true if there is any TID mapped to this link, otherwise false. + */ + public boolean isAnyTidMapped() { + if (mTidsDownlinkMap.isEmpty() && mTidsUplinkMap.isEmpty()) { + return false; + } + return true; + } + + /** + * Check if a TID is mapped to this link in uplink direction. + * + * @param tid TID value. + * @return true if the TID is mapped in uplink direction. Otherwise, false. + */ + public boolean isTidMappedToUplink(byte tid) { + if (tid < mTidsUplinkMap.length()) { + return mTidsUplinkMap.get(tid); + } + return false; + } + + /** + * Check if a TID is mapped to this link in downlink direction. Otherwise, false. + * + * @param tid TID value + * @return true if the TID is mapped in downlink direction. Otherwise, false. + */ + public boolean isTidMappedtoDownlink(byte tid) { + if (tid < mTidsDownlinkMap.length()) { + return mTidsDownlinkMap.get(tid); + } + return false; + } + + /** + * Get link id for the link. + * + * @return link id. + */ + public int getLinkId() { + return mLinkId; + } + + /** + * Get link address. + * + * @return link mac address. + */ + public MacAddress getMacAddress() { + return mStaMacAddress; + } } /** @@ -3737,11 +3756,11 @@ public class WifiNative { } public static class RingBufferStatus{ - String name; - int flag; - int ringBufferId; - int ringBufferByteSize; - int verboseLevel; + public String name; + public int flag; + public int ringBufferId; + public int ringBufferByteSize; + public int verboseLevel; int writtenBytes; int readBytes; int writtenRecords; @@ -3817,18 +3836,18 @@ public class WifiNative { /* Packet fate API */ @Immutable - abstract static class FateReport { + public abstract static class FateReport { final static int USEC_PER_MSEC = 1000; // The driver timestamp is a 32-bit counter, in microseconds. This field holds the // maximal value of a driver timestamp in milliseconds. final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000); final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS"); - final byte mFate; - final long mDriverTimestampUSec; - final byte mFrameType; - final byte[] mFrameBytes; - final long mEstimatedWallclockMSec; + public final byte mFate; + public final long mDriverTimestampUSec; + public final byte mFrameType; + public final byte[] mFrameBytes; + public final long mEstimatedWallclockMSec; FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { mFate = fate; @@ -3931,7 +3950,8 @@ public class WifiNative { */ @Immutable public static final class TxFateReport extends FateReport { - TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { + public TxFateReport(byte fate, long driverTimestampUSec, byte frameType, + byte[] frameBytes) { super(fate, driverTimestampUSec, frameType, frameBytes); } @@ -3974,7 +3994,8 @@ public class WifiNative { */ @Immutable public static final class RxFateReport extends FateReport { - RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { + public RxFateReport(byte fate, long driverTimestampUSec, byte frameType, + byte[] frameBytes) { super(fate, driverTimestampUSec, frameType, frameBytes); } @@ -4479,4 +4500,80 @@ public class WifiNative { public boolean isSoftApInstanceDiedHandlerSupported() { return mHostapdHal.isSoftApInstanceDiedHandlerSupported(); } + + @VisibleForTesting + /** Checks if there are any STA (for connectivity) iface active. */ + boolean hasAnyStaIfaceForConnectivity() { + return mIfaceMgr.hasAnyStaIfaceForConnectivity(); + } + + @VisibleForTesting + /** Checks if there are any STA (for scan) iface active. */ + boolean hasAnyStaIfaceForScan() { + return mIfaceMgr.hasAnyStaIfaceForScan(); + } + + @VisibleForTesting + /** Checks if there are any AP iface active. */ + boolean hasAnyApIface() { + return mIfaceMgr.hasAnyApIface(); + } + + @VisibleForTesting + /** Checks if there are any iface active. */ + boolean hasAnyIface() { + return mIfaceMgr.hasAnyIface(); + } + + /** + * Sets or clean mock wifi service + * + * @param serviceName the service name of mock wifi service. When service name is empty, the + * framework will clean mock wifi service. + */ + public void setMockWifiService(String serviceName) { + Log.d(TAG, "set MockWifiModemService to " + serviceName); + if (TextUtils.isEmpty(serviceName)) { + mMockWifiModem = null; + return; + } + mMockWifiModem = new MockWifiServiceUtil(mContext, serviceName); + if (mMockWifiModem == null) { + Log.e(TAG, "MockWifiServiceUtil creation failed."); + return; + } + + // mock wifi modem service is set, try to bind all supported mock HAL services + mMockWifiModem.bindAllMockModemService(); + for (int service = MockWifiServiceUtil.MIN_SERVICE_IDX; + service < MockWifiServiceUtil.NUM_SERVICES; service++) { + int retryCount = 0; + IBinder binder; + do { + binder = mMockWifiModem.getServiceBinder(service); + retryCount++; + if (binder == null) { + Log.d(TAG, "Retry(" + retryCount + ") for " + + mMockWifiModem.getModuleName(service)); + try { + Thread.sleep(MockWifiServiceUtil.BINDER_RETRY_MILLIS); + } catch (InterruptedException e) { + } + } + } while ((binder == null) && (retryCount < MockWifiServiceUtil.BINDER_MAX_RETRY)); + + if (binder == null) { + Log.e(TAG, "Mock " + mMockWifiModem.getModuleName(service) + " bind fail"); + } + } + } + + /** + * Returns mock wifi service name. + */ + public String getMockWifiServiceName() { + String serviceName = mMockWifiModem != null ? mMockWifiModem.getServiceName() : null; + Log.d(TAG, "getMockWifiServiceName - service name is " + serviceName); + return serviceName; + } } diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java index 02ab14bd60..3d650e6f0f 100644 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java @@ -16,6 +16,9 @@ package com.android.server.wifi; +import static android.net.wifi.WifiScanner.WIFI_BAND_ALL; +import static android.net.wifi.WifiScanner.WIFI_BAND_UNSPECIFIED; + import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; @@ -165,6 +168,7 @@ public class WifiNetworkFactory extends NetworkFactory { @Nullable private NetworkRequest mConnectedSpecificNetworkRequest; @Nullable private WifiNetworkSpecifier mConnectedSpecificNetworkRequestSpecifier; @Nullable private WifiConfiguration mUserSelectedNetwork; + private boolean mShouldHaveInternetCapabilities = false; private Set<Integer> mConnectedUids = new ArraySet<>(); private int mUserSelectedNetworkConnectRetryCount; // Map of bssid to latest scan results for all scan results matching a request. Will be @@ -377,6 +381,10 @@ public class WifiNetworkFactory extends NetworkFactory { mActiveModeWarden.removeClientModeManager(modeManager); return; } + if (modeManager != mClientModeManager) { + // If clientModeManager changes, teardown the current connection + removeClientModeManagerIfNecessary(); + } mClientModeManager = modeManager; mClientModeManagerRole = modeManager.getRole(); if (mVerboseLoggingEnabled) { @@ -711,7 +719,8 @@ public class WifiNetworkFactory extends NetworkFactory { Log.e(TAG, "Requesting specific frequency bands is not yet supported. Rejecting"); return false; } - if (!WifiConfigurationUtil.validateNetworkSpecifier(wns)) { + if (!WifiConfigurationUtil.validateNetworkSpecifier(wns, mContext.getResources() + .getInteger(R.integer.config_wifiNetworkSpecifierMaxPreferredChannels))) { Log.e(TAG, "Invalid wifi network specifier: " + wns + ". Rejecting "); return false; } @@ -726,6 +735,8 @@ public class WifiNetworkFactory extends NetworkFactory { @Override public boolean acceptRequest(NetworkRequest networkRequest) { NetworkSpecifier ns = networkRequest.getNetworkSpecifier(); + boolean isFromSetting = mWifiPermissionsUtil.checkNetworkSettingsPermission( + networkRequest.getRequestorUid()); if (ns == null) { // Generic wifi request. Always accept. } else { @@ -736,7 +747,8 @@ public class WifiNetworkFactory extends NetworkFactory { } // MultiInternet Request to be handled by MultiInternetWifiNetworkFactory. if (mMultiInternetManager.isStaConcurrencyForMultiInternetEnabled() - && MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(networkRequest)) { + && MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(networkRequest, + isFromSetting)) { return false; } // Invalid request with wifi network specifier. @@ -800,6 +812,8 @@ public class WifiNetworkFactory extends NetworkFactory { @Override protected void needNetworkFor(NetworkRequest networkRequest) { NetworkSpecifier ns = networkRequest.getNetworkSpecifier(); + boolean isFromSetting = mWifiPermissionsUtil.checkNetworkSettingsPermission( + networkRequest.getRequestorUid()); if (ns == null) { // Generic wifi request. Turn on auto-join if necessary. if (++mGenericConnectionReqCount == 1) { @@ -813,7 +827,8 @@ public class WifiNetworkFactory extends NetworkFactory { } // MultiInternet Request to be handled by MultiInternetWifiNetworkFactory. if (mMultiInternetManager.isStaConcurrencyForMultiInternetEnabled() - && MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(networkRequest)) { + && MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(networkRequest, + isFromSetting)) { return; } // Invalid request with wifi network specifier. @@ -843,7 +858,7 @@ public class WifiNetworkFactory extends NetworkFactory { WifiNetworkSpecifier wns = (WifiNetworkSpecifier) ns; mActiveSpecificNetworkRequestSpecifier = new WifiNetworkSpecifier( wns.ssidPatternMatcher, wns.bssidPatternMatcher, wns.getBand(), - wns.wifiConfiguration); + wns.wifiConfiguration, wns.getPreferredChannelFrequenciesMhz()); mSkipUserDialogue = false; mWifiMetrics.incrementNetworkRequestApiNumRequest(); @@ -994,6 +1009,14 @@ public class WifiNetworkFactory extends NetworkFactory { return Collections.emptySet(); } + /** + * Return whether if current network request should have the internet capabilities due to a + * same saved/suggestion network is present. + */ + public boolean shouldHaveInternetCapabilities() { + return mShouldHaveInternetCapabilities; + } + // Helper method to add the provided network configuration to WifiConfigManager, if it does not // already exist & return the allocated network ID. This ID will be used in the CONNECT_NETWORK // request to ClientModeImpl. @@ -1114,12 +1137,30 @@ public class WifiNetworkFactory extends NetworkFactory { Log.v(TAG, "Requesting new ClientModeManager instance - didUserSeeUi = " + didUserSeeUi); } + mShouldHaveInternetCapabilities = false; + ClientModeManagerRequestListener listener = new ClientModeManagerRequestListener(); + if (mWifiPermissionsUtil.checkEnterCarModePrioritized(mActiveSpecificNetworkRequest + .getRequestorUid())) { + mShouldHaveInternetCapabilities = hasNetworkForInternet(mUserSelectedNetwork); + if (mShouldHaveInternetCapabilities) { + listener.onAnswer(mActiveModeWarden.getPrimaryClientModeManager()); + return; + } + } WorkSource ws = new WorkSource(mActiveSpecificNetworkRequest.getRequestorUid(), mActiveSpecificNetworkRequest.getRequestorPackageName()); mActiveModeWarden.requestLocalOnlyClientModeManager(new ClientModeManagerRequestListener(), ws, networkToConnect.SSID, networkToConnect.BSSID, didUserSeeUi); } + private boolean hasNetworkForInternet(WifiConfiguration network) { + List<WifiConfiguration> networks = mWifiConfigManager.getConfiguredNetworksWithPasswords(); + return networks.stream().anyMatch(a -> Objects.equals(a.SSID, network.SSID) + && !WifiConfigurationUtil.hasCredentialChanged(a, network) + && !a.fromWifiNetworkSpecifier + && !a.noInternetAccessExpected); + } + private void handleConnectToNetworkUserSelection(WifiConfiguration network, boolean didUserSeeUi) { Log.d(TAG, "User initiated connect to network: " + network.SSID); @@ -1278,7 +1319,6 @@ public class WifiNetworkFactory extends NetworkFactory { mActiveSpecificNetworkRequest = null; mActiveSpecificNetworkRequestSpecifier = null; mSkipUserDialogue = false; - mUserSelectedNetwork = null; mUserSelectedNetworkConnectRetryCount = 0; mIsPeriodicScanEnabled = false; mIsPeriodicScanPaused = false; @@ -1493,8 +1533,20 @@ public class WifiNetworkFactory extends NetworkFactory { mScanSettings.hiddenNetworks.add(new WifiScanner.ScanSettings.HiddenNetwork( addEnclosingQuotes(wns.ssidPatternMatcher.getPath()))); } + int[] channelFreqs = wns.getPreferredChannelFrequenciesMhz(); + if (channelFreqs.length > 0) { + int index = 0; + mScanSettings.channels = new WifiScanner.ChannelSpec[channelFreqs.length]; + for (int freq : channelFreqs) { + mScanSettings.channels[index++] = new WifiScanner.ChannelSpec(freq); + } + mScanSettings.band = WIFI_BAND_UNSPECIFIED; + } mIsPeriodicScanEnabled = true; startScan(); + // Clear the channel settings to perform a full band scan. + mScanSettings.channels = new WifiScanner.ChannelSpec[0]; + mScanSettings.band = WIFI_BAND_ALL; } private void cancelPeriodicScans() { diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java index 06acf5f4a0..36cae2eac3 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -128,6 +128,8 @@ public class WifiNetworkSelector { private boolean mIsEnhancedOpenSupported; private boolean mSufficiencyCheckEnabledWhenScreenOff = true; private boolean mSufficiencyCheckEnabledWhenScreenOn = true; + private boolean mUserConnectChoiceOverrideEnabled = true; + private boolean mLastSelectionWeightEnabled = true; private @AssociatedNetworkSelectionOverride int mAssociatedNetworkSelectionOverride = ASSOCIATED_NETWORK_SELECTION_OVERRIDE_NONE; private boolean mScreenOn = false; @@ -319,7 +321,7 @@ public class WifiNetworkSelector { } // Metered networks costs the user data, so this is insufficient. - if (network.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) { + if (WifiConfiguration.isMetered(network, wifiInfo)) { localLog("Current network is metered"); return false; } @@ -880,7 +882,7 @@ public class WifiNetworkSelector { ifaceName = clientModeManager.getInterfaceName(); connected = clientModeManager.isConnected(); disconnected = clientModeManager.isDisconnected(); - wifiInfo = clientModeManager.syncRequestConnectionInfo(); + wifiInfo = clientModeManager.getConnectionInfo(); } ClientModeManagerState() { @@ -968,6 +970,20 @@ public class WifiNetworkSelector { } /** + * Enable or disable candidate override with user connect choice. + */ + public void setUserConnectChoiceOverrideEnabled(boolean enabled) { + mUserConnectChoiceOverrideEnabled = enabled; + } + + /** + * Enable or disable last selection weight. + */ + public void setLastSelectionWeightEnabled(boolean enabled) { + mLastSelectionWeightEnabled = enabled; + } + + /** * Returns the list of Candidates from networks in range. * * @param scanDetails List of ScanDetail for all the APs in range @@ -1044,7 +1060,8 @@ public class WifiNetworkSelector { cmmState.wifiInfo.getRssi(), cmmState.wifiInfo.getFrequency(), ScanResult.CHANNEL_WIDTH_20MHZ, // channel width not available in WifiInfo - calculateLastSelectionWeight(currentNetwork.networkId), + calculateLastSelectionWeight(currentNetwork.networkId, + WifiConfiguration.isMetered(currentNetwork, cmmState.wifiInfo)), WifiConfiguration.isMetered(currentNetwork, cmmState.wifiInfo), isFromCarrierOrPrivilegedApp(currentNetwork), predictedTputMbps); @@ -1076,7 +1093,7 @@ public class WifiNetworkSelector { scanDetail.getScanResult().level, scanDetail.getScanResult().frequency, scanDetail.getScanResult().channelWidth, - calculateLastSelectionWeight(config.networkId), + calculateLastSelectionWeight(config.networkId, metered), metered, isFromCarrierOrPrivilegedApp(config), predictThroughput(scanDetail)); @@ -1360,7 +1377,8 @@ public class WifiNetworkSelector { // Get a fresh copy of WifiConfiguration reflecting any scan result updates WifiConfiguration selectedNetwork = mWifiConfigManager.getConfiguredNetwork(selectedNetworkId); - if (selectedNetwork != null && legacyOverrideWanted && overrideEnabled) { + if (selectedNetwork != null && legacyOverrideWanted && overrideEnabled + && mUserConnectChoiceOverrideEnabled) { selectedNetwork = overrideCandidateWithUserConnectChoice(selectedNetwork); } if (selectedNetwork != null) { @@ -1423,11 +1441,16 @@ public class WifiNetworkSelector { } } - private double calculateLastSelectionWeight(int networkId) { - if (networkId != mWifiConfigManager.getLastSelectedNetwork()) return 0.0; + private double calculateLastSelectionWeight(int networkId, boolean isMetered) { + if (!mLastSelectionWeightEnabled + || networkId != mWifiConfigManager.getLastSelectedNetwork()) { + return 0.0; + } double timeDifference = mClock.getElapsedSinceBootMillis() - mWifiConfigManager.getLastSelectedTimeStamp(); - long millis = TimeUnit.MINUTES.toMillis(mScoringParams.getLastSelectionMinutes()); + long millis = TimeUnit.MINUTES.toMillis(isMetered + ? mScoringParams.getLastMeteredSelectionMinutes() + : mScoringParams.getLastUnmeteredSelectionMinutes()); if (timeDifference >= millis) return 0.0; double unclipped = 1.0 - (timeDifference / millis); return Math.min(Math.max(unclipped, 0.0), 1.0); diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index 773393cf57..79087532fe 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -48,7 +48,6 @@ import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.Handler; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -161,7 +160,7 @@ public class WifiNetworkSuggestionsManager { private final WifiContext mContext; private final Resources mResources; - private final Handler mHandler; + private final RunnerHandler mHandler; private final AppOpsManager mAppOps; private final ActivityManager mActivityManager; private final WifiNotificationManager mNotificationManager; @@ -659,7 +658,7 @@ public class WifiNetworkSuggestionsManager { } } - public WifiNetworkSuggestionsManager(WifiContext context, Handler handler, + public WifiNetworkSuggestionsManager(WifiContext context, RunnerHandler handler, WifiInjector wifiInjector, WifiPermissionsUtil wifiPermissionsUtil, WifiConfigManager wifiConfigManager, WifiConfigStore wifiConfigStore, WifiMetrics wifiMetrics, WifiCarrierInfoManager wifiCarrierInfoManager, @@ -695,7 +694,7 @@ public class WifiNetworkSuggestionsManager { mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, handler); mLruConnectionTracker = lruConnectionTracker; - mHandler.postAtFrontOfQueue(() -> mWifiConfigManager.addOnNetworkUpdateListener( + mHandler.postToFront(() -> mWifiConfigManager.addOnNetworkUpdateListener( new WifiNetworkSuggestionsManager.OnNetworkUpdateListener())); } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 7fcca1d8bd..57204b4938 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -210,6 +210,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; /** * WifiService handles remote WiFi operation requests by implementing @@ -852,6 +853,8 @@ public class WifiServiceImpl extends BaseWifiService { try { mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, null); + mLastCallerInfoManager.put(WifiManager.API_START_SCAN, Process.myTid(), + callingUid, Binder.getCallingPid(), packageName, true); Boolean scanSuccess = mWifiThreadRunner.call(() -> mScanRequestProxy.startScan(callingUid, packageName), null); if (scanSuccess == null) { @@ -1144,6 +1147,14 @@ public class WifiServiceImpl extends BaseWifiService { uid); } + private boolean isPlatformOrTargetSdkLessThanU(String packageName, int uid) { + if (!SdkLevel.isAtLeastU()) { + return true; + } + return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, + Build.VERSION_CODES.UPSIDE_DOWN_CAKE, uid); + } + /** * Get the current primary ClientModeManager in a thread safe manner, but blocks on the main * Wifi thread. @@ -1247,8 +1258,7 @@ public class WifiServiceImpl extends BaseWifiService { () -> mWifiConnectivityManager.setAutoJoinEnabledExternal(true, false)); mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON); } else { - WifiInfo wifiInfo = - getPrimaryClientModeManagerBlockingThreadSafe().syncRequestConnectionInfo(); + WifiInfo wifiInfo = mActiveModeWarden.getConnectionInfo(); mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF, wifiInfo == null ? -1 : wifiInfo.getNetworkId()); } @@ -1361,8 +1371,7 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("restartWifiSubsystem uid=%").c(Binder.getCallingUid()).flush(); } mWifiThreadRunner.post(() -> { - WifiInfo wifiInfo = - mActiveModeWarden.getPrimaryClientModeManager().syncRequestConnectionInfo(); + WifiInfo wifiInfo = mActiveModeWarden.getConnectionInfo(); mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_RESTART_WIFI_SUB_SYSTEM, wifiInfo == null ? -1 : wifiInfo.getNetworkId()); mWifiInjector.getSelfRecovery().trigger(REASON_API_CALL); @@ -1487,6 +1496,24 @@ public class WifiServiceImpl extends BaseWifiService { } /** + * Check if input configuration is valid. + * + * Call this before calling {@link startTetheredHotspot(SoftApConfiguration)} or + * {@link #setSoftApConfiguration(softApConfiguration)} to avoid unexpected error duo to + * configuration is invalid. + * + * @param config a configuration would like to be checked. + * @return true if config is valid, otherwise false. + */ + @Override + public boolean validateSoftApConfiguration(SoftApConfiguration config) { + int uid = Binder.getCallingUid(); + boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid); + return WifiApConfigStore.validateApWifiConfiguration( + config, privileged, mContext); + } + + /** * See {@link WifiManager#unregisterCoexCallback(WifiManager.CoexCallback)} */ @RequiresApi(Build.VERSION_CODES.S) @@ -2496,6 +2523,8 @@ public class WifiServiceImpl extends BaseWifiService { return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; } + mLastCallerInfoManager.put(WifiManager.API_START_LOCAL_ONLY_HOTSPOT, Process.myTid(), + uid, Binder.getCallingPid(), packageName, true); // the app should be in the foreground long ident = Binder.clearCallingIdentity(); @@ -2661,10 +2690,9 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getWifiApConfiguration uid=%").c(uid).flush(); } - // hand off work to the ClientModeImpl handler thread to sync work between calls - // and SoftApManager starting up softap - return (mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, - new SoftApConfiguration.Builder().build())).toWifiConfiguration(); + final SoftApConfiguration config = mWifiApConfigStore.getApConfiguration(); + return config == null ? new SoftApConfiguration.Builder().build().toWifiConfiguration() + : config.toWifiConfiguration(); } /** @@ -2687,10 +2715,8 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getSoftApConfiguration uid=%").c(uid).flush(); } - // hand off work to the ClientModeImpl handler thread to sync work between calls - // and SoftApManager starting up softap - return mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, - new SoftApConfiguration.Builder().build()); + final SoftApConfiguration config = mWifiApConfigStore.getApConfiguration(); + return config == null ? new SoftApConfiguration.Builder().build() : config; } /** @@ -2717,14 +2743,13 @@ public class WifiServiceImpl extends BaseWifiService { return false; SoftApConfiguration softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig); if (softApConfig == null) return false; - if (WifiApConfigStore.validateApWifiConfiguration( + if (!WifiApConfigStore.validateApWifiConfiguration( softApConfig, false, mContext)) { - mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(softApConfig)); - return true; - } else { Log.e(TAG, "Invalid WifiConfiguration"); return false; } + mWifiApConfigStore.setApConfiguration(softApConfig); + return true; } /** @@ -2748,8 +2773,9 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("setSoftApConfiguration uid=%").c(uid).flush(); if (softApConfig == null) return false; if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged, mContext)) { + mWifiApConfigStore.setApConfiguration(softApConfig); + // Send the message for AP config update after the save is done. mActiveModeWarden.updateSoftApConfiguration(softApConfig); - mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(softApConfig)); return true; } else { Log.e(TAG, "Invalid SoftAp Configuration"); @@ -3101,9 +3127,7 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getPrivilegedConnectedNetwork uid=%").c(callingUid).flush(); } - WifiInfo wifiInfo = mWifiThreadRunner.call( - () -> mActiveModeWarden.getPrimaryClientModeManager().syncRequestConnectionInfo(), - new WifiInfo()); + WifiInfo wifiInfo = mActiveModeWarden.getConnectionInfo(); int networkId = wifiInfo.getNetworkId(); if (networkId < 0) { if (mVerboseLoggingEnabled) { @@ -3623,7 +3647,10 @@ public class WifiServiceImpl extends BaseWifiService { Log.w(TAG, "Insecure Enterprise network " + config.SSID + " configured by Settings/SUW"); } - + mLastCallerInfoManager.put(config.networkId < 0 + ? WifiManager.API_ADD_NETWORK : WifiManager.API_UPDATE_NETWORK, + Process.myTid(), Binder.getCallingUid(), + Binder.getCallingPid(), packageName, true); Log.i("addOrUpdateNetworkInternal", " uid = " + Binder.getCallingUid() + " SSID " + config.SSID + " nid=" + config.networkId); @@ -3760,6 +3787,8 @@ public class WifiServiceImpl extends BaseWifiService { return false; } + mLastCallerInfoManager.put(WifiManager.API_ENABLE_NETWORK, Process.myTid(), + callingUid, Binder.getCallingPid(), packageName, disableOthers); // TODO b/33807876 Log netId mLog.info("enableNetwork uid=% disableOthers=%") .c(callingUid) @@ -3793,6 +3822,8 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("disableNetwork not allowed for uid=%").c(callingUid).flush(); return false; } + mLastCallerInfoManager.put(WifiManager.API_DISABLE_NETWORK, Process.myTid(), + callingUid, Binder.getCallingPid(), packageName, true); mLog.info("disableNetwork uid=%").c(callingUid).flush(); return mWifiThreadRunner.call( () -> mWifiConfigManager.disableNetwork(netId, callingUid, packageName), false); @@ -3936,6 +3967,8 @@ public class WifiServiceImpl extends BaseWifiService { int callingUid = Binder.getCallingUid(); mLog.info("allowAutojoin=% uid=%").c(choice).c(callingUid).flush(); + mLastCallerInfoManager.put(WifiManager.API_ALLOW_AUTOJOIN, Process.myTid(), + callingUid, Binder.getCallingPid(), "<unknown>", choice); mWifiThreadRunner.post(() -> { WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); if (config == null) { @@ -4093,7 +4126,7 @@ public class WifiServiceImpl extends BaseWifiService { WifiInfo wifiInfo = mWifiThreadRunner.call( () -> getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( uid, callingPackage) - .syncRequestConnectionInfo(), new WifiInfo()); + .getConnectionInfo(), new WifiInfo()); long redactions = wifiInfo.getApplicableRedactions(); if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { if (mVerboseLoggingEnabled) { @@ -4505,9 +4538,7 @@ public class WifiServiceImpl extends BaseWifiService { if (mContext.getResources().getBoolean(R.bool.config_wifi24ghzSupport)) { return true; } - return mWifiThreadRunner.call( - () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ).length > 0, - false); + return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ); } @@ -4524,9 +4555,7 @@ public class WifiServiceImpl extends BaseWifiService { if (mContext.getResources().getBoolean(R.bool.config_wifi5ghzSupport)) { return true; } - return mWifiThreadRunner.call( - () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ).length > 0, - false); + return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ); } @Override @@ -4542,9 +4571,7 @@ public class WifiServiceImpl extends BaseWifiService { if (mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport)) { return true; } - return mWifiThreadRunner.call( - () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ).length > 0, - false); + return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ); } @Override @@ -4564,9 +4591,7 @@ public class WifiServiceImpl extends BaseWifiService { if (mContext.getResources().getBoolean(R.bool.config_wifi60ghzSupport)) { return true; } - return mWifiThreadRunner.call( - () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ).length > 0, - false); + return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_60_GHZ); } @Override @@ -5209,7 +5234,7 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("getCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); } - return getPrimaryClientModeManagerBlockingThreadSafe().syncGetCurrentNetwork(); + return mActiveModeWarden.getCurrentNetwork(); } public static String toHexString(String s) { @@ -5971,6 +5996,9 @@ public class WifiServiceImpl extends BaseWifiService { throw new IllegalArgumentException("packageName must not be null"); } mLog.info("connect uid=%").c(uid).flush(); + mLastCallerInfoManager.put(config != null + ? WifiManager.API_CONNECT_CONFIG : WifiManager.API_CONNECT_NETWORK_ID, + Process.myTid(), uid, Binder.getCallingPid(), packageName, true); mWifiThreadRunner.post(() -> { ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); final NetworkUpdateResult result; @@ -6070,6 +6098,8 @@ public class WifiServiceImpl extends BaseWifiService { throw new IllegalArgumentException("packageName must not be null"); } mLog.info("save uid=%").c(uid).flush(); + mLastCallerInfoManager.put(WifiManager.API_SAVE, Process.myTid(), + uid, Binder.getCallingPid(), packageName, true); mWifiThreadRunner.post(() -> { ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); NetworkUpdateResult result = @@ -6104,6 +6134,8 @@ public class WifiServiceImpl extends BaseWifiService { // the netId becomes invalid after the forget operation. mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_FORGET_WIFI, netId); } + mLastCallerInfoManager.put(WifiManager.API_FORGET, Process.myTid(), + uid, Binder.getCallingPid(), "<unknown>", true); mWifiThreadRunner.post(() -> { WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); boolean success = mWifiConfigManager.removeNetwork(netId, uid, null); @@ -6229,8 +6261,7 @@ public class WifiServiceImpl extends BaseWifiService { int uid = Binder.getCallingUid(); mWifiPermissionsUtil.checkPackage(uid, packageName); if (!mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission(uid) - || !mWifiPermissionsUtil.checkCallersLocationPermission(packageName, featureId, - uid, false, null)) { + || !mWifiPermissionsUtil.checkCallersLocationPermissionInManifest(uid, false)) { throw new SecurityException(TAG + " Caller uid " + uid + " has no permission"); } if (mVerboseLoggingEnabled) { @@ -6353,10 +6384,10 @@ public class WifiServiceImpl extends BaseWifiService { @Override public void setScanThrottleEnabled(boolean enable) { enforceNetworkSettingsPermission(); - mLog.info("setScanThrottleEnabled uid=% verbose=%") + mLog.info("setScanThrottleEnabled uid=% enable=%") .c(Binder.getCallingUid()) .c(enable).flush(); - mWifiThreadRunner.post(()-> mScanRequestProxy.setScanThrottleEnabled(enable)); + mScanRequestProxy.setScanThrottleEnabled(enable); } /** @@ -6365,10 +6396,12 @@ public class WifiServiceImpl extends BaseWifiService { @Override public boolean isScanThrottleEnabled() { enforceAccessPermission(); + final boolean enable = mScanRequestProxy.isScanThrottleEnabled(); if (mVerboseLoggingEnabled) { - mLog.info("isScanThrottleEnabled uid=%").c(Binder.getCallingUid()).flush(); + mLog.info("isScanThrottleEnabled uid=% enable=%") + .c(Binder.getCallingUid()).c(enable).flush(); } - return mWifiThreadRunner.call(()-> mScanRequestProxy.isScanThrottleEnabled(), true); + return enable; } /** @@ -6380,7 +6413,12 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("setWalkeupEnabled uid=% verbose=%") .c(Binder.getCallingUid()) .c(enable).flush(); - mWifiThreadRunner.post(()-> mWifiInjector.getWakeupController().setEnabled(enable)); + long ident = Binder.clearCallingIdentity(); + try { + mWifiInjector.getWakeupController().setEnabled(enable); + } finally { + Binder.restoreCallingIdentity(ident); + } } /** @@ -6392,7 +6430,12 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("isAutoWakeupEnabled uid=%").c(Binder.getCallingUid()).flush(); } - return mWifiThreadRunner.call(()-> mWifiInjector.getWakeupController().isEnabled(), false); + long ident = Binder.clearCallingIdentity(); + try { + return mWifiInjector.getWakeupController().isEnabled(); + } finally { + Binder.restoreCallingIdentity(ident); + } } /** @@ -6407,8 +6450,7 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("setCarrierNetworkOffloadEnabled uid=%").c(Binder.getCallingUid()).flush(); } - mWifiThreadRunner.post(() -> - mWifiCarrierInfoManager.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled)); + mWifiCarrierInfoManager.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled); } /** @@ -6421,8 +6463,7 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("isCarrierNetworkOffload uid=%").c(Binder.getCallingUid()).flush(); } - return mWifiThreadRunner.call(()-> - mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(subId, merged), true); + return mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(subId, merged); } /** @@ -6546,26 +6587,72 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band, - @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) { - // Location mode must be enabled - long ident = Binder.clearCallingIdentity(); - try { - if (!mWifiPermissionsUtil.isLocationModeEnabled()) { - throw new SecurityException("Location mode is disabled for the device"); + @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter, + String packageName, Bundle extras) { + final int uid = Binder.getCallingUid(); + if (isPlatformOrTargetSdkLessThanU(packageName, uid)) { + // Location mode must be enabled + long ident = Binder.clearCallingIdentity(); + try { + if (!mWifiPermissionsUtil.isLocationModeEnabled()) { + throw new SecurityException("Location mode is disabled for the device"); + } + } finally { + Binder.restoreCallingIdentity(ident); } - } finally { - Binder.restoreCallingIdentity(ident); + if (!mWifiPermissionsUtil.checkCallersHardwareLocationPermission(uid)) { + throw new SecurityException( + "UID " + uid + " does not have location h/w permission"); + } + } else { + mWifiPermissionsUtil.enforceNearbyDevicesPermission( + extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), + true, TAG + " getUsableChannels"); } - final int uid = Binder.getCallingUid(); if (mVerboseLoggingEnabled) { mLog.info("getUsableChannels uid=%").c(Binder.getCallingUid()).flush(); } - if (!mWifiPermissionsUtil.checkCallersHardwareLocationPermission(uid)) { - throw new SecurityException("UID " + uid + " does not have location h/w permission"); - } if (!isValidBandForGetUsableChannels(band)) { throw new IllegalArgumentException("Unsupported band: " + band); } + // If querying the usable channels for SoftAp mode and regulatory filtered, return from + // cached softAp capabilities directly. + if (mode == WifiAvailableChannel.OP_MODE_SAP + && filter == WifiAvailableChannel.FILTER_REGULATORY) { + int[] chans; + switch (band) { + case WifiScanner.WIFI_BAND_24_GHZ: + chans = + mTetheredSoftApTracker.getSoftApCapability().getSupportedChannelList( + SoftApConfiguration.BAND_2GHZ); + break; + case WifiScanner.WIFI_BAND_5_GHZ: + chans = + mTetheredSoftApTracker.getSoftApCapability().getSupportedChannelList( + SoftApConfiguration.BAND_5GHZ); + break; + case WifiScanner.WIFI_BAND_6_GHZ: + chans = + mTetheredSoftApTracker.getSoftApCapability().getSupportedChannelList( + SoftApConfiguration.BAND_6GHZ); + break; + case WifiScanner.WIFI_BAND_60_GHZ: + chans = + mTetheredSoftApTracker.getSoftApCapability().getSupportedChannelList( + SoftApConfiguration.BAND_60GHZ); + break; + default: + chans = null; + break; + } + if (chans != null) { + return Arrays.stream(chans).mapToObj( + v -> new WifiAvailableChannel( + ScanResult.convertChannelToFrequencyMhzIfSupported(v, band), + WifiAvailableChannel.OP_MODE_SAP)).collect( + Collectors.toList()); + } + } List<WifiAvailableChannel> channels = mWifiThreadRunner.call( () -> mWifiNative.getUsableChannels(band, mode, filter), null); if (channels == null) { @@ -6712,7 +6799,7 @@ public class WifiServiceImpl extends BaseWifiService { } mWifiThreadRunner.post(() -> { for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { - WifiInfo wifiInfo = cmm.syncRequestConnectionInfo(); + WifiInfo wifiInfo = cmm.getConnectionInfo(); if (wifiInfo == null) continue; //check minimum security level restriction @@ -6750,7 +6837,7 @@ public class WifiServiceImpl extends BaseWifiService { } mWifiThreadRunner.post(() -> { for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { - WifiInfo wifiInfo = cmm.syncRequestConnectionInfo(); + WifiInfo wifiInfo = cmm.getConnectionInfo(); if (wifiInfo == null) continue; //skip SSID restriction check for Osu and Passpoint networks @@ -6913,4 +7000,9 @@ public class WifiServiceImpl extends BaseWifiService { } }); } + @Override + public int getMaxNumberOfChannelsPerRequest() { + return mContext.getResources() + .getInteger(R.integer.config_wifiNetworkSpecifierMaxPreferredChannels); + } } diff --git a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java index 4837e98302..e67fe9e95b 100644 --- a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java +++ b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java @@ -109,6 +109,13 @@ public class WifiSettingsConfigStore { new Key<>("wifi_sta_factory_mac_address", null); /** + * Store the Secondary STA factory MAC address retrieved from the driver on the first bootup. + */ + public static final Key<String> SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS = + new Key<>("secondary_wifi_sta_factory_mac_address", null); + + + /** * Store the default country code updated via {@link WifiManager#setDefaultCountryCode(String)} */ public static final Key<String> WIFI_DEFAULT_COUNTRY_CODE = @@ -121,6 +128,12 @@ public class WifiSettingsConfigStore { new Key<>("wifi_native_supported_features", 0L); /** + * Store the supported features retrieved from WiFi HAL and Supplicant HAL + */ + public static final Key<Integer> WIFI_NATIVE_SUPPORTED_STA_BANDS = + new Key<>("wifi_native_supported_sta_bands", 0); + + /** * Store the static chip info retrieved from WiFi HAL */ public static final Key<String> WIFI_STATIC_CHIP_INFO = new Key<>("wifi_static_chip_info", ""); diff --git a/service/java/com/android/server/wifi/WifiSettingsStore.java b/service/java/com/android/server/wifi/WifiSettingsStore.java index 573b347ecc..1a9d561d34 100644 --- a/service/java/com/android/server/wifi/WifiSettingsStore.java +++ b/service/java/com/android/server/wifi/WifiSettingsStore.java @@ -28,6 +28,7 @@ import android.net.wifi.WifiContext; import android.provider.Settings; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.wifi.resources.R; import java.io.FileDescriptor; @@ -131,10 +132,6 @@ public class WifiSettingsStore { /* Tracks when airplane mode has been enabled in milliseconds since boot */ private long mApmEnabledTimeSinceBootMillis = 0; - // TODO(b/240650689): Replace NOTE_WIFI_APM_NOTIFICATION with - // SystemMessage.NOTE_WIFI_APM_NOTIFICATION - private static final int WIFI_APM_NOTIFICATION_ID = 73; - private final String mApmEnhancementHelpLink; private final WifiContext mContext; private final WifiSettingsConfigStore mSettingsConfigStore; @@ -232,7 +229,7 @@ public class WifiSettingsStore { .setStyle(new Notification.BigTextStyle().bigText(message)) .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), R.drawable.ic_wifi_settings)); - mNotificationManager.notify(WIFI_APM_NOTIFICATION_ID, builder.build()); + mNotificationManager.notify(SystemMessage.NOTE_WIFI_APM_NOTIFICATION, builder.build()); } public synchronized boolean handleWifiToggled(boolean wifiEnabled) { diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java index 17dbcd5c84..4dbd48b024 100644 --- a/service/java/com/android/server/wifi/WifiShellCommand.java +++ b/service/java/com/android/server/wifi/WifiShellCommand.java @@ -1250,6 +1250,11 @@ public class WifiShellCommand extends BasicShellCommandHandler { mActiveModeWarden.emergencyCallStateChanged(enabled); return 0; } + case "set-emergency-scan-request": { + boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); + mWifiService.setEmergencyScanRequestInProgress(enabled); + return 0; + } case "trigger-recovery": { mSelfRecovery.trigger(REASON_API_CALL); return 0; @@ -1769,6 +1774,27 @@ public class WifiShellCommand extends BasicShellCommandHandler { } return 0; } + case "set-mock-wifimodem-service": + String opt = null; + String serviceName = null; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "-s": { + serviceName = getNextArgRequired(); + break; + } + default: + pw.println("set-mock-wifimodem-service requires '-s' option"); + return -1; + } + } + mWifiNative.setMockWifiService(serviceName); + // The result will be checked, must print result "true" + pw.print("true"); + return 0; + case "get-mock-wifimodem-service": + pw.print(mWifiNative.getMockWifiServiceName()); + return 0; default: return handleDefaultCommands(cmd); } @@ -2335,12 +2361,12 @@ public class WifiShellCommand extends BasicShellCommandHandler { // privileged, dump out all the client mode manager manager statuses for (ClientModeManager cm : mActiveModeWarden.getClientModeManagers()) { pw.println("==== ClientModeManager instance: " + cm + " ===="); - WifiInfo info = cm.syncRequestConnectionInfo(); + WifiInfo info = cm.getConnectionInfo(); printWifiInfo(pw, info); if (info.getSupplicantState() != SupplicantState.COMPLETED) { continue; } - Network network = cm.syncGetCurrentNetwork(); + Network network = cm.getCurrentNetwork(); NetworkCapabilities capabilities = mConnectivityManager.getNetworkCapabilities(network); pw.println("NetworkCapabilities: " + capabilities); @@ -2673,6 +2699,8 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" Sets whether we are in the middle of an emergency call."); pw.println("Equivalent to receiving the " + "TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED broadcast."); + pw.println(" set-emergency-scan-request enabled|disabled"); + pw.println(" Sets whether there is a emergency scan request in progress."); pw.println(" network-suggestions-set-as-carrier-provider <packageName> yes|no"); pw.println(" Set the <packageName> work as carrier provider or not."); pw.println(" is-network-suggestions-set-as-carrier-provider <packageName>"); diff --git a/service/java/com/android/server/wifi/WifiThreadRunner.java b/service/java/com/android/server/wifi/WifiThreadRunner.java index a3c0c2295e..491e30cf65 100644 --- a/service/java/com/android/server/wifi/WifiThreadRunner.java +++ b/service/java/com/android/server/wifi/WifiThreadRunner.java @@ -216,6 +216,14 @@ public class WifiThreadRunner { return mHandler.hasCallbacks(r); } + /** + * Package private + * @return Scissors timeout threshold + */ + static long getScissorsTimeoutThreshold() { + return RUN_WITH_SCISSORS_TIMEOUT_MILLIS; + } + // Note: @hide methods copied from android.os.Handler /** * Runs the specified task synchronously. diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java index 9d73cd333f..ba0d4b219d 100644 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ b/service/java/com/android/server/wifi/WifiVendorHal.java @@ -15,8 +15,6 @@ */ package com.android.server.wifi; -import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE; - 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; @@ -25,40 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask; -import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters; -import android.hardware.wifi.V1_0.StaBackgroundScanParameters; -import android.hardware.wifi.V1_0.StaLinkLayerIfaceStats; -import android.hardware.wifi.V1_0.StaLinkLayerRadioStats; -import android.hardware.wifi.V1_0.StaLinkLayerStats; -import android.hardware.wifi.V1_0.StaRoamingConfig; -import android.hardware.wifi.V1_0.StaRoamingState; -import android.hardware.wifi.V1_0.StaScanData; -import android.hardware.wifi.V1_0.StaScanDataFlagMask; -import android.hardware.wifi.V1_0.StaScanResult; -import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; -import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; -import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; -import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; -import android.hardware.wifi.V1_0.WifiInformationElement; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_2.IWifiChipEventCallback.IfaceInfo; -import android.hardware.wifi.V1_5.IWifiChip.MultiStaUseCase; -import android.hardware.wifi.V1_5.WifiBand; -import android.hardware.wifi.V1_5.WifiIfaceMode; -import android.hardware.wifi.V1_6.IWifiChip.UsableChannelFilter; import android.net.MacAddress; import android.net.apf.ApfCapabilities; import android.net.wifi.ScanResult; @@ -68,7 +32,6 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; import android.os.Handler; -import android.os.RemoteException; import android.os.WorkSource; import android.text.TextUtils; import android.util.Log; @@ -76,19 +39,13 @@ import android.util.Pair; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.HexDump; -import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; -import com.android.server.wifi.WifiLinkLayerStats.ChannelStats; -import com.android.server.wifi.WifiLinkLayerStats.PeerInfo; -import com.android.server.wifi.WifiLinkLayerStats.RadioStat; -import com.android.server.wifi.WifiLinkLayerStats.RateStat; import com.android.server.wifi.WifiNative.RxFateReport; import com.android.server.wifi.WifiNative.TxFateReport; -import com.android.server.wifi.util.BitMask; -import com.android.server.wifi.util.GeneralUtil.Mutable; -import com.android.server.wifi.util.NativeUtil; -import com.android.wifi.resources.R; +import com.android.server.wifi.hal.WifiApIface; +import com.android.server.wifi.hal.WifiChip; +import com.android.server.wifi.hal.WifiHal; +import com.android.server.wifi.hal.WifiStaIface; import com.google.errorprone.annotations.CompileTimeConstant; @@ -100,7 +57,8 @@ import java.util.Set; import java.util.stream.Collectors; /** - * Vendor HAL via HIDL + * Wi-Fi Vendor HAL. + * Interface management is handled by the HalDeviceManager. */ public class WifiVendorHal { @@ -135,103 +93,6 @@ public class WifiVendorHal { } /** - * Checks for a successful status result. - * - * Failures are logged to mLog. - * - * @param status is the WifiStatus generated by a hal call - * @return true for success, false for failure - */ - private boolean ok(WifiStatus status) { - if (status.code == WifiStatusCode.SUCCESS) return true; - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mLog.err("% failed %") - .c(niceMethodName(trace, 3)) - .c(status.toString()) - .flush(); - - return false; - } - - /** - * Logs the argument along with the method name. - * - * Always returns its argument. - */ - private boolean boolResult(boolean result) { - if (mVerboseLog == sNoLog) return result; - // Currently only seen if verbose logging is on - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mVerboseLog.err("% returns %") - .c(niceMethodName(trace, 3)) - .c(result) - .flush(); - - return result; - } - - private <T> T objResult(T obj) { - if (mVerboseLog == sNoLog) return obj; - // Currently only seen if verbose logging is on - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mVerboseLog.err("% returns %") - .c(niceMethodName(trace, 3)) - .c(String.valueOf(obj)) - .flush(); - - return obj; - } - - /** - * Logs the argument along with the method name. - * - * Always returns its argument. - */ - private <T> T nullResult() { - if (mVerboseLog == sNoLog) return null; - // Currently only seen if verbose logging is on - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mVerboseLog.err("% returns %") - .c(niceMethodName(trace, 3)) - .c(null) - .flush(); - - return null; - } - - /** - * Logs the argument along with the method name. - * - * Always returns its argument. - */ - private byte[] byteArrayResult(byte[] result) { - if (mVerboseLog == sNoLog) return result; - // Currently only seen if verbose logging is on - - Thread cur = Thread.currentThread(); - StackTraceElement[] trace = cur.getStackTrace(); - - mVerboseLog.err("% returns %") - .c(niceMethodName(trace, 3)) - .c(result == null ? "(null)" : HexDump.dumpHexString(result)) - .flush(); - - return result; - } - - /** * Logs at method entry * * @param format string with % placeholders @@ -242,47 +103,17 @@ public class WifiVendorHal { return mVerboseLog.trace(format, 1); } - /** - * Gets the method name and line number from a stack trace. - * - * Attempts to skip frames created by lambdas to get a human-sensible name. - * - * @param trace, fo example obtained by Thread.currentThread().getStackTrace() - * @param start frame number to log, typically 3 - * @return string containing the method name and line number - */ - private static String niceMethodName(StackTraceElement[] trace, int start) { - if (start >= trace.length) return ""; - StackTraceElement s = trace[start]; - String name = s.getMethodName(); - if (name.contains("lambda$")) { - // Try to find a friendlier method name - String myFile = s.getFileName(); - if (myFile != null) { - for (int i = start + 1; i < trace.length; i++) { - if (myFile.equals(trace[i].getFileName())) { - name = trace[i].getMethodName(); - break; - } - } - } - } - return (name + "(l." + s.getLineNumber() + ")"); - } - - // Vendor HAL HIDL interface objects. - private IWifiChip mIWifiChip; - private HashMap<String, IWifiStaIface> mIWifiStaIfaces = new HashMap<>(); - private HashMap<String, IWifiApIface> mIWifiApIfaces = new HashMap<>(); + // Vendor HAL interface objects. + private WifiChip mWifiChip; + private HashMap<String, WifiStaIface> mWifiStaIfaces = new HashMap<>(); + private HashMap<String, WifiApIface> mWifiApIfaces = new HashMap<>(); private static Context sContext; private final HalDeviceManager mHalDeviceManager; private final WifiGlobals mWifiGlobals; private final SsidTranslator mSsidTranslator; private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; - private final IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; - private final ChipEventCallback mIWifiChipEventCallback; - private final ChipEventCallbackV12 mIWifiChipEventCallbackV12; - private final ChipEventCallbackV14 mIWifiChipEventCallbackV14; + private final WifiStaIface.Callback mWifiStaIfaceEventCallback; + private final ChipEventCallback mWifiChipEventCallback; // Plumbing for event handling. // @@ -300,20 +131,12 @@ public class WifiVendorHal { mWifiGlobals = wifiGlobals; mSsidTranslator = ssidTranslator; mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener(); - mIWifiStaIfaceEventCallback = new StaIfaceEventCallback(); - mIWifiChipEventCallback = new ChipEventCallback(); - mIWifiChipEventCallbackV12 = new ChipEventCallbackV12(); - mIWifiChipEventCallbackV14 = new ChipEventCallbackV14(); + mWifiStaIfaceEventCallback = new StaIfaceEventCallback(); + mWifiChipEventCallback = new ChipEventCallback(); } public static final Object sLock = new Object(); - private void handleRemoteException(RemoteException e) { - String methodName = niceMethodName(Thread.currentThread().getStackTrace(), 3); - mVerboseLog.err("% RemoteException in HIDL call %").c(methodName).c(e.toString()).flush(); - // Recovery on HAL crash will be triggered by death listener. - } - private WifiNative.VendorHalDeathEventHandler mDeathEventHandler; /** @@ -375,7 +198,7 @@ public class WifiVendorHal { } /** - * Bring up the HIDL Vendor HAL and configure for STA (Station) mode + * Bring up the Vendor HAL and configure for STA (Station) mode * * @return true for success */ @@ -393,7 +216,7 @@ public class WifiVendorHal { } /** - * Bring up the HIDL Vendor HAL. + * Bring up the Vendor HAL. * @return true on success, false otherwise. */ public boolean startVendorHal() { @@ -409,9 +232,9 @@ public class WifiVendorHal { /** Helper method to lookup the corresponding STA iface object using iface name. */ - private IWifiStaIface getStaIface(@NonNull String ifaceName) { + private WifiStaIface getStaIface(@NonNull String ifaceName) { synchronized (sLock) { - return mIWifiStaIfaces.get(ifaceName); + return mWifiStaIfaces.get(ifaceName); } } @@ -425,7 +248,7 @@ public class WifiVendorHal { @Override public void onDestroyed(@NonNull String ifaceName) { synchronized (sLock) { - mIWifiStaIfaces.remove(ifaceName); + mWifiStaIfaces.remove(ifaceName); } if (mExternalListener != null) { mExternalListener.onDestroyed(ifaceName); @@ -443,27 +266,27 @@ public class WifiVendorHal { public String createStaIface(@Nullable InterfaceDestroyedListener destroyedListener, @NonNull WorkSource requestorWs) { synchronized (sLock) { - IWifiStaIface iface = mHalDeviceManager.createStaIface( + WifiStaIface iface = mHalDeviceManager.createStaIface( new StaInterfaceDestroyedListenerInternal(destroyedListener), mHalEventHandler, requestorWs); if (iface == null) { mLog.err("Failed to create STA iface").flush(); - return nullResult(); + return null; } - String ifaceName = mHalDeviceManager.getName((IWifiIface) iface); + String ifaceName = iface.getName(); if (TextUtils.isEmpty(ifaceName)) { mLog.err("Failed to get iface name").flush(); - return nullResult(); + return null; } if (!registerStaIfaceCallback(iface)) { mLog.err("Failed to register STA iface callback").flush(); - return nullResult(); + return null; } - if (!retrieveWifiChip((IWifiIface) iface)) { + if (!retrieveWifiChip(iface)) { mLog.err("Failed to get wifi chip").flush(); - return nullResult(); + return null; } - mIWifiStaIfaces.put(ifaceName, iface); + mWifiStaIfaces.put(ifaceName, iface); return ifaceName; } } @@ -478,12 +301,12 @@ public class WifiVendorHal { public boolean replaceStaIfaceRequestorWs(@NonNull String ifaceName, @NonNull WorkSource requestorWs) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; if (!mHalDeviceManager.replaceRequestorWs(iface, requestorWs)) { mLog.err("Failed to replace requestor worksource for STA iface").flush(); - return boolResult(false); + return false; } return true; } @@ -497,21 +320,21 @@ public class WifiVendorHal { */ public boolean removeStaIface(@NonNull String ifaceName) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - if (!mHalDeviceManager.removeIface((IWifiIface) iface)) { + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + if (!mHalDeviceManager.removeIface(iface)) { mLog.err("Failed to remove STA iface").flush(); - return boolResult(false); + return false; } - mIWifiStaIfaces.remove(ifaceName); + mWifiStaIfaces.remove(ifaceName); return true; } } /** Helper method to lookup the corresponding AP iface object using iface name. */ - private IWifiApIface getApIface(@NonNull String ifaceName) { + private WifiApIface getApIface(@NonNull String ifaceName) { synchronized (sLock) { - return mIWifiApIfaces.get(ifaceName); + return mWifiApIfaces.get(ifaceName); } } @@ -525,7 +348,7 @@ public class WifiVendorHal { @Override public void onDestroyed(@NonNull String ifaceName) { synchronized (sLock) { - mIWifiApIfaces.remove(ifaceName); + mWifiApIfaces.remove(ifaceName); } if (mExternalListener != null) { mExternalListener.onDestroyed(ifaceName); @@ -536,13 +359,13 @@ public class WifiVendorHal { private long getNecessaryCapabilitiesForSoftApMode(@SoftApConfiguration.BandType int band) { long caps = HalDeviceManager.CHIP_CAPABILITY_ANY; if ((band & SoftApConfiguration.BAND_60GHZ) != 0) { - caps |= android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG; + caps |= WifiManager.WIFI_FEATURE_INFRA_60G; } return caps; } /** - * Create a AP iface using {@link HalDeviceManager}. + * Create an AP iface using {@link HalDeviceManager}. * * @param destroyedListener Listener to be invoked when the interface is destroyed. * @param requestorWs Requestor worksource. @@ -557,30 +380,30 @@ public class WifiVendorHal { boolean isBridged, @NonNull SoftApManager softApManager) { synchronized (sLock) { - IWifiApIface iface = mHalDeviceManager.createApIface( + WifiApIface iface = mHalDeviceManager.createApIface( getNecessaryCapabilitiesForSoftApMode(band), new ApInterfaceDestroyedListenerInternal(destroyedListener), mHalEventHandler, requestorWs, isBridged, softApManager); if (iface == null) { mLog.err("Failed to create AP iface").flush(); - return nullResult(); + return null; } - String ifaceName = mHalDeviceManager.getName((IWifiIface) iface); + String ifaceName = iface.getName(); if (TextUtils.isEmpty(ifaceName)) { mLog.err("Failed to get iface name").flush(); - return nullResult(); + return null; } - if (!retrieveWifiChip((IWifiIface) iface)) { + if (!retrieveWifiChip(iface)) { mLog.err("Failed to get wifi chip").flush(); - return nullResult(); + return null; } - mIWifiApIfaces.put(ifaceName, iface); + mWifiApIfaces.put(ifaceName, iface); return ifaceName; } } /** - * Replace the requestor worksource info for a AP iface using {@link HalDeviceManager}. + * Replace the requestor worksource info for an AP iface using {@link HalDeviceManager}. * * @param ifaceName Name of the interface being removed. * @param requestorWs Requestor worksource. @@ -589,12 +412,12 @@ public class WifiVendorHal { public boolean replaceApIfaceRequestorWs(@NonNull String ifaceName, @NonNull WorkSource requestorWs) { synchronized (sLock) { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return boolResult(false); + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return false; - if (!mHalDeviceManager.replaceRequestorWs((IWifiIface) iface, requestorWs)) { + if (!mHalDeviceManager.replaceRequestorWs(iface, requestorWs)) { mLog.err("Failed to replace requestor worksource for AP iface").flush(); - return boolResult(false); + return false; } return true; } @@ -608,14 +431,14 @@ public class WifiVendorHal { */ public boolean removeApIface(@NonNull String ifaceName) { synchronized (sLock) { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return boolResult(false); + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return false; - if (!mHalDeviceManager.removeIface((IWifiIface) iface)) { + if (!mHalDeviceManager.removeIface(iface)) { mLog.err("Failed to remove AP iface").flush(); - return boolResult(false); + return false; } - mIWifiApIfaces.remove(ifaceName); + mWifiApIfaces.remove(ifaceName); return true; } } @@ -629,76 +452,8 @@ public class WifiVendorHal { */ public boolean removeIfaceInstanceFromBridgedApIface(@NonNull String ifaceName, @NonNull String apIfaceInstance) { - try { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 == null) return boolResult(false); - return ok(iWifiChipV15.removeIfaceInstanceFromBridgedApIface( - ifaceName, apIfaceInstance)); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - - @NonNull - private ArrayList<android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel> - frameworkCoexUnsafeChannelsToHidl( - @NonNull List<android.net.wifi.CoexUnsafeChannel> frameworkUnsafeChannels) { - final ArrayList<android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel> hidlList = - new ArrayList<>(); - if (!SdkLevel.isAtLeastS()) { - return hidlList; - } - for (android.net.wifi.CoexUnsafeChannel frameworkUnsafeChannel : frameworkUnsafeChannels) { - final android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel hidlUnsafeChannel = - new android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel(); - switch (frameworkUnsafeChannel.getBand()) { - case (WifiScanner.WIFI_BAND_24_GHZ): - hidlUnsafeChannel.band = WifiBand.BAND_24GHZ; - break; - case (WifiScanner.WIFI_BAND_5_GHZ): - hidlUnsafeChannel.band = WifiBand.BAND_5GHZ; - break; - case (WifiScanner.WIFI_BAND_6_GHZ): - hidlUnsafeChannel.band = WifiBand.BAND_6GHZ; - break; - case (WifiScanner.WIFI_BAND_60_GHZ): - hidlUnsafeChannel.band = WifiBand.BAND_60GHZ; - break; - default: - mLog.err("Tried to set unsafe channel with unknown band: %") - .c(frameworkUnsafeChannel.getBand()) - .flush(); - continue; - } - hidlUnsafeChannel.channel = frameworkUnsafeChannel.getChannel(); - final int powerCapDbm = frameworkUnsafeChannel.getPowerCapDbm(); - if (powerCapDbm != POWER_CAP_NONE) { - hidlUnsafeChannel.powerCapDbm = powerCapDbm; - } else { - hidlUnsafeChannel.powerCapDbm = - android.hardware.wifi.V1_5.IWifiChip.PowerCapConstant.NO_POWER_CAP; - } - hidlList.add(hidlUnsafeChannel); - } - return hidlList; - } - - private int frameworkCoexRestrictionsToHidl(@WifiManager.CoexRestriction int restrictions) { - int hidlRestrictions = 0; - if (!SdkLevel.isAtLeastS()) { - return hidlRestrictions; - } - if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_DIRECT) != 0) { - hidlRestrictions |= android.hardware.wifi.V1_5.IWifiChip.CoexRestriction.WIFI_DIRECT; - } - if ((restrictions & WifiManager.COEX_RESTRICTION_SOFTAP) != 0) { - hidlRestrictions |= android.hardware.wifi.V1_5.IWifiChip.CoexRestriction.SOFTAP; - } - if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_AWARE) != 0) { - hidlRestrictions |= android.hardware.wifi.V1_5.IWifiChip.CoexRestriction.WIFI_AWARE; - } - return hidlRestrictions; + if (mWifiChip == null) return false; + return mWifiChip.removeIfaceInstanceFromBridgedApIface(ifaceName, apIfaceInstance); } /** @@ -710,23 +465,15 @@ public class WifiVendorHal { */ public boolean setCoexUnsafeChannels( @NonNull List<android.net.wifi.CoexUnsafeChannel> unsafeChannels, int restrictions) { - try { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 == null) return boolResult(false); - return ok(iWifiChipV15.setCoexUnsafeChannels( - frameworkCoexUnsafeChannelsToHidl(unsafeChannels), - frameworkCoexRestrictionsToHidl(restrictions))); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + if (mWifiChip == null) return false; + return mWifiChip.setCoexUnsafeChannels(unsafeChannels, restrictions); } - private boolean retrieveWifiChip(IWifiIface iface) { + private boolean retrieveWifiChip(WifiHal.WifiInterface iface) { synchronized (sLock) { - boolean registrationNeeded = mIWifiChip == null; - mIWifiChip = mHalDeviceManager.getChip(iface); - if (mIWifiChip == null) { + boolean registrationNeeded = mWifiChip == null; + mWifiChip = mHalDeviceManager.getChip(iface); + if (mWifiChip == null) { mLog.err("Failed to get the chip created for the Iface").flush(); return false; } @@ -735,7 +482,7 @@ public class WifiVendorHal { } if (!registerChipCallback()) { mLog.err("Failed to register chip callback").flush(); - mIWifiChip = null; + mWifiChip = null; return false; } return true; @@ -745,18 +492,11 @@ public class WifiVendorHal { /** * Registers the sta iface callback. */ - private boolean registerStaIfaceCallback(IWifiStaIface iface) { + private boolean registerStaIfaceCallback(WifiStaIface iface) { synchronized (sLock) { - if (iface == null) return boolResult(false); - if (mIWifiStaIfaceEventCallback == null) return boolResult(false); - try { - WifiStatus status = - iface.registerEventCallback(mIWifiStaIfaceEventCallback); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + if (iface == null) return false; + if (mWifiStaIfaceEventCallback == null) return false; + return iface.registerFrameworkCallback(mWifiStaIfaceEventCallback); } } @@ -765,24 +505,8 @@ public class WifiVendorHal { */ private boolean registerChipCallback() { synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - try { - WifiStatus status; - android.hardware.wifi.V1_4.IWifiChip iWifiChipV14 = getWifiChipForV1_4Mockable(); - android.hardware.wifi.V1_2.IWifiChip iWifiChipV12 = getWifiChipForV1_2Mockable(); - - if (iWifiChipV14 != null) { - status = iWifiChipV14.registerEventCallback_1_4(mIWifiChipEventCallbackV14); - } else if (iWifiChipV12 != null) { - status = iWifiChipV12.registerEventCallback_1_2(mIWifiChipEventCallbackV12); - } else { - status = mIWifiChip.registerEventCallback(mIWifiChipEventCallback); - } - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + if (mWifiChip == null) return false; + return mWifiChip.registerCallback(mWifiChipEventCallback); } } @@ -803,20 +527,20 @@ public class WifiVendorHal { * Caller should hold the lock. */ private void clearState() { - mIWifiChip = null; - mIWifiStaIfaces.clear(); - mIWifiApIfaces.clear(); + mWifiChip = null; + mWifiStaIfaces.clear(); + mWifiApIfaces.clear(); mDriverDescription = null; mFirmwareDescription = null; } /** - * Tests whether the HAL is started and atleast one iface is up. + * Tests whether the HAL is started and at least one iface is up. */ public boolean isHalStarted() { // For external use only. Methods in this class should test for null directly. synchronized (sLock) { - return (!mIWifiStaIfaces.isEmpty() || !mIWifiApIfaces.isEmpty()); + return (!mWifiStaIfaces.isEmpty() || !mWifiApIfaces.isEmpty()); } } @@ -830,27 +554,18 @@ public class WifiVendorHal { public boolean getBgScanCapabilities( @NonNull String ifaceName, WifiNative.ScanCapabilities capabilities) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - Mutable<Boolean> ans = new Mutable<>(false); - WifiNative.ScanCapabilities out = capabilities; - iface.getBackgroundScanCapabilities((status, cap) -> { - if (!ok(status)) return; - mVerboseLog.info("scan capabilities %").c(cap.toString()).flush(); - out.max_scan_cache_size = cap.maxCacheSize; - out.max_ap_cache_per_scan = cap.maxApCachePerScan; - out.max_scan_buckets = cap.maxBuckets; - out.max_rssi_sample_size = 0; - out.max_scan_reporting_threshold = cap.maxReportingThreshold; - ans.value = true; - } - ); - return ans.value; - } catch (RemoteException e) { - handleRemoteException(e); - return false; + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + + WifiNative.ScanCapabilities result = iface.getBackgroundScanCapabilities(); + if (result != null) { + capabilities.max_scan_cache_size = result.max_scan_cache_size; + capabilities.max_ap_cache_per_scan = result.max_ap_cache_per_scan; + capabilities.max_scan_buckets = result.max_scan_buckets; + capabilities.max_rssi_sample_size = result.max_rssi_sample_size; + capabilities.max_scan_reporting_threshold = result.max_scan_reporting_threshold; } + return result != null; } } @@ -860,122 +575,23 @@ public class WifiVendorHal { @VisibleForTesting class CurrentBackgroundScan { public int cmdId; - public StaBackgroundScanParameters param; + public WifiStaIface.StaBackgroundScanParameters param; public WifiNative.ScanEventHandler eventHandler = null; public boolean paused = false; public WifiScanner.ScanData[] latestScanResults = null; CurrentBackgroundScan(int id, WifiNative.ScanSettings settings) { cmdId = id; - param = new StaBackgroundScanParameters(); - param.basePeriodInMs = settings.base_period_ms; - param.maxApPerScan = settings.max_ap_per_scan; - param.reportThresholdPercent = settings.report_threshold_percent; - param.reportThresholdNumScans = settings.report_threshold_num_scans; + List<WifiNative.BucketSettings> buckets = new ArrayList<>(); if (settings.buckets != null) { - for (WifiNative.BucketSettings bs : settings.buckets) { - param.buckets.add(makeStaBackgroundScanBucketParametersFromBucketSettings(bs)); - } + buckets = Arrays.asList(settings.buckets); } + param = new WifiStaIface.StaBackgroundScanParameters(settings.base_period_ms, + settings.max_ap_per_scan, settings.report_threshold_percent, + settings.report_threshold_num_scans, buckets); } } - /** - * Makes the Hal flavor of WifiNative.BucketSettings - * - * @param bs WifiNative.BucketSettings - * @return Hal flavor of bs - * @throws IllegalArgumentException if band value is not recognized - */ - private StaBackgroundScanBucketParameters - makeStaBackgroundScanBucketParametersFromBucketSettings(WifiNative.BucketSettings bs) { - StaBackgroundScanBucketParameters pa = new StaBackgroundScanBucketParameters(); - pa.bucketIdx = bs.bucket; - pa.band = makeWifiBandFromFrameworkBand(bs.band); - if (bs.channels != null) { - for (WifiNative.ChannelSettings cs : bs.channels) { - pa.frequencies.add(cs.frequency); - } - } - pa.periodInMs = bs.period_ms; - pa.eventReportScheme = makeReportSchemeFromBucketSettingsReportEvents(bs.report_events); - pa.exponentialMaxPeriodInMs = bs.max_period_ms; - // Although HAL API allows configurable base value for the truncated - // exponential back off scan. Native API and above support only - // truncated binary exponential back off scan. - // Hard code value of base to 2 here. - pa.exponentialBase = 2; - pa.exponentialStepCount = bs.step_count; - return pa; - } - - /** - * Makes the Hal flavor of WifiScanner's band indication - * - * Note: This method is only used by background scan which does not - * support 6GHz, hence band combinations including 6GHz are considered invalid - * - * @param frameworkBand one of WifiScanner.WIFI_BAND_* - * @return A WifiBand value - * @throws IllegalArgumentException if frameworkBand is not recognized - */ - private int makeWifiBandFromFrameworkBand(int frameworkBand) { - switch (frameworkBand) { - case WifiScanner.WIFI_BAND_UNSPECIFIED: - return WifiBand.BAND_UNSPECIFIED; - case WifiScanner.WIFI_BAND_24_GHZ: - return WifiBand.BAND_24GHZ; - case WifiScanner.WIFI_BAND_5_GHZ: - return WifiBand.BAND_5GHZ; - case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: - return WifiBand.BAND_5GHZ_DFS; - case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: - return WifiBand.BAND_5GHZ_WITH_DFS; - case WifiScanner.WIFI_BAND_BOTH: - return WifiBand.BAND_24GHZ_5GHZ; - case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: - return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; - case WifiScanner.WIFI_BAND_6_GHZ: - return WifiBand.BAND_6GHZ; - case WifiScanner.WIFI_BAND_24_5_6_GHZ: - return WifiBand.BAND_24GHZ_5GHZ_6GHZ; - case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: - return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ; - case WifiScanner.WIFI_BAND_60_GHZ: - return WifiBand.BAND_60GHZ; - case WifiScanner.WIFI_BAND_24_5_6_60_GHZ: - return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ; - case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: - return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ; - case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS: - default: - throw new IllegalArgumentException("bad band " + frameworkBand); - } - } - - /** - * Makes the Hal flavor of WifiScanner's report event mask - * - * @param reportUnderscoreEvents is logical OR of WifiScanner.REPORT_EVENT_* values - * @return Corresponding StaBackgroundScanBucketEventReportSchemeMask value - * @throws IllegalArgumentException if a mask bit is not recognized - */ - private int makeReportSchemeFromBucketSettingsReportEvents(int reportUnderscoreEvents) { - int ans = 0; - BitMask in = new BitMask(reportUnderscoreEvents); - if (in.testAndClear(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)) { - ans |= StaBackgroundScanBucketEventReportSchemeMask.EACH_SCAN; - } - if (in.testAndClear(WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)) { - ans |= StaBackgroundScanBucketEventReportSchemeMask.FULL_RESULTS; - } - if (in.testAndClear(WifiScanner.REPORT_EVENT_NO_BATCH)) { - ans |= StaBackgroundScanBucketEventReportSchemeMask.NO_BATCH; - } - if (in.value != 0) throw new IllegalArgumentException("bad " + reportUnderscoreEvents); - return ans; - } - private int mLastScanCmdId; // For assigning cmdIds to scans @VisibleForTesting @@ -994,70 +610,55 @@ public class WifiVendorHal { public boolean startBgScan(@NonNull String ifaceName, WifiNative.ScanSettings settings, WifiNative.ScanEventHandler eventHandler) { - WifiStatus status; - if (eventHandler == null) return boolResult(false); + if (eventHandler == null) return false; synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - if (mScan != null && !mScan.paused) { - ok(iface.stopBackgroundScan(mScan.cmdId)); - mScan = null; - } - mLastScanCmdId = (mLastScanCmdId % 9) + 1; // cycle through non-zero single digits - CurrentBackgroundScan scan = new CurrentBackgroundScan(mLastScanCmdId, settings); - status = iface.startBackgroundScan(scan.cmdId, scan.param); - if (!ok(status)) return false; - scan.eventHandler = eventHandler; - mScan = scan; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + if (mScan != null && !mScan.paused) { + iface.stopBackgroundScan(mScan.cmdId); + mScan = null; } + + mLastScanCmdId = (mLastScanCmdId % 9) + 1; // cycle through non-zero single digits + CurrentBackgroundScan scan = new CurrentBackgroundScan(mLastScanCmdId, settings); + boolean success = iface.startBackgroundScan(scan.cmdId, scan.param); + if (!success) return false; + + scan.eventHandler = eventHandler; + mScan = scan; + return true; } } /** - * Stops any ongoing backgound scan + * Stops any ongoing background scan * * @param ifaceName Name of the interface. */ public void stopBgScan(@NonNull String ifaceName) { - WifiStatus status; synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return; - try { - if (mScan != null) { - ok(iface.stopBackgroundScan(mScan.cmdId)); - mScan = null; - } - } catch (RemoteException e) { - handleRemoteException(e); + if (mScan != null) { + iface.stopBackgroundScan(mScan.cmdId); + mScan = null; } } } /** - * Pauses an ongoing backgound scan + * Pauses an ongoing background scan * * @param ifaceName Name of the interface. */ public void pauseBgScan(@NonNull String ifaceName) { - WifiStatus status; synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return; - if (mScan != null && !mScan.paused) { - status = iface.stopBackgroundScan(mScan.cmdId); - if (!ok(status)) return; - mScan.paused = true; - } - } catch (RemoteException e) { - handleRemoteException(e); + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return; + if (mScan != null && !mScan.paused) { + if (!iface.stopBackgroundScan(mScan.cmdId)) return; + mScan.paused = true; } } } @@ -1068,32 +669,24 @@ public class WifiVendorHal { * @param ifaceName Name of the interface. */ public void restartBgScan(@NonNull String ifaceName) { - WifiStatus status; synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return; - try { - if (mScan != null && mScan.paused) { - status = iface.startBackgroundScan(mScan.cmdId, mScan.param); - if (!ok(status)) return; - mScan.paused = false; - } - } catch (RemoteException e) { - handleRemoteException(e); + if (mScan != null && mScan.paused) { + if (!iface.startBackgroundScan(mScan.cmdId, mScan.param)) return; + mScan.paused = false; } } } /** - * Gets the latest scan results received from the HIDL interface callback. - * TODO(b/35754840): This hop to fetch scan results after callback is unnecessary. Refactor - * WifiScanner to use the scan results from the callback. + * Gets the latest scan results received from the HAL interface callback. * * @param ifaceName Name of the interface. */ public WifiScanner.ScanData[] getBgScanResults(@NonNull String ifaceName) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return null; if (mScan == null) return null; return mScan.latestScanResults; @@ -1109,506 +702,13 @@ public class WifiVendorHal { * @return the statistics, or null if unable to do so */ public WifiLinkLayerStats getWifiLinkLayerStats(@NonNull String ifaceName) { - if (getWifiStaIfaceForV1_6Mockable(ifaceName) != null) { - return getWifiLinkLayerStats_1_6_Internal(ifaceName); - } else if (getWifiStaIfaceForV1_5Mockable(ifaceName) != null) { - return getWifiLinkLayerStats_1_5_Internal(ifaceName); - } else if (getWifiStaIfaceForV1_3Mockable(ifaceName) != null) { - return getWifiLinkLayerStats_1_3_Internal(ifaceName); - } else { - return getWifiLinkLayerStats_internal(ifaceName); - } - } - - private WifiLinkLayerStats getWifiLinkLayerStats_internal(@NonNull String ifaceName) { - class AnswerBox { - public StaLinkLayerStats value = null; - } - AnswerBox answer = new AnswerBox(); - synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - iface.getLinkLayerStats((status, stats) -> { - if (!ok(status)) return; - answer.value = stats; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats(answer.value); - return stats; - } - - private WifiLinkLayerStats getWifiLinkLayerStats_1_3_Internal(@NonNull String ifaceName) { - class AnswerBox { - public android.hardware.wifi.V1_3.StaLinkLayerStats value = null; - } - AnswerBox answer = new AnswerBox(); - synchronized (sLock) { - try { - android.hardware.wifi.V1_3.IWifiStaIface iface = - getWifiStaIfaceForV1_3Mockable(ifaceName); - if (iface == null) return null; - iface.getLinkLayerStats_1_3((status, stats) -> { - if (!ok(status)) return; - answer.value = stats; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats_1_3(answer.value); - return stats; - } - - private WifiLinkLayerStats getWifiLinkLayerStats_1_5_Internal(@NonNull String ifaceName) { - class AnswerBox { - public android.hardware.wifi.V1_5.StaLinkLayerStats value = null; - } - AnswerBox answer = new AnswerBox(); synchronized (sLock) { - try { - android.hardware.wifi.V1_5.IWifiStaIface iface = - getWifiStaIfaceForV1_5Mockable(ifaceName); - if (iface == null) return null; - iface.getLinkLayerStats_1_5((status, stats) -> { - if (!ok(status)) return; - answer.value = stats; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats_1_5(answer.value); - return stats; - } - - private WifiLinkLayerStats getWifiLinkLayerStats_1_6_Internal(@NonNull String ifaceName) { - class AnswerBox { - public android.hardware.wifi.V1_6.StaLinkLayerStats value = null; - } - AnswerBox answer = new AnswerBox(); - synchronized (sLock) { - try { - android.hardware.wifi.V1_6.IWifiStaIface iface = - getWifiStaIfaceForV1_6Mockable(ifaceName); - if (iface == null) return null; - iface.getLinkLayerStats_1_6((status, stats) -> { - if (!ok(status)) return; - answer.value = stats; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats_1_6(answer.value); - return stats; - } - - /** - * Makes the framework version of link layer stats from the hal version. - */ - @VisibleForTesting - static WifiLinkLayerStats frameworkFromHalLinkLayerStats(StaLinkLayerStats stats) { - if (stats == null) return null; - WifiLinkLayerStats out = new WifiLinkLayerStats(); - setIfaceStats(out, stats.iface); - setRadioStats(out, stats.radios); - setTimeStamp(out, stats.timeStampInMs); - out.version = WifiLinkLayerStats.V1_0; - return out; - } - - /** - * Makes the framework version of link layer stats from the hal version. - */ - @VisibleForTesting - static WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_3( - android.hardware.wifi.V1_3.StaLinkLayerStats stats) { - if (stats == null) return null; - WifiLinkLayerStats out = new WifiLinkLayerStats(); - setIfaceStats(out, stats.iface); - setRadioStats_1_3(out, stats.radios); - setTimeStamp(out, stats.timeStampInMs); - out.version = WifiLinkLayerStats.V1_3; - return out; - } - - /** - * Makes the framework version of link layer stats from the hal version. - */ - @VisibleForTesting - static WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_5( - android.hardware.wifi.V1_5.StaLinkLayerStats stats) { - if (stats == null) return null; - WifiLinkLayerStats out = new WifiLinkLayerStats(); - setIfaceStats_1_5(out, stats.iface); - setRadioStats_1_5(out, stats.radios); - setTimeStamp(out, stats.timeStampInMs); - out.version = WifiLinkLayerStats.V1_5; - return out; - } - - /** - * Makes the framework version of link layer stats from the hal version. - */ - @VisibleForTesting - static WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_6( - android.hardware.wifi.V1_6.StaLinkLayerStats stats) { - if (stats == null) return null; - WifiLinkLayerStats out = new WifiLinkLayerStats(); - setIfaceStats_1_6(out, stats.iface); - setRadioStats_1_6(out, stats.radios); - setTimeStamp(out, stats.timeStampInMs); - out.version = WifiLinkLayerStats.V1_5; //TODO: Does the change justify moving to 1.6 ?? - return out; - } - - private static void setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface) { - if (iface == null) return; - stats.beacon_rx = iface.beaconRx; - stats.rssi_mgmt = iface.avgRssiMgmt; - // Statistics are broken out by Wireless Multimedia Extensions categories - // WME Best Effort Access Category - stats.rxmpdu_be = iface.wmeBePktStats.rxMpdu; - stats.txmpdu_be = iface.wmeBePktStats.txMpdu; - stats.lostmpdu_be = iface.wmeBePktStats.lostMpdu; - stats.retries_be = iface.wmeBePktStats.retries; - // WME Background Access Category - stats.rxmpdu_bk = iface.wmeBkPktStats.rxMpdu; - stats.txmpdu_bk = iface.wmeBkPktStats.txMpdu; - stats.lostmpdu_bk = iface.wmeBkPktStats.lostMpdu; - stats.retries_bk = iface.wmeBkPktStats.retries; - // WME Video Access Category - stats.rxmpdu_vi = iface.wmeViPktStats.rxMpdu; - stats.txmpdu_vi = iface.wmeViPktStats.txMpdu; - stats.lostmpdu_vi = iface.wmeViPktStats.lostMpdu; - stats.retries_vi = iface.wmeViPktStats.retries; - // WME Voice Access Category - stats.rxmpdu_vo = iface.wmeVoPktStats.rxMpdu; - stats.txmpdu_vo = iface.wmeVoPktStats.txMpdu; - stats.lostmpdu_vo = iface.wmeVoPktStats.lostMpdu; - stats.retries_vo = iface.wmeVoPktStats.retries; - } - - private static void setIfaceStats_1_5(WifiLinkLayerStats stats, - android.hardware.wifi.V1_5.StaLinkLayerIfaceStats iface) { - if (iface == null) return; - setIfaceStats(stats, iface.V1_0); - stats.timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent; - // WME Best Effort Access Category - stats.contentionTimeMinBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesBe = iface.wmeBeContentionTimeStats.contentionNumSamples; - // WME Background Access Category - stats.contentionTimeMinBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesBk = iface.wmeBkContentionTimeStats.contentionNumSamples; - // WME Video Access Category - stats.contentionTimeMinViInUsec = iface.wmeViContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxViInUsec = iface.wmeViContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgViInUsec = iface.wmeViContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesVi = iface.wmeViContentionTimeStats.contentionNumSamples; - // WME Voice Access Category - stats.contentionTimeMinVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesVo = iface.wmeVoContentionTimeStats.contentionNumSamples; - // Peer information statistics - stats.peerInfo = new PeerInfo[iface.peers.size()]; - for (int i = 0; i < stats.peerInfo.length; i++) { - PeerInfo peer = new PeerInfo(); - android.hardware.wifi.V1_5.StaPeerInfo staPeerInfo = iface.peers.get(i); - peer.staCount = staPeerInfo.staCount; - peer.chanUtil = staPeerInfo.chanUtil; - RateStat[] rateStats = new RateStat[staPeerInfo.rateStats.size()]; - for (int j = 0; j < staPeerInfo.rateStats.size(); j++) { - rateStats[j] = new RateStat(); - android.hardware.wifi.V1_5.StaRateStat staRateStat = staPeerInfo.rateStats.get(j); - rateStats[j].preamble = staRateStat.rateInfo.preamble; - rateStats[j].nss = staRateStat.rateInfo.nss; - rateStats[j].bw = staRateStat.rateInfo.bw; - rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx; - rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps; - rateStats[j].txMpdu = staRateStat.txMpdu; - rateStats[j].rxMpdu = staRateStat.rxMpdu; - rateStats[j].mpduLost = staRateStat.mpduLost; - rateStats[j].retries = staRateStat.retries; - } - peer.rateStats = rateStats; - stats.peerInfo[i] = peer; - } - } - - private static void setIfaceStats_1_6(WifiLinkLayerStats stats, - android.hardware.wifi.V1_6.StaLinkLayerIfaceStats iface) { - if (iface == null) return; - setIfaceStats(stats, iface.V1_0); - stats.timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent; - // WME Best Effort Access Category - stats.contentionTimeMinBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesBe = iface.wmeBeContentionTimeStats.contentionNumSamples; - // WME Background Access Category - stats.contentionTimeMinBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesBk = iface.wmeBkContentionTimeStats.contentionNumSamples; - // WME Video Access Category - stats.contentionTimeMinViInUsec = iface.wmeViContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxViInUsec = iface.wmeViContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgViInUsec = iface.wmeViContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesVi = iface.wmeViContentionTimeStats.contentionNumSamples; - // WME Voice Access Category - stats.contentionTimeMinVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMinInUsec; - stats.contentionTimeMaxVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec; - stats.contentionTimeAvgVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec; - stats.contentionNumSamplesVo = iface.wmeVoContentionTimeStats.contentionNumSamples; - // Peer information statistics - stats.peerInfo = new PeerInfo[iface.peers.size()]; - for (int i = 0; i < stats.peerInfo.length; i++) { - PeerInfo peer = new PeerInfo(); - android.hardware.wifi.V1_6.StaPeerInfo staPeerInfo = iface.peers.get(i); - peer.staCount = staPeerInfo.staCount; - peer.chanUtil = staPeerInfo.chanUtil; - RateStat[] rateStats = new RateStat[staPeerInfo.rateStats.size()]; - for (int j = 0; j < staPeerInfo.rateStats.size(); j++) { - rateStats[j] = new RateStat(); - android.hardware.wifi.V1_6.StaRateStat staRateStat = staPeerInfo.rateStats.get(j); - rateStats[j].preamble = staRateStat.rateInfo.preamble; - rateStats[j].nss = staRateStat.rateInfo.nss; - rateStats[j].bw = staRateStat.rateInfo.bw; - rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx; - rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps; - rateStats[j].txMpdu = staRateStat.txMpdu; - rateStats[j].rxMpdu = staRateStat.rxMpdu; - rateStats[j].mpduLost = staRateStat.mpduLost; - rateStats[j].retries = staRateStat.retries; - } - peer.rateStats = rateStats; - stats.peerInfo[i] = peer; - } - } - - private static void setRadioStats(WifiLinkLayerStats stats, - List<StaLinkLayerRadioStats> radios) { - if (radios == null) return; - // Do not coalesce this info for multi radio devices with older HALs. - if (radios.size() > 0) { - StaLinkLayerRadioStats radioStats = radios.get(0); - stats.on_time = radioStats.onTimeInMs; - stats.tx_time = radioStats.txTimeInMs; - stats.tx_time_per_level = new int[radioStats.txTimeInMsPerLevel.size()]; - for (int i = 0; i < stats.tx_time_per_level.length; i++) { - stats.tx_time_per_level[i] = radioStats.txTimeInMsPerLevel.get(i); - } - stats.rx_time = radioStats.rxTimeInMs; - stats.on_time_scan = radioStats.onTimeInMsForScan; - stats.numRadios = 1; - } - } - - /** - * Set individual radio stats from the hal radio stats for V1_3 - */ - private static void setFrameworkPerRadioStatsFromHidl_1_3(int radioId, RadioStat radio, - android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) { - radio.radio_id = radioId; - radio.on_time = hidlRadioStats.V1_0.onTimeInMs; - radio.tx_time = hidlRadioStats.V1_0.txTimeInMs; - radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs; - radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan; - radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan; - radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan; - radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan; - radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan; - radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan; - /* Copy list of channel stats */ - for (android.hardware.wifi.V1_3.WifiChannelStats channelStats - : hidlRadioStats.channelStats) { - ChannelStats channelStatsEntry = new ChannelStats(); - channelStatsEntry.frequency = channelStats.channel.centerFreq; - channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; - channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; - radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); - } - } - - /** - * Set individual radio stats from the hal radio stats for V1_6 - */ - private static void setFrameworkPerRadioStatsFromHidl_1_6(RadioStat radio, - android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) { - radio.radio_id = hidlRadioStats.radioId; - radio.on_time = hidlRadioStats.V1_0.onTimeInMs; - radio.tx_time = hidlRadioStats.V1_0.txTimeInMs; - radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs; - radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan; - radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan; - radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan; - radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan; - radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan; - radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan; - /* Copy list of channel stats */ - for (android.hardware.wifi.V1_6.WifiChannelStats channelStats - : hidlRadioStats.channelStats) { - ChannelStats channelStatsEntry = new ChannelStats(); - channelStatsEntry.frequency = channelStats.channel.centerFreq; - channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; - channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; - radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); - } - } - - /** - * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate - * the radio stats from all the radios else process the stats from Radio 0 only. - * This method is for V1_3 - */ - private static void aggregateFrameworkRadioStatsFromHidl_1_3(int radioIndex, - WifiLinkLayerStats stats, - android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) { - if (!sContext.getResources() - .getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled) - && radioIndex > 0) { - return; - } - // Aggregate the radio stats from all the radios - stats.on_time += hidlRadioStats.V1_0.onTimeInMs; - stats.tx_time += hidlRadioStats.V1_0.txTimeInMs; - // Aggregate tx_time_per_level based on the assumption that the length of - // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other - // radios at array indices greater than the length of first radio will be dropped. - if (stats.tx_time_per_level == null) { - stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()]; - } - for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size() - && i < stats.tx_time_per_level.length; i++) { - stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i); - } - stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs; - stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan; - stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan; - stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan; - stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan; - stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan; - stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan; - /* Copy list of channel stats */ - for (android.hardware.wifi.V1_3.WifiChannelStats channelStats - : hidlRadioStats.channelStats) { - ChannelStats channelStatsEntry = - stats.channelStatsMap.get(channelStats.channel.centerFreq); - if (channelStatsEntry == null) { - channelStatsEntry = new ChannelStats(); - channelStatsEntry.frequency = channelStats.channel.centerFreq; - stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); - } - channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs; - channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs; - } - stats.numRadios++; - } - - /** - * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate - * the radio stats from all the radios else process the stats from Radio 0 only. - * This method is for V1_6 - */ - private static void aggregateFrameworkRadioStatsFromHidl_1_6(int radioIndex, - WifiLinkLayerStats stats, - android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) { - if (!sContext.getResources() - .getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled) - && radioIndex > 0) { - return; - } - // Aggregate the radio stats from all the radios - stats.on_time += hidlRadioStats.V1_0.onTimeInMs; - stats.tx_time += hidlRadioStats.V1_0.txTimeInMs; - // Aggregate tx_time_per_level based on the assumption that the length of - // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other - // radios at array indices greater than the length of first radio will be dropped. - if (stats.tx_time_per_level == null) { - stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()]; - } - for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size() - && i < stats.tx_time_per_level.length; i++) { - stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i); - } - stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs; - stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan; - stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan; - stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan; - stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan; - stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan; - stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan; - /* Copy list of channel stats */ - for (android.hardware.wifi.V1_6.WifiChannelStats channelStats - : hidlRadioStats.channelStats) { - ChannelStats channelStatsEntry = - stats.channelStatsMap.get(channelStats.channel.centerFreq); - if (channelStatsEntry == null) { - channelStatsEntry = new ChannelStats(); - channelStatsEntry.frequency = channelStats.channel.centerFreq; - stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); - } - channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs; - channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs; - } - stats.numRadios++; - } - - private static void setRadioStats_1_3(WifiLinkLayerStats stats, - List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios) { - if (radios == null) return; - int radioIndex = 0; - for (android.hardware.wifi.V1_3.StaLinkLayerRadioStats radioStats : radios) { - aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats); - radioIndex++; - } - } - - private static void setRadioStats_1_5(WifiLinkLayerStats stats, - List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios) { - if (radios == null) return; - int radioIndex = 0; - stats.radioStats = new RadioStat[radios.size()]; - for (android.hardware.wifi.V1_5.StaLinkLayerRadioStats radioStats : radios) { - RadioStat radio = new RadioStat(); - setFrameworkPerRadioStatsFromHidl_1_3(radioStats.radioId, radio, radioStats.V1_3); - stats.radioStats[radioIndex] = radio; - aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats.V1_3); - radioIndex++; - } - } - - private static void setRadioStats_1_6(WifiLinkLayerStats stats, - List<android.hardware.wifi.V1_6.StaLinkLayerRadioStats> radios) { - if (radios == null) return; - int radioIndex = 0; - stats.radioStats = new RadioStat[radios.size()]; - for (android.hardware.wifi.V1_6.StaLinkLayerRadioStats radioStats : radios) { - RadioStat radio = new RadioStat(); - setFrameworkPerRadioStatsFromHidl_1_6(radio, radioStats); - stats.radioStats[radioIndex] = radio; - aggregateFrameworkRadioStatsFromHidl_1_6(radioIndex, stats, radioStats); - radioIndex++; + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return null; + return iface.getLinkLayerStats(); } } - private static void setTimeStamp(WifiLinkLayerStats stats, long timeStampInMs) { - stats.timeStampInMs = timeStampInMs; - } - @VisibleForTesting boolean mLinkLayerStatsDebug = false; // Passed to Hal @@ -1617,181 +717,20 @@ public class WifiVendorHal { * * This is called unconditionally whenever we create a STA interface. * - * @param iface Iface object. + * @param ifaceName Name of the interface. */ public void enableLinkLayerStats(@NonNull String ifaceName) { synchronized (sLock) { - try { - WifiStatus status; - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) { - mLog.err("STA iface object is NULL - Failed to enable link layer stats") - .flush(); - return; - } - status = iface.enableLinkLayerStatsCollection(mLinkLayerStatsDebug); - if (!ok(status)) { - mLog.err("unable to enable link layer stats collection").flush(); - } - } catch (RemoteException e) { - handleRemoteException(e); - } - } - } - - /** - * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for V1.1 - */ - private static final long[][] sChipFeatureCapabilityTranslation = { - {WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT - }, - {WifiManager.WIFI_FEATURE_D2D_RTT, - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT - }, - {WifiManager.WIFI_FEATURE_D2AP_RTT, - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT - } - }; - - /** - * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for - * additional capabilities introduced in V1.5 - */ - private static final long[][] sChipFeatureCapabilityTranslation15 = { - {WifiManager.WIFI_FEATURE_INFRA_60G, - android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG - } - }; - - /** - * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for - * additional capabilities introduced in V1.3 - */ - private static final long[][] sChipFeatureCapabilityTranslation13 = { - {WifiManager.WIFI_FEATURE_LOW_LATENCY, - android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE - }, - {WifiManager.WIFI_FEATURE_P2P_RAND_MAC, - android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.P2P_RAND_MAC - } - - }; - - /** - * Feature bit mask translation for Chip V1.1 - * - * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - @VisibleForTesting - int wifiFeatureMaskFromChipCapabilities(int capabilities) { - int features = 0; - for (int i = 0; i < sChipFeatureCapabilityTranslation.length; i++) { - if ((capabilities & sChipFeatureCapabilityTranslation[i][1]) != 0) { - features |= sChipFeatureCapabilityTranslation[i][0]; - } - } - return features; - } - - /** - * Feature bit mask translation for Chip V1.5 - * - * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - @VisibleForTesting - long wifiFeatureMaskFromChipCapabilities_1_5(int capabilities) { - // First collect features from previous versions - long 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]; - } - } - return features; - } - - /** - * Feature bit mask translation for Chip V1.3 - * - * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - @VisibleForTesting - long wifiFeatureMaskFromChipCapabilities_1_3(int capabilities) { - // First collect features from previous versions - long 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]; - } - } - return features; - } - - /** - * Translation table used by getSupportedFeatureSet for translating IWifiStaIface caps - */ - private static final long[][] sStaFeatureCapabilityTranslation = { - {WifiManager.WIFI_FEATURE_PASSPOINT, - IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT - }, - {WifiManager.WIFI_FEATURE_SCANNER, - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN, - }, - {WifiManager.WIFI_FEATURE_PNO, - IWifiStaIface.StaIfaceCapabilityMask.PNO - }, - {WifiManager.WIFI_FEATURE_TDLS, - IWifiStaIface.StaIfaceCapabilityMask.TDLS - }, - {WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL, - IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL - }, - {WifiManager.WIFI_FEATURE_LINK_LAYER_STATS, - IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - }, - {WifiManager.WIFI_FEATURE_RSSI_MONITOR, - IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR - }, - {WifiManager.WIFI_FEATURE_MKEEP_ALIVE, - IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE - }, - {WifiManager.WIFI_FEATURE_CONFIG_NDO, - IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD - }, - {WifiManager.WIFI_FEATURE_CONTROL_ROAMING, - IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING - }, - {WifiManager.WIFI_FEATURE_IE_WHITELIST, - IWifiStaIface.StaIfaceCapabilityMask.PROBE_IE_WHITELIST - }, - {WifiManager.WIFI_FEATURE_SCAN_RAND, - IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) { + mLog.err("STA iface object is NULL - Failed to enable link layer stats") + .flush(); + return; } - }; - - /** - * Feature bit mask translation for STAs - * - * @param capabilities bitmask defined IWifiStaIface.StaIfaceCapabilityMask - * @return bitmask defined by WifiManager.WIFI_FEATURE_* - */ - @VisibleForTesting - long wifiFeatureMaskFromStaCapabilities(int capabilities) { - long features = 0; - for (int i = 0; i < sStaFeatureCapabilityTranslation.length; i++) { - if ((capabilities & sStaFeatureCapabilityTranslation[i][1]) != 0) { - features |= sStaFeatureCapabilityTranslation[i][0]; + if (!iface.enableLinkLayerStatsCollection(mLinkLayerStatsDebug)) { + mLog.err("unable to enable link layer stats collection").flush(); } } - return features; } /** @@ -1831,44 +770,29 @@ public class WifiVendorHal { * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ public long getSupportedFeatureSet(@NonNull String ifaceName) { - long featureSet = 0; + long featureSet = 0L; if (!mHalDeviceManager.isStarted() || !mHalDeviceManager.isSupported()) { return getSupportedFeatureSetFromPackageManager(); } - try { - final Mutable<Long> feat = new Mutable<>(0L); - synchronized (sLock) { - android.hardware.wifi.V1_3.IWifiChip iWifiChipV13 = getWifiChipForV1_3Mockable(); - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 != null) { - iWifiChipV15.getCapabilities_1_5((status, capabilities) -> { - if (!ok(status)) return; - feat.value = wifiFeatureMaskFromChipCapabilities_1_5(capabilities); - }); - } else if (iWifiChipV13 != null) { - iWifiChipV13.getCapabilities_1_3((status, capabilities) -> { - if (!ok(status)) return; - feat.value = wifiFeatureMaskFromChipCapabilities_1_3(capabilities); - }); - } else if (mIWifiChip != null) { - mIWifiChip.getCapabilities((status, capabilities) -> { - if (!ok(status)) return; - feat.value = (long) wifiFeatureMaskFromChipCapabilities(capabilities); - }); + + synchronized (sLock) { + if (mWifiChip != null) { + WifiChip.Response<Long> 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; } + } - IWifiStaIface iface = getStaIface(ifaceName); - if (iface != null) { - iface.getCapabilities((status, capabilities) -> { - if (!ok(status)) return; - feat.value |= wifiFeatureMaskFromStaCapabilities(capabilities); - }); + WifiStaIface iface = getStaIface(ifaceName); + if (iface != null) { + featureSet |= iface.getCapabilities(); + if (mHalDeviceManager.is24g5gDbsSupported(iface) + || mHalDeviceManager.is5g6gDbsSupported(iface)) { + featureSet |= WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS; } } - featureSet = feat.value; - } catch (RemoteException e) { - handleRemoteException(e); - return 0; } if (mWifiGlobals.isWpa3SaeH2eSupported()) { @@ -1876,16 +800,16 @@ public class WifiVendorHal { } Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes(); - if (supportedIfaceTypes.contains(IfaceType.STA)) { + if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_STA)) { featureSet |= WifiManager.WIFI_FEATURE_INFRA; } - if (supportedIfaceTypes.contains(IfaceType.AP)) { + if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_AP)) { featureSet |= WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT; } - if (supportedIfaceTypes.contains(IfaceType.P2P)) { + if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_P2P)) { featureSet |= WifiManager.WIFI_FEATURE_P2P; } - if (supportedIfaceTypes.contains(IfaceType.NAN)) { + if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_NAN)) { featureSet |= WifiManager.WIFI_FEATURE_AWARE; } @@ -1900,17 +824,10 @@ public class WifiVendorHal { * @return true for success */ public boolean setStaMacAddress(@NonNull String ifaceName, @NonNull MacAddress mac) { - byte[] macByteArray = mac.toByteArray(); synchronized (sLock) { - try { - android.hardware.wifi.V1_2.IWifiStaIface sta12 = - getWifiStaIfaceForV1_2Mockable(ifaceName); - if (sta12 == null) return boolResult(false); - return ok(sta12.setMacAddress(macByteArray)); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + return iface.setMacAddress(mac); } } @@ -1922,18 +839,9 @@ public class WifiVendorHal { */ public boolean resetApMacToFactoryMacAddress(@NonNull String ifaceName) { synchronized (sLock) { - try { - android.hardware.wifi.V1_5.IWifiApIface ap15 = - getWifiApIfaceForV1_5Mockable(ifaceName); - if (ap15 == null) { - MacAddress mac = getApFactoryMacAddress(ifaceName); - return mac != null && setApMacAddress(ifaceName, mac); - } - return ok(ap15.resetToFactoryMacAddress()); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return false; + return iface.resetToFactoryMacAddress(); } } @@ -1945,30 +853,10 @@ public class WifiVendorHal { * @return true for success */ public boolean setApMacAddress(@NonNull String ifaceName, @NonNull MacAddress mac) { - byte[] macByteArray = mac.toByteArray(); - synchronized (sLock) { - try { - android.hardware.wifi.V1_4.IWifiApIface ap14 = - getWifiApIfaceForV1_4Mockable(ifaceName); - if (ap14 == null) return boolResult(false); - return ok(ap14.setMacAddress(macByteArray)); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Returns true if Hal version supports setMacAddress, otherwise false. - * - * @param ifaceName Name of the interface - */ - public boolean isStaSetMacAddressSupported(@NonNull String ifaceName) { synchronized (sLock) { - android.hardware.wifi.V1_2.IWifiStaIface sta12 = - getWifiStaIfaceForV1_2Mockable(ifaceName); - return sta12 != null; + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return false; + return iface.setMacAddress(mac); } } @@ -1979,9 +867,9 @@ public class WifiVendorHal { */ public boolean isApSetMacAddressSupported(@NonNull String ifaceName) { synchronized (sLock) { - android.hardware.wifi.V1_4.IWifiApIface ap14 = - getWifiApIfaceForV1_4Mockable(ifaceName); - return ap14 != null; + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return false; + return iface.isSetMacAddressSupported(); } } @@ -1992,25 +880,10 @@ public class WifiVendorHal { * @return factory MAC address of the interface or null. */ public MacAddress getStaFactoryMacAddress(@NonNull String ifaceName) { - class AnswerBox { - public MacAddress mac = null; - } synchronized (sLock) { - try { - AnswerBox box = new AnswerBox(); - - android.hardware.wifi.V1_3.IWifiStaIface sta13 = - getWifiStaIfaceForV1_3Mockable(ifaceName); - if (sta13 == null) return null; - sta13.getFactoryMacAddress((status, macBytes) -> { - if (!ok(status)) return; - box.mac = MacAddress.fromBytes(macBytes); - }); - return box.mac; - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return null; + return iface.getFactoryMacAddress(); } } @@ -2021,24 +894,10 @@ public class WifiVendorHal { * @return factory MAC address of the interface or null. */ public MacAddress getApFactoryMacAddress(@NonNull String ifaceName) { - class AnswerBox { - public MacAddress mac = null; - } synchronized (sLock) { - try { - AnswerBox box = new AnswerBox(); - android.hardware.wifi.V1_4.IWifiApIface ap14 = - getWifiApIfaceForV1_4Mockable(ifaceName); - if (ap14 == null) return null; - ap14.getFactoryMacAddress((status, macBytes) -> { - if (!ok(status)) return; - box.mac = MacAddress.fromBytes(macBytes); - }); - return box.mac; - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return null; + return iface.getFactoryMacAddress(); } } @@ -2049,26 +908,10 @@ public class WifiVendorHal { * @return APF capabilities object. */ public ApfCapabilities getApfCapabilities(@NonNull String ifaceName) { - class AnswerBox { - public ApfCapabilities value = sNoApfCapabilities; - } synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return sNoApfCapabilities; - AnswerBox box = new AnswerBox(); - iface.getApfPacketFilterCapabilities((status, capabilities) -> { - if (!ok(status)) return; - box.value = new ApfCapabilities( - /* apfVersionSupported */ capabilities.version, - /* maximumApfProgramSize */ capabilities.maxLength, - /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); - }); - return box.value; - } catch (RemoteException e) { - handleRemoteException(e); - return sNoApfCapabilities; - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return sNoApfCapabilities; + return iface.getApfPacketFilterCapabilities(); } } @@ -2082,22 +925,12 @@ public class WifiVendorHal { * @return true for success */ public boolean installPacketFilter(@NonNull String ifaceName, byte[] filter) { - int cmdId = 0; // We only aspire to support one program at a time - if (filter == null) return boolResult(false); - // Copy the program before taking the lock. - ArrayList<Byte> program = NativeUtil.byteArrayToArrayList(filter); + if (filter == null) return false; enter("filter length %").c(filter.length).flush(); synchronized (sLock) { - try { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - WifiStatus status = iface.installApfPacketFilter(cmdId, program); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + return iface.installApfPacketFilter(filter); } } @@ -2108,26 +941,12 @@ public class WifiVendorHal { * @return the buffer returned by the driver, or null in case of an error */ public byte[] readPacketFilter(@NonNull String ifaceName) { - class AnswerBox { - public byte[] data = null; - } - AnswerBox answer = new AnswerBox(); enter("").flush(); // TODO: Must also take the wakelock here to prevent going to sleep with APF disabled. synchronized (sLock) { - try { - android.hardware.wifi.V1_2.IWifiStaIface ifaceV12 = - getWifiStaIfaceForV1_2Mockable(ifaceName); - if (ifaceV12 == null) return byteArrayResult(null); - ifaceV12.readApfPacketFilterData((status, dataByteArray) -> { - if (!ok(status)) return; - answer.data = NativeUtil.byteArrayFromArrayList(dataByteArray); - }); - return byteArrayResult(answer.data); - } catch (RemoteException e) { - handleRemoteException(e); - return byteArrayResult(null); - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return null; + return iface.readApfPacketFilterData(); } } @@ -2138,25 +957,9 @@ public class WifiVendorHal { * @return true for success */ public boolean setChipCountryCode(String countryCode) { - if (countryCode == null) return boolResult(false); - if (countryCode.length() != 2) return boolResult(false); - byte[] code; - try { - code = NativeUtil.stringToByteArray(countryCode); - } catch (IllegalArgumentException e) { - return boolResult(false); - } synchronized (sLock) { - try { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 == null) return boolResult(false); - WifiStatus status = iWifiChipV15.setCountryCode(code); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + if (mWifiChip == null) return false; + return mWifiChip.setCountryCode(countryCode); } } @@ -2169,20 +972,9 @@ public class WifiVendorHal { @Nullable public List<String> getBridgedApInstances(@NonNull String ifaceName) { synchronized (sLock) { - try { - Mutable<List<String>> instancesResp = new Mutable<>(); - android.hardware.wifi.V1_5.IWifiApIface ap15 = - getWifiApIfaceForV1_5Mockable(ifaceName); - if (ap15 == null) return null; - ap15.getBridgedInstances((status, instances) -> { - if (!ok(status)) return; - instancesResp.value = new ArrayList<>(instances); - }); - return instancesResp.value; - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return null; + return iface.getBridgedInstances(); } } @@ -2194,25 +986,10 @@ public class WifiVendorHal { * @return true for success */ public boolean setApCountryCode(@NonNull String ifaceName, String countryCode) { - if (countryCode == null) return boolResult(false); - if (countryCode.length() != 2) return boolResult(false); - byte[] code; - try { - code = NativeUtil.stringToByteArray(countryCode); - } catch (IllegalArgumentException e) { - return boolResult(false); - } synchronized (sLock) { - try { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return boolResult(false); - WifiStatus status = iface.setCountryCode(code); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + WifiApIface iface = getApIface(ifaceName); + if (iface == null) return false; + return iface.setCountryCode(countryCode); } } @@ -2223,19 +1000,15 @@ public class WifiVendorHal { * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. */ public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) { - if (handler == null) return boolResult(false); + if (handler == null) return false; synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - if (mLogEventHandler != null) return boolResult(false); - try { - WifiStatus status = mIWifiChip.enableDebugErrorAlerts(true); - if (!ok(status)) return false; - mLogEventHandler = handler; - return true; - } catch (RemoteException e) { - handleRemoteException(e); + if (mWifiChip == null) return false; + if (mLogEventHandler != null) return false; + if (!mWifiChip.enableDebugErrorAlerts(true)) { return false; } + mLogEventHandler = handler; + return true; } } @@ -2247,17 +1020,11 @@ public class WifiVendorHal { public boolean resetLogHandler() { synchronized (sLock) { mLogEventHandler = null; - if (mIWifiChip == null) return boolResult(false); - try { - WifiStatus status = mIWifiChip.enableDebugErrorAlerts(false); - if (!ok(status)) return false; - status = mIWifiChip.stopLoggingToDebugRingBuffer(); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); + if (mWifiChip == null) return false; + if (!mWifiChip.enableDebugErrorAlerts(false)) { return false; } + return mWifiChip.stopLoggingToDebugRingBuffer(); } } @@ -2277,20 +1044,13 @@ public class WifiVendorHal { .c(verboseLevel).c(flags).c(maxIntervalInSec).c(minDataSizeInBytes).c(ringName) .flush(); synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - try { - // note - flags are not used - WifiStatus status = mIWifiChip.startLoggingToDebugRingBuffer( - ringName, - verboseLevel, - maxIntervalInSec, - minDataSizeInBytes - ); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + if (mWifiChip == null) return false; + return mWifiChip.startLoggingToDebugRingBuffer( + ringName, + verboseLevel, + maxIntervalInSec, + minDataSizeInBytes + ); } } @@ -2333,16 +1093,12 @@ public class WifiVendorHal { private void requestChipDebugInfo() { mDriverDescription = null; mFirmwareDescription = null; - try { - if (mIWifiChip == null) return; - mIWifiChip.requestChipDebugInfo((status, chipDebugInfo) -> { - if (!ok(status)) return; - mDriverDescription = chipDebugInfo.driverDescription; - mFirmwareDescription = chipDebugInfo.firmwareDescription; - }); - } catch (RemoteException e) { - handleRemoteException(e); - return; + synchronized (sLock) { + if (mWifiChip == null) return; + WifiChip.ChipDebugInfo info = mWifiChip.requestChipDebugInfo(); + if (info == null) return; + mDriverDescription = info.driverDescription; + mFirmwareDescription = info.firmwareDescription; } mLog.info("Driver: % Firmware: %") .c(mDriverDescription) @@ -2351,77 +1107,19 @@ public class WifiVendorHal { } /** - * Creates RingBufferStatus from the Hal version - */ - private static WifiNative.RingBufferStatus ringBufferStatus(WifiDebugRingBufferStatus h) { - WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus(); - ans.name = h.ringName; - ans.flag = frameworkRingBufferFlagsFromHal(h.flags); - ans.ringBufferId = h.ringId; - ans.ringBufferByteSize = h.sizeInBytes; - ans.verboseLevel = h.verboseLevel; - // Remaining fields are unavailable - // writtenBytes; - // readBytes; - // writtenRecords; - return ans; - } - - /** - * Translates a hal wifiDebugRingBufferFlag to the WifiNative version - */ - private static int frameworkRingBufferFlagsFromHal(int wifiDebugRingBufferFlag) { - BitMask checkoff = new BitMask(wifiDebugRingBufferFlag); - int flags = 0; - if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) { - flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES; - } - if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) { - flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES; - } - if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) { - flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES; - } - if (checkoff.value != 0) { - throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value); - } - return flags; - } - - /** - * Creates array of RingBufferStatus from the Hal version - */ - private static WifiNative.RingBufferStatus[] makeRingBufferStatusArray( - ArrayList<WifiDebugRingBufferStatus> ringBuffers) { - WifiNative.RingBufferStatus[] ans = new WifiNative.RingBufferStatus[ringBuffers.size()]; - int i = 0; - for (WifiDebugRingBufferStatus b : ringBuffers) { - ans[i++] = ringBufferStatus(b); - } - return ans; - } - - /** * API to get the status of all ring buffers supported by driver */ public WifiNative.RingBufferStatus[] getRingBufferStatus() { - class AnswerBox { - public WifiNative.RingBufferStatus[] value = null; - } - AnswerBox ans = new AnswerBox(); synchronized (sLock) { - if (mIWifiChip == null) return null; - try { - mIWifiChip.getDebugRingBuffersStatus((status, ringBuffers) -> { - if (!ok(status)) return; - ans.value = makeRingBufferStatusArray(ringBuffers); - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + if (mWifiChip == null) return null; + List<WifiNative.RingBufferStatus> statusList = mWifiChip.getDebugRingBuffersStatus(); + if (statusList == null) return null; + + WifiNative.RingBufferStatus[] statusArray = + new WifiNative.RingBufferStatus[statusList.size()]; + statusList.toArray(statusArray); + return statusArray; } - return ans.value; } /** @@ -2430,14 +1128,8 @@ public class WifiVendorHal { public boolean getRingBufferData(String ringName) { enter("ringName %").c(ringName).flush(); synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - try { - WifiStatus status = mIWifiChip.forceDumpToDebugRingBuffer(ringName); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + if (mWifiChip == null) return false; + return mWifiChip.forceDumpToDebugRingBuffer(ringName); } } @@ -2446,18 +1138,8 @@ public class WifiVendorHal { */ public boolean flushRingBufferData() { synchronized (sLock) { - if (mIWifiChip == null) return boolResult(false); - android.hardware.wifi.V1_3.IWifiChip iWifiChipV13 = getWifiChipForV1_3Mockable(); - if (iWifiChipV13 != null) { - try { - WifiStatus status = iWifiChipV13.flushRingBufferToFile(); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - return false; + if (mWifiChip == null) return false; + return mWifiChip.flushRingBufferToFile(); } } @@ -2465,46 +1147,20 @@ public class WifiVendorHal { * Request vendor debug info from the firmware */ public byte[] getFwMemoryDump() { - class AnswerBox { - public byte[] value; - } - AnswerBox ans = new AnswerBox(); synchronized (sLock) { - if (mIWifiChip == null) return (null); - try { - mIWifiChip.requestFirmwareDebugDump((status, blob) -> { - if (!ok(status)) return; - ans.value = NativeUtil.byteArrayFromArrayList(blob); - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + if (mWifiChip == null) return null; + return mWifiChip.requestFirmwareDebugDump(); } - return ans.value; } /** * Request vendor debug info from the driver */ public byte[] getDriverStateDump() { - class AnswerBox { - public byte[] value; - } - AnswerBox ans = new AnswerBox(); synchronized (sLock) { - if (mIWifiChip == null) return (null); - try { - mIWifiChip.requestDriverDebugDump((status, blob) -> { - if (!ok(status)) return; - ans.value = NativeUtil.byteArrayFromArrayList(blob); - }); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + if (mWifiChip == null) return (null); + return mWifiChip.requestDriverDebugDump(); } - return ans.value; } /** @@ -2517,84 +1173,9 @@ public class WifiVendorHal { */ public boolean startPktFateMonitoring(@NonNull String ifaceName) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - WifiStatus status = iface.startDebugPacketFateMonitoring(); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - private byte halToFrameworkPktFateFrameType(int type) { - switch (type) { - case WifiDebugPacketFateFrameType.UNKNOWN: - return WifiLoggerHal.FRAME_TYPE_UNKNOWN; - case WifiDebugPacketFateFrameType.ETHERNET_II: - return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; - case WifiDebugPacketFateFrameType.MGMT_80211: - return WifiLoggerHal.FRAME_TYPE_80211_MGMT; - default: - throw new IllegalArgumentException("bad " + type); - } - } - - private byte halToFrameworkRxPktFate(int type) { - switch (type) { - case WifiDebugRxPacketFate.SUCCESS: - return WifiLoggerHal.RX_PKT_FATE_SUCCESS; - case WifiDebugRxPacketFate.FW_QUEUED: - return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; - case WifiDebugRxPacketFate.FW_DROP_FILTER: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; - case WifiDebugRxPacketFate.FW_DROP_INVALID: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; - case WifiDebugRxPacketFate.FW_DROP_NOBUFS: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; - case WifiDebugRxPacketFate.FW_DROP_OTHER: - return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; - case WifiDebugRxPacketFate.DRV_QUEUED: - return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; - case WifiDebugRxPacketFate.DRV_DROP_FILTER: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; - case WifiDebugRxPacketFate.DRV_DROP_INVALID: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; - case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; - case WifiDebugRxPacketFate.DRV_DROP_OTHER: - return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; - default: - throw new IllegalArgumentException("bad " + type); - } - } - - private byte halToFrameworkTxPktFate(int type) { - switch (type) { - case WifiDebugTxPacketFate.ACKED: - return WifiLoggerHal.TX_PKT_FATE_ACKED; - case WifiDebugTxPacketFate.SENT: - return WifiLoggerHal.TX_PKT_FATE_SENT; - case WifiDebugTxPacketFate.FW_QUEUED: - return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; - case WifiDebugTxPacketFate.FW_DROP_INVALID: - return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; - case WifiDebugTxPacketFate.FW_DROP_NOBUFS: - return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; - case WifiDebugTxPacketFate.FW_DROP_OTHER: - return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; - case WifiDebugTxPacketFate.DRV_QUEUED: - return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; - case WifiDebugTxPacketFate.DRV_DROP_INVALID: - return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; - case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: - return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; - case WifiDebugTxPacketFate.DRV_DROP_OTHER: - return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; - default: - throw new IllegalArgumentException("bad " + type); + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + return iface.startDebugPacketFateMonitoring(); } } @@ -2609,27 +1190,9 @@ public class WifiVendorHal { */ public List<TxFateReport> getTxPktFates(@NonNull String ifaceName) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return objResult(new ArrayList<>()); - try { - List<TxFateReport> reportBufs = new ArrayList<>(); - iface.getDebugTxPacketFates((status, fates) -> { - if (!ok(status)) return; - for (WifiDebugTxPacketFateReport fate : fates) { - if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; - byte code = halToFrameworkTxPktFate(fate.fate); - long us = fate.frameInfo.driverTimestampUsec; - byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType); - byte[] frame = NativeUtil.byteArrayFromArrayList( - fate.frameInfo.frameContent); - reportBufs.add(new TxFateReport(code, us, type, frame)); - } - }); - return reportBufs; - } catch (RemoteException e) { - handleRemoteException(e); - return new ArrayList<>(); - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return new ArrayList<>(); + return iface.getDebugTxPacketFates(); } } @@ -2644,27 +1207,9 @@ public class WifiVendorHal { */ public List<RxFateReport> getRxPktFates(@NonNull String ifaceName) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return objResult(new ArrayList<>()); - try { - List<RxFateReport> reportBufs = new ArrayList<>(); - iface.getDebugRxPacketFates((status, fates) -> { - if (!ok(status)) return; - for (WifiDebugRxPacketFateReport fate : fates) { - if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; - byte code = halToFrameworkRxPktFate(fate.fate); - long us = fate.frameInfo.driverTimestampUsec; - byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType); - byte[] frame = NativeUtil.byteArrayFromArrayList( - fate.frameInfo.frameContent); - reportBufs.add(new RxFateReport(code, us, type, frame)); - } - }); - return reportBufs; - } catch (RemoteException e) { - handleRemoteException(e); - return new ArrayList<>(); - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return new ArrayList<>(); + return iface.getDebugRxPacketFates(); } } @@ -2672,38 +1217,37 @@ public class WifiVendorHal { * Start sending the specified keep alive packets periodically. * * @param ifaceName Name of the interface. - * @param slot - * @param srcMac - * @param dstMac - * @param keepAlivePacket - * @param protocol - * @param periodInMs + * @param slot Command ID to use for this invocation. + * @param srcAddr Source MAC address of the packet. + * @param dstAddr Destination MAC address of the packet. + * @param packet IP packet contents to be transmitted. + * @param protocol Ether type to be set in the ethernet frame transmitted. + * @param periodInMs Interval at which this packet must be transmitted. * @return 0 for success, -1 for error */ public int startSendingOffloadedPacket( - @NonNull String ifaceName, int slot, byte[] srcMac, byte[] dstMac, + @NonNull String ifaceName, int slot, byte[] srcAddr, byte[] dstAddr, byte[] packet, int protocol, int periodInMs) { enter("slot=% periodInMs=%").c(slot).c(periodInMs).flush(); - - ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(packet); - synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return -1; + MacAddress srcMac, dstMac; try { - WifiStatus status = iface.startSendingKeepAlivePackets( + srcMac = MacAddress.fromBytes(srcAddr); + dstMac = MacAddress.fromBytes(dstAddr); + } catch (IllegalArgumentException e) { + mLog.info("Invalid MacAddress in startSendingOffloadedPacket").flush(); + return -1; + } + boolean success = iface.startSendingKeepAlivePackets( slot, - data, + packet, (short) protocol, srcMac, dstMac, periodInMs); - if (!ok(status)) return -1; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } + return success ? 0 : -1; } } @@ -2718,16 +1262,10 @@ public class WifiVendorHal { enter("slot=%").c(slot).flush(); synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return -1; - try { - WifiStatus status = iface.stopSendingKeepAlivePackets(slot); - if (!ok(status)) return -1; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } + boolean success = iface.stopSendingKeepAlivePackets(slot); + return success ? 0 : -1; } } @@ -2757,19 +1295,12 @@ public class WifiVendorHal { if (maxRssi <= minRssi) return -1; if (rssiEventHandler == null) return -1; synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return -1; - try { - iface.stopRssiMonitoring(sRssiMonCmdId); - WifiStatus status; - status = iface.startRssiMonitoring(sRssiMonCmdId, maxRssi, minRssi); - if (!ok(status)) return -1; - mWifiRssiEventHandler = rssiEventHandler; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } + iface.stopRssiMonitoring(sRssiMonCmdId); + if (!iface.startRssiMonitoring(sRssiMonCmdId, maxRssi, minRssi)) return -1; + mWifiRssiEventHandler = rssiEventHandler; + return 0; } } @@ -2782,80 +1313,22 @@ public class WifiVendorHal { public int stopRssiMonitoring(@NonNull String ifaceName) { synchronized (sLock) { mWifiRssiEventHandler = null; - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return -1; - try { - WifiStatus status = iface.stopRssiMonitoring(sRssiMonCmdId); - if (!ok(status)) return -1; - return 0; - } catch (RemoteException e) { - handleRemoteException(e); - return -1; - } + boolean success = iface.stopRssiMonitoring(sRssiMonCmdId); + return success ? 0 : -1; } } - //TODO - belongs in NativeUtil - private static int[] intsFromArrayList(ArrayList<Integer> a) { - if (a == null) return null; - int[] b = new int[a.size()]; - int i = 0; - for (Integer e : a) b[i++] = e; - return b; - } - - /** - * Translates from Hal version of wake reason stats to the framework version of same - * - * @param h - Hal version of wake reason stats - * @return framework version of same - */ - private static WlanWakeReasonAndCounts halToFrameworkWakeReasons( - WifiDebugHostWakeReasonStats h) { - if (h == null) return null; - WlanWakeReasonAndCounts ans = new WlanWakeReasonAndCounts(); - ans.totalCmdEventWake = h.totalCmdEventWakeCnt; - ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt; - ans.totalRxDataWake = h.totalRxPacketWakeCnt; - ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt; - ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt; - ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt; - ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt; - ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt; - ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra; - ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na; - ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns; - ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt; - ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt; - ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt; - ans.cmdEventWakeCntArray = intsFromArrayList(h.cmdEventWakeCntPerType); - ans.driverFWLocalWakeCntArray = intsFromArrayList(h.driverFwLocalWakeCntPerType); - return ans; - } - /** * Fetch the host wakeup reasons stats from wlan driver. * * @return the |WlanWakeReasonAndCounts| from the wlan driver, or null on failure. */ public WlanWakeReasonAndCounts getWlanWakeReasonCount() { - class AnswerBox { - public WifiDebugHostWakeReasonStats value = null; - } - AnswerBox ans = new AnswerBox(); synchronized (sLock) { - if (mIWifiChip == null) return null; - try { - mIWifiChip.getDebugHostWakeReasonStats((status, stats) -> { - if (ok(status)) { - ans.value = stats; - } - }); - return halToFrameworkWakeReasons(ans.value); - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + if (mWifiChip == null) return null; + return mWifiChip.getDebugHostWakeReasonStats(); } } @@ -2869,17 +1342,10 @@ public class WifiVendorHal { public boolean configureNeighborDiscoveryOffload(@NonNull String ifaceName, boolean enabled) { enter("enabled=%").c(enabled).flush(); synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); - try { - WifiStatus status = iface.enableNdOffload(enabled); - if (!ok(status)) return false; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + return iface.enableNdOffload(enabled); } - return true; } // Firmware roaming control. @@ -2893,26 +1359,9 @@ public class WifiVendorHal { @Nullable public WifiNative.RoamingCapabilities getRoamingCapabilities(@NonNull String ifaceName) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return nullResult(); - try { - Mutable<Boolean> ok = new Mutable<>(false); - WifiNative.RoamingCapabilities out = new WifiNative.RoamingCapabilities(); - iface.getRoamingCapabilities((status, cap) -> { - if (!ok(status)) return; - out.maxBlocklistSize = cap.maxBlacklistSize; - out.maxAllowlistSize = cap.maxWhitelistSize; - ok.value = true; - }); - if (ok.value) { - return out; - } else { - return null; - } - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return null; + return iface.getRoamingCapabilities(); } } @@ -2927,33 +1376,9 @@ public class WifiVendorHal { public @WifiNative.RoamingEnableStatus int enableFirmwareRoaming(@NonNull String ifaceName, @WifiNative.RoamingEnableState int state) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); + WifiStaIface iface = getStaIface(ifaceName); if (iface == null) return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - try { - byte val; - switch (state) { - case WifiNative.DISABLE_FIRMWARE_ROAMING: - val = StaRoamingState.DISABLED; - break; - case WifiNative.ENABLE_FIRMWARE_ROAMING: - val = StaRoamingState.ENABLED; - break; - default: - mLog.err("enableFirmwareRoaming invalid argument %").c(state).flush(); - return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - } - WifiStatus status = iface.setRoamingState(val); - if (ok(status)) { - return WifiNative.SET_FIRMWARE_ROAMING_SUCCESS; - } else if (status.code == WifiStatusCode.ERROR_BUSY) { - return WifiNative.SET_FIRMWARE_ROAMING_BUSY; - } else { - return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - } - } catch (RemoteException e) { - handleRemoteException(e); - return WifiNative.SET_FIRMWARE_ROAMING_FAILURE; - } + return iface.setRoamingState(state); } } @@ -2966,20 +1391,19 @@ public class WifiVendorHal { */ public boolean configureRoaming(@NonNull String ifaceName, WifiNative.RoamingConfig config) { synchronized (sLock) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return boolResult(false); + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; try { - StaRoamingConfig roamingConfig = new StaRoamingConfig(); - - // parse the blacklist BSSIDs if any + // parse the blocklist BSSIDs if any + List<MacAddress> bssidBlocklist = new ArrayList<>(); if (config.blocklistBssids != null) { for (String bssid : config.blocklistBssids) { - byte[] mac = NativeUtil.macAddressToByteArray(bssid); - roamingConfig.bssidBlacklist.add(mac); + bssidBlocklist.add(MacAddress.fromString(bssid)); } } - // parse the whitelist SSIDs if any + // parse the allowlist SSIDs if any + List<byte[]> ssidAllowlist = new ArrayList<>(); if (config.allowlistSsids != null) { for (String ssidStr : config.allowlistSsids) { for (WifiSsid originalSsid : mSsidTranslator.getAllPossibleOriginalSsids( @@ -2988,240 +1412,17 @@ public class WifiVendorHal { // SSIDs with less than 32 byte length this is due to HAL definition of // SSID declared it as 32-byte fixed length array. Thus pad additional // bytes with 0's to pass SSIDs as byte arrays of 32 length - roamingConfig.ssidWhitelist.add( + ssidAllowlist.add( Arrays.copyOf(originalSsid.getBytes(), 32)); } } } - WifiStatus status = iface.configureRoaming(roamingConfig); - if (!ok(status)) return false; - } catch (RemoteException e) { - handleRemoteException(e); - return false; + return iface.configureRoaming(bssidBlocklist, ssidAllowlist); } catch (IllegalArgumentException e) { mLog.err("Illegal argument for roaming configuration").c(e.toString()).flush(); return false; } - return true; - } - } - - /** - * Method to mock out the V1_1 IWifiChip retrieval in unit tests. - * - * @return 1.1 IWifiChip object if the device is running the 1.1 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_1.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_2 IWifiChip retrieval in unit tests. - * - * @return 1.2 IWifiChip object if the device is running the 1.2 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_2.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_3 IWifiChip retrieval in unit tests. - * - * @return 1.3 IWifiChip object if the device is running the 1.3 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_3.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_4 IWifiChip retrieval in unit tests. - * - * @return 1.4 IWifiChip object if the device is running the 1.4 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_4.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_5 IWifiChip retrieval in unit tests. - * - * @return 1.5 IWifiChip object if the device is running the 1.5 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_5.IWifiChip getWifiChipForV1_5Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_5.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_6 IWifiChip retrieval in unit tests. - * - * @return 1.6 IWifiChip object if the device is running the 1.6 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_6.IWifiChip getWifiChipForV1_6Mockable() { - if (mIWifiChip == null) return null; - return android.hardware.wifi.V1_6.IWifiChip.castFrom(mIWifiChip); - } - - /** - * Method to mock out the V1_2 IWifiStaIface retrieval in unit tests. - * - * @param ifaceName Name of the interface - * @return 1.2 IWifiStaIface object if the device is running the 1.2 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - @NonNull String ifaceName) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_2.IWifiStaIface.castFrom(iface); - } - - /** - * Method to mock out the V1_3 IWifiStaIface retrieval in unit tests. - * - * @param ifaceName Name of the interface - * @return 1.3 IWifiStaIface object if the device is running the 1.3 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - @NonNull String ifaceName) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_3.IWifiStaIface.castFrom(iface); - } - - /** - * Method to mock out the V1_5 IWifiStaIface retrieval in unit tests. - * - * @param ifaceName Name of the interface - * @return 1.5 IWifiStaIface object if the device is running the 1.5 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_5.IWifiStaIface getWifiStaIfaceForV1_5Mockable( - @NonNull String ifaceName) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_5.IWifiStaIface.castFrom(iface); - } - - /** - * Method to mock out the V1_6 IWifiStaIface retrieval in unit tests. - * - * @param ifaceName Name of the interface - * @return 1.6 IWifiStaIface object if the device is running the 1.6 wifi hal service, null - * otherwise. - */ - protected android.hardware.wifi.V1_6.IWifiStaIface getWifiStaIfaceForV1_6Mockable( - @NonNull String ifaceName) { - IWifiStaIface iface = getStaIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_6.IWifiStaIface.castFrom(iface); - } - - protected android.hardware.wifi.V1_4.IWifiApIface getWifiApIfaceForV1_4Mockable( - String ifaceName) { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_4.IWifiApIface.castFrom(iface); - } - - protected android.hardware.wifi.V1_5.IWifiApIface getWifiApIfaceForV1_5Mockable( - String ifaceName) { - IWifiApIface iface = getApIface(ifaceName); - if (iface == null) return null; - return android.hardware.wifi.V1_5.IWifiApIface.castFrom(iface); - } - - /** - * sarPowerBackoffRequired_1_1() - * This method checks if we need to backoff wifi Tx power due to SAR requirements. - * It handles the case when the device is running the V1_1 version of WifiChip HAL - * In that HAL version, it is required to perform wifi Tx power backoff only if - * a voice call is ongoing. - */ - private boolean sarPowerBackoffRequired_1_1(SarInfo sarInfo) { - /* As long as no voice call is active (in case voice call is supported), - * no backoff is needed */ - if (sarInfo.sarVoiceCallSupported) { - return (sarInfo.isVoiceCall || sarInfo.isEarPieceActive); - } else { - return false; - } - } - - /** - * frameworkToHalTxPowerScenario_1_1() - * This method maps the information inside the SarInfo instance into a SAR scenario - * when device is running the V1_1 version of WifiChip HAL. - * In this HAL version, only one scenario is defined which is for VOICE_CALL (if voice call is - * supported). - * Otherwise, an exception is thrown. - */ - private int frameworkToHalTxPowerScenario_1_1(SarInfo sarInfo) { - if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) { - return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL; - } else { - throw new IllegalArgumentException("bad scenario: voice call not active/supported"); - } - } - - /** - * sarPowerBackoffRequired_1_2() - * This method checks if we need to backoff wifi Tx power due to SAR requirements. - * It handles the case when the device is running the V1_2 version of WifiChip HAL - */ - private boolean sarPowerBackoffRequired_1_2(SarInfo sarInfo) { - if (sarInfo.sarSapSupported && sarInfo.isWifiSapEnabled) { - return true; - } - if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) { - return true; - } - return false; - } - - /** - * frameworkToHalTxPowerScenario_1_2() - * This method maps the information inside the SarInfo instance into a SAR scenario - * when device is running the V1_2 version of WifiChip HAL. - * If SAR SoftAP input is supported, - * we make these assumptions: - * - All voice calls are treated as if device is near the head. - * - SoftAP scenario is treated as if device is near the body. - * In case SoftAP is not supported, then we should revert to the V1_1 HAL - * behavior, and the only valid scenario would be when a voice call is ongoing. - */ - private int frameworkToHalTxPowerScenario_1_2(SarInfo sarInfo) { - if (sarInfo.sarSapSupported && sarInfo.sarVoiceCallSupported) { - if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { - return android.hardware.wifi.V1_2.IWifiChip - .TxPowerScenario.ON_HEAD_CELL_ON; - } else if (sarInfo.isWifiSapEnabled) { - return android.hardware.wifi.V1_2.IWifiChip - .TxPowerScenario.ON_BODY_CELL_ON; - } else { - throw new IllegalArgumentException("bad scenario: no voice call/softAP active"); - } - } else if (sarInfo.sarVoiceCallSupported) { - /* SAR SoftAP input not supported, act like V1_1 */ - if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { - return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL; - } else { - throw new IllegalArgumentException("bad scenario: voice call not active"); - } - } else { - throw new IllegalArgumentException("Invalid case: voice call not supported"); } } @@ -3241,116 +1442,8 @@ public class WifiVendorHal { */ public boolean selectTxPowerScenario(SarInfo sarInfo) { synchronized (sLock) { - // First attempt to get a V_1_2 instance of the Wifi HAL. - android.hardware.wifi.V1_2.IWifiChip iWifiChipV12 = getWifiChipForV1_2Mockable(); - if (iWifiChipV12 != null) { - return selectTxPowerScenario_1_2(iWifiChipV12, sarInfo); - } - - // Now attempt to get a V_1_1 instance of the Wifi HAL. - android.hardware.wifi.V1_1.IWifiChip iWifiChipV11 = getWifiChipForV1_1Mockable(); - if (iWifiChipV11 != null) { - return selectTxPowerScenario_1_1(iWifiChipV11, sarInfo); - } - - // HAL version does not support SAR - return false; - } - } - - private boolean selectTxPowerScenario_1_1( - android.hardware.wifi.V1_1.IWifiChip iWifiChip, SarInfo sarInfo) { - WifiStatus status; - try { - if (sarPowerBackoffRequired_1_1(sarInfo)) { - // Power backoff is needed, so calculate the required scenario, - // and attempt to set it. - int halScenario = frameworkToHalTxPowerScenario_1_1(sarInfo); - if (sarInfo.setSarScenarioNeeded(halScenario)) { - status = iWifiChip.selectTxPowerScenario(halScenario); - if (ok(status)) { - mLog.d("Setting SAR scenario to " + halScenario); - return true; - } else { - mLog.e("Failed to set SAR scenario to " + halScenario); - return false; - } - } - - // Reaching here means setting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } - - // We don't need to perform power backoff, so attempt to reset SAR scenario. - if (sarInfo.resetSarScenarioNeeded()) { - status = iWifiChip.resetTxPowerScenario(); - if (ok(status)) { - mLog.d("Resetting SAR scenario"); - return true; - } else { - mLog.e("Failed to reset SAR scenario"); - return false; - } - } - - // Resetting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } catch (IllegalArgumentException e) { - mLog.err("Illegal argument for selectTxPowerScenario_1_1()").c(e.toString()).flush(); - return false; - } - } - - private boolean selectTxPowerScenario_1_2( - android.hardware.wifi.V1_2.IWifiChip iWifiChip, SarInfo sarInfo) { - WifiStatus status; - try { - if (sarPowerBackoffRequired_1_2(sarInfo)) { - // Power backoff is needed, so calculate the required scenario, - // and attempt to set it. - int halScenario = frameworkToHalTxPowerScenario_1_2(sarInfo); - if (sarInfo.setSarScenarioNeeded(halScenario)) { - status = iWifiChip.selectTxPowerScenario_1_2(halScenario); - if (ok(status)) { - mLog.d("Setting SAR scenario to " + halScenario); - return true; - } else { - mLog.e("Failed to set SAR scenario to " + halScenario); - return false; - } - } - - // Reaching here means setting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } - - // We don't need to perform power backoff, so attempt to reset SAR scenario. - if (sarInfo.resetSarScenarioNeeded()) { - status = iWifiChip.resetTxPowerScenario(); - if (ok(status)) { - mLog.d("Resetting SAR scenario"); - return true; - } else { - mLog.e("Failed to reset SAR scenario"); - return false; - } - } - - // Resetting SAR scenario would be redundant, - // do nothing and return with success. - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } catch (IllegalArgumentException e) { - mLog.err("Illegal argument for selectTxPowerScenario_1_2()").c(e.toString()).flush(); - return false; + if (mWifiChip == null) return false; + return mWifiChip.selectTxPowerScenario(sarInfo); } } @@ -3361,32 +1454,8 @@ public class WifiVendorHal { */ public boolean setLowLatencyMode(boolean enabled) { synchronized (sLock) { - android.hardware.wifi.V1_3.IWifiChip iWifiChipV13 = getWifiChipForV1_3Mockable(); - if (iWifiChipV13 != null) { - try { - int mode; - if (enabled) { - mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.LOW; - } else { - mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.NORMAL; - } - - WifiStatus status = iWifiChipV13.setLatencyMode(mode); - if (ok(status)) { - mVerboseLog.d("Setting low-latency mode to " + enabled); - return true; - } else { - mLog.e("Failed to set low-latency mode to " + enabled); - return false; - } - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - - // HAL version does not support this api - return false; + if (mWifiChip == null) return false; + return mWifiChip.setLowLatencyMode(enabled); } } @@ -3470,30 +1539,10 @@ public class WifiVendorHal { * @return true for success */ public boolean setMultiStaPrimaryConnection(@NonNull String ifaceName) { - if (TextUtils.isEmpty(ifaceName)) return boolResult(false); + if (TextUtils.isEmpty(ifaceName)) return false; synchronized (sLock) { - try { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 == null) return boolResult(false); - WifiStatus status = iWifiChipV15.setMultiStaPrimaryConnection(ifaceName); - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - private byte frameworkMultiStaUseCaseToHidl(@WifiNative.MultiStaUseCase int useCase) - throws IllegalArgumentException { - switch (useCase) { - case WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY: - return MultiStaUseCase.DUAL_STA_TRANSIENT_PREFER_PRIMARY; - case WifiNative.DUAL_STA_NON_TRANSIENT_UNBIASED: - return MultiStaUseCase.DUAL_STA_NON_TRANSIENT_UNBIASED; - default: - throw new IllegalArgumentException("Invalid use case " + useCase); + if (mWifiChip == null) return false; + return mWifiChip.setMultiStaPrimaryConnection(ifaceName); } } @@ -3505,20 +1554,8 @@ public class WifiVendorHal { */ public boolean setMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase) { synchronized (sLock) { - try { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 == null) return boolResult(false); - WifiStatus status = iWifiChipV15.setMultiStaUseCase( - frameworkMultiStaUseCaseToHidl(useCase)); - if (!ok(status)) return false; - return true; - } catch (IllegalArgumentException e) { - mLog.e("Invalid use case " + e); - return boolResult(false); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } + if (mWifiChip == null) return false; + return mWifiChip.setMultiStaUseCase(useCase); } } @@ -3531,102 +1568,16 @@ public class WifiVendorHal { */ public boolean setScanMode(@NonNull String ifaceName, boolean enable) { synchronized (sLock) { - try { - android.hardware.wifi.V1_5.IWifiStaIface iface = - getWifiStaIfaceForV1_5Mockable(ifaceName); - if (iface != null) { - WifiStatus status = iface.setScanMode(enable); - if (!ok(status)) return false; - return true; - } - return false; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - // This creates a blob of IE elements from the array received. - // TODO: This ugly conversion can be removed if we put IE elements in ScanResult. - private static byte[] hidlIeArrayToFrameworkIeBlob(ArrayList<WifiInformationElement> ies) { - if (ies == null || ies.isEmpty()) return new byte[0]; - ArrayList<Byte> ieBlob = new ArrayList<>(); - for (WifiInformationElement ie : ies) { - ieBlob.add(ie.id); - ieBlob.addAll(ie.data); - } - return NativeUtil.byteArrayFromArrayList(ieBlob); - } - - // This is only filling up the fields of Scan Result used by Gscan clients. - private ScanResult hidlToFrameworkScanResult(StaScanResult scanResult) { - if (scanResult == null) return null; - WifiSsid originalSsid = WifiSsid.fromBytes( - NativeUtil.byteArrayFromArrayList(scanResult.ssid)); - MacAddress bssid; - try { - bssid = MacAddress.fromString(NativeUtil.macAddressFromByteArray(scanResult.bssid)); - } catch (IllegalArgumentException e) { - mLog.e("Failed to get BSSID of scan result: " + e); - return null; - } - ScanResult frameworkScanResult = new ScanResult(); - frameworkScanResult.setWifiSsid(mSsidTranslator.getTranslatedSsidAndRecordBssidCharset( - originalSsid, bssid)); - frameworkScanResult.BSSID = bssid.toString(); - frameworkScanResult.level = scanResult.rssi; - frameworkScanResult.frequency = scanResult.frequency; - frameworkScanResult.timestamp = scanResult.timeStampInUs; - return frameworkScanResult; - } - - private ScanResult[] hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults) { - if (scanResults == null || scanResults.isEmpty()) return new ScanResult[0]; - ScanResult[] frameworkScanResults = new ScanResult[scanResults.size()]; - int i = 0; - for (StaScanResult scanResult : scanResults) { - ScanResult frameworkScanResult = hidlToFrameworkScanResult(scanResult); - if (frameworkScanResult == null) { - mLog.e("hidlToFrameworkScanResults: unable to convert hidl to framework scan" - + " result!"); - continue; - } - frameworkScanResults[i++] = frameworkScanResult; + WifiStaIface iface = getStaIface(ifaceName); + if (iface == null) return false; + return iface.setScanMode(enable); } - return frameworkScanResults; - } - - /** - * This just returns whether the scan was interrupted or not. - */ - private static int hidlToFrameworkScanDataFlags(int flag) { - if (flag == StaScanDataFlagMask.INTERRUPTED) { - return 1; - } else { - return 0; - } - } - - private WifiScanner.ScanData[] hidlToFrameworkScanDatas( - int cmdId, ArrayList<StaScanData> scanDatas) { - if (scanDatas == null || scanDatas.isEmpty()) return new WifiScanner.ScanData[0]; - WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.size()]; - int i = 0; - for (StaScanData scanData : scanDatas) { - int flags = hidlToFrameworkScanDataFlags(scanData.flags); - ScanResult[] frameworkScanResults = hidlToFrameworkScanResults(scanData.results); - frameworkScanDatas[i++] = - new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned, - WifiScanner.WIFI_BAND_UNSPECIFIED, frameworkScanResults); - } - return frameworkScanDatas; } /** * Callback for events on the STA interface. */ - private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { + private class StaIfaceEventCallback implements WifiStaIface.Callback { @Override public void onBackgroundScanFailure(int cmdId) { mVerboseLog.d("onBackgroundScanFailure " + cmdId); @@ -3640,23 +1591,18 @@ public class WifiVendorHal { @Override public void onBackgroundFullScanResult( - int cmdId, int bucketsScanned, StaScanResult result) { + int cmdId, int bucketsScanned, ScanResult result) { mVerboseLog.d("onBackgroundFullScanResult " + cmdId); WifiNative.ScanEventHandler eventHandler; synchronized (sLock) { if (mScan == null || cmdId != mScan.cmdId) return; eventHandler = mScan.eventHandler; } - ScanResult frameworkScanResult = hidlToFrameworkScanResult(result); - if (frameworkScanResult == null) { - mLog.e("onBackgroundFullScanResult: unable to convert hidl to framework scan" - + " result!"); - } - eventHandler.onFullScanResult(frameworkScanResult, bucketsScanned); + eventHandler.onFullScanResult(result, bucketsScanned); } @Override - public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) { + public void onBackgroundScanResults(int cmdId, WifiScanner.ScanData[] scanDatas) { mVerboseLog.d("onBackgroundScanResults " + cmdId); WifiNative.ScanEventHandler eventHandler; // WifiScanner currently uses the results callback to fetch the scan results. @@ -3665,7 +1611,7 @@ public class WifiVendorHal { synchronized (sLock) { if (mScan == null || cmdId != mScan.cmdId) return; eventHandler = mScan.eventHandler; - mScan.latestScanResults = hidlToFrameworkScanDatas(cmdId, scanDatas); + mScan.latestScanResults = scanDatas; } eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); } @@ -3685,14 +1631,14 @@ public class WifiVendorHal { /** * Callback for events on the chip. */ - private class ChipEventCallback extends IWifiChipEventCallback.Stub { + private class ChipEventCallback implements WifiChip.Callback { @Override public void onChipReconfigured(int modeId) { mVerboseLog.d("onChipReconfigured " + modeId); } @Override - public void onChipReconfigureFailure(WifiStatus status) { + public void onChipReconfigureFailure(int status) { mVerboseLog.d("onChipReconfigureFailure " + status); } @@ -3707,9 +1653,7 @@ public class WifiVendorHal { @Override public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { - //TODO(b/35875078) Reinstate logging when execessive callbacks are fixed - // mVerboseLog.d("onDebugRingBufferDataAvailable " + status); + WifiNative.RingBufferStatus status, byte[] data) { mHalEventHandler.post(() -> { WifiNative.WifiLoggerEventHandler eventHandler; synchronized (sLock) { @@ -3732,12 +1676,11 @@ public class WifiVendorHal { // The problem here is that the two threads acquire the locks in opposite order. // If, for example, T2.2 executes between T1.2 and 1.4, then T1 and T2 // will be deadlocked. - int sizeBefore = data.size(); + int sizeBefore = data.length; boolean conversionFailure = false; try { - eventHandler.onRingBufferData( - ringBufferStatus(status), NativeUtil.byteArrayFromArrayList(data)); - int sizeAfter = data.size(); + eventHandler.onRingBufferData(status, data); + int sizeAfter = data.length; if (sizeAfter != sizeBefore) { conversionFailure = true; } @@ -3749,13 +1692,13 @@ public class WifiVendorHal { + "onDebugRingBufferDataAvailable. " + "The input ArrayList |data| is potentially corrupted. " + "Starting size=" + sizeBefore + ", " - + "final size=" + data.size()); + + "final size=" + data.length); } }); } @Override - public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { + public void onDebugErrorAlert(int errorCode, byte[] debugData) { mLog.w("onDebugErrorAlert " + errorCode); mHalEventHandler.post(() -> { WifiNative.WifiLoggerEventHandler eventHandler; @@ -3765,61 +1708,12 @@ public class WifiVendorHal { } // See comment in onDebugRingBufferDataAvailable(), for an explanation // of why this callback is invoked without |sLock| held. - eventHandler.onWifiAlert( - errorCode, NativeUtil.byteArrayFromArrayList(debugData)); + eventHandler.onWifiAlert(errorCode, debugData); }); } - } - - private boolean areSameIfaceNames(List<IfaceInfo> ifaceList1, List<IfaceInfo> ifaceList2) { - List<String> ifaceNamesList1 = ifaceList1 - .stream() - .map(i -> i.name) - .collect(Collectors.toList()); - List<String> ifaceNamesList2 = ifaceList2 - .stream() - .map(i -> i.name) - .collect(Collectors.toList()); - return ifaceNamesList1.containsAll(ifaceNamesList2); - } - - /** - * Callback for events on the 1.2 chip. - */ - private class ChipEventCallbackV12 extends - android.hardware.wifi.V1_2.IWifiChipEventCallback.Stub { - @Override - public void onChipReconfigured(int modeId) { - mIWifiChipEventCallback.onChipReconfigured(modeId); - } - - @Override - public void onChipReconfigureFailure(WifiStatus status) { - mIWifiChipEventCallback.onChipReconfigureFailure(status); - } - - public void onIfaceAdded(int type, String name) { - mIWifiChipEventCallback.onIfaceAdded(type, name); - } - - @Override - public void onIfaceRemoved(int type, String name) { - mIWifiChipEventCallback.onIfaceRemoved(type, name); - } @Override - public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { - mIWifiChipEventCallback.onDebugRingBufferDataAvailable(status, data); - } - - @Override - public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { - mIWifiChipEventCallback.onDebugErrorAlert(errorCode, debugData); - } - - @Override - public void onRadioModeChange(ArrayList<RadioModeInfo> radioModeInfoList) { + public void onRadioModeChange(List<WifiChip.RadioModeInfo> radioModeInfoList) { mVerboseLog.d("onRadioModeChange " + radioModeInfoList); WifiNative.VendorHalRadioModeChangeEventHandler handler; synchronized (sLock) { @@ -3831,8 +1725,8 @@ public class WifiVendorHal { mLog.e("Unexpected number of radio info in list " + radioModeInfoList.size()); return; } - RadioModeInfo radioModeInfo0 = radioModeInfoList.get(0); - RadioModeInfo radioModeInfo1 = + WifiChip.RadioModeInfo radioModeInfo0 = radioModeInfoList.get(0); + WifiChip.RadioModeInfo radioModeInfo1 = radioModeInfoList.size() == 2 ? radioModeInfoList.get(1) : null; // Number of ifaces on each radio should be equal. if (radioModeInfo1 != null @@ -3867,8 +1761,8 @@ public class WifiVendorHal { } // 2 ifaces time sharing on 1 radio. } else if (radioModeInfoList.size() == 1 && numIfacesOnEachRadio == 2) { - IfaceInfo ifaceInfo0 = radioModeInfo0.ifaceInfos.get(0); - IfaceInfo ifaceInfo1 = radioModeInfo0.ifaceInfos.get(1); + WifiChip.IfaceInfo ifaceInfo0 = radioModeInfo0.ifaceInfos.get(0); + WifiChip.IfaceInfo ifaceInfo1 = radioModeInfo0.ifaceInfos.get(1); if (ifaceInfo0.channel != ifaceInfo1.channel) { runnable = () -> { handler.onMcc(radioModeInfo0.bandInfo); @@ -3885,113 +1779,17 @@ public class WifiVendorHal { } } - /** - * Callback for events on the 1.4 chip. - */ - private class ChipEventCallbackV14 extends - android.hardware.wifi.V1_4.IWifiChipEventCallback.Stub { - @Override - public void onChipReconfigured(int modeId) { - mIWifiChipEventCallback.onChipReconfigured(modeId); - } - - @Override - public void onChipReconfigureFailure(WifiStatus status) { - mIWifiChipEventCallback.onChipReconfigureFailure(status); - } - - public void onIfaceAdded(int type, String name) { - mIWifiChipEventCallback.onIfaceAdded(type, name); - } - - @Override - public void onIfaceRemoved(int type, String name) { - mIWifiChipEventCallback.onIfaceRemoved(type, name); - } - - @Override - public void onDebugRingBufferDataAvailable( - WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { - mIWifiChipEventCallback.onDebugRingBufferDataAvailable(status, data); - } - - @Override - public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { - mIWifiChipEventCallback.onDebugErrorAlert(errorCode, debugData); - } - - @Override - public void onRadioModeChange( - ArrayList<android.hardware.wifi.V1_2.IWifiChipEventCallback.RadioModeInfo> - radioModeInfoList) { - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfoList); - } - - @Override - public void onRadioModeChange_1_4(ArrayList<RadioModeInfo> radioModeInfoList) { - mVerboseLog.d("onRadioModeChange_1_4 " + radioModeInfoList); - WifiNative.VendorHalRadioModeChangeEventHandler handler; - synchronized (sLock) { - if (mRadioModeChangeEventHandler == null || radioModeInfoList == null) return; - handler = mRadioModeChangeEventHandler; - } - // Should only contain 1 or 2 radio infos. - if (radioModeInfoList.size() == 0 || radioModeInfoList.size() > 2) { - mLog.e("Unexpected number of radio info in list " + radioModeInfoList.size()); - return; - } - RadioModeInfo radioModeInfo0 = radioModeInfoList.get(0); - RadioModeInfo radioModeInfo1 = - radioModeInfoList.size() == 2 ? radioModeInfoList.get(1) : null; - // Number of ifaces on each radio should be equal. - if (radioModeInfo1 != null - && radioModeInfo0.ifaceInfos.size() != radioModeInfo1.ifaceInfos.size()) { - mLog.e("Unexpected number of iface info in list " - + radioModeInfo0.ifaceInfos.size() + ", " - + radioModeInfo1.ifaceInfos.size()); - return; - } - int numIfacesOnEachRadio = radioModeInfo0.ifaceInfos.size(); - // Only 1 or 2 ifaces should be present on each radio. - if (numIfacesOnEachRadio == 0 || numIfacesOnEachRadio > 2) { - mLog.e("Unexpected number of iface info in list " + numIfacesOnEachRadio); - return; - } - Runnable runnable = null; - // 2 ifaces simultaneous on 2 radios. - if (radioModeInfoList.size() == 2 && numIfacesOnEachRadio == 1) { - // Iface on radio0 should be different from the iface on radio1 for DBS & SBS. - if (areSameIfaceNames(radioModeInfo0.ifaceInfos, radioModeInfo1.ifaceInfos)) { - mLog.e("Unexpected for both radio infos to have same iface"); - return; - } - if (radioModeInfo0.bandInfo != radioModeInfo1.bandInfo) { - runnable = () -> { - handler.onDbs(); - }; - } else { - runnable = () -> { - handler.onSbs(radioModeInfo0.bandInfo); - }; - } - // 2 ifaces time sharing on 1 radio. - } else if (radioModeInfoList.size() == 1 && numIfacesOnEachRadio == 2) { - IfaceInfo ifaceInfo0 = radioModeInfo0.ifaceInfos.get(0); - IfaceInfo ifaceInfo1 = radioModeInfo0.ifaceInfos.get(1); - if (ifaceInfo0.channel != ifaceInfo1.channel) { - runnable = () -> { - handler.onMcc(radioModeInfo0.bandInfo); - }; - } else { - runnable = () -> { - handler.onScc(radioModeInfo0.bandInfo); - }; - } - } else { - // Not concurrency scenario, uninteresting... - } - if (runnable != null) mHalEventHandler.post(runnable); - } + private boolean areSameIfaceNames(List<WifiChip.IfaceInfo> ifaceList1, + List<WifiChip.IfaceInfo> ifaceList2) { + List<String> ifaceNamesList1 = ifaceList1 + .stream() + .map(i -> i.name) + .collect(Collectors.toList()); + List<String> ifaceNamesList2 = ifaceList2 + .stream() + .map(i -> i.name) + .collect(Collectors.toList()); + return ifaceNamesList1.containsAll(ifaceNamesList2); } /** @@ -4024,105 +1822,9 @@ public class WifiVendorHal { */ public boolean startSubsystemRestart() { synchronized (sLock) { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 != null) { - try { - return ok(iWifiChipV15.triggerSubsystemRestart()); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - // HAL version does not support this api - return false; - } - } - - /** - * Convert framework's operational mode to HAL's operational mode. - */ - private int frameworkToHalIfaceMode(@WifiAvailableChannel.OpMode int mode) { - int halMode = 0; - if ((mode & WifiAvailableChannel.OP_MODE_STA) != 0) { - halMode |= WifiIfaceMode.IFACE_MODE_STA; - } - if ((mode & WifiAvailableChannel.OP_MODE_SAP) != 0) { - halMode |= WifiIfaceMode.IFACE_MODE_SOFTAP; - } - if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI) != 0) { - halMode |= WifiIfaceMode.IFACE_MODE_P2P_CLIENT; - } - if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO) != 0) { - halMode |= WifiIfaceMode.IFACE_MODE_P2P_GO; - } - if ((mode & WifiAvailableChannel.OP_MODE_WIFI_AWARE) != 0) { - halMode |= WifiIfaceMode.IFACE_MODE_NAN; - } - if ((mode & WifiAvailableChannel.OP_MODE_TDLS) != 0) { - halMode |= WifiIfaceMode.IFACE_MODE_TDLS; - } - return halMode; - } - - /** - * Convert from HAL's operational mode to framework's operational mode. - */ - private @WifiAvailableChannel.OpMode int frameworkFromHalIfaceMode(int halMode) { - int mode = 0; - if ((halMode & WifiIfaceMode.IFACE_MODE_STA) != 0) { - mode |= WifiAvailableChannel.OP_MODE_STA; - } - if ((halMode & WifiIfaceMode.IFACE_MODE_SOFTAP) != 0) { - mode |= WifiAvailableChannel.OP_MODE_SAP; - } - if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_CLIENT) != 0) { - mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI; - } - if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_GO) != 0) { - mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO; - } - if ((halMode & WifiIfaceMode.IFACE_MODE_NAN) != 0) { - mode |= WifiAvailableChannel.OP_MODE_WIFI_AWARE; - } - if ((halMode & WifiIfaceMode.IFACE_MODE_TDLS) != 0) { - mode |= WifiAvailableChannel.OP_MODE_TDLS; - } - return mode; - } - - /** - * Convert framework's WifiAvailableChannel.FILTER_* to HAL's UsableChannelFilter. - */ - private int frameworkToHalUsableFilter(@WifiAvailableChannel.Filter int filter) { - int halFilter = 0; // O implies no additional filter other than regulatory (default) - - if ((filter & WifiAvailableChannel.FILTER_CONCURRENCY) != 0) { - halFilter |= UsableChannelFilter.CONCURRENCY; - } - if ((filter & WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE) != 0) { - halFilter |= UsableChannelFilter.CELLULAR_COEXISTENCE; + if (mWifiChip == null) return false; + return mWifiChip.triggerSubsystemRestart(); } - - return halFilter; - } - - /** - * Convert framework's WifiAvailableChannel.FILTER_* to HAL's UsableChannelFilter 1.6. - */ - private int frameworkToHalUsableFilter_1_6(@WifiAvailableChannel.Filter int filter) { - int halFilter = 0; // O implies no additional filter other than regulatory (default) - - if ((filter & WifiAvailableChannel.FILTER_CONCURRENCY) != 0) { - halFilter |= UsableChannelFilter.CONCURRENCY; - } - if ((filter & WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE) != 0) { - halFilter |= UsableChannelFilter.CELLULAR_COEXISTENCE; - } - if ((filter & WifiAvailableChannel.FILTER_NAN_INSTANT_MODE) != 0) { - halFilter |= UsableChannelFilter.NAN_INSTANT_MODE; - } - - return halFilter; } /** @@ -4133,52 +1835,8 @@ public class WifiVendorHal { @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) { synchronized (sLock) { - try { - android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = null; - android.hardware.wifi.V1_6.IWifiChip iWifiChipV16 = getWifiChipForV1_6Mockable(); - if (iWifiChipV16 == null) { - iWifiChipV15 = getWifiChipForV1_5Mockable(); - if (iWifiChipV15 == null) { - return null; - } - } - - Mutable<List<WifiAvailableChannel>> answer = new Mutable<>(); - - if (iWifiChipV16 != null) { - iWifiChipV16.getUsableChannels_1_6( - makeWifiBandFromFrameworkBand(band), - frameworkToHalIfaceMode(mode), - frameworkToHalUsableFilter_1_6(filter), (status, channels) -> { - if (!ok(status)) return; - answer.value = new ArrayList<>(); - for (android.hardware.wifi.V1_6.WifiUsableChannel ch : channels) { - answer.value.add(new WifiAvailableChannel(ch.channel, - frameworkFromHalIfaceMode(ch.ifaceModeMask))); - } - }); - } else { - iWifiChipV15.getUsableChannels( - makeWifiBandFromFrameworkBand(band), - frameworkToHalIfaceMode(mode), - frameworkToHalUsableFilter(filter), (status, channels) -> { - if (!ok(status)) return; - answer.value = new ArrayList<>(); - for (android.hardware.wifi.V1_5.WifiUsableChannel ch : channels) { - answer.value.add(new WifiAvailableChannel(ch.channel, - frameworkFromHalIfaceMode(ch.ifaceModeMask))); - } - }); - } - - return answer.value; - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } catch (IllegalArgumentException e) { - mLog.e("Illegal argument for getUsableChannels() " + e); - return null; - } + if (mWifiChip == null) return null; + return mWifiChip.getUsableChannels(band, mode, filter); } } } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java index 9e199c7850..b13ae386a9 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java @@ -19,8 +19,6 @@ package com.android.server.wifi.aware; import static android.net.RouteInfo.RTN_UNICAST; import android.content.Context; -import android.hardware.wifi.V1_0.NanDataPathChannelCfg; -import android.hardware.wifi.V1_0.NanStatusType; import android.net.ConnectivityManager; import android.net.IpPrefix; import android.net.LinkAddress; @@ -56,6 +54,8 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.Clock; +import com.android.server.wifi.hal.WifiNanIface.NanDataPathChannelCfg; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.server.wifi.util.WifiPermissionsWrapper; @@ -747,7 +747,7 @@ public class WifiAwareDataPathStateManager { NETWORK_FACTORY_SCORE_AVAIL, naConfig, mNetworkFactory.getProvider(), nnri); mNiWrapper.setConnected(nnri.networkAgent); } - mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, isOutOfBand, ndpInfo.startTimestamp); + mAwareMetrics.recordNdpStatus(NanStatusCode.SUCCESS, isOutOfBand, ndpInfo.startTimestamp); mAwareMetrics.recordNdpCreation(nnri.uid, nnri.packageName, mNetworkRequestsCache); } @@ -875,7 +875,7 @@ public class WifiAwareDataPathStateManager { } AwareNetworkRequestInformation nnri = nnriE.getValue(); NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId); - mAwareMetrics.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, + mAwareMetrics.recordNdpStatus(NanStatusCode.INTERNAL_FAILURE, nnri.networkSpecifier.isOutOfBand(), ndpInfo.startTimestamp); mMgr.endDataPath(ndpId); nnri.ndpInfos.remove(ndpId); diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java index 557ef0110d..d06132e775 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java @@ -20,7 +20,6 @@ import static com.android.server.wifi.aware.WifiAwareStateManager.INSTANT_MODE_2 import static com.android.server.wifi.aware.WifiAwareStateManager.INSTANT_MODE_5GHZ; import static com.android.server.wifi.aware.WifiAwareStateManager.INSTANT_MODE_DISABLED; -import android.hardware.wifi.V1_0.NanStatusType; import android.net.wifi.WifiScanner; import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; import android.net.wifi.aware.PublishConfig; @@ -32,6 +31,8 @@ import android.util.LocalLog; import android.util.Log; import android.util.SparseArray; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; @@ -168,7 +169,7 @@ public class WifiAwareDiscoverySessionState { */ public void terminate() { try { - mCallback.onSessionTerminated(NanStatusType.SUCCESS); + mCallback.onSessionTerminated(NanStatusCode.SUCCESS); } catch (RemoteException e) { Log.w(TAG, "onSessionTerminatedLocal onSessionTerminated(): RemoteException (FYI): " + e); @@ -204,7 +205,7 @@ public class WifiAwareDiscoverySessionState { if (!mIsPublishSession) { Log.e(TAG, "A SUBSCRIBE session is being used to publish"); try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + mCallback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.e(TAG, "updatePublish: RemoteException=" + e); } @@ -215,7 +216,7 @@ public class WifiAwareDiscoverySessionState { boolean success = mWifiAwareNativeApi.publish(transactionId, mPubSubId, config); if (!success) { try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + mCallback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "updatePublish onSessionConfigFail(): RemoteException (FYI): " + e); } @@ -235,7 +236,7 @@ public class WifiAwareDiscoverySessionState { if (mIsPublishSession) { Log.e(TAG, "A PUBLISH session is being used to subscribe"); try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + mCallback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.e(TAG, "updateSubscribe: RemoteException=" + e); } @@ -246,7 +247,7 @@ public class WifiAwareDiscoverySessionState { boolean success = mWifiAwareNativeApi.subscribe(transactionId, mPubSubId, config); if (!success) { try { - mCallback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + mCallback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "updateSubscribe onSessionConfigFail(): RemoteException (FYI): " + e); } @@ -272,7 +273,7 @@ public class WifiAwareDiscoverySessionState { Log.e(TAG, "sendMessage: attempting to send a message to an address which didn't " + "match/contact us"); try { - mCallback.onMessageSendFail(messageId, NanStatusType.INTERNAL_FAILURE); + mCallback.onMessageSendFail(messageId, NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.e(TAG, "sendMessage: RemoteException=" + e); } @@ -283,7 +284,7 @@ public class WifiAwareDiscoverySessionState { peerInfo.mInstanceId, peerInfo.mMac, message, messageId); if (!success) { try { - mCallback.onMessageSendFail(messageId, NanStatusType.INTERNAL_FAILURE); + mCallback.onMessageSendFail(messageId, NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.e(TAG, "sendMessage: RemoteException=" + e); } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java b/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java index 75b3ef96b6..c935c9fc86 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java @@ -21,7 +21,6 @@ import static android.net.wifi.aware.WifiAwareNetworkSpecifier.NETWORK_SPECIFIER import static android.net.wifi.aware.WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB; import static android.net.wifi.aware.WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER; -import android.hardware.wifi.V1_0.NanStatusType; import android.net.wifi.aware.WifiAwareNetworkSpecifier; import android.text.TextUtils; import android.util.Log; @@ -30,6 +29,7 @@ import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wifi.Clock; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.util.MetricsUtils; @@ -229,7 +229,7 @@ public class WifiAwareMetrics { data.mUsesIdentityCallback |= usesIdentityCallback; data.mMaxConcurrentAttaches = Math.max(data.mMaxConcurrentAttaches, currentConcurrentCount); - recordAttachStatus(NanStatusType.SUCCESS); + recordAttachStatus(NanStatusCode.SUCCESS); } } @@ -363,7 +363,7 @@ public class WifiAwareMetrics { addNanHalStatusToHistogram(status, mSubscribeStatusData); } - if (status == NanStatusType.NO_RESOURCES_AVAILABLE) { + if (status == NanStatusCode.NO_RESOURCES_AVAILABLE) { mAppsWithDiscoverySessionResourceFailure.add(uid); } } @@ -474,7 +474,7 @@ public class WifiAwareMetrics { addNanHalStatusToHistogram(status, mInBandNdpStatusData); } - if (status == NanStatusType.SUCCESS) { + if (status == NanStatusCode.SUCCESS) { long creationTime = mClock.getElapsedSinceBootMillis() - startTimestamp; MetricsUtils.addValueToLogHistogram(creationTime, mNdpCreationTimeDuration, DURATION_LOG_HISTOGRAM); @@ -828,7 +828,7 @@ public class WifiAwareMetrics { * Adds the NanStatusType to the histogram (translating to the proto enumeration of the status). */ public static void addNanHalStatusToHistogram(int halStatus, SparseIntArray histogram) { - int protoStatus = convertNanStatusTypeToProtoEnum(halStatus); + int protoStatus = convertNanStatusCodeToProtoEnum(halStatus); int newValue = histogram.get(protoStatus) + 1; histogram.put(protoStatus, newValue); } @@ -852,38 +852,38 @@ public class WifiAwareMetrics { } /** - * Convert a HAL NanStatusType enum to a Metrics proto enum NanStatusTypeEnum. + * Convert a NanStatusCode to a Metrics proto enum NanStatusCodeEnum. */ - public static int convertNanStatusTypeToProtoEnum(int nanStatusType) { - switch (nanStatusType) { - case NanStatusType.SUCCESS: + public static int convertNanStatusCodeToProtoEnum(int nanStatusCode) { + switch (nanStatusCode) { + case NanStatusCode.SUCCESS: return WifiMetricsProto.WifiAwareLog.SUCCESS; - case NanStatusType.INTERNAL_FAILURE: + case NanStatusCode.INTERNAL_FAILURE: return WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE; - case NanStatusType.PROTOCOL_FAILURE: + case NanStatusCode.PROTOCOL_FAILURE: return WifiMetricsProto.WifiAwareLog.PROTOCOL_FAILURE; - case NanStatusType.INVALID_SESSION_ID: + case NanStatusCode.INVALID_SESSION_ID: return WifiMetricsProto.WifiAwareLog.INVALID_SESSION_ID; - case NanStatusType.NO_RESOURCES_AVAILABLE: + case NanStatusCode.NO_RESOURCES_AVAILABLE: return WifiMetricsProto.WifiAwareLog.NO_RESOURCES_AVAILABLE; - case NanStatusType.INVALID_ARGS: + case NanStatusCode.INVALID_ARGS: return WifiMetricsProto.WifiAwareLog.INVALID_ARGS; - case NanStatusType.INVALID_PEER_ID: + case NanStatusCode.INVALID_PEER_ID: return WifiMetricsProto.WifiAwareLog.INVALID_PEER_ID; - case NanStatusType.INVALID_NDP_ID: + case NanStatusCode.INVALID_NDP_ID: return WifiMetricsProto.WifiAwareLog.INVALID_NDP_ID; - case NanStatusType.NAN_NOT_ALLOWED: + case NanStatusCode.NAN_NOT_ALLOWED: return WifiMetricsProto.WifiAwareLog.NAN_NOT_ALLOWED; - case NanStatusType.NO_OTA_ACK: + case NanStatusCode.NO_OTA_ACK: return WifiMetricsProto.WifiAwareLog.NO_OTA_ACK; - case NanStatusType.ALREADY_ENABLED: + case NanStatusCode.ALREADY_ENABLED: return WifiMetricsProto.WifiAwareLog.ALREADY_ENABLED; - case NanStatusType.FOLLOWUP_TX_QUEUE_FULL: + case NanStatusCode.FOLLOWUP_TX_QUEUE_FULL: return WifiMetricsProto.WifiAwareLog.FOLLOWUP_TX_QUEUE_FULL; - case NanStatusType.UNSUPPORTED_CONCURRENCY_NAN_DISABLED: + case NanStatusCode.UNSUPPORTED_CONCURRENCY_NAN_DISABLED: return WifiMetricsProto.WifiAwareLog.UNSUPPORTED_CONCURRENCY_NAN_DISABLED; default: - Log.e(TAG, "Unrecognized NanStatusType: " + nanStatusType); + Log.e(TAG, "Unrecognized NanStatusCode: " + nanStatusCode); return WifiMetricsProto.WifiAwareLog.UNKNOWN_HAL_STATUS; } } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java index 8af9409556..811e94064a 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java @@ -16,51 +16,29 @@ package com.android.server.wifi.aware; -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_SK_128; -import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; - -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.NanBandIndex; -import android.hardware.wifi.V1_0.NanBandSpecificConfig; -import android.hardware.wifi.V1_0.NanConfigRequest; -import android.hardware.wifi.V1_0.NanDataPathSecurityType; -import android.hardware.wifi.V1_0.NanEnableRequest; -import android.hardware.wifi.V1_0.NanInitiateDataPathRequest; -import android.hardware.wifi.V1_0.NanMatchAlg; -import android.hardware.wifi.V1_0.NanPublishRequest; -import android.hardware.wifi.V1_0.NanRangingIndication; -import android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest; -import android.hardware.wifi.V1_0.NanSubscribeRequest; -import android.hardware.wifi.V1_0.NanTransmitFollowupRequest; -import android.hardware.wifi.V1_0.NanTxType; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_6.NanCipherSuiteType; +import android.net.MacAddress; import android.net.wifi.aware.AwareParams; import android.net.wifi.aware.ConfigRequest; import android.net.wifi.aware.PublishConfig; import android.net.wifi.aware.SubscribeConfig; import android.net.wifi.aware.WifiAwareDataPathSecurityConfig; import android.net.wifi.util.HexEncoding; -import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; import android.util.SparseIntArray; -import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.BasicShellCommandHandler; +import com.android.server.wifi.hal.WifiNanIface; +import com.android.server.wifi.hal.WifiNanIface.PowerParameters; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** - * Translates Wi-Fi Aware requests from the framework to the HAL (HIDL). + * Translates Wi-Fi Aware requests from the framework to the HAL. * * Delegates the management of the NAN interface to WifiAwareNativeManager. */ @@ -69,9 +47,6 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC private static final boolean VDBG = false; // STOPSHIP if true private boolean mVerboseLoggingEnabled = false; - @VisibleForTesting - static final String SERVICE_NAME_FOR_OOB_DATA_PATH = "Wi-Fi Aware Data Path"; - private final WifiAwareNativeManager mHal; private SparseIntArray mTransactionIds; // VDBG only! @@ -105,42 +80,6 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC mTransactionIds.append(transactionId, count + 1); } - /** - * (HIDL) Cast the input to a 1.2 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return android.hardware.wifi.V1_2.IWifiNanIface.castFrom(iface); - } - - /** - * (HIDL) Cast the input to a 1.4 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_4.IWifiNanIface mockableCastTo_1_4(IWifiNanIface iface) { - return android.hardware.wifi.V1_4.IWifiNanIface.castFrom(iface); - } - - /** - * (HIDL) Cast the input to a 1.5 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_5.IWifiNanIface mockableCastTo_1_5(IWifiNanIface iface) { - return android.hardware.wifi.V1_5.IWifiNanIface.castFrom(iface); - } - - /** - * (HIDL) Cast the input to a 1.6 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_6.IWifiNanIface mockableCastTo_1_6(IWifiNanIface iface) { - return android.hardware.wifi.V1_6.IWifiNanIface.castFrom(iface); - } - /* * Parameters settable through the shell command. * see wifi/1.0/types.hal NanBandSpecificConfig.discoveryWindowIntervalVal and @@ -160,7 +99,6 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC private static final int PARAM_DW_5GHZ_INACTIVE = 0; // 0 = disabled private static final int PARAM_DW_5GHZ_IDLE = 0; // == inactive - // TODO: /* package */ static final String PARAM_DW_6GHZ = "dw_6ghz"; private static final int PARAM_DW_6GHZ_DEFAULT = 1; // 1 -> DW=1, latency=512ms private static final int PARAM_DW_6GHZ_INACTIVE = 0; // 0 = disabled @@ -389,31 +327,12 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC if (mVerboseLoggingEnabled) Log.v(TAG, "getCapabilities: transactionId=" + transactionId); recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "getCapabilities: null interface"); return false; } - android.hardware.wifi.V1_5.IWifiNanIface iface15 = mockableCastTo_1_5(iface); - - - try { - WifiStatus status; - if (iface15 == null) { - status = iface.getCapabilitiesRequest(transactionId); - } else { - status = iface15.getCapabilitiesRequest_1_5(transactionId); - } - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "getCapabilities: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "getCapabilities: exception: " + e); - return false; - } + return iface.getCapabilities(transactionId); } /** @@ -443,283 +362,17 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC + ", instantModeChannel=" + instantModeChannel); recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "enableAndConfigure: null interface"); return false; } - android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(iface); - android.hardware.wifi.V1_4.IWifiNanIface iface14 = mockableCastTo_1_4(iface); - android.hardware.wifi.V1_5.IWifiNanIface iface15 = mockableCastTo_1_5(iface); - android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(iface); - android.hardware.wifi.V1_2.NanConfigRequestSupplemental configSupplemental12 = - new android.hardware.wifi.V1_2.NanConfigRequestSupplemental(); - android.hardware.wifi.V1_5.NanConfigRequestSupplemental configSupplemental15 = - new android.hardware.wifi.V1_5.NanConfigRequestSupplemental(); - android.hardware.wifi.V1_6.NanConfigRequestSupplemental configSupplemental16 = - new android.hardware.wifi.V1_6.NanConfigRequestSupplemental(); - if (iface12 != null || iface14 != null) { - configSupplemental12.discoveryBeaconIntervalMs = 0; - configSupplemental12.numberOfSpatialStreamsInDiscovery = 0; - configSupplemental12.enableDiscoveryWindowEarlyTermination = false; - configSupplemental12.enableRanging = rangingEnabled; - } - - if (iface15 != null) { - configSupplemental15.V1_2 = configSupplemental12; - configSupplemental15.enableInstantCommunicationMode = isInstantCommunicationEnabled; - } - if (iface16 != null) { - configSupplemental16.V1_5 = configSupplemental15; - configSupplemental16.instantModeChannel = instantModeChannel; - } - - NanBandSpecificConfig config24 = new NanBandSpecificConfig(); - config24.rssiClose = 60; - config24.rssiMiddle = 70; - config24.rssiCloseProximity = 60; - config24.dwellTimeMs = (byte) 200; - config24.scanPeriodSec = 20; - if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ] - == ConfigRequest.DW_INTERVAL_NOT_INIT) { - config24.validDiscoveryWindowIntervalVal = false; - } else { - config24.validDiscoveryWindowIntervalVal = true; - config24.discoveryWindowIntervalVal = - (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_24GHZ]; - } - - NanBandSpecificConfig config5 = new NanBandSpecificConfig(); - config5.rssiClose = 60; - config5.rssiMiddle = 75; - config5.rssiCloseProximity = 60; - config5.dwellTimeMs = (byte) 200; - config5.scanPeriodSec = 20; - if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ] - == ConfigRequest.DW_INTERVAL_NOT_INIT) { - config5.validDiscoveryWindowIntervalVal = false; - } else { - config5.validDiscoveryWindowIntervalVal = true; - config5.discoveryWindowIntervalVal = - (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_5GHZ]; - } - - // TODO: b/145609058 - // Need to review values for this config, currently it is a copy from config5 - NanBandSpecificConfig config6 = new NanBandSpecificConfig(); - config6.rssiClose = 60; - config6.rssiMiddle = 75; - config6.rssiCloseProximity = 60; - config6.dwellTimeMs = (byte) 200; - config6.scanPeriodSec = 20; - if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_6GHZ] - == ConfigRequest.DW_INTERVAL_NOT_INIT) { - config6.validDiscoveryWindowIntervalVal = false; - } else { - config6.validDiscoveryWindowIntervalVal = true; - config6.discoveryWindowIntervalVal = - (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest - .NAN_BAND_6GHZ]; - } - - try { - WifiStatus status; - if (initialConfiguration) { - if (iface14 != null || iface15 != null || iface16 != null) { - // translate framework to HIDL configuration (V_1.4) - android.hardware.wifi.V1_4.NanEnableRequest req = - new android.hardware.wifi.V1_4.NanEnableRequest(); - - req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; - req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; - req.operateInBand[android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = - configRequest.mSupport6gBand; - req.hopCountMax = 2; - req.configParams.masterPref = (byte) configRequest.mMasterPreference; - req.configParams.disableDiscoveryAddressChangeIndication = - !notifyIdentityChange; - req.configParams.disableStartedClusterIndication = !notifyIdentityChange; - req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; - req.configParams.includePublishServiceIdsInBeacon = true; - req.configParams.numberOfPublishServiceIdsInBeacon = 0; - req.configParams.includeSubscribeServiceIdsInBeacon = true; - req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; - req.configParams.rssiWindowSize = 8; - req.configParams.macAddressRandomizationIntervalSec = - mExternalSetParams.getOrDefault(PARAM_MAC_RANDOM_INTERVAL_SEC, - mSettableParameters.get(PARAM_MAC_RANDOM_INTERVAL_SEC)); - - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - req.configParams.bandSpecificConfig[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = config6; - - req.debugConfigs.validClusterIdVals = true; - req.debugConfigs.clusterIdTopRangeVal = (short) configRequest.mClusterHigh; - req.debugConfigs.clusterIdBottomRangeVal = (short) configRequest.mClusterLow; - req.debugConfigs.validIntfAddrVal = false; - req.debugConfigs.validOuiVal = false; - req.debugConfigs.ouiVal = 0; - req.debugConfigs.validRandomFactorForceVal = false; - req.debugConfigs.randomFactorForceVal = 0; - req.debugConfigs.validHopCountForceVal = false; - req.debugConfigs.hopCountForceVal = 0; - req.debugConfigs.validDiscoveryChannelVal = false; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; - req.debugConfigs.discoveryChannelMhzVal[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = 0; - req.debugConfigs.validUseBeaconsInBandVal = false; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - req.debugConfigs.useBeaconsInBandVal[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = true; - req.debugConfigs.validUseSdfInBandVal = false; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - req.debugConfigs.useSdfInBandVal[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = true; - updateConfigForPowerSettings14(req.configParams, configSupplemental12, - isInteractive, isIdle); - - if (iface16 != null) { - status = iface16.enableRequest_1_6(transactionId, req, - configSupplemental16); - } else if (iface15 != null) { - status = iface15.enableRequest_1_5(transactionId, req, - configSupplemental15); - } else { - status = iface14.enableRequest_1_4(transactionId, req, - configSupplemental12); - } - } else { - // translate framework to HIDL configuration (before V_1.4) - NanEnableRequest req = new NanEnableRequest(); - - req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; - req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; - req.hopCountMax = 2; - req.configParams.masterPref = (byte) configRequest.mMasterPreference; - req.configParams.disableDiscoveryAddressChangeIndication = - !notifyIdentityChange; - req.configParams.disableStartedClusterIndication = !notifyIdentityChange; - req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; - req.configParams.includePublishServiceIdsInBeacon = true; - req.configParams.numberOfPublishServiceIdsInBeacon = 0; - req.configParams.includeSubscribeServiceIdsInBeacon = true; - req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; - req.configParams.rssiWindowSize = 8; - req.configParams.macAddressRandomizationIntervalSec = - mExternalSetParams.getOrDefault(PARAM_MAC_RANDOM_INTERVAL_SEC, - mSettableParameters.get(PARAM_MAC_RANDOM_INTERVAL_SEC)); - - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - - req.debugConfigs.validClusterIdVals = true; - req.debugConfigs.clusterIdTopRangeVal = (short) configRequest.mClusterHigh; - req.debugConfigs.clusterIdBottomRangeVal = (short) configRequest.mClusterLow; - req.debugConfigs.validIntfAddrVal = false; - req.debugConfigs.validOuiVal = false; - req.debugConfigs.ouiVal = 0; - req.debugConfigs.validRandomFactorForceVal = false; - req.debugConfigs.randomFactorForceVal = 0; - req.debugConfigs.validHopCountForceVal = false; - req.debugConfigs.hopCountForceVal = 0; - req.debugConfigs.validDiscoveryChannelVal = false; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; - req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; - req.debugConfigs.validUseBeaconsInBandVal = false; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - req.debugConfigs.validUseSdfInBandVal = false; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; - req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; - - updateConfigForPowerSettings(req.configParams, configSupplemental12, - isInteractive, isIdle); - - if (iface12 != null) { - status = iface12.enableRequest_1_2(transactionId, req, - configSupplemental12); - } else { - status = iface.enableRequest(transactionId, req); - } - } - } else { - if (iface14 != null || iface15 != null || iface16 != null) { - android.hardware.wifi.V1_4.NanConfigRequest req = - new android.hardware.wifi.V1_4.NanConfigRequest(); - req.masterPref = (byte) configRequest.mMasterPreference; - req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; - req.disableStartedClusterIndication = !notifyIdentityChange; - req.disableJoinedClusterIndication = !notifyIdentityChange; - req.includePublishServiceIdsInBeacon = true; - req.numberOfPublishServiceIdsInBeacon = 0; - req.includeSubscribeServiceIdsInBeacon = true; - req.numberOfSubscribeServiceIdsInBeacon = 0; - req.rssiWindowSize = 8; - req.macAddressRandomizationIntervalSec = - mExternalSetParams.getOrDefault(PARAM_MAC_RANDOM_INTERVAL_SEC, - mSettableParameters.get(PARAM_MAC_RANDOM_INTERVAL_SEC)); - - req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - req.bandSpecificConfig[android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = - config6; - - updateConfigForPowerSettings14(req, configSupplemental12, - isInteractive, isIdle); - if (iface16 != null) { - status = iface16.configRequest_1_6(transactionId, req, - configSupplemental16); - } else if (iface15 != null) { - status = iface15.configRequest_1_5(transactionId, req, - configSupplemental15); - } else { - status = iface14.configRequest_1_4(transactionId, req, - configSupplemental12); - } - } else { - NanConfigRequest req = new NanConfigRequest(); - req.masterPref = (byte) configRequest.mMasterPreference; - req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; - req.disableStartedClusterIndication = !notifyIdentityChange; - req.disableJoinedClusterIndication = !notifyIdentityChange; - req.includePublishServiceIdsInBeacon = true; - req.numberOfPublishServiceIdsInBeacon = 0; - req.includeSubscribeServiceIdsInBeacon = true; - req.numberOfSubscribeServiceIdsInBeacon = 0; - req.rssiWindowSize = 8; - req.macAddressRandomizationIntervalSec = - mExternalSetParams.getOrDefault(PARAM_MAC_RANDOM_INTERVAL_SEC, - mSettableParameters.get(PARAM_MAC_RANDOM_INTERVAL_SEC)); - - req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; - req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; - - updateConfigForPowerSettings(req, configSupplemental12, isInteractive, isIdle); - - if (iface12 != null) { - status = iface12.configRequest_1_2(transactionId, req, - configSupplemental12); - } else { - status = iface.configRequest(transactionId, req); - } - } - } - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "enableAndConfigure: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "enableAndConfigure: exception: " + e); - return false; - } + return iface.enableAndConfigure(transactionId, configRequest, notifyIdentityChange, + initialConfiguration, rangingEnabled, + isInstantCommunicationEnabled, instantModeChannel, + mExternalSetParams.getOrDefault(PARAM_MAC_RANDOM_INTERVAL_SEC, + mSettableParameters.get(PARAM_MAC_RANDOM_INTERVAL_SEC)), + getPowerParameters(isInteractive, isIdle)); } /** @@ -732,24 +385,13 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC if (mVerboseLoggingEnabled) Log.d(TAG, "disable"); recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "disable: null interface"); return false; } - - try { - WifiStatus status = iface.disableRequest(transactionId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "disable: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "disable: exception: " + e); - return false; - } + boolean result = iface.disable(transactionId); + return result; } /** @@ -768,132 +410,12 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "publish: null interface"); return false; } - - android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(iface); - if (iface16 == null) { - NanPublishRequest req = new NanPublishRequest(); - req.baseConfigs.sessionId = publishId; - req.baseConfigs.ttlSec = (short) publishConfig.mTtlSec; - req.baseConfigs.discoveryWindowPeriod = 1; - req.baseConfigs.discoveryCount = 0; - convertNativeByteArrayToArrayList(publishConfig.mServiceName, - req.baseConfigs.serviceName); - req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER; - convertNativeByteArrayToArrayList(publishConfig.mServiceSpecificInfo, - req.baseConfigs.serviceSpecificInfo); - convertNativeByteArrayToArrayList(publishConfig.mMatchFilter, - publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED - ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); - req.baseConfigs.useRssiThreshold = false; - req.baseConfigs.disableDiscoveryTerminationIndication = - !publishConfig.mEnableTerminateNotification; - req.baseConfigs.disableMatchExpirationIndication = true; - req.baseConfigs.disableFollowupReceivedIndication = false; - - req.autoAcceptDataPathRequests = false; - - req.baseConfigs.rangingRequired = publishConfig.mEnableRanging; - - req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; - WifiAwareDataPathSecurityConfig securityConfig = publishConfig.getSecurityConfig(); - if (securityConfig != null) { - req.baseConfigs.securityConfig.cipherType = getHalCipherSuiteType( - securityConfig.getCipherSuite()); - if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { - req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(securityConfig.getPmk(), req.baseConfigs.securityConfig.pmk); - } - if (securityConfig.getPskPassphrase() != null - && securityConfig.getPskPassphrase().length() != 0) { - req.baseConfigs.securityConfig.securityType = - NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), - req.baseConfigs.securityConfig.passphrase); - } - } - - req.publishType = publishConfig.mPublishType; - req.txType = NanTxType.BROADCAST; - - try { - WifiStatus status = iface.startPublishRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "publish: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "publish: exception: " + e); - return false; - } - } else { - android.hardware.wifi.V1_6.NanPublishRequest req = - new android.hardware.wifi.V1_6.NanPublishRequest(); - req.baseConfigs.sessionId = publishId; - req.baseConfigs.ttlSec = (short) publishConfig.mTtlSec; - req.baseConfigs.discoveryWindowPeriod = 1; - req.baseConfigs.discoveryCount = 0; - convertNativeByteArrayToArrayList(publishConfig.mServiceName, - req.baseConfigs.serviceName); - req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER; - convertNativeByteArrayToArrayList(publishConfig.mServiceSpecificInfo, - req.baseConfigs.serviceSpecificInfo); - convertNativeByteArrayToArrayList(publishConfig.mMatchFilter, - publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED - ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); - req.baseConfigs.useRssiThreshold = false; - req.baseConfigs.disableDiscoveryTerminationIndication = - !publishConfig.mEnableTerminateNotification; - req.baseConfigs.disableMatchExpirationIndication = true; - req.baseConfigs.disableFollowupReceivedIndication = false; - - req.autoAcceptDataPathRequests = false; - - req.baseConfigs.rangingRequired = publishConfig.mEnableRanging; - - req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; - WifiAwareDataPathSecurityConfig securityConfig = publishConfig.getSecurityConfig(); - if (securityConfig != null) { - req.baseConfigs.securityConfig.cipherType = getHalCipherSuiteType( - securityConfig.getCipherSuite()); - if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { - req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(securityConfig.getPmk(), req.baseConfigs.securityConfig.pmk); - } - if (securityConfig.getPskPassphrase() != null - && securityConfig.getPskPassphrase().length() != 0) { - req.baseConfigs.securityConfig.securityType = - NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), - req.baseConfigs.securityConfig.passphrase); - } - if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { - copyArray(securityConfig.getPmkId(), req.baseConfigs.securityConfig.scid); - } - } - - req.publishType = publishConfig.mPublishType; - req.txType = NanTxType.BROADCAST; - - try { - WifiStatus status = iface16.startPublishRequest_1_6(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "publish: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "publish: exception: " + e); - return false; - } - } + return iface.publish(transactionId, publishId, publishConfig); } /** @@ -913,63 +435,12 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "subscribe: null interface"); return false; } - - NanSubscribeRequest req = new NanSubscribeRequest(); - req.baseConfigs.sessionId = subscribeId; - req.baseConfigs.ttlSec = (short) subscribeConfig.mTtlSec; - req.baseConfigs.discoveryWindowPeriod = 1; - req.baseConfigs.discoveryCount = 0; - convertNativeByteArrayToArrayList(subscribeConfig.mServiceName, - req.baseConfigs.serviceName); - req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_ONCE; - convertNativeByteArrayToArrayList(subscribeConfig.mServiceSpecificInfo, - req.baseConfigs.serviceSpecificInfo); - convertNativeByteArrayToArrayList(subscribeConfig.mMatchFilter, - subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE - ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); - req.baseConfigs.useRssiThreshold = false; - req.baseConfigs.disableDiscoveryTerminationIndication = - !subscribeConfig.mEnableTerminateNotification; - req.baseConfigs.disableMatchExpirationIndication = false; - req.baseConfigs.disableFollowupReceivedIndication = false; - - req.baseConfigs.rangingRequired = - subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet; - req.baseConfigs.configRangingIndications = 0; - // TODO: b/69428593 remove correction factors once HAL converted from CM to MM - if (subscribeConfig.mMinDistanceMmSet) { - req.baseConfigs.distanceEgressCm = (short) Math.min( - subscribeConfig.mMinDistanceMm / 10, Short.MAX_VALUE); - req.baseConfigs.configRangingIndications |= NanRangingIndication.EGRESS_MET_MASK; - } - if (subscribeConfig.mMaxDistanceMmSet) { - req.baseConfigs.distanceIngressCm = (short) Math.min( - subscribeConfig.mMaxDistanceMm / 10, Short.MAX_VALUE); - req.baseConfigs.configRangingIndications |= NanRangingIndication.INGRESS_MET_MASK; - } - - // TODO: configure security - req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; - - req.subscribeType = subscribeConfig.mSubscribeType; - - try { - WifiStatus status = iface.startSubscribeRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "subscribe: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "subscribe: exception: " + e); - return false; - } + return iface.subscribe(transactionId, subscribeId, subscribeConfig); } /** @@ -999,31 +470,18 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "sendMessage: null interface"); return false; } - NanTransmitFollowupRequest req = new NanTransmitFollowupRequest(); - req.discoverySessionId = pubSubId; - req.peerId = requestorInstanceId; - copyArray(dest, req.addr); - req.isHighPriority = false; - req.shouldUseDiscoveryWindow = true; - convertNativeByteArrayToArrayList(message, req.serviceSpecificInfo); - req.disableFollowupResultIndication = false; - try { - WifiStatus status = iface.transmitFollowupRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "sendMessage: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "sendMessage: exception: " + e); + MacAddress destMac = MacAddress.fromBytes(dest); + return iface.sendMessage( + transactionId, pubSubId, requestorInstanceId, destMac, message); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid dest mac received: " + Arrays.toString(dest)); return false; } } @@ -1042,24 +500,12 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "stopPublish: null interface"); return false; } - - try { - WifiStatus status = iface.stopPublishRequest(transactionId, pubSubId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "stopPublish: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "stopPublish: exception: " + e); - return false; - } + return iface.stopPublish(transactionId, pubSubId); } /** @@ -1076,24 +522,12 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "stopSubscribe: null interface"); return false; } - - try { - WifiStatus status = iface.stopSubscribeRequest(transactionId, pubSubId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "stopSubscribe: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "stopSubscribe: exception: " + e); - return false; - } + return iface.stopSubscribe(transactionId, pubSubId); } /** @@ -1109,24 +543,12 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC + "interfaceName=" + interfaceName); recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "createAwareNetworkInterface: null interface"); return false; } - - try { - WifiStatus status = iface.createDataInterfaceRequest(transactionId, interfaceName); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "createAwareNetworkInterface: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "createAwareNetworkInterface: exception: " + e); - return false; - } + return iface.createAwareNetworkInterface(transactionId, interfaceName); } /** @@ -1141,24 +563,12 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC + "interfaceName=" + interfaceName); recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "deleteAwareNetworkInterface: null interface"); return false; } - - try { - WifiStatus status = iface.deleteDataInterfaceRequest(transactionId, interfaceName); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "deleteAwareNetworkInterface: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "deleteAwareNetworkInterface: exception: " + e); - return false; - } + return iface.deleteAwareNetworkInterface(transactionId, interfaceName); } /** @@ -1194,113 +604,22 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "initiateDataPath: null interface"); return false; } - if (capabilities == null) { - Log.e(TAG, "initiateDataPath: null capabilities"); + try { + MacAddress peerMac = MacAddress.fromBytes(peer); + return iface.initiateDataPath(transactionId, peerId, channelRequestType, channel, + peerMac, interfaceName, isOutOfBand, appInfo, capabilities, securityConfig); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid peer mac received: " + Arrays.toString(peer)); return false; } - - android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(iface); - - if (iface16 == null) { - NanInitiateDataPathRequest req = new NanInitiateDataPathRequest(); - req.peerId = peerId; - copyArray(peer, req.peerDiscMacAddr); - req.channelRequestType = channelRequestType; - req.channel = channel; - req.ifaceName = interfaceName; - req.securityConfig.securityType = NanDataPathSecurityType.OPEN; - if (securityConfig != null) { - req.securityConfig.cipherType = getHalCipherSuiteType( - securityConfig.getCipherSuite()); - if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { - - req.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(securityConfig.getPmk(), req.securityConfig.pmk); - } - if (securityConfig.getPskPassphrase() != null - && securityConfig.getPskPassphrase().length() != 0) { - req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), - req.securityConfig.passphrase); - } - } - - if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { - convertNativeByteArrayToArrayList( - SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), - req.serviceNameOutOfBand); - } - convertNativeByteArrayToArrayList(appInfo, req.appInfo); - - try { - WifiStatus status = iface.initiateDataPathRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "initiateDataPath: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "initiateDataPath: exception: " + e); - return false; - } - } else { - android.hardware.wifi.V1_6.NanInitiateDataPathRequest req = - new android.hardware.wifi.V1_6.NanInitiateDataPathRequest(); - req.peerId = peerId; - copyArray(peer, req.peerDiscMacAddr); - req.channelRequestType = channelRequestType; - req.channel = channel; - req.ifaceName = interfaceName; - req.securityConfig.securityType = NanDataPathSecurityType.OPEN; - if (securityConfig != null) { - req.securityConfig.cipherType = getHalCipherSuiteType( - securityConfig.getCipherSuite()); - if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { - req.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(securityConfig.getPmk(), req.securityConfig.pmk); - } - if (securityConfig.getPskPassphrase() != null - && securityConfig.getPskPassphrase().length() != 0) { - req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), - req.securityConfig.passphrase); - } - if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { - copyArray(securityConfig.getPmkId(), req.securityConfig.scid); - } - } - - if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { - convertNativeByteArrayToArrayList( - SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), - req.serviceNameOutOfBand); - } - convertNativeByteArrayToArrayList(appInfo, req.appInfo); - - try { - WifiStatus status = iface16.initiateDataPathRequest_1_6(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "initiateDataPath_1_6: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "initiateDataPath_1_6: exception: " + e); - return false; - } - } } - - /** * Responds to a data request from a peer. Security is provided by either PMK or Passphrase (not * both) - if both are null then an open (unencrypted) link is set up. @@ -1328,107 +647,13 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "respondToDataPathRequest: null interface"); return false; } - - if (capabilities == null) { - Log.e(TAG, "respondToDataPathRequest: null capabilities"); - return false; - } - - android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(iface); - - if (iface16 == null) { - NanRespondToDataPathIndicationRequest req = new NanRespondToDataPathIndicationRequest(); - req.acceptRequest = accept; - req.ndpInstanceId = ndpId; - req.ifaceName = interfaceName; - req.securityConfig.securityType = NanDataPathSecurityType.OPEN; - if (securityConfig != null) { - req.securityConfig.cipherType = getHalCipherSuiteType( - securityConfig.getCipherSuite()); - if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { - - req.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(securityConfig.getPmk(), req.securityConfig.pmk); - } - if (securityConfig.getPskPassphrase() != null - && securityConfig.getPskPassphrase().length() != 0) { - req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), - req.securityConfig.passphrase); - } - } - - if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { - convertNativeByteArrayToArrayList( - SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), - req.serviceNameOutOfBand); - } - convertNativeByteArrayToArrayList(appInfo, req.appInfo); - - try { - WifiStatus status = iface.respondToDataPathIndicationRequest(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "respondToDataPathRequest: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "respondToDataPathRequest: exception: " + e); - return false; - } - } else { - android.hardware.wifi.V1_6.NanRespondToDataPathIndicationRequest req = - new android.hardware.wifi.V1_6.NanRespondToDataPathIndicationRequest(); - req.acceptRequest = accept; - req.ndpInstanceId = ndpId; - req.ifaceName = interfaceName; - req.securityConfig.securityType = NanDataPathSecurityType.OPEN; - if (securityConfig != null) { - req.securityConfig.cipherType = getHalCipherSuiteType( - securityConfig.getCipherSuite()); - if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { - - req.securityConfig.securityType = NanDataPathSecurityType.PMK; - copyArray(securityConfig.getPmk(), req.securityConfig.pmk); - } - if (securityConfig.getPskPassphrase() != null - && securityConfig.getPskPassphrase().length() != 0) { - req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; - convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), - req.securityConfig.passphrase); - } - if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { - copyArray(securityConfig.getPmkId(), req.securityConfig.scid); - } - } - - if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { - convertNativeByteArrayToArrayList( - SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), - req.serviceNameOutOfBand); - } - convertNativeByteArrayToArrayList(appInfo, req.appInfo); - - try { - WifiStatus status = iface16 - .respondToDataPathIndicationRequest_1_6(transactionId, req); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "respondToDataPathRequest_1_6: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "respondToDataPathRequest_1_6: exception: " + e); - return false; - } - } + return iface.respondToDataPathRequest(transactionId, accept, ndpId, interfaceName, appInfo, + isOutOfBand, capabilities, securityConfig); } /** @@ -1444,35 +669,22 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC } recordTransactionId(transactionId); - IWifiNanIface iface = mHal.getWifiNanIface(); + WifiNanIface iface = mHal.getWifiNanIface(); if (iface == null) { Log.e(TAG, "endDataPath: null interface"); return false; } - - try { - WifiStatus status = iface.terminateDataPathRequest(transactionId, ndpId); - if (status.code == WifiStatusCode.SUCCESS) { - return true; - } else { - Log.e(TAG, "endDataPath: error: " + statusString(status)); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "endDataPath: exception: " + e); - return false; - } + return iface.endDataPath(transactionId, ndpId); } - // utilities /** - * Update the NAN configuration to reflect the current power settings (before V1.4) + * Create a PowerParameters object to pass our cached parameters to the HAL. */ - private void updateConfigForPowerSettings(NanConfigRequest req, - android.hardware.wifi.V1_2.NanConfigRequestSupplemental configSupplemental12, + private PowerParameters getPowerParameters( boolean isInteractive, boolean isIdle) { + PowerParameters params = new PowerParameters(); String key = POWER_PARAM_DEFAULT_KEY; if (isIdle) { key = POWER_PARAM_IDLE_KEY; @@ -1480,46 +692,16 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC key = POWER_PARAM_INACTIVE_KEY; } - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], - getSettablePowerParameters(key, PARAM_DW_5GHZ)); - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], - getSettablePowerParameters(key, PARAM_DW_24GHZ)); - - configSupplemental12.discoveryBeaconIntervalMs = getSettablePowerParameters(key, + params.discoveryWindow24Ghz = getSettablePowerParameters(key, PARAM_DW_24GHZ); + params.discoveryWindow5Ghz = getSettablePowerParameters(key, PARAM_DW_5GHZ); + params.discoveryWindow6Ghz = getSettablePowerParameters(key, PARAM_DW_6GHZ); + params.discoveryBeaconIntervalMs = getSettablePowerParameters(key, PARAM_DISCOVERY_BEACON_INTERVAL_MS); - configSupplemental12.numberOfSpatialStreamsInDiscovery = getSettablePowerParameters(key, + params.numberOfSpatialStreamsInDiscovery = getSettablePowerParameters(key, PARAM_NUM_SS_IN_DISCOVERY); - configSupplemental12.enableDiscoveryWindowEarlyTermination = getSettablePowerParameters(key, + params.enableDiscoveryWindowEarlyTermination = getSettablePowerParameters(key, PARAM_ENABLE_DW_EARLY_TERM) != 0; - } - - /** - * Update the NAN configuration to reflect the current power settings (V1.4) - */ - private void updateConfigForPowerSettings14(android.hardware.wifi.V1_4.NanConfigRequest req, - android.hardware.wifi.V1_2.NanConfigRequestSupplemental configSupplemental12, - boolean isInteractive, boolean isIdle) { - String key = POWER_PARAM_DEFAULT_KEY; - if (isIdle) { - key = POWER_PARAM_IDLE_KEY; - } else if (!isInteractive) { - key = POWER_PARAM_INACTIVE_KEY; - } - - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], - getSettablePowerParameters(key, PARAM_DW_5GHZ)); - updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], - getSettablePowerParameters(key, PARAM_DW_24GHZ)); - updateSingleConfigForPowerSettings(req.bandSpecificConfig[ - android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ], - getSettablePowerParameters(key, PARAM_DW_6GHZ)); - - configSupplemental12.discoveryBeaconIntervalMs = getSettablePowerParameters(key, - PARAM_DISCOVERY_BEACON_INTERVAL_MS); - configSupplemental12.numberOfSpatialStreamsInDiscovery = getSettablePowerParameters(key, - PARAM_NUM_SS_IN_DISCOVERY); - configSupplemental12.enableDiscoveryWindowEarlyTermination = - getSettablePowerParameters(key, PARAM_ENABLE_DW_EARLY_TERM) != 0; + return params; } private int getSettablePowerParameters(String state, String key) { @@ -1529,74 +711,6 @@ public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellC return mSettablePowerParameters.get(state).get(key); } - private void updateSingleConfigForPowerSettings(NanBandSpecificConfig cfg, int override) { - if (override != -1) { - cfg.validDiscoveryWindowIntervalVal = true; - cfg.discoveryWindowIntervalVal = (byte) override; - } - } - - /** - * Returns the HAL cipher suite. - */ - private 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_128_MASK; - case WIFI_AWARE_CIPHER_SUITE_NCS_PK_256: - return NanCipherSuiteType.PUBLIC_KEY_256_MASK; - } - return NanCipherSuiteType.NONE; - } - - /** - * Converts a byte[] to an ArrayList<Byte>. Fills in the entries of the 'to' array if - * provided (non-null), otherwise creates and returns a new ArrayList<>. - * - * @param from The input byte[] to convert from. - * @param to An optional ArrayList<> to fill in from 'from'. - * - * @return A newly allocated ArrayList<> if 'to' is null, otherwise null. - */ - private ArrayList<Byte> convertNativeByteArrayToArrayList(byte[] from, ArrayList<Byte> to) { - if (from == null) { - from = new byte[0]; - } - - if (to == null) { - to = new ArrayList<>(from.length); - } else { - to.ensureCapacity(from.length); - } - for (int i = 0; i < from.length; ++i) { - to.add(from[i]); - } - return to; - } - - private void copyArray(byte[] from, byte[] to) { - if (from == null || to == null || from.length != to.length) { - Log.e(TAG, "copyArray error: from=" + from + ", to=" + to); - return; - } - for (int i = 0; i < from.length; ++i) { - to[i] = from[i]; - } - } - - private static String statusString(WifiStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.code).append(" (").append(status.description).append(")"); - return sb.toString(); - } - /** * Dump the internal state of the class. */ diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java index 63296e638b..79496a104e 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java @@ -16,30 +16,15 @@ package com.android.server.wifi.aware; -import android.hardware.wifi.V1_0.NanClusterEventInd; -import android.hardware.wifi.V1_0.NanClusterEventType; -import android.hardware.wifi.V1_0.NanDataPathConfirmInd; -import android.hardware.wifi.V1_0.NanDataPathRequestInd; -import android.hardware.wifi.V1_0.NanFollowupReceivedInd; -import android.hardware.wifi.V1_0.NanMatchInd; -import android.hardware.wifi.V1_0.NanStatusType; -import android.hardware.wifi.V1_0.WifiNanStatus; -import android.hardware.wifi.V1_2.NanDataPathScheduleUpdateInd; -import android.hardware.wifi.V1_6.IWifiNanIfaceEventCallback; -import android.hardware.wifi.V1_6.NanCipherSuiteType; -import android.hardware.wifi.V1_6.WifiChannelWidthInMhz; -import android.net.MacAddress; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiAnnotations; -import android.net.wifi.aware.Characteristics; import android.net.wifi.aware.WifiAwareChannelInfo; -import android.net.wifi.util.HexEncoding; -import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.modules.utils.BasicShellCommandHandler; +import com.android.server.wifi.hal.WifiNanIface; +import com.android.server.wifi.hal.WifiNanIface.NanClusterEventType; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import org.json.JSONArray; import org.json.JSONException; @@ -48,21 +33,16 @@ import org.json.JSONObject; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** - * Manages the callbacks from Wi-Fi Aware HIDL (HAL). + * Manages the callbacks from Wi-Fi Aware HAL. */ -public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub implements +public class WifiAwareNativeCallback implements WifiNanIface.Callback, WifiAwareShellCommand.DelegatedShellCommand { private static final String TAG = "WifiAwareNativeCallback"; private boolean mVerboseHalLoggingEnabled = false; - /* package */ boolean mIsHal12OrLater = false; - /* package */ boolean mIsHal15OrLater = false; - /* package */ boolean mIsHal16OrLater = false; - private final WifiAwareStateManager mWifiAwareStateManager; public WifiAwareNativeCallback(WifiAwareStateManager wifiAwareStateManager) { @@ -172,602 +152,198 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp } @Override - public void notifyCapabilitiesResponse(short id, WifiNanStatus status, - android.hardware.wifi.V1_0.NanCapabilities capabilities) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyCapabilitiesResponse: id=" + id + ", status=" + statusString(status) - + ", capabilities=" + capabilities); - } - - if (mIsHal15OrLater) { - Log.wtf(TAG, "notifyCapabilitiesResponse should not be called by a >=1.5 HAL!"); - } - - if (status.status == NanStatusType.SUCCESS) { - Capabilities frameworkCapabilities = toFrameworkCapability10(capabilities); - - mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, frameworkCapabilities); - } else { - Log.e(TAG, "notifyCapabilitiesResponse: error code=" + status.status + " (" - + status.description + ")"); - } - } - - @Override - public void notifyCapabilitiesResponse_1_5(short id, WifiNanStatus status, - android.hardware.wifi.V1_5.NanCapabilities capabilities) throws RemoteException { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyCapabilitiesResponse_1_5: id=" + id + ", status=" - + statusString(status) + ", capabilities=" + capabilities); - } - - if (!mIsHal15OrLater) { - Log.wtf(TAG, "notifyCapabilitiesResponse_1_5 should not be called by a <1.5 HAL!"); - return; - } - - if (status.status == NanStatusType.SUCCESS) { - Capabilities frameworkCapabilities = toFrameworkCapability10(capabilities.V1_0); - frameworkCapabilities.isInstantCommunicationModeSupported = - capabilities.instantCommunicationModeSupportFlag; - - mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, frameworkCapabilities); - } else { - Log.e(TAG, "notifyCapabilitiesResponse_1_5: error code=" + status.status + " (" - + status.description + ")"); - } - } - - @Override - public void notifyCapabilitiesResponse_1_6(short id, WifiNanStatus status, - android.hardware.wifi.V1_6.NanCapabilities capabilities) throws RemoteException { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyCapabilitiesResponse_1_6: id=" + id + ", status=" - + statusString(status) + ", capabilities=" + capabilities); - } - - if (!mIsHal16OrLater) { - Log.wtf(TAG, "notifyCapabilitiesResponse_1_6 should not be called by a <1.6 HAL!"); - return; - } - - if (status.status == NanStatusType.SUCCESS) { - Capabilities frameworkCapabilities = toFrameworkCapability1_6(capabilities); - - mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, frameworkCapabilities); - } else { - Log.e(TAG, "notifyCapabilitiesResponse_1_6: error code=" + status.status + " (" - + status.description + ")"); - } - } - - private Capabilities toFrameworkCapability1_6( - android.hardware.wifi.V1_6.NanCapabilities capabilities) { - Capabilities frameworkCapabilities = new Capabilities(); - frameworkCapabilities.maxConcurrentAwareClusters = capabilities.maxConcurrentClusters; - frameworkCapabilities.maxPublishes = capabilities.maxPublishes; - frameworkCapabilities.maxSubscribes = capabilities.maxSubscribes; - frameworkCapabilities.maxServiceNameLen = capabilities.maxServiceNameLen; - frameworkCapabilities.maxMatchFilterLen = capabilities.maxMatchFilterLen; - frameworkCapabilities.maxTotalMatchFilterLen = capabilities.maxTotalMatchFilterLen; - frameworkCapabilities.maxServiceSpecificInfoLen = - capabilities.maxServiceSpecificInfoLen; - frameworkCapabilities.maxExtendedServiceSpecificInfoLen = - capabilities.maxExtendedServiceSpecificInfoLen; - frameworkCapabilities.maxNdiInterfaces = capabilities.maxNdiInterfaces; - frameworkCapabilities.maxNdpSessions = capabilities.maxNdpSessions; - frameworkCapabilities.maxAppInfoLen = capabilities.maxAppInfoLen; - frameworkCapabilities.maxQueuedTransmitMessages = - capabilities.maxQueuedTransmitFollowupMsgs; - frameworkCapabilities.maxSubscribeInterfaceAddresses = - capabilities.maxSubscribeInterfaceAddresses; - frameworkCapabilities.supportedCipherSuites = toPublicCipherSuites( - capabilities.supportedCipherSuites); - frameworkCapabilities.isInstantCommunicationModeSupported = - capabilities.instantCommunicationModeSupportFlag; - return frameworkCapabilities; - } - - private Capabilities toFrameworkCapability10( - android.hardware.wifi.V1_0.NanCapabilities capabilities) { - Capabilities frameworkCapabilities = new Capabilities(); - frameworkCapabilities.maxConcurrentAwareClusters = capabilities.maxConcurrentClusters; - frameworkCapabilities.maxPublishes = capabilities.maxPublishes; - frameworkCapabilities.maxSubscribes = capabilities.maxSubscribes; - frameworkCapabilities.maxServiceNameLen = capabilities.maxServiceNameLen; - frameworkCapabilities.maxMatchFilterLen = capabilities.maxMatchFilterLen; - frameworkCapabilities.maxTotalMatchFilterLen = capabilities.maxTotalMatchFilterLen; - frameworkCapabilities.maxServiceSpecificInfoLen = - capabilities.maxServiceSpecificInfoLen; - frameworkCapabilities.maxExtendedServiceSpecificInfoLen = - capabilities.maxExtendedServiceSpecificInfoLen; - frameworkCapabilities.maxNdiInterfaces = capabilities.maxNdiInterfaces; - frameworkCapabilities.maxNdpSessions = capabilities.maxNdpSessions; - frameworkCapabilities.maxAppInfoLen = capabilities.maxAppInfoLen; - frameworkCapabilities.maxQueuedTransmitMessages = - capabilities.maxQueuedTransmitFollowupMsgs; - frameworkCapabilities.maxSubscribeInterfaceAddresses = - capabilities.maxSubscribeInterfaceAddresses; - frameworkCapabilities.supportedCipherSuites = toPublicCipherSuites( - capabilities.supportedCipherSuites); - frameworkCapabilities.isInstantCommunicationModeSupported = false; - return frameworkCapabilities; - } - - private int toPublicCipherSuites(int nativeCipherSuites) { - int publicCipherSuites = 0; - - if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_128_MASK) != 0) { - publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; - } - if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_256_MASK) != 0) { - publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; - } - if ((nativeCipherSuites & NanCipherSuiteType.PUBLIC_KEY_128_MASK) != 0) { - publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_128; - } - if ((nativeCipherSuites & NanCipherSuiteType.PUBLIC_KEY_256_MASK) != 0) { - publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_256; - } - - return publicCipherSuites; + public void notifyCapabilitiesResponse(short id, Capabilities capabilities) { + mWifiAwareStateManager.onCapabilitiesUpdateResponse(id, capabilities); } @Override - public void notifyEnableResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyEnableResponse: id=" + id + ", status=" + statusString(status)); - } - - if (status.status == NanStatusType.ALREADY_ENABLED) { - Log.wtf(TAG, "notifyEnableResponse: id=" + id + ", already enabled!?"); - } - - if (status.status == NanStatusType.SUCCESS - || status.status == NanStatusType.ALREADY_ENABLED) { + public void notifyEnableResponse(short id, int status) { + if (status == NanStatusCode.SUCCESS + || status == NanStatusCode.ALREADY_ENABLED) { mWifiAwareStateManager.onConfigSuccessResponse(id); } else { - mWifiAwareStateManager.onConfigFailedResponse(id, status.status); + mWifiAwareStateManager.onConfigFailedResponse(id, status); } } @Override - public void notifyConfigResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyConfigResponse: id=" + id + ", status=" + statusString(status)); - } - - if (status.status == NanStatusType.SUCCESS) { + public void notifyConfigResponse(short id, int status) { + if (status == NanStatusCode.SUCCESS) { mWifiAwareStateManager.onConfigSuccessResponse(id); } else { - mWifiAwareStateManager.onConfigFailedResponse(id, status.status); + mWifiAwareStateManager.onConfigFailedResponse(id, status); } } @Override - public void notifyDisableResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyDisableResponse: id=" + id + ", status=" + statusString(status)); - } - - if (status.status != NanStatusType.SUCCESS) { - Log.e(TAG, "notifyDisableResponse: failure - code=" + status.status + " (" - + status.description + ")"); - } - mWifiAwareStateManager.onDisableResponse(id, status.status); + public void notifyDisableResponse(short id, int status) { + mWifiAwareStateManager.onDisableResponse(id, status); } @Override - public void notifyStartPublishResponse(short id, WifiNanStatus status, byte publishId) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyStartPublishResponse: id=" + id + ", status=" + statusString(status) - + ", publishId=" + publishId); - } - - if (status.status == NanStatusType.SUCCESS) { + public void notifyStartPublishResponse(short id, int status, byte publishId) { + if (status == NanStatusCode.SUCCESS) { mWifiAwareStateManager.onSessionConfigSuccessResponse(id, true, publishId); } else { - mWifiAwareStateManager.onSessionConfigFailResponse(id, true, status.status); - } - } - - @Override - public void notifyStopPublishResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyStopPublishResponse: id=" + id + ", status=" + statusString(status)); - } - - if (status.status == NanStatusType.SUCCESS) { - // NOP - } else { - Log.e(TAG, "notifyStopPublishResponse: failure - code=" + status.status + " (" - + status.description + ")"); + mWifiAwareStateManager.onSessionConfigFailResponse(id, true, status); } } @Override - public void notifyStartSubscribeResponse(short id, WifiNanStatus status, byte subscribeId) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyStartSubscribeResponse: id=" + id + ", status=" + statusString(status) - + ", subscribeId=" + subscribeId); - } - - if (status.status == NanStatusType.SUCCESS) { + public void notifyStartSubscribeResponse(short id, int status, byte subscribeId) { + if (status == NanStatusCode.SUCCESS) { mWifiAwareStateManager.onSessionConfigSuccessResponse(id, false, subscribeId); } else { - mWifiAwareStateManager.onSessionConfigFailResponse(id, false, status.status); + mWifiAwareStateManager.onSessionConfigFailResponse(id, false, status); } } @Override - public void notifyStopSubscribeResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyStopSubscribeResponse: id=" + id + ", status=" - + statusString(status)); - } - - if (status.status == NanStatusType.SUCCESS) { - // NOP - } else { - Log.e(TAG, "notifyStopSubscribeResponse: failure - code=" + status.status + " (" - + status.description + ")"); - } - } - - @Override - public void notifyTransmitFollowupResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyTransmitFollowupResponse: id=" + id + ", status=" - + statusString(status)); - } - - if (status.status == NanStatusType.SUCCESS) { + public void notifyTransmitFollowupResponse(short id, int status) { + if (status == NanStatusCode.SUCCESS) { mWifiAwareStateManager.onMessageSendQueuedSuccessResponse(id); } else { - mWifiAwareStateManager.onMessageSendQueuedFailResponse(id, status.status); + mWifiAwareStateManager.onMessageSendQueuedFailResponse(id, status); } } @Override - public void notifyCreateDataInterfaceResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyCreateDataInterfaceResponse: id=" + id + ", status=" - + statusString(status)); - } - + public void notifyCreateDataInterfaceResponse(short id, int status) { mWifiAwareStateManager.onCreateDataPathInterfaceResponse(id, - status.status == NanStatusType.SUCCESS, status.status); + status == NanStatusCode.SUCCESS, status); } @Override - public void notifyDeleteDataInterfaceResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyDeleteDataInterfaceResponse: id=" + id + ", status=" - + statusString(status)); - } - + public void notifyDeleteDataInterfaceResponse(short id, int status) { mWifiAwareStateManager.onDeleteDataPathInterfaceResponse(id, - status.status == NanStatusType.SUCCESS, status.status); + status == NanStatusCode.SUCCESS, status); } @Override - public void notifyInitiateDataPathResponse(short id, WifiNanStatus status, + public void notifyInitiateDataPathResponse(short id, int status, int ndpInstanceId) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyInitiateDataPathResponse: id=" + id + ", status=" - + statusString(status) + ", ndpInstanceId=" + ndpInstanceId); - } - - if (status.status == NanStatusType.SUCCESS) { + if (status == NanStatusCode.SUCCESS) { mWifiAwareStateManager.onInitiateDataPathResponseSuccess(id, ndpInstanceId); } else { - mWifiAwareStateManager.onInitiateDataPathResponseFail(id, status.status); + mWifiAwareStateManager.onInitiateDataPathResponseFail(id, status); } } @Override - public void notifyRespondToDataPathIndicationResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyRespondToDataPathIndicationResponse: id=" + id - + ", status=" + statusString(status)); - } - + public void notifyRespondToDataPathIndicationResponse(short id, int status) { mWifiAwareStateManager.onRespondToDataPathSetupRequestResponse(id, - status.status == NanStatusType.SUCCESS, status.status); + status == NanStatusCode.SUCCESS, status); } @Override - public void notifyTerminateDataPathResponse(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "notifyTerminateDataPathResponse: id=" + id + ", status=" - + statusString(status)); - } - - mWifiAwareStateManager.onEndDataPathResponse(id, status.status == NanStatusType.SUCCESS, - status.status); + public void notifyTerminateDataPathResponse(short id, int status) { + mWifiAwareStateManager.onEndDataPathResponse(id, status == NanStatusCode.SUCCESS, + status); } @Override - public void eventClusterEvent(NanClusterEventInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventClusterEvent: eventType=" + event.eventType + ", addr=" - + String.valueOf(HexEncoding.encode(event.addr))); - } + public void eventClusterEvent(int eventType, byte[] addr) { incrementCbCount(CB_EV_CLUSTER); - - if (event.eventType == NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED) { - mWifiAwareStateManager.onInterfaceAddressChangeNotification(event.addr); - } else if (event.eventType == NanClusterEventType.STARTED_CLUSTER) { + if (eventType == NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED) { + mWifiAwareStateManager.onInterfaceAddressChangeNotification(addr); + } else if (eventType == NanClusterEventType.STARTED_CLUSTER) { mWifiAwareStateManager.onClusterChangeNotification( - WifiAwareClientState.CLUSTER_CHANGE_EVENT_STARTED, event.addr); - } else if (event.eventType == NanClusterEventType.JOINED_CLUSTER) { + WifiAwareClientState.CLUSTER_CHANGE_EVENT_STARTED, addr); + } else if (eventType == NanClusterEventType.JOINED_CLUSTER) { mWifiAwareStateManager.onClusterChangeNotification( - WifiAwareClientState.CLUSTER_CHANGE_EVENT_JOINED, event.addr); + WifiAwareClientState.CLUSTER_CHANGE_EVENT_JOINED, addr); } else { - Log.e(TAG, "eventClusterEvent: invalid eventType=" + event.eventType); + Log.e(TAG, "eventClusterEvent: invalid eventType=" + eventType); } } @Override - public void eventDisabled(WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) Log.v(TAG, "eventDisabled: status=" + statusString(status)); + public void eventDisabled(int status) { incrementCbCount(CB_EV_DISABLED); - - mWifiAwareStateManager.onAwareDownNotification(status.status); + mWifiAwareStateManager.onAwareDownNotification(status); } @Override - public void eventPublishTerminated(byte sessionId, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventPublishTerminated: sessionId=" + sessionId + ", status=" - + statusString(status)); - } + public void eventPublishTerminated(byte sessionId, int status) { incrementCbCount(CB_EV_PUBLISH_TERMINATED); - - mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status.status, true); + mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status, true); } @Override - public void eventSubscribeTerminated(byte sessionId, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventSubscribeTerminated: sessionId=" + sessionId + ", status=" - + statusString(status)); - } + public void eventSubscribeTerminated(byte sessionId, int status) { incrementCbCount(CB_EV_SUBSCRIBE_TERMINATED); - - mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status.status, false); - } - - @Override - public void eventMatch(NanMatchInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventMatch: discoverySessionId=" + event.discoverySessionId + ", peerId=" - + event.peerId + ", addr=" + String.valueOf(HexEncoding.encode(event.addr)) - + ", serviceSpecificInfo=" + Arrays.toString( - convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" - + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size()) - + ", matchFilter=" + Arrays.toString( - convertArrayListToNativeByteArray(event.matchFilter)) + ", mf.size()=" + ( - event.matchFilter == null ? 0 : event.matchFilter.size()) - + ", rangingIndicationType=" + event.rangingIndicationType - + ", rangingMeasurementInCm=" + event.rangingMeasurementInCm); - } - incrementCbCount(CB_EV_MATCH); - - // TODO: b/69428593 get rid of conversion once HAL moves from CM to MM - mWifiAwareStateManager.onMatchNotification(event.discoverySessionId, event.peerId, - event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo), - convertArrayListToNativeByteArray(event.matchFilter), event.rangingIndicationType, - event.rangingMeasurementInCm * 10, new byte[0], 0); + mWifiAwareStateManager.onSessionTerminatedNotification(sessionId, status, false); } @Override - public void eventMatch_1_6(android.hardware.wifi.V1_6.NanMatchInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventMatch_1_6: discoverySessionId=" + event.discoverySessionId - + ", peerId=" + event.peerId - + ", addr=" + String.valueOf(HexEncoding.encode(event.addr)) - + ", serviceSpecificInfo=" + Arrays.toString( - convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" - + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size()) - + ", matchFilter=" + Arrays.toString( - convertArrayListToNativeByteArray(event.matchFilter)) + ", mf.size()=" + ( - event.matchFilter == null ? 0 : event.matchFilter.size()) - + ", rangingIndicationType=" + event.rangingIndicationType - + ", rangingMeasurementInCm=" + event.rangingMeasurementInMm + ", " - + "scid=" + Arrays.toString(convertArrayListToNativeByteArray(event.scid))); - } + public void eventMatch(byte discoverySessionId, int peerId, byte[] addr, + byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndicationType, + int rangingMeasurementInMm, byte[] scid, int peerCipherType) { incrementCbCount(CB_EV_MATCH); - - // TODO: b/69428593 get rid of conversion once HAL moves from CM to MM - mWifiAwareStateManager.onMatchNotification(event.discoverySessionId, event.peerId, - event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo), - convertArrayListToNativeByteArray(event.matchFilter), event.rangingIndicationType, - event.rangingMeasurementInMm, - convertArrayListToNativeByteArray(event.scid), - toPublicCipherSuites(event.peerCipherType)); + mWifiAwareStateManager.onMatchNotification(discoverySessionId, peerId, + addr, serviceSpecificInfo, matchFilter, rangingIndicationType, + rangingMeasurementInMm, scid, peerCipherType); } @Override public void eventMatchExpired(byte discoverySessionId, int peerId) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventMatchExpired: discoverySessionId=" + discoverySessionId - + ", peerId=" + peerId); - } incrementCbCount(CB_EV_MATCH_EXPIRED); mWifiAwareStateManager.onMatchExpiredNotification(discoverySessionId, peerId); } @Override - public void eventFollowupReceived(NanFollowupReceivedInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventFollowupReceived: discoverySessionId=" + event.discoverySessionId - + ", peerId=" + event.peerId + ", addr=" + String.valueOf( - HexEncoding.encode(event.addr)) + ", serviceSpecificInfo=" + Arrays.toString( - convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" - + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size())); - } + public void eventFollowupReceived(byte discoverySessionId, int peerId, byte[] addr, + byte[] serviceSpecificInfo) { incrementCbCount(CB_EV_FOLLOWUP_RECEIVED); - - mWifiAwareStateManager.onMessageReceivedNotification(event.discoverySessionId, event.peerId, - event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo)); + mWifiAwareStateManager.onMessageReceivedNotification(discoverySessionId, peerId, + addr, serviceSpecificInfo); } @Override - public void eventTransmitFollowup(short id, WifiNanStatus status) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventTransmitFollowup: id=" + id + ", status=" + statusString(status)); - } + public void eventTransmitFollowup(short id, int status) { incrementCbCount(CB_EV_TRANSMIT_FOLLOWUP); - - if (status.status == NanStatusType.SUCCESS) { + if (status == NanStatusCode.SUCCESS) { mWifiAwareStateManager.onMessageSendSuccessNotification(id); } else { - mWifiAwareStateManager.onMessageSendFailNotification(id, status.status); + mWifiAwareStateManager.onMessageSendFailNotification(id, status); } } @Override - public void eventDataPathRequest(NanDataPathRequestInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventDataPathRequest: discoverySessionId=" + event.discoverySessionId - + ", peerDiscMacAddr=" + String.valueOf( - HexEncoding.encode(event.peerDiscMacAddr)) + ", ndpInstanceId=" - + event.ndpInstanceId + ", appInfo.size()=" + event.appInfo.size()); - } + public void eventDataPathRequest(byte discoverySessionId, byte[] peerDiscMacAddr, + int ndpInstanceId, byte[] appInfo) { incrementCbCount(CB_EV_DATA_PATH_REQUEST); - - mWifiAwareStateManager.onDataPathRequestNotification(event.discoverySessionId, - event.peerDiscMacAddr, event.ndpInstanceId, - convertArrayListToNativeByteArray(event.appInfo)); + mWifiAwareStateManager.onDataPathRequestNotification(discoverySessionId, + peerDiscMacAddr, ndpInstanceId, appInfo); } @Override - public void eventDataPathConfirm(NanDataPathConfirmInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "onDataPathConfirm: ndpInstanceId=" + event.ndpInstanceId - + ", peerNdiMacAddr=" + String.valueOf(HexEncoding.encode(event.peerNdiMacAddr)) - + ", dataPathSetupSuccess=" + event.dataPathSetupSuccess + ", reason=" - + event.status.status + ", appInfo.size()=" + event.appInfo.size()); - } - if (mIsHal12OrLater) { - Log.wtf(TAG, "eventDataPathConfirm should not be called by a >=1.2 HAL!"); - } + public void eventDataPathConfirm(int status, int ndpInstanceId, boolean dataPathSetupSuccess, + byte[] peerNdiMacAddr, byte[] appInfo, + List<WifiAwareChannelInfo> channelInfos) { incrementCbCount(CB_EV_DATA_PATH_CONFIRM); - - mWifiAwareStateManager.onDataPathConfirmNotification(event.ndpInstanceId, - event.peerNdiMacAddr, event.dataPathSetupSuccess, event.status.status, - convertArrayListToNativeByteArray(event.appInfo), null); - } - - @Override - public void eventDataPathConfirm_1_2(android.hardware.wifi.V1_2.NanDataPathConfirmInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventDataPathConfirm_1_2: ndpInstanceId=" + event.V1_0.ndpInstanceId - + ", peerNdiMacAddr=" + String.valueOf( - HexEncoding.encode(event.V1_0.peerNdiMacAddr)) + ", dataPathSetupSuccess=" - + event.V1_0.dataPathSetupSuccess + ", reason=" + event.V1_0.status.status - + ", appInfo.size()=" + event.V1_0.appInfo.size() - + ", channelInfo" + event.channelInfo); - } - if (!mIsHal12OrLater) { - Log.wtf(TAG, "eventDataPathConfirm_1_2 should not be called by a <1.2 HAL!"); - return; - } - - List<WifiAwareChannelInfo> wifiAwareChannelInfos = - convertHalChannelInfo_1_2(event.channelInfo); - incrementCbCount(CB_EV_DATA_PATH_CONFIRM); - mChannelInfoPerNdp.put(event.V1_0.ndpInstanceId, wifiAwareChannelInfos); - - mWifiAwareStateManager.onDataPathConfirmNotification(event.V1_0.ndpInstanceId, - event.V1_0.peerNdiMacAddr, event.V1_0.dataPathSetupSuccess, - event.V1_0.status.status, convertArrayListToNativeByteArray(event.V1_0.appInfo), - wifiAwareChannelInfos); - } - - @Override - public void eventDataPathConfirm_1_6(android.hardware.wifi.V1_6.NanDataPathConfirmInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventDataPathConfirm_1_6: ndpInstanceId=" + event.V1_0.ndpInstanceId - + ", peerNdiMacAddr=" + String.valueOf( - HexEncoding.encode(event.V1_0.peerNdiMacAddr)) + ", dataPathSetupSuccess=" - + event.V1_0.dataPathSetupSuccess + ", reason=" + event.V1_0.status.status - + ", appInfo.size()=" + event.V1_0.appInfo.size() - + ", channelInfo" + event.channelInfo); - } - if (!mIsHal16OrLater) { - Log.wtf(TAG, "eventDataPathConfirm_1_6 should not be called by a <1.6 HAL!"); - return; - } - - List<WifiAwareChannelInfo> wifiAwareChannelInfos = - convertHalChannelInfo_1_6(event.channelInfo); - incrementCbCount(CB_EV_DATA_PATH_CONFIRM); - mChannelInfoPerNdp.put(event.V1_0.ndpInstanceId, wifiAwareChannelInfos); - - mWifiAwareStateManager.onDataPathConfirmNotification(event.V1_0.ndpInstanceId, - event.V1_0.peerNdiMacAddr, event.V1_0.dataPathSetupSuccess, - event.V1_0.status.status, convertArrayListToNativeByteArray(event.V1_0.appInfo), - wifiAwareChannelInfos); - } - - @Override - public void eventDataPathScheduleUpdate(NanDataPathScheduleUpdateInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventDataPathScheduleUpdate: peerMac=" - + MacAddress.fromBytes(event.peerDiscoveryAddress).toString() - + ", ndpIds=" + event.ndpInstanceIds + ", channelInfo=" + event.channelInfo); + if (channelInfos != null) { + mChannelInfoPerNdp.put(ndpInstanceId, channelInfos); } - if (!mIsHal12OrLater) { - Log.wtf(TAG, "eventDataPathScheduleUpdate should not be called by a <1.2 HAL!"); - return; - } - - List<WifiAwareChannelInfo> wifiAwareChannelInfos = - convertHalChannelInfo_1_2(event.channelInfo); - incrementCbCount(CB_EV_DATA_PATH_SCHED_UPDATE); - for (int ndpInstanceId : event.ndpInstanceIds) { - mChannelInfoPerNdp.put(ndpInstanceId, wifiAwareChannelInfos); - } - - mWifiAwareStateManager.onDataPathScheduleUpdateNotification(event.peerDiscoveryAddress, - event.ndpInstanceIds, wifiAwareChannelInfos); + mWifiAwareStateManager.onDataPathConfirmNotification(ndpInstanceId, + peerNdiMacAddr, dataPathSetupSuccess, status, appInfo, channelInfos); } @Override - public void eventDataPathScheduleUpdate_1_6( - android.hardware.wifi.V1_6.NanDataPathScheduleUpdateInd event) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, "eventDataPathScheduleUpdate_1_6: peerMac=" - + MacAddress.fromBytes(event.peerDiscoveryAddress).toString() - + ", ndpIds=" + event.ndpInstanceIds + ", channelInfo=" + event.channelInfo); - } - if (!mIsHal16OrLater) { - Log.wtf(TAG, "eventDataPathScheduleUpdate_1_6 should not be called by a <1.6 HAL!"); - return; - } - - List<WifiAwareChannelInfo> wifiAwareChannelInfos = - convertHalChannelInfo_1_6(event.channelInfo); + public void eventDataPathScheduleUpdate(byte[] peerDiscoveryAddress, + ArrayList<Integer> ndpInstanceIds, List<WifiAwareChannelInfo> channelInfo) { incrementCbCount(CB_EV_DATA_PATH_SCHED_UPDATE); - for (int ndpInstanceId : event.ndpInstanceIds) { - mChannelInfoPerNdp.put(ndpInstanceId, wifiAwareChannelInfos); + for (int ndpInstanceId : ndpInstanceIds) { + mChannelInfoPerNdp.put(ndpInstanceId, channelInfo); } - - mWifiAwareStateManager.onDataPathScheduleUpdateNotification(event.peerDiscoveryAddress, - event.ndpInstanceIds, wifiAwareChannelInfos); + mWifiAwareStateManager.onDataPathScheduleUpdateNotification(peerDiscoveryAddress, + ndpInstanceIds, channelInfo); } @Override public void eventDataPathTerminated(int ndpInstanceId) { - if (mVerboseHalLoggingEnabled) { - Log.v(TAG, - "eventDataPathTerminated: ndpInstanceId=" + ndpInstanceId); - } incrementCbCount(CB_EV_DATA_PATH_TERMINATED); mChannelInfoPerNdp.remove(ndpInstanceId); - mWifiAwareStateManager.onDataPathEndNotification(ndpInstanceId); } @@ -791,34 +367,6 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp // utilities /** - * Converts an ArrayList<Byte> to a byte[]. - * - * @param from The input ArrayList<Byte></Byte> to convert from. - * - * @return A newly allocated byte[]. - */ - private byte[] convertArrayListToNativeByteArray(ArrayList<Byte> from) { - if (from == null) { - return null; - } - - byte[] to = new byte[from.size()]; - for (int i = 0; i < from.size(); ++i) { - to[i] = from.get(i); - } - return to; - } - - private static String statusString(WifiNanStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.status).append(" (").append(status.description).append(")"); - return sb.toString(); - } - - /** * Transfer the channel Info dict into a Json String which can be decoded by Json reader. * The Format is: "{ndpInstanceId: [{"channelFreq": channelFreq, * "channelBandwidth": channelBandwidth, "numSpatialStreams": numSpatialStreams}]}" @@ -843,56 +391,4 @@ public class WifiAwareNativeCallback extends IWifiNanIfaceEventCallback.Stub imp } return channelInfoJson.toString(); } - - /** - * Convert HAL channelBandwidth to framework enum - */ - private @WifiAnnotations.ChannelWidth int getChannelBandwidthFromHal(int channelBandwidth) { - switch(channelBandwidth) { - case WifiChannelWidthInMhz.WIDTH_40: - return ScanResult.CHANNEL_WIDTH_40MHZ; - case WifiChannelWidthInMhz.WIDTH_80: - return ScanResult.CHANNEL_WIDTH_80MHZ; - case WifiChannelWidthInMhz.WIDTH_160: - return ScanResult.CHANNEL_WIDTH_160MHZ; - case WifiChannelWidthInMhz.WIDTH_80P80: - return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; - case WifiChannelWidthInMhz.WIDTH_320: - return ScanResult.CHANNEL_WIDTH_320MHZ; - default: - return ScanResult.CHANNEL_WIDTH_20MHZ; - } - } - /** - * Convert HAL V1_2 NanDataPathChannelInfo to WifiAwareChannelInfo - */ - private List<WifiAwareChannelInfo> convertHalChannelInfo_1_2( - List<android.hardware.wifi.V1_2.NanDataPathChannelInfo> channelInfos) { - List<WifiAwareChannelInfo> wifiAwareChannelInfos = new ArrayList<>(); - if (channelInfos == null) { - return null; - } - for (android.hardware.wifi.V1_2.NanDataPathChannelInfo channelInfo : channelInfos) { - wifiAwareChannelInfos.add(new WifiAwareChannelInfo(channelInfo.channelFreq, - getChannelBandwidthFromHal(channelInfo.channelBandwidth), - channelInfo.numSpatialStreams)); - } - return wifiAwareChannelInfos; - } - /** - * Convert HAL V1_6 NanDataPathChannelInfo to WifiAwareChannelInfo - */ - private List<WifiAwareChannelInfo> convertHalChannelInfo_1_6( - List<android.hardware.wifi.V1_6.NanDataPathChannelInfo> channelInfos) { - List<WifiAwareChannelInfo> wifiAwareChannelInfos = new ArrayList<>(); - if (channelInfos == null) { - return null; - } - for (android.hardware.wifi.V1_6.NanDataPathChannelInfo channelInfo : channelInfos) { - wifiAwareChannelInfos.add(new WifiAwareChannelInfo(channelInfo.channelFreq, - getChannelBandwidthFromHal(channelInfo.channelBandwidth), - channelInfo.numSpatialStreams)); - } - return wifiAwareChannelInfos; - } } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java index 682c2f8668..5d9b3feb61 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java @@ -17,22 +17,19 @@ package com.android.server.wifi.aware; import android.annotation.NonNull; -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; import android.os.Handler; -import android.os.RemoteException; import android.os.WorkSource; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wifi.HalDeviceManager; +import com.android.server.wifi.hal.WifiNanIface; import java.io.FileDescriptor; import java.io.PrintWriter; /** - * Manages the interface to Wi-Fi Aware HIDL (HAL). + * Manages the interface to the Wi-Fi Aware HAL. */ public class WifiAwareNativeManager { private static final String TAG = "WifiAwareNativeManager"; @@ -45,7 +42,7 @@ public class WifiAwareNativeManager { private HalDeviceManager mHalDeviceManager; private Handler mHandler; private WifiAwareNativeCallback mWifiAwareNativeCallback; - private IWifiNanIface mWifiNanIface = null; + private WifiNanIface mWifiNanIface = null; private InterfaceDestroyedListener mInterfaceDestroyedListener; private int mReferenceCount = 0; @@ -62,33 +59,9 @@ public class WifiAwareNativeManager { */ public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) { mVerboseHalLoggingEnabled = halVerboseEnabled; - } - - /** - * (HIDL) Cast the input to a 1.2 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return android.hardware.wifi.V1_2.IWifiNanIface.castFrom(iface); - } - - /** - * (HIDL) Cast the input to a 1.5 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_5.IWifiNanIface mockableCastTo_1_5(IWifiNanIface iface) { - return android.hardware.wifi.V1_5.IWifiNanIface.castFrom(iface); - } - - /** - * (HIDL) Cast the input to a 1.6 NAN interface (possibly resulting in a null). - * - * Separate function so can be mocked in unit tests. - */ - public android.hardware.wifi.V1_6.IWifiNanIface mockableCastTo_1_6(IWifiNanIface iface) { - return android.hardware.wifi.V1_6.IWifiNanIface.castFrom(iface); + if (mWifiNanIface != null) { + mWifiNanIface.enableVerboseLogging(mVerboseHalLoggingEnabled); + } } /** @@ -119,11 +92,11 @@ public class WifiAwareNativeManager { } /** - * Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched. + * Returns the WifiNanIface through which commands to the NAN HAL are dispatched. * Return may be null if not initialized/available. */ @VisibleForTesting - public IWifiNanIface getWifiNanIface() { + public WifiNanIface getWifiNanIface() { synchronized (mLock) { return mWifiNanIface; } @@ -135,8 +108,8 @@ public class WifiAwareNativeManager { public void tryToGetAware(@NonNull WorkSource requestorWs) { synchronized (mLock) { if (mVerboseHalLoggingEnabled) { - Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount=" - + mReferenceCount + ", requestorWs=" + requestorWs); + Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface + + ", mReferenceCount=" + mReferenceCount + ", requestorWs=" + requestorWs); } if (mWifiNanIface != null) { @@ -150,48 +123,22 @@ public class WifiAwareNativeManager { } mInterfaceDestroyedListener = new InterfaceDestroyedListener(); - IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener, + WifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener, mHandler, requestorWs); if (iface == null) { - Log.e(TAG, "Was not able to obtain an IWifiNanIface (even though enabled!?)"); + Log.e(TAG, "Was not able to obtain a WifiNanIface (even though enabled!?)"); awareIsDown(true); } else { - if (mVerboseHalLoggingEnabled) Log.v(TAG, "Obtained an IWifiNanIface"); - - try { - android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(iface); - android.hardware.wifi.V1_5.IWifiNanIface iface15 = mockableCastTo_1_5(iface); - android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(iface); - WifiStatus status; - if (iface16 != null) { - mWifiAwareNativeCallback.mIsHal12OrLater = true; - mWifiAwareNativeCallback.mIsHal15OrLater = true; - mWifiAwareNativeCallback.mIsHal16OrLater = true; - status = iface16.registerEventCallback_1_6(mWifiAwareNativeCallback); - } else if (iface15 != null) { - mWifiAwareNativeCallback.mIsHal12OrLater = true; - mWifiAwareNativeCallback.mIsHal15OrLater = true; - status = iface15.registerEventCallback_1_5(mWifiAwareNativeCallback); - } else if (iface12 != null) { - mWifiAwareNativeCallback.mIsHal12OrLater = true; - status = iface12.registerEventCallback_1_2(mWifiAwareNativeCallback); - } else { - status = iface.registerEventCallback(mWifiAwareNativeCallback); - } - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString( - status)); - mHalDeviceManager.removeIface(iface); - awareIsDown(false); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e); + if (mVerboseHalLoggingEnabled) Log.v(TAG, "Obtained a WifiNanIface"); + if (!iface.registerFrameworkCallback(mWifiAwareNativeCallback)) { + Log.e(TAG, "Unable to register callback with WifiNanIface"); + mHalDeviceManager.removeIface(iface); awareIsDown(false); return; } mWifiNanIface = iface; mReferenceCount = 1; + mWifiNanIface.enableVerboseLogging(mVerboseHalLoggingEnabled); } } } @@ -245,15 +192,15 @@ public class WifiAwareNativeManager { return false; } - return mHalDeviceManager.replaceRequestorWs(mWifiNanIface, requestorWs); + return mHalDeviceManager.replaceRequestorWsForNanIface(mWifiNanIface, requestorWs); } } private void awareIsDown(boolean markAsAvailable) { synchronized (mLock) { if (mVerboseHalLoggingEnabled) { - Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount =" - + mReferenceCount); + Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface + + ", mReferenceCount =" + mReferenceCount); } mWifiNanIface = null; mReferenceCount = 0; @@ -268,8 +215,8 @@ public class WifiAwareNativeManager { @Override public void onDestroyed(@NonNull String ifaceName) { if (mVerboseHalLoggingEnabled) { - Log.d(TAG, "Interface was destroyed: mWifiNanIface=" + mWifiNanIface + ", active=" - + active); + Log.d(TAG, "Interface was destroyed: mWifiNanIface=" + mWifiNanIface + + ", active=" + active); } if (active && mWifiNanIface != null) { awareIsDown(true); @@ -277,15 +224,6 @@ public class WifiAwareNativeManager { } } - private static String statusString(WifiStatus status) { - if (status == null) { - return "status=null"; - } - StringBuilder sb = new StringBuilder(); - sb.append(status.code).append(" (").append(status.description).append(")"); - return sb.toString(); - } - /** * Dump the internal state of the class. */ diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java index 3555da355f..293bde69ca 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.NanStatusType; import android.net.wifi.WifiManager; import android.net.wifi.aware.AwareParams; import android.net.wifi.aware.AwareResources; @@ -56,6 +55,7 @@ import com.android.server.wifi.FrameworkFacade; import com.android.server.wifi.InterfaceConflictManager; import com.android.server.wifi.SystemBuildProperties; import com.android.server.wifi.WifiSettingsConfigStore; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import com.android.server.wifi.WifiThreadRunner; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.WifiPermissionsUtil; @@ -302,7 +302,7 @@ public class WifiAwareServiceImpl extends IWifiAwareManager.Stub { } catch (RemoteException e) { Log.e(TAG, "Error on linkToDeath - " + e); try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); + callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e1) { Log.e(TAG, "Error on onConnectFail()"); } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java index 76aeb89f9a..89d6a6eef7 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java @@ -25,7 +25,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.hardware.wifi.V1_0.NanStatusType; import android.hardware.wifi.V1_0.WifiStatusCode; import android.location.LocationManager; import android.net.MacAddress; @@ -75,6 +74,7 @@ import com.android.server.wifi.Clock; import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.InterfaceConflictManager; import com.android.server.wifi.WifiInjector; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.WaitingState; import com.android.server.wifi.util.WifiPermissionsUtil; @@ -261,6 +261,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe private boolean mCurrentIdentityNotification = false; private boolean mCurrentRangingEnabled = false; private boolean mInstantCommModeGlobalEnable = false; + private int mOverrideInstantMode = INSTANT_MODE_DISABLED; private int mInstantCommModeClientRequest = INSTANT_MODE_DISABLED; private static final int AWARE_BAND_2_INSTANT_COMMUNICATION_CHANNEL_FREQ = 2437; // Channel 6 private int mAwareBand5InstantCommunicationChannelFreq = -1; // -1 is not set, 0 is unsupported. @@ -439,6 +440,22 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe pw_out.println(out.toString()); return 0; } + case "set_override_instant_communication_mode": { + String arg = parentShell.getNextArgRequired(); + if (TextUtils.equals(arg, "2G")) { + mOverrideInstantMode = INSTANT_MODE_24GHZ; + } else if (TextUtils.equals(arg, "5G")) { + mOverrideInstantMode = INSTANT_MODE_5GHZ; + } else { + pw_err.println("Unknown band -- " + arg); + return -1; + } + return 0; + } + case "clear_override_instant_communication_mode": { + mOverrideInstantMode = INSTANT_MODE_DISABLED; + return 0; + } default: pw_err.println("Unknown 'wifiaware state_mgr <cmd>'"); } @@ -469,6 +486,10 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe + "accept requests from ANY requestor (null peer spec)"); pw.println(" get_instant_communication_channel 2G|5G: get instant communication mode " + "channel available for the target band"); + pw.println(" set_override_instant_communication_mode 2G|5G: override the instant " + + "communication mode to 'enabled' with the specified band"); + pw.println(" clear_override_instant_communication_mode: clear the override of the instant " + + "communication mode"); } /** @@ -687,7 +708,10 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe public void requestMacAddresses(int uid, int[] peerIds, IWifiAwareMacAddressProvider callback) { mSm.getHandler().post(() -> { - if (VDBG) Log.v(TAG, "requestMacAddresses: uid=" + uid + ", peerIds=" + peerIds); + if (VDBG) { + Log.v(TAG, "requestMacAddresses: uid=" + uid + ", peerIds=" + + Arrays.toString(peerIds)); + } Map<Integer, MacAddrMapping> peerIdToMacMap = new HashMap<>(); for (int i = 0; i < mClients.size(); ++i) { WifiAwareClientState client = mClients.valueAt(i); @@ -1706,7 +1730,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe */ onAwareDownLocal(); - if (reason != NanStatusType.SUCCESS) { + if (reason != NanStatusCode.SUCCESS) { sendAwareStateChangedBroadcast(false); } break; @@ -1752,7 +1776,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe int retryCount = sentMessage.getData() .getInt(MESSAGE_BUNDLE_KEY_RETRY_COUNT); - if (retryCount > 0 && reason == NanStatusType.NO_OTA_ACK) { + if (retryCount > 0 && reason == NanStatusCode.NO_OTA_ACK) { if (mVerboseLoggingEnabled) { Log.v(TAG, "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL: transactionId=" @@ -1883,9 +1907,9 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe // handling user rejection or possible conflict (pending command) try { callback.onConnectFail( - NanStatusType.NO_RESOURCES_AVAILABLE); + NanStatusCode.NO_RESOURCES_AVAILABLE); mAwareMetrics.recordAttachStatus( - NanStatusType.NO_RESOURCES_AVAILABLE); + NanStatusCode.NO_RESOURCES_AVAILABLE); } catch (RemoteException e) { Log.w(TAG, "displayUserApprovalDialog user refusal: RemoteException " + "(FYI): " + e); @@ -1981,7 +2005,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe + " at messageId=" + msg.getData().getInt(MESSAGE_BUNDLE_KEY_MESSAGE_ID)); } - onMessageSendFailLocal(msg, NanStatusType.INTERNAL_FAILURE); + onMessageSendFailLocal(msg, NanStatusCode.INTERNAL_FAILURE); waitForResponse = false; break; } @@ -2190,7 +2214,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe Log.v(TAG, "processResponse: ON_MESSAGE_SEND_QUEUED_FAIL - blocking!"); } int reason = (Integer) msg.obj; - if (reason == NanStatusType.FOLLOWUP_TX_QUEUE_FULL) { + if (reason == NanStatusCode.FOLLOWUP_TX_QUEUE_FULL) { Message sentMessage = mCurrentCommand.getData().getParcelable( MESSAGE_BUNDLE_KEY_SENT_MESSAGE); int arrivalSeq = sentMessage.getData().getInt( @@ -2205,7 +2229,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe } else { Message sentMessage = mCurrentCommand.getData().getParcelable( MESSAGE_BUNDLE_KEY_SENT_MESSAGE); - onMessageSendFailLocal(sentMessage, NanStatusType.INTERNAL_FAILURE); + onMessageSendFailLocal(sentMessage, NanStatusCode.INTERNAL_FAILURE); if (!mSendQueueBlocked) { transmitNextMessage(); } @@ -2285,7 +2309,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe switch (msg.arg1) { case COMMAND_TYPE_CONNECT: case COMMAND_TYPE_DISCONNECT: - onConfigFailedLocal(mCurrentCommand, NanStatusType.INTERNAL_FAILURE); + onConfigFailedLocal(mCurrentCommand, NanStatusCode.INTERNAL_FAILURE); break; case COMMAND_TYPE_RECONFIGURE: @@ -2293,7 +2317,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe * Reconfigure timed-out. There is nothing to do but log the issue - which * will be done in the callback. */ - onConfigFailedLocal(mCurrentCommand, NanStatusType.INTERNAL_FAILURE); + onConfigFailedLocal(mCurrentCommand, NanStatusCode.INTERNAL_FAILURE); break; case COMMAND_TYPE_TERMINATE_SESSION: { Log.wtf(TAG, "processTimeout: TERMINATE_SESSION - shouldn't be waiting!"); @@ -2301,13 +2325,13 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe } case COMMAND_TYPE_PUBLISH: case COMMAND_TYPE_UPDATE_PUBLISH: { - onSessionConfigFailLocal(mCurrentCommand, true, NanStatusType.INTERNAL_FAILURE); + onSessionConfigFailLocal(mCurrentCommand, true, NanStatusCode.INTERNAL_FAILURE); break; } case COMMAND_TYPE_SUBSCRIBE: case COMMAND_TYPE_UPDATE_SUBSCRIBE: { onSessionConfigFailLocal(mCurrentCommand, false, - NanStatusType.INTERNAL_FAILURE); + NanStatusCode.INTERNAL_FAILURE); break; } case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE: { @@ -2317,7 +2341,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE: { Message sentMessage = mCurrentCommand.getData().getParcelable( MESSAGE_BUNDLE_KEY_SENT_MESSAGE); - onMessageSendFailLocal(sentMessage, NanStatusType.INTERNAL_FAILURE); + onMessageSendFailLocal(sentMessage, NanStatusCode.INTERNAL_FAILURE); mSendQueueBlocked = false; transmitNextMessage(); break; @@ -2372,7 +2396,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe "processTimeout: COMMAND_TYPE_RELEASE_AWARE - shouldn't be waiting!"); break; case COMMAND_TYPE_DISABLE: - onDisableResponseLocal(mCurrentCommand, NanStatusType.INTERNAL_FAILURE); + onDisableResponseLocal(mCurrentCommand, NanStatusCode.INTERNAL_FAILURE); break; default: Log.wtf(TAG, "processTimeout: this isn't a COMMAND -- msg=" + msg); @@ -2433,7 +2457,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe + ", due to messageEnqueueTime=" + messageEnqueueTime + ", currentTime=" + currentTime); } - onMessageSendFailLocal(message, NanStatusType.INTERNAL_FAILURE); + onMessageSendFailLocal(message, NanStatusCode.INTERNAL_FAILURE); it.remove(); first = false; } else { @@ -2528,8 +2552,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe if (!mUsageEnabled) { Log.w(TAG, "connect(): called with mUsageEnabled=false"); try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); - mAwareMetrics.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); + callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE); + mAwareMetrics.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); } @@ -2550,8 +2574,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe Log.e(TAG, "connectLocal: requested configRequest=" + configRequest + ", incompatible with current configurations"); try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); - mAwareMetrics.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); + callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE); + mAwareMetrics.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); } @@ -2604,8 +2628,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe mWifiAwareNativeManager.releaseAware(); } try { - callback.onConnectFail(NanStatusType.INTERNAL_FAILURE); - mAwareMetrics.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); + callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE); + mAwareMetrics.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "connectLocal onConnectFail(): RemoteException (FYI): " + e); } @@ -2727,7 +2751,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe if (client == null) { Log.e(TAG, "publishLocal: no client exists for clientId=" + clientId); try { - callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "publishLocal onSessionConfigFail(): RemoteException (FYI): " + e); } @@ -2737,11 +2761,11 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe boolean success = mWifiAwareNativeApi.publish(transactionId, (byte) 0, publishConfig); if (!success) { try { - callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "publishLocal onSessionConfigFail(): RemoteException (FYI): " + e); } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, + mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE, true); } @@ -2770,7 +2794,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe boolean status = session.updatePublish(transactionId, publishConfig); if (!status) { - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, + mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE, true); } return status; @@ -2784,7 +2808,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe WifiAwareClientState client = mClients.get(clientId); if (client == null) { try { - callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "subscribeLocal onSessionConfigFail(): RemoteException (FYI): " + e); } @@ -2795,11 +2819,11 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe boolean success = mWifiAwareNativeApi.subscribe(transactionId, (byte) 0, subscribeConfig); if (!success) { try { - callback.onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + callback.onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); } catch (RemoteException e) { Log.w(TAG, "subscribeLocal onSessionConfigFail(): RemoteException (FYI): " + e); } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, + mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE, false); } @@ -2830,7 +2854,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe boolean status = session.updateSubscribe(transactionId, subscribeConfig); if (!status) { - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.INTERNAL_FAILURE, + mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.INTERNAL_FAILURE, false); } return status; @@ -2910,7 +2934,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe channelRequestType, channel, peer, interfaceName, isOutOfBand, appInfo, mCapabilities, networkSpecifier.getWifiAwareDataPathSecurityConfig()); if (!success) { - mDataPathMgr.onDataPathInitiateFail(networkSpecifier, NanStatusType.INTERNAL_FAILURE); + mDataPathMgr.onDataPathInitiateFail(networkSpecifier, NanStatusCode.INTERNAL_FAILURE); } return success; @@ -2927,7 +2951,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe boolean success = mWifiAwareNativeApi.respondToDataPathRequest(transactionId, accept, ndpId, interfaceName, appInfo, isOutOfBand, mCapabilities, securityConfig); if (!success) { - mDataPathMgr.onRespondToDataPathRequest(ndpId, false, NanStatusType.INTERNAL_FAILURE); + mDataPathMgr.onRespondToDataPathRequest(ndpId, false, NanStatusCode.INTERNAL_FAILURE); } else { sendAwareResourcesChangedBroadcast(); } @@ -3051,7 +3075,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe * - success: was waiting so that don't enable while disabling * - fail: shouldn't happen (though can if already disabled for instance) */ - if (reason != NanStatusType.SUCCESS) { + if (reason != NanStatusCode.SUCCESS) { Log.e(TAG, "onDisableResponseLocal: FAILED!? command=" + command + ", reason=" + reason); } @@ -3128,7 +3152,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe } else { mAwareMetrics.recordDiscoverySession(client.getUid(), mClients); } - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.SUCCESS, + mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.SUCCESS, completedCommand.arg1 == COMMAND_TYPE_PUBLISH); sendAwareResourcesChangedBroadcast(); } else if (completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH @@ -3159,7 +3183,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe session.setRangingEnabled(isRangingEnabled); session.setInstantModeEnabled(enableInstantMode); session.setInstantModeBand(instantModeBand); - mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.SUCCESS, + mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusCode.SUCCESS, completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH); } else { Log.wtf(TAG, @@ -3225,7 +3249,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe mAwareMetrics.recordDiscoveryStatus(client.getUid(), reason, failedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH); - if (reason == NanStatusType.INVALID_SESSION_ID) { + if (reason == NanStatusCode.INVALID_SESSION_ID) { client.removeSession(sessionId); // If Ranging enabled or instant mode require changes, reconfigure. if (mCurrentRangingEnabled != doesAnyClientNeedRanging() @@ -3666,6 +3690,9 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe } private int getInstantModeFromAllClients() { + if (mOverrideInstantMode != INSTANT_MODE_DISABLED) { + return mOverrideInstantMode; + } int instantMode = INSTANT_MODE_DISABLED; for (int i = 0; i < mClients.size(); ++i) { int currentClient = mClients.valueAt(i).getInstantMode((long) mContext.getResources() diff --git a/service/java/com/android/server/wifi/hal/IWifiApIface.java b/service/java/com/android/server/wifi/hal/IWifiApIface.java new file mode 100644 index 0000000000..0c8b019afd --- /dev/null +++ b/service/java/com/android/server/wifi/hal/IWifiApIface.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.net.MacAddress; + +import java.util.List; + +/** Abstraction of WifiApIface */ +public interface IWifiApIface { + /** + * Get the name of this interface. + * + * @return Name of this interface, or null on error. + */ + String getName(); + + /** + * Get the names of the bridged AP instances. + * + * @return List containing the names of the bridged AP instances, + * or an empty vector for a non-bridged AP. Returns null + * if an error occurred. + */ + List<String> getBridgedInstances(); + + /** + * Gets the factory MAC address of the interface. + * + * @return Factory MAC address of the interface, or null on error. + */ + MacAddress getFactoryMacAddress(); + + /** + * Set the country code for this interface. + * + * @param countryCode two-letter country code (as ISO 3166). + * @return true if successful, false otherwise. + */ + boolean setCountryCode(byte[] countryCode); + + /** + * Reset all the AP interfaces' MAC address to the factory MAC address. + * + * @return true if successful, false otherwise. + */ + boolean resetToFactoryMacAddress(); + + /** + * Check whether {@link #setMacAddress(MacAddress)} is supported by this HAL. + * + * @return true if supported, false otherwise. + */ + boolean isSetMacAddressSupported(); + + /** + * Changes the MAC address of the interface to the given MAC address. + * + * @param mac MAC address to change to. + * @return true if successful, false otherwise. + */ + boolean setMacAddress(MacAddress mac); +} diff --git a/service/java/com/android/server/wifi/hal/IWifiChip.java b/service/java/com/android/server/wifi/hal/IWifiChip.java new file mode 100644 index 0000000000..3a2caf30b8 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/IWifiChip.java @@ -0,0 +1,438 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.Nullable; +import android.net.wifi.CoexUnsafeChannel; +import android.net.wifi.WifiAvailableChannel; +import android.net.wifi.WifiScanner; + +import com.android.server.wifi.SarInfo; +import com.android.server.wifi.WifiNative; +import com.android.server.wifi.WlanWakeReasonAndCounts; + +import java.util.List; + +/** Abstraction of WifiChip */ +public interface IWifiChip { + /** + * Configure the chip. + * + * @param modeId Mode that the chip must switch to, corresponding to the + * id property of the target ChipMode. + * @return true if successful, false otherwise. + */ + boolean configureChip(int modeId); + + /** + * Create an AP interface on the chip. + * + * @return {@link WifiApIface} object, or null if a failure occurred. + */ + @Nullable + WifiApIface createApIface(); + + /** + * Create a bridged AP interface on the chip. + * + * @return {@link WifiApIface} object, or null if a failure occurred. + */ + @Nullable + WifiApIface createBridgedApIface(); + + /** + * Create a NAN interface on the chip. + * + * @return {@link WifiNanIface} object, or null if a failure occurred. + */ + @Nullable + WifiNanIface createNanIface(); + + /** + * Create a P2P interface on the chip. + * + * @return {@link WifiP2pIface} object, or null if a failure occurred. + */ + @Nullable + WifiP2pIface createP2pIface(); + + /** + * Create an RTTController instance. Implementation will decide the iface to use for + * RTT operations. + * + * @return {@link WifiRttController} object, or null if a failure occurred. + */ + @Nullable + WifiRttController createRttController(); + + /** + * Create a STA iface on the chip. + * + * @return {@link WifiStaIface} object, or null if a failure occurred. + */ + @Nullable + WifiStaIface createStaIface(); + + /** + * Enable/disable alert notifications from the chip. + * + * @param enable true to enable, false to disable. + * @return true if successful, false otherwise. + */ + boolean enableDebugErrorAlerts(boolean enable); + + /** + * Flush debug ring buffer data to files. + * + * @return true if successful, false otherwise. + */ + boolean flushRingBufferToFile(); + + /** + * Force dump data into the corresponding ring buffer. + * + * @param ringName Name of the ring for which data collection should be forced. + * @return true if successful, false otherwise. + */ + boolean forceDumpToDebugRingBuffer(String ringName); + + /** + * Get the AP interface corresponding to the provided ifaceName. + * + * @param ifaceName Name of the interface. + * @return {@link WifiApIface} if the interface exists, null otherwise. + */ + @Nullable + WifiApIface getApIface(String ifaceName); + + /** + * List all the AP iface names configured on the chip. + * The corresponding |WifiApIface| object for any iface + * can be retrieved using the |getApIface| method. + * + * @return List of all AP interface names on the chip, or null if an error occurred. + */ + @Nullable + List<String> getApIfaceNames(); + + /** + * Get the set of operation modes that the chip supports. + * + * @return List of modes supported by the device, or null if an error occurred. + */ + @Nullable + List<WifiChip.ChipMode> getAvailableModes(); + + /** + * Get the capabilities supported by this chip. + * Call if no interfaces have been created on this chip. + * + * Note: This method can still be called safely after ifaces have been created, + * but it is recommended to use {@link #getCapabilitiesAfterIfacesExist()} once + * any ifaces are up. + * + * @return {@link WifiChip.Response} where the value is a bitset of + * WifiManager.WIFI_FEATURE_* values. + */ + WifiChip.Response<Long> 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 + * WifiManager.WIFI_FEATURE_* values. + */ + WifiChip.Response<Long> getCapabilitiesAfterIfacesExist(); + + /** + * Retrieve the Wi-Fi wakeup reason stats for debugging. + * + * @return {@link WlanWakeReasonAndCounts} object, or null if an error occurred. + */ + @Nullable + WlanWakeReasonAndCounts getDebugHostWakeReasonStats(); + + /** + * Get the status of all ring buffers supported by driver. + * + * @return List of {@link WifiNative.RingBufferStatus} corresponding to the + * status of each ring buffer on the device, or null if an error occurred. + */ + @Nullable + List<WifiNative.RingBufferStatus> getDebugRingBuffersStatus(); + + /** + * Get the ID assigned to this chip. + * + * @return Chip ID, or -1 if an error occurred. + */ + int getId(); + + /** + * Get the current mode that the chip is in. + * + * @return {@link WifiChip.Response} where the value is the mode that the chip + * is currently configured to. + */ + WifiChip.Response<Integer> getMode(); + + /** + * Get the NAN interface corresponding to the provided ifaceName. + * + * @param ifaceName Name of the interface. + * @return {@link WifiNanIface} if the interface exists, null otherwise. + */ + @Nullable + WifiNanIface getNanIface(String ifaceName); + + /** + * List all the NAN iface names configured on the chip. + * The corresponding |WifiNanIface| object for any iface + * can be retrieved using the |getNanIface| method. + * + * @return List of all NAN interface names on the chip, or null if an error occurred. + */ + @Nullable + List<String> getNanIfaceNames(); + + /** + * Get the P2P interface corresponding to the provided ifaceName. + * + * @param ifaceName Name of the interface. + * @return {@link WifiP2pIface} if the interface exists, null otherwise. + */ + @Nullable + WifiP2pIface getP2pIface(String ifaceName); + + /** + * List all the P2P iface names configured on the chip. + * The corresponding |WifiP2pIface| object for any iface + * can be retrieved using the |getP2pIface| method. + * + * @return List of all P2P interface names on the chip, or null if an error occurred. + */ + @Nullable + List<String> getP2pIfaceNames(); + + /** + * Get the STA interface corresponding to the provided ifaceName. + * + * @param ifaceName Name of the interface. + * @return {@link WifiStaIface} if the interface exists, null otherwise. + */ + @Nullable + WifiStaIface getStaIface(String ifaceName); + + /** + * List all the STA iface names configured on the chip. + * The corresponding |WifiStaIface| object for any iface + * can be retrieved using the |getStaIface| method. + * + * @return List of all P2P interface names on the chip, or null if an error occurred. + */ + @Nullable + List<String> getStaIfaceNames(); + + /** + * Retrieve the list of all the possible radio combinations supported by this chip. + * + * @return |WifiRadioCombinationMatrix| representation of all the possible radio combinations, + * or null if an error occurred. + * + */ + @Nullable + WifiChip.WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix(); + + /** + * Retrieve a list of usable Wifi channels for the specified band and operational modes. + * + * @param band Band for which the list of usable channels is requested. + * @param mode Bitmask of modes that the caller is interested in. + * @param filter Bitmask of filters. Specifies whether driver should filter + * channels based on additional criteria. If no filter is specified, + * then the driver should return usable channels purely based on + * regulatory constraints. + * @return List of channels represented by {@link WifiAvailableChannel}, + * or null if an error occurred. + */ + @Nullable + List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band, + @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter); + + /** + * Register for chip event callbacks. + * + * @param callback Instance of {@link WifiChip.Callback} + * @return true if successful, false otherwise. + */ + boolean registerCallback(WifiChip.Callback callback); + + /** + * Removes the AP interface with the provided ifaceName. + * + * @param ifaceName Name of the iface. + * @return true if successful, false otherwise. + */ + boolean removeApIface(String ifaceName); + + /** + * Removes an instance of AP iface with name |ifaceName| from the + * bridged AP with name |brIfaceName|. + * + * Note: Use {@link #removeApIface(String)} with the |brIfaceName| to remove the bridged iface. + * + * @param brIfaceName Name of the bridged AP iface. + * @param ifaceName Name of the AP instance. + * @return true if successful, false otherwise. + */ + boolean removeIfaceInstanceFromBridgedApIface(String brIfaceName, String ifaceName); + + /** + * Removes the NAN interface with the provided ifaceName. + * + * @param ifaceName Name of the iface. + * @return true if successful, false otherwise. + */ + boolean removeNanIface(String ifaceName); + + /** + * Removes the P2P interface with the provided ifaceName. + * + * @param ifaceName Name of the iface. + * @return true if successful, false otherwise. + */ + boolean removeP2pIface(String ifaceName); + + /** + * Removes the STA interface with the provided ifaceName. + * + * @param ifaceName Name of the iface. + * @return true if successful, false otherwise. + */ + boolean removeStaIface(String ifaceName); + + /** + * Request information about the chip. + * + * @return Instance of {@link WifiChip.ChipDebugInfo}, or null if an error occurred. + */ + @Nullable + WifiChip.ChipDebugInfo requestChipDebugInfo(); + + /** + * Request vendor debug info from the driver. + * + * @return Byte array retrieved from the driver, or null if an error occurred. + */ + @Nullable + byte[] requestDriverDebugDump(); + + /** + * Request vendor debug info from the firmware. + * + * @return Byte array retrieved from the firmware, or null if an error occurred. + */ + @Nullable + byte[] requestFirmwareDebugDump(); + + /** + * Reset TX power levels. + * + * @return true if successful, false otherwise. + */ + boolean resetTxPowerScenario(); + + /** + * Select one of the preset TX power scenarios. + * + * @param sarInfo SarInfo to select the proper scenario. + * @return true if successful, false otherwise. + */ + boolean selectTxPowerScenario(SarInfo sarInfo); + + /** + * Set the current coex unsafe channels to avoid and their restrictions. + * + * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. + * @param restrictions int containing a bitwise-OR combination of + * {@link android.net.wifi.WifiManager.CoexRestriction}. + * @return true if successful, false otherwise. + */ + boolean setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions); + + /** + * Set the country code for this Wifi chip. + * + * @param code 2-byte country code to set (as defined in ISO 3166). + * @return true if successful, false otherwise. + */ + boolean setCountryCode(byte[] code); + + /** + * Enable/disable low-latency mode. + * + * @param enable true to enable, false to disable. + * @return true if successful, false otherwise. + */ + boolean setLowLatencyMode(boolean enable); + + /** + * Set primary connection when multiple STA ifaces are active. + * + * @param ifaceName Name of the interface. + * @return true if successful, false otherwise. + */ + boolean setMultiStaPrimaryConnection(String ifaceName); + + /** + * Set use-case when multiple STA ifaces are active. + * + * @param useCase use case from {@link WifiNative.MultiStaUseCase}. + * @return true if successful, false otherwise. + */ + boolean setMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase); + + /** + * Control debug data collection. + * + * @param ringName Name of the ring for which data collection is to start. + * @param verboseLevel 0 to 3, inclusive. 0 stops logging. + * @param maxIntervalInSec Maximum interval between reports; ignore if 0. + * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0. + * @return true if successful, false otherwise. + */ + boolean startLoggingToDebugRingBuffer(String ringName, int verboseLevel, int maxIntervalInSec, + int minDataSizeInBytes); + + /** + * Stop the debug data collection for all ring buffers. + * + * @return true if successful, false otherwise. + */ + boolean stopLoggingToDebugRingBuffer(); + + /** + * Trigger subsystem restart. + * + * Use if the framework detects a problem (e.g. connection failure), + * in order to attempt recovery. + * + * @return true if successful, false otherwise. + */ + boolean triggerSubsystemRestart(); +} diff --git a/service/java/com/android/server/wifi/hal/IWifiHal.java b/service/java/com/android/server/wifi/hal/IWifiHal.java new file mode 100644 index 0000000000..bec614453a --- /dev/null +++ b/service/java/com/android/server/wifi/hal/IWifiHal.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.Nullable; + +import java.util.List; + +/** Abstraction of the root Wifi HAL */ +public interface IWifiHal { + /** + * Get the chip corresponding to the provided chipId. + * + * @param chipId ID of the chip. + * @return {@link WifiChip} if successful, null otherwise. + */ + @Nullable + WifiChip getChip(int chipId); + + /** + * Retrieves the list of all chip id's on the device. + * The corresponding |WifiChip| object for any chip can be + * retrieved using the |getChip| method. + * + * @return List of all chip id's on the device, or null if an error occurred. + */ + @Nullable + List<Integer> getChipIds(); + + /** + * Register for HAL event callbacks. + * + * @param callback Instance of {@link WifiHal.Callback} + * @return true if successful, false otherwise. + */ + boolean registerEventCallback(WifiHal.Callback callback); + + /** + * Initialize the Wi-Fi HAL service. Must initialize before calling {@link #start()} + * + * @param deathRecipient Instance of {@link WifiHal.DeathRecipient} + */ + void initialize(WifiHal.DeathRecipient deathRecipient); + + /** + * Check if the initialization is complete and the HAL is ready to accept commands. + * + * @return true if initialization is complete, false otherwise. + */ + boolean isInitializationComplete(); + + /** + * Check if the Wi-Fi HAL supported on this device. + * + * @return true if supported, false otherwise. + */ + boolean isSupported(); + + /** + * Start the Wi-Fi HAL. + * + * @return {@link WifiHal.WifiStatusCode} indicating the result. + */ + @WifiHal.WifiStatusCode int start(); + + /** + * Get the current state of the HAL. + * + * @return true if started, false otherwise. + */ + boolean isStarted(); + + /** + * Stop the Wi-Fi HAL. + * + * Note: Calling stop() and then start() is a valid way of resetting state in + * the HAL, driver, and firmware. + * + * @return true if successful, false otherwise. + */ + boolean stop(); + + /** + * Invalidate the Wi-Fi HAL. Call when a significant error occurred external to the root + * Wi-Fi HAL, for instance in a Wi-Fi chip retrieved from this HAL. + */ + void invalidate(); +} diff --git a/service/java/com/android/server/wifi/hal/IWifiNanIface.java b/service/java/com/android/server/wifi/hal/IWifiNanIface.java new file mode 100644 index 0000000000..81b22b6eea --- /dev/null +++ b/service/java/com/android/server/wifi/hal/IWifiNanIface.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.Nullable; +import android.net.MacAddress; +import android.net.wifi.aware.ConfigRequest; +import android.net.wifi.aware.PublishConfig; +import android.net.wifi.aware.SubscribeConfig; +import android.net.wifi.aware.WifiAwareDataPathSecurityConfig; + +import com.android.server.wifi.aware.Capabilities; + +/** Abstraction of WifiNanIface */ +public interface IWifiNanIface { + /** + * Enable verbose logging. + */ + void enableVerboseLogging(boolean verbose); + + /** + * Get the underlying HIDL WifiNanIfaceObject. + * TODO: Remove this API. Will only be used temporarily until HalDeviceManager is refactored. + * + * @return HIDL IWifiNanIface object. + */ + android.hardware.wifi.V1_0.IWifiNanIface getNanIface(); + + /** + * Register a framework callback to receive notifications from the HAL. + * + * @param callback Instance of {@link WifiNanIface.Callback}. + * @return true if successful, false otherwise + */ + boolean registerFrameworkCallback(WifiNanIface.Callback callback); + + /** + * Get the name of this interface. + * + * @return Name of this interface, or null on error. + */ + @Nullable + String getName(); + + /** + * Query the firmware's capabilities. + * + * @param transactionId Transaction ID for the transaction - used in the async callback to + * match with the original request. + */ + boolean getCapabilities(short transactionId); + + /** + * Enable and configure Aware. + * + * @param transactionId Transaction ID for the transaction - used in the + * async callback to match with the original request. + * @param configRequest Requested Aware configuration. + * @param notifyIdentityChange Indicates whether to get address change callbacks. + * @param initialConfiguration Specifies whether initial configuration + * (true) or an update (false) to the configuration. + * @param rangingEnabled Indicates whether to enable ranging. + * @param isInstantCommunicationEnabled Indicates whether to enable instant communication + * @param instantModeChannel + * @param macAddressRandomizationIntervalSec + * @param powerParameters Instance of {@link WifiNanIface.PowerParameters} containing the + * parameters to use in our config request. + */ + boolean enableAndConfigure(short transactionId, ConfigRequest configRequest, + boolean notifyIdentityChange, boolean initialConfiguration, boolean rangingEnabled, + boolean isInstantCommunicationEnabled, int instantModeChannel, + int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters); + + /** + * Disable Aware. + * + * @param transactionId Transaction ID for the transaction - + * used in the async callback to match with the original request. + */ + boolean disable(short transactionId); + + /** + * Start or modify a service publish session. + * + * @param transactionId Transaction ID for the transaction - + * used in the async callback to match with the original request. + * @param publishId ID of the requested session - 0 to request a new publish + * session. + * @param publishConfig Configuration of the discovery session. + */ + boolean publish(short transactionId, byte publishId, PublishConfig publishConfig); + + /** + * Start or modify a service subscription session. + * + * @param transactionId Transaction ID for the transaction - + * used in the async callback to match with the original request. + * @param subscribeId ID of the requested session - 0 to request a new + * subscribe session. + * @param subscribeConfig Configuration of the discovery session. + */ + boolean subscribe(short transactionId, byte subscribeId, SubscribeConfig subscribeConfig); + + /** + * Send a message through an existing discovery session. + * + * @param transactionId Transaction ID for the transaction - + * used in the async callback to match with the original request. + * @param pubSubId ID of the existing publish/subscribe session. + * @param requestorInstanceId ID of the peer to communicate with - obtained + * through a previous discovery (match) operation with that peer. + * @param dest MAC address of the peer to communicate with - obtained + * together with requestorInstanceId. + * @param message Message. + */ + boolean sendMessage(short transactionId, byte pubSubId, int requestorInstanceId, + MacAddress dest, byte[] message); + + /** + * Terminate a publish discovery session. + * + * @param transactionId Transaction ID for the transaction - + * used in the async callback to match with the original request. + * @param pubSubId ID of the publish/subscribe session - obtained when + * creating a session. + */ + boolean stopPublish(short transactionId, byte pubSubId); + + /** + * Terminate a subscribe discovery session. + * + * @param transactionId transactionId Transaction ID for the transaction - + * used in the async callback to match with the original request. + * @param pubSubId ID of the publish/subscribe session - obtained when + * creating a session. + */ + boolean stopSubscribe(short transactionId, byte pubSubId); + + /** + * Create an Aware network interface. This only creates the Linux interface - it doesn't + * actually create the data connection. + * + * @param transactionId Transaction ID for the transaction - used in the async callback to + * match with the original request. + * @param interfaceName The name of the interface, e.g. "aware0". + */ + boolean createAwareNetworkInterface(short transactionId, String interfaceName); + + /** + * Deletes an Aware network interface. The data connection can (should?) be torn + * down previously. + * + * @param transactionId Transaction ID for the transaction - used in the async callback to + * match with the original request. + * @param interfaceName The name of the interface, e.g. "aware0". + */ + boolean deleteAwareNetworkInterface(short transactionId, String interfaceName); + + /** + * Initiates setting up a data-path between device and peer. Security is provided by either + * PMK or Passphrase (not both) - if both are null then an open (unencrypted) link is set up. + * + * @param transactionId Transaction ID for the transaction - used in the async callback to + * match with the original request. + * @param peerId ID of the peer ID to associate the data path with. A value of 0 + * indicates that not associated with an existing session. + * @param channelRequestType Indicates whether the specified channel is available, if available + * requested or forced (resulting in failure if cannot be + * accommodated). + * @param channel The channel on which to set up the data-path. + * @param peer The MAC address of the peer to create a connection with. + * @param interfaceName The interface on which to create the data connection. + * @param isOutOfBand Is the data-path out-of-band (i.e. without a corresponding Aware discovery + * session). + * @param appInfo Arbitrary binary blob transmitted to the peer. + * @param capabilities The capabilities of the firmware. + * @param securityConfig Security config to encrypt the data-path + */ + boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, + int channel, MacAddress peer, String interfaceName, + boolean isOutOfBand, byte[] appInfo, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig); + + /** + * Responds to a data request from a peer. Security is provided by either PMK or Passphrase (not + * both) - if both are null then an open (unencrypted) link is set up. + * + * @param transactionId Transaction ID for the transaction - used in the async callback to + * match with the original request. + * @param accept Accept (true) or reject (false) the original call. + * @param ndpId The NDP (Aware data path) ID. Obtained from the request callback. + * @param interfaceName The interface on which the data path will be setup. Obtained from the + * request callback. + * @param appInfo Arbitrary binary blob transmitted to the peer. + * @param isOutOfBand Is the data-path out-of-band (i.e. without a corresponding Aware discovery + * session). + * @param capabilities The capabilities of the firmware. + * @param securityConfig Security config to encrypt the data-path + */ + boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, + String interfaceName, byte[] appInfo, + boolean isOutOfBand, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig); + + /** + * Terminate an existing data-path (does not delete the interface). + * + * @param transactionId Transaction ID for the transaction - used in the async callback to + * match with the original request. + * @param ndpId The NDP (Aware data path) ID to be terminated. + */ + boolean endDataPath(short transactionId, int ndpId); +} diff --git a/service/java/com/android/server/wifi/hal/IWifiP2pIface.java b/service/java/com/android/server/wifi/hal/IWifiP2pIface.java new file mode 100644 index 0000000000..367feecc5d --- /dev/null +++ b/service/java/com/android/server/wifi/hal/IWifiP2pIface.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 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.hal; + +/** Abstraction of WifiP2pIface */ +public interface IWifiP2pIface { + /** + * Get the name of this interface. + * + * @return Name of this interface, or null on error. + */ + String getName(); +} diff --git a/service/java/com/android/server/wifi/hal/IWifiRttController.java b/service/java/com/android/server/wifi/hal/IWifiRttController.java new file mode 100644 index 0000000000..9fa35ab096 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/IWifiRttController.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.Nullable; +import android.net.MacAddress; +import android.net.wifi.rtt.RangingRequest; + +import java.io.PrintWriter; +import java.util.List; + +interface IWifiRttController { + /** + * Set up the IWifiRttController. + * + * @return true if successful, false otherwise. + */ + boolean setup(); + + /** + * Enable/disable verbose logging. + */ + void enableVerboseLogging(boolean verbose); + + /** + * Register a callback to receive ranging results. + * + * @param callback Callback to register. + */ + void registerRangingResultsCallback( + WifiRttController.RttControllerRangingResultsCallback callback); + + /** + * Check whether the RTT controller is valid. + * + * @return true if the RTT controller is valid, false otherwise or if an error occurred. + */ + boolean validate(); + + /** + * Get the RTT capabilities. + * + * @return Capabilities, or null if they could not be retrieved. + */ + @Nullable + WifiRttController.Capabilities getRttCapabilities(); + + /** + * Issue a range request to the HAL. + * + * @param cmdId Command ID for the request. Will be used in the corresponding response from + * {@link HalDeviceManager.InterfaceRttControllerLifecycleCallback} + * onRangingResults() + * @param request Range request. + * @return true if successful, false otherwise. + */ + boolean rangeRequest(int cmdId, RangingRequest request); + + /** + * Cancel an outstanding ranging request. + * + * Note: No guarantees of execution. Can ignore any results which are returned for the + * canceled request. + * + * @param cmdId The cmdId issued with the original rangeRequest command. + * @param macAddresses A list of MAC addresses for which to cancel the operation. + * @return true for success, false for failure. + */ + boolean rangeCancel(int cmdId, List<MacAddress> macAddresses); + + /** + * Dump the internal state of the class. + */ + void dump(PrintWriter pw); +} diff --git a/service/java/com/android/server/wifi/hal/IWifiStaIface.java b/service/java/com/android/server/wifi/hal/IWifiStaIface.java new file mode 100644 index 0000000000..ed5451e162 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/IWifiStaIface.java @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.Nullable; +import android.net.MacAddress; +import android.net.apf.ApfCapabilities; + +import com.android.server.wifi.WifiLinkLayerStats; +import com.android.server.wifi.WifiLoggerHal; +import com.android.server.wifi.WifiNative; + +import java.util.List; + +/** Abstraction of WifiStaIface */ +public interface IWifiStaIface { + /** + * Register for event callbacks. + * + * @param callback Instance of {@link WifiStaIface.Callback} + * @return true if successful, false otherwise. + */ + boolean registerFrameworkCallback(WifiStaIface.Callback callback); + + /** + * Get the name of this interface. + * + * @return Name of this interface, or null on error. + */ + @Nullable + String getName(); + + /** + * Configure roaming control parameters. + * + * @param bssidBlocklist List of BSSIDs that are blocklisted for roaming. + * @param ssidAllowlist List of SSIDs that are allowlisted for roaming. + * @return true if successful, false otherwise. + */ + boolean configureRoaming(List<MacAddress> bssidBlocklist, List<byte[]> ssidAllowlist); + + /** + * Enable link layer stats collection. + * + * Radio statistics (once started) must not stop until disabled. + * Iface statistics (once started) reset and start afresh after each + * connection until disabled. + * + * @param debug true to enable field debug mode, false to disable. Driver + * must collect all statistics regardless of performance impact. + * @return true if successful, false otherwise. + */ + boolean enableLinkLayerStatsCollection(boolean debug); + + /** + * Enable/disable the neighbor discovery offload functionality in the firmware. + * + * @param enable true to enable, false to disable. + * @return true if successful, false otherwise. + */ + boolean enableNdOffload(boolean enable); + + /** + * Used to query additional information about the chip's APF capabilities. + * + * @return Instance of {@link ApfCapabilities}. + */ + ApfCapabilities getApfPacketFilterCapabilities(); + + /** + * Used to query additional information about the chip's Background Scan capabilities. + * + * @return Instance of {@link WifiNative.ScanCapabilities}, or null on error. + */ + @Nullable + WifiNative.ScanCapabilities getBackgroundScanCapabilities(); + + /** + * Get the capabilities supported by this STA iface. + * + * @return Bitset of WifiManager.WIFI_FEATURE_* values. + */ + long getCapabilities(); + + /** + * Retrieve the fates of inbound packets. + * Reports the inbound frames for the most recent association (space allowing). + * + * @return List of RxFateReports up to size {@link WifiLoggerHal#MAX_FATE_LOG_LEN}, + * or empty list on failure. + */ + List<WifiNative.RxFateReport> getDebugRxPacketFates(); + + /** + * Retrieve fates of outbound packets. + * Reports the outbound frames for the most recent association (space allowing). + * + * @return List of TxFateReports up to size {@link WifiLoggerHal#MAX_FATE_LOG_LEN}, + * or empty list on failure. + */ + List<WifiNative.TxFateReport> getDebugTxPacketFates(); + + /** + * Get the factory MAC address of the STA interface. + * + * @return Factory MAC address of the STA interface, or null on error. + */ + @Nullable + MacAddress getFactoryMacAddress(); + + /** + * Retrieve the latest link layer stats. + * Note: will fail if link layer stats collection has not been explicitly enabled. + * + * @return Instance of {@link WifiLinkLayerStats}, or null on error. + */ + @Nullable + WifiLinkLayerStats getLinkLayerStats(); + + /** + * Get roaming control capabilities. + * + * @return Instance of {@link WifiNative.RoamingCapabilities}, or null on error. + */ + @Nullable + WifiNative.RoamingCapabilities getRoamingCapabilities(); + + /** + * Install an APF program on this interface, replacing any existing program. + * + * @param program APF Program to be set. + * @return true if successful, false otherwise. + */ + boolean installApfPacketFilter(byte[] program); + + /** + * Read the APF program and data buffer on this interface. + * + * @return Buffer returned by the driver, or null if an error occurred. + */ + @Nullable + byte[] readApfPacketFilterData(); + + /** + * Changes the MAC address of the interface to the given MAC address. + * + * @param mac MAC address to change to. + * @return true if successful, false otherwise. + */ + boolean setMacAddress(MacAddress mac); + + /** + * Enable/disable firmware roaming. + * + * @param state State of the roaming control. + * @return SET_FIRMWARE_ROAMING_SUCCESS, SET_FIRMWARE_ROAMING_FAILURE, + * or SET_FIRMWARE_ROAMING_BUSY + */ + @WifiNative.RoamingEnableStatus int setRoamingState(@WifiNative.RoamingEnableState int state); + + /** + * Enable/disable scan-only mode for this interface. + * + * @param enable True to enable scan only mode, false to disable. + * @return true if successful, false otherwise. + */ + boolean setScanMode(boolean enable); + + /** + * Starts a background scan. + * Note: any ongoing scan will be stopped first. + * + * @param cmdId Command ID to use for this invocation. + * @param params Background scan parameters. + * @return true if successful, false otherwise. + */ + boolean startBackgroundScan(int cmdId, WifiStaIface.StaBackgroundScanParameters params); + + /** + * Start packet fate monitoring. Once started, monitoring remains active until + * the HAL is unloaded. + * + * @return true if successful, false otherwise. + */ + boolean startDebugPacketFateMonitoring(); + + /** + * Start RSSI monitoring on the currently connected access point. + * + * @param cmdId Command ID to use for this invocation. + * @param maxRssi Maximum RSSI threshold. + * @param minRssi Minimum RSSI threshold. + * @return true if successful, false otherwise. + */ + boolean startRssiMonitoring(int cmdId, int maxRssi, int minRssi); + + /** + * Start sending the specified keep-alive packets periodically. + * + * @param cmdId Command ID to use for this invocation. + * @param ipPacketData IP packet contents to be transmitted. + * @param etherType Ether type to be set in the ethernet frame transmitted. + * @param srcAddress Source MAC address of the packet. + * @param dstAddress Destination MAC address of the packet. + * @param periodInMs Interval at which this packet must be transmitted. + * @return true if successful, false otherwise. + */ + boolean startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, + MacAddress srcAddress, MacAddress dstAddress, int periodInMs); + + /** + * Stop the current background scan. + * + * @param cmdId Command ID corresponding to the request. + * @return true if successful, false otherwise. + */ + boolean stopBackgroundScan(int cmdId); + + /** + * Stop RSSI monitoring. + * + * @param cmdId Command ID corresponding to the request. + * @return true if successful, false otherwise. + */ + boolean stopRssiMonitoring(int cmdId); + + /** + * Stop sending the specified keep-alive packets. + * + * @param cmdId Command ID corresponding to the request. + * @return true if successful, false otherwise. + */ + boolean stopSendingKeepAlivePackets(int cmdId); +} diff --git a/service/java/com/android/server/wifi/hal/WifiApIface.java b/service/java/com/android/server/wifi/hal/WifiApIface.java new file mode 100644 index 0000000000..14992bfc82 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiApIface.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.MacAddress; +import android.util.Log; + +import com.android.server.wifi.util.NativeUtil; + +import java.util.List; +import java.util.function.Supplier; + +/** + * Wrapper around a WifiApIface. + * May be initialized using a HIDL or AIDL WifiApIface. + */ +public class WifiApIface implements WifiHal.WifiInterface { + private static final String TAG = "WifiApIface"; + private final IWifiApIface mWifiApIface; + + public WifiApIface(@NonNull android.hardware.wifi.V1_0.IWifiApIface apIface) { + mWifiApIface = createWifiApIfaceHidlImplMockable(apIface); + } + + public WifiApIface(@NonNull android.hardware.wifi.IWifiApIface apIface) { + mWifiApIface = createWifiApIfaceAidlImplMockable(apIface); + } + + protected WifiApIfaceHidlImpl createWifiApIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiApIface apIface) { + return new WifiApIfaceHidlImpl(apIface); + } + + protected WifiApIfaceAidlImpl createWifiApIfaceAidlImplMockable( + android.hardware.wifi.IWifiApIface apIface) { + return new WifiApIfaceAidlImpl(apIface); + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiApIface == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiApIface is null"); + return defaultVal; + } + return supplier.get(); + } + + /** + * See comments for {@link IWifiApIface#getName()} + */ + @Override + @Nullable + public String getName() { + return validateAndCall("getName", null, + () -> mWifiApIface.getName()); + } + + /** + * See comments for {@link IWifiApIface#getBridgedInstances()} + */ + public List<String> getBridgedInstances() { + return validateAndCall("getBridgedInstances", null, + () -> mWifiApIface.getBridgedInstances()); + } + + /** + * See comments for {@link IWifiApIface#getFactoryMacAddress()} + */ + public MacAddress getFactoryMacAddress() { + return validateAndCall("getFactoryMacAddress", null, + () -> mWifiApIface.getFactoryMacAddress()); + } + + /** + * See comments for {@link IWifiApIface#setCountryCode(byte[])} + */ + public boolean setCountryCode(String countryCode) { + if (countryCode == null || countryCode.length() != 2) { + Log.e(TAG, "Invalid country code " + countryCode); + return false; + } + try { + final byte[] code = NativeUtil.stringToByteArray(countryCode); + return validateAndCall("setCountryCode", false, + () -> mWifiApIface.setCountryCode(code)); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid country code " + countryCode + ", error: " + e); + return false; + } + + } + + /** + * See comments for {@link IWifiApIface#resetToFactoryMacAddress()} + */ + public boolean resetToFactoryMacAddress() { + return validateAndCall("resetToFactoryMacAddress", false, + () -> mWifiApIface.resetToFactoryMacAddress()); + } + + /** + * See comments for {@link IWifiApIface#isSetMacAddressSupported()} + */ + public boolean isSetMacAddressSupported() { + return validateAndCall("isSetMacAddressSupported", false, + () -> mWifiApIface.isSetMacAddressSupported()); + } + + /** + * See comments for {@link IWifiApIface#setMacAddress(MacAddress)} + */ + public boolean setMacAddress(MacAddress mac) { + if (mac == null) { + Log.e(TAG, "setMacAddress received a null MAC address"); + return false; + } + return validateAndCall("setMacAddress", false, + () -> mWifiApIface.setMacAddress(mac)); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiApIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiApIfaceAidlImpl.java new file mode 100644 index 0000000000..f903a200c6 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiApIfaceAidlImpl.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.MacAddress; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.util.Log; + +import java.util.Arrays; +import java.util.List; + +/** + * AIDL implementation of the IWifiApIface interface. + */ +public class WifiApIfaceAidlImpl implements IWifiApIface { + private static final String TAG = "WifiApIfaceAidlImpl"; + private android.hardware.wifi.IWifiApIface mWifiApIface; + private final Object mLock = new Object(); + private String mIfaceName; + + public WifiApIfaceAidlImpl(@NonNull android.hardware.wifi.IWifiApIface apIface) { + mWifiApIface = apIface; + } + + /** + * See comments for {@link IWifiApIface#getName()} + */ + @Override + @Nullable + public String getName() { + final String methodStr = "getName"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return null; + if (mIfaceName != null) return mIfaceName; + try { + String ifaceName = mWifiApIface.getName(); + mIfaceName = ifaceName; + return mIfaceName; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiApIface#getBridgedInstances()} + */ + @Override + @Nullable + public List<String> getBridgedInstances() { + final String methodStr = "getBridgedInstances"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + String[] instances = mWifiApIface.getBridgedInstances(); + if (instances == null) { + Log.e(TAG, methodStr + " received a null array from the HAL"); + return null; + } + return Arrays.asList(instances); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiApIface#getFactoryMacAddress()} + */ + @Override + @Nullable + public MacAddress getFactoryMacAddress() { + final String methodStr = "getFactoryMacAddress"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return null; + try { + byte[] macBytes = mWifiApIface.getFactoryMacAddress(); + return MacAddress.fromBytes(macBytes); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + Log.e(TAG, methodStr + " received invalid MAC address: " + e); + } + return null; + } + } + + /** + * See comments for {@link IWifiApIface#setCountryCode(byte[])} + */ + @Override + public boolean setCountryCode(byte[] countryCode) { + final String methodStr = "setCountryCode"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiApIface.setCountryCode(countryCode); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiApIface#resetToFactoryMacAddress()} + */ + @Override + public boolean resetToFactoryMacAddress() { + final String methodStr = "resetToFactoryMacAddress"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiApIface.resetToFactoryMacAddress(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiApIface#isSetMacAddressSupported()} + */ + @Override + public boolean isSetMacAddressSupported() { + return true; // supported by default in the AIDL HAL + } + + /** + * See comments for {@link IWifiApIface#setMacAddress(MacAddress)} + */ + @Override + public boolean setMacAddress(MacAddress mac) { + final String methodStr = "setMacAddress"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiApIface.setMacAddress(mac.toByteArray()); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + private boolean checkIfaceAndLogFailure(String methodStr) { + if (mWifiApIface == null) { + Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); + return false; + } + return true; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + mWifiApIface = null; + mIfaceName = null; + Log.e(TAG, methodStr + " failed with remote exception: " + e); + } + + private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { + Log.e(TAG, methodStr + " failed with service-specific exception: " + e); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiApIfaceHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiApIfaceHidlImpl.java new file mode 100644 index 0000000000..f872bf0f47 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiApIfaceHidlImpl.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.hardware.wifi.V1_0.WifiStatus; +import android.hardware.wifi.V1_0.WifiStatusCode; +import android.net.MacAddress; +import android.os.RemoteException; +import android.util.Log; + +import com.android.server.wifi.util.GeneralUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * HIDL implementation of the IWifiApIface interface. + */ +public class WifiApIfaceHidlImpl implements IWifiApIface { + private static final String TAG = "WifiApIfaceHidlImpl"; + private android.hardware.wifi.V1_0.IWifiApIface mWifiApIface; + private String mIfaceName; + + public WifiApIfaceHidlImpl(@NonNull android.hardware.wifi.V1_0.IWifiApIface apIface) { + mWifiApIface = apIface; + } + + /** + * See comments for {@link IWifiApIface#getName()} + */ + public String getName() { + final String methodStr = "getName"; + return validateAndCall(methodStr, null, + () -> getNameInternal(methodStr)); + } + + /** + * See comments for {@link IWifiApIface#getBridgedInstances()} + */ + public List<String> getBridgedInstances() { + final String methodStr = "getBridgedInstances"; + return validateAndCall(methodStr, null, + () -> getBridgedInstancesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiApIface#getFactoryMacAddress()} + */ + public MacAddress getFactoryMacAddress() { + final String methodStr = "getFactoryMacAddress"; + return validateAndCall(methodStr, null, + () -> getFactoryMacAddressInternal(methodStr)); + } + + /** + * See comments for {@link IWifiApIface#setCountryCode(byte[])} + */ + public boolean setCountryCode(byte[] countryCode) { + final String methodStr = "setCountryCode"; + return validateAndCall(methodStr, false, + () -> setCountryCodeInternal(methodStr, countryCode)); + } + + /** + * See comments for {@link IWifiApIface#resetToFactoryMacAddress()} + * + * Note: If HAL < 1.5, will only reset the MAC address for this interface. + */ + public boolean resetToFactoryMacAddress() { + final String methodStr = "resetToFactoryMacAddress"; + return validateAndCall(methodStr, false, + () -> resetToFactoryMacAddressInternal(methodStr)); + } + + /** + * See comments for {@link IWifiApIface#isSetMacAddressSupported()} + */ + public boolean isSetMacAddressSupported() { + if (mWifiApIface == null) return false; + return getWifiApIfaceV1_4Mockable() != null; + } + + /** + * See comments for {@link IWifiApIface#setMacAddress(MacAddress)} + */ + public boolean setMacAddress(MacAddress mac) { + final String methodStr = "setMacAddress"; + return validateAndCall(methodStr, false, + () -> setMacAddressInternal(methodStr, mac)); + } + + + // Internal Implementations + + private String getNameInternal(String methodStr) { + if (mIfaceName != null) return mIfaceName; + GeneralUtil.Mutable<String> nameResp = new GeneralUtil.Mutable<>(); + try { + mWifiApIface.getName((WifiStatus status, String name) -> { + if (isOk(status, methodStr)) { + nameResp.value = name; + mIfaceName = name; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return nameResp.value; + } + + private List<String> getBridgedInstancesInternal(String methodStr) { + GeneralUtil.Mutable<List<String>> instancesResp = new GeneralUtil.Mutable<>(); + try { + android.hardware.wifi.V1_5.IWifiApIface ap15 = getWifiApIfaceV1_5Mockable(); + if (ap15 == null) return null; + ap15.getBridgedInstances((status, instances) -> { + if (isOk(status, methodStr)) { + instancesResp.value = new ArrayList<>(instances); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return instancesResp.value; + } + + private MacAddress getFactoryMacAddressInternal(String methodStr) { + GeneralUtil.Mutable<MacAddress> macResp = new GeneralUtil.Mutable<>(); + try { + android.hardware.wifi.V1_4.IWifiApIface ap14 = getWifiApIfaceV1_4Mockable(); + if (ap14 == null) return null; + ap14.getFactoryMacAddress((status, macBytes) -> { + if (isOk(status, methodStr)) { + macResp.value = MacAddress.fromBytes(macBytes); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return macResp.value; + } + + private boolean setCountryCodeInternal(String methodStr, byte[] countryCode) { + try { + WifiStatus status = mWifiApIface.setCountryCode(countryCode); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean resetToFactoryMacAddressInternal(String methodStr) { + try { + android.hardware.wifi.V1_5.IWifiApIface ap15 = getWifiApIfaceV1_5Mockable(); + if (ap15 == null) { + MacAddress mac = getFactoryMacAddress(); + return mac != null && setMacAddress(mac); + } + WifiStatus status = ap15.resetToFactoryMacAddress(); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean setMacAddressInternal(String methodStr, MacAddress mac) { + try { + android.hardware.wifi.V1_4.IWifiApIface ap14 = getWifiApIfaceV1_4Mockable(); + if (ap14 == null) return false; + WifiStatus status = ap14.setMacAddress(mac.toByteArray()); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + + // Helper Functions + + protected android.hardware.wifi.V1_4.IWifiApIface getWifiApIfaceV1_4Mockable() { + return android.hardware.wifi.V1_4.IWifiApIface.castFrom(mWifiApIface); + } + + protected android.hardware.wifi.V1_5.IWifiApIface getWifiApIfaceV1_5Mockable() { + return android.hardware.wifi.V1_5.IWifiApIface.castFrom(mWifiApIface); + } + + private boolean isOk(WifiStatus status, String methodStr) { + if (status.code == WifiStatusCode.SUCCESS) return true; + Log.e(TAG, methodStr + " failed with status: " + status); + return false; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + Log.e(TAG, methodStr + " failed with remote exception: " + e); + mWifiApIface = null; + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiApIface == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiApIface is null"); + return defaultVal; + } + return supplier.get(); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiChip.java b/service/java/com/android/server/wifi/hal/WifiChip.java new file mode 100644 index 0000000000..ca759fc193 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiChip.java @@ -0,0 +1,860 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.net.wifi.CoexUnsafeChannel; +import android.net.wifi.WifiAvailableChannel; +import android.net.wifi.WifiScanner; +import android.util.Log; + +import com.android.server.wifi.SarInfo; +import com.android.server.wifi.SsidTranslator; +import com.android.server.wifi.WifiNative; +import com.android.server.wifi.WlanWakeReasonAndCounts; +import com.android.server.wifi.util.GeneralUtil.Mutable; +import com.android.server.wifi.util.NativeUtil; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; +import java.util.function.Supplier; + +/** + * Wrapper around a WifiChip. + * May be initialized using a HIDL or AIDL WifiChip. + */ +public class WifiChip { + public static final String TAG = "WifiChip"; + private IWifiChip mWifiChip; + + /** + * Interface concurrency types used in reporting device concurrency capabilities. + */ + public static final int IFACE_CONCURRENCY_TYPE_STA = 0; + public static final int IFACE_CONCURRENCY_TYPE_AP = 1; + public static final int IFACE_CONCURRENCY_TYPE_AP_BRIDGED = 2; + public static final int IFACE_CONCURRENCY_TYPE_P2P = 3; + public static final int IFACE_CONCURRENCY_TYPE_NAN = 4; + + @IntDef(prefix = { "IFACE_CONCURRENCY_TYPE_" }, value = { + IFACE_CONCURRENCY_TYPE_STA, + IFACE_CONCURRENCY_TYPE_AP, + IFACE_CONCURRENCY_TYPE_AP_BRIDGED, + IFACE_CONCURRENCY_TYPE_P2P, + IFACE_CONCURRENCY_TYPE_NAN, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface IfaceConcurrencyType {} + + /** + * Supported interface types. + */ + public static final int IFACE_TYPE_STA = 0; + public static final int IFACE_TYPE_AP = 1; + public static final int IFACE_TYPE_P2P = 2; + public static final int IFACE_TYPE_NAN = 3; + + @IntDef(prefix = { "IFACE_TYPE_" }, value = { + IFACE_TYPE_STA, + IFACE_TYPE_AP, + IFACE_TYPE_P2P, + IFACE_TYPE_NAN, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface IfaceType {} + + /** + * Antenna configurations. + */ + public static final int WIFI_ANTENNA_MODE_UNSPECIFIED = 0; + public static final int WIFI_ANTENNA_MODE_1X1 = 1; + public static final int WIFI_ANTENNA_MODE_2X2 = 2; + public static final int WIFI_ANTENNA_MODE_3X3 = 3; + public static final int WIFI_ANTENNA_MODE_4X4 = 4; + + @IntDef(prefix = { "WIFI_ANTENNA_MODE_" }, value = { + WIFI_ANTENNA_MODE_UNSPECIFIED, + WIFI_ANTENNA_MODE_1X1, + WIFI_ANTENNA_MODE_2X2, + WIFI_ANTENNA_MODE_3X3, + WIFI_ANTENNA_MODE_4X4, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WifiAntennaMode {} + + /** + * Response containing a value and a status code. + * + * @param <T> Type of value that should be returned. + */ + public static class Response<T> { + private Mutable<T> mMutable; + private int mStatusCode; + + public Response(T initialValue) { + mMutable = new Mutable<>(initialValue); + mStatusCode = WifiHal.WIFI_STATUS_ERROR_UNKNOWN; + } + + public void setValue(T value) { + mMutable.value = value; + } + + public T getValue() { + return mMutable.value; + } + + public void setStatusCode(@WifiHal.WifiStatusCode int statusCode) { + mStatusCode = statusCode; + } + + public @WifiHal.WifiStatusCode int getStatusCode() { + return mStatusCode; + } + } + + /** + * Set of interface concurrency types, along with the maximum number of interfaces that can have + * one of the specified concurrency types for a given ChipConcurrencyCombination. See + * ChipConcurrencyCombination below for examples. + */ + public static class ChipConcurrencyCombinationLimit { + public final int maxIfaces; + public final @IfaceConcurrencyType List<Integer> types; + + public ChipConcurrencyCombinationLimit(int inMaxIfaces, + @IfaceConcurrencyType List<Integer> inTypes) { + maxIfaces = inMaxIfaces; + types = inTypes; + } + + @Override + public String toString() { + return "{maxIfaces=" + maxIfaces + ", types=" + types + "}"; + } + } + + /** + * Set of interfaces that can operate concurrently when in a given mode. + * + * For example: + * [{STA} <= 2] + * At most two STA interfaces are supported + * [], [STA], [STA+STA] + * + * [{STA} <= 1, {NAN} <= 1, {AP_BRIDGED} <= 1] + * Any combination of STA, NAN, AP_BRIDGED + * [], [STA], [NAN], [AP_BRIDGED], [STA+NAN], [STA+AP_BRIDGED], [NAN+AP_BRIDGED], + * [STA+NAN+AP_BRIDGED] + * + * [{STA} <= 1, {NAN,P2P} <= 1] + * Optionally a STA and either NAN or P2P + * [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P] + * Not included [NAN+P2P], [STA+NAN+P2P] + * + * [{STA} <= 1, {STA,NAN} <= 1] + * Optionally a STA and either a second STA or a NAN + * [], [STA], [STA+NAN], [STA+STA], [NAN] + * Not included [STA+STA+NAN] + */ + public static class ChipConcurrencyCombination { + public final List<ChipConcurrencyCombinationLimit> limits; + + public ChipConcurrencyCombination(List<ChipConcurrencyCombinationLimit> inLimits) { + limits = inLimits; + } + + @Override + public String toString() { + return "{limits=" + limits + "}"; + } + } + + /** + * A mode that the chip can be put in. A mode defines a set of constraints on + * the interfaces that can exist while in that mode. Modes define a unit of + * configuration where all interfaces must be torn down to switch to a + * different mode. Some HALs may only have a single mode, but an example where + * multiple modes would be required is if a chip has different firmwares with + * different capabilities. + * + * When in a mode, it must be possible to perform any combination of creating + * and removing interfaces as long as at least one of the + * ChipConcurrencyCombinations is satisfied. This means that if a chip has two + * available combinations, [{STA} <= 1] and [{AP_BRIDGED} <= 1] then it is expected + * that exactly one STA type or one AP_BRIDGED type can be created, but it + * is not expected that both a STA and AP_BRIDGED type could be created. If it + * was then there would be a single available combination + * [{STA} <=1, {AP_BRIDGED} <= 1]. + * + * When switching between two available combinations it is expected that + * interfaces only supported by the initial combination must be removed until + * the target combination is also satisfied. At that point new interfaces + * satisfying only the target combination can be added (meaning the initial + * combination limits will no longer satisfied). The addition of these new + * interfaces must not impact the existence of interfaces that satisfy both + * combinations. + * + * For example, a chip with available combinations: + * [{STA} <= 2, {NAN} <=1] and [{STA} <=1, {NAN} <= 1, {AP_BRIDGED} <= 1}] + * If the chip currently has 3 interfaces STA, STA and NAN and wants to add an + * AP_BRIDGED interface in place of one of the STAs, then one of the STA interfaces + * must be removed first, and then the AP interface can be created after + * the STA has been torn down. During this process the remaining STA and NAN + * interfaces must not be removed/recreated. + * + * If a chip does not support this kind of reconfiguration in this mode then + * the combinations must be separated into two separate modes. Before + * switching modes, all interfaces must be torn down, the mode switch must be + * enacted, and when it completes the new interfaces must be brought up. + */ + public static class ChipMode { + public final int id; + public final List<ChipConcurrencyCombination> availableCombinations; + + public ChipMode(int inId, List<ChipConcurrencyCombination> inAvailableCombinations) { + id = inId; + availableCombinations = inAvailableCombinations; + } + + @Override + public String toString() { + return "{id=" + id + ", availableCombinations=" + availableCombinations + "}"; + } + } + + /** + * Wifi radio configuration. + */ + public static class WifiRadioConfiguration { + public final @WifiScanner.WifiBand int bandInfo; + public final @WifiAntennaMode int antennaMode; + + public WifiRadioConfiguration(int inBandInfo, int inAntennaMode) { + bandInfo = inBandInfo; + antennaMode = inAntennaMode; + } + + @Override + public String toString() { + return "{bandInfo=" + bandInfo + ", antennaMode=" + antennaMode + "}"; + } + } + + /** + * Wifi radio combination. + */ + public static class WifiRadioCombination { + public final List<WifiRadioConfiguration> radioConfigurations; + + public WifiRadioCombination(List<WifiRadioConfiguration> inRadioConfigurations) { + radioConfigurations = inRadioConfigurations; + } + + @Override + public String toString() { + return "{radioConfigurations=" + radioConfigurations + "}"; + } + } + + /** + * Wifi radio combinations matrix. + */ + public static class WifiRadioCombinationMatrix { + public final List<WifiRadioCombination> radioCombinations; + + public WifiRadioCombinationMatrix(List<WifiRadioCombination> inRadioCombinations) { + radioCombinations = inRadioCombinations; + } + + @Override + public String toString() { + return "{radioCombinations=" + radioCombinations + "}"; + } + } + + /** + * Information about the version of the driver and firmware running this chip. + * + * The information in these ASCII strings are vendor specific and does not + * need to follow any particular format. It may be dumped as part of the bug + * report. + */ + public static class ChipDebugInfo { + public final String driverDescription; + public final String firmwareDescription; + + public ChipDebugInfo(String inDriverDescription, String inFirmwareDescription) { + driverDescription = inDriverDescription; + firmwareDescription = inFirmwareDescription; + } + } + + /** + * State of an iface operating on the radio chain (hardware MAC) on the device. + */ + public static class IfaceInfo { + public final String name; + public final int channel; + + public IfaceInfo(String inName, int inChannel) { + name = inName; + channel = inChannel; + } + } + + /** + * State of a hardware radio chain (hardware MAC) on the device. + */ + public static class RadioModeInfo { + public final int radioId; + public final @WifiScanner.WifiBand int bandInfo; + public final List<IfaceInfo> ifaceInfos; + + public RadioModeInfo(int inRadioId, @WifiScanner.WifiBand int inBandInfo, + List<IfaceInfo> inIfaceInfos) { + radioId = inRadioId; + bandInfo = inBandInfo; + ifaceInfos = inIfaceInfos; + } + } + + /** + * Framework callback object. Will get called when the equivalent events are received + * from the HAL. + */ + public interface Callback { + /** + * Indicates that a chip reconfiguration failed. This is a fatal + * error and any iface objects available previously must be considered + * invalid. The client can attempt to recover by trying to reconfigure the + * chip again using {@link IWifiChip#configureChip(int)}. + * + * @param status Failure reason code. + */ + void onChipReconfigureFailure(int status); + + /** + * Indicates that the chip has been reconfigured successfully. At + * this point, the interfaces available in the mode must be able to be + * configured. When this is called, any previous iface objects must be + * considered invalid. + * + * @param modeId The mode that the chip switched to, corresponding to the id + * property of the target ChipMode. + */ + void onChipReconfigured(int modeId); + + /** + * Indicates that the chip has encountered a fatal error. + * Client must not attempt to parse either the errorCode or debugData. + * Must only be captured in a bugreport. + * + * @param errorCode Vendor defined error code. + * @param debugData Vendor defined data used for debugging. + */ + void onDebugErrorAlert(int errorCode, byte[] debugData); + + /** + * Reports debug ring buffer data. + * + * The ring buffer data collection is event based: + * - Driver calls this callback when new records are available, the + * |WifiDebugRingBufferStatus| passed up to framework in the callback + * indicates to framework if more data is available in the ring buffer. + * It is not expected that driver will necessarily always empty the ring + * immediately as data is available. Instead the driver will report data + * every X seconds, or if N bytes are available, based on the parameters + * set via |startLoggingToDebugRingBuffer|. + * - In the case where a bug report has to be captured, the framework will + * require driver to upload all data immediately. This is indicated to + * driver when framework calls |forceDumpToDebugRingBuffer|. The driver + * will start sending all available data in the indicated ring by repeatedly + * invoking this callback. + * + * @param status Status of the corresponding ring buffer. This should + * contain the name of the ring buffer on which the data is + * available. + * @param data Raw bytes of data sent by the driver. Must be dumped + * out to a bugreport and post processed. + */ + void onDebugRingBufferDataAvailable(WifiNative.RingBufferStatus status, byte[] data); + + /** + * Indicates that a new iface has been added to the chip. + * + * @param type Type of iface added. + * @param name Name of iface added. + */ + void onIfaceAdded(@IfaceType int type, String name); + + /** + * Indicates that an existing iface has been removed from the chip. + * + * @param type Type of iface removed. + * @param name Name of iface removed. + */ + void onIfaceRemoved(@IfaceType int type, String name); + + /** + * Indicates a radio mode change. + * Radio mode change could be a result of: + * a) Bringing up concurrent interfaces (ex. STA + AP). + * b) Change in operating band of one of the concurrent interfaces + * (ex. STA connection moved from 2.4G to 5G) + * + * @param radioModeInfos List of RadioModeInfo structures for each + * radio chain (hardware MAC) on the device. + */ + void onRadioModeChange(List<RadioModeInfo> radioModeInfos); + } + + public WifiChip(@NonNull android.hardware.wifi.V1_0.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiChip = createWifiChipHidlImplMockable(chip, context, ssidTranslator); + } + + public WifiChip(@NonNull android.hardware.wifi.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiChip = createWifiChipAidlImplMockable(chip, context, ssidTranslator); + } + + protected WifiChipHidlImpl createWifiChipHidlImplMockable( + @NonNull android.hardware.wifi.V1_0.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return new WifiChipHidlImpl(chip, context, ssidTranslator); + } + + protected WifiChipAidlImpl createWifiChipAidlImplMockable( + @NonNull android.hardware.wifi.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return new WifiChipAidlImpl(chip, context, ssidTranslator); + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiChip == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiChip is null"); + return defaultVal; + } + return supplier.get(); + } + + /** + * See comments for {@link IWifiChip#configureChip(int)} + */ + public boolean configureChip(int modeId) { + return validateAndCall("configureChip", false, + () -> mWifiChip.configureChip(modeId)); + } + + /** + * See comments for {@link IWifiChip#createApIface()} + */ + @Nullable + public WifiApIface createApIface() { + return validateAndCall("createApIface", null, + () -> mWifiChip.createApIface()); + } + + /** + * See comments for {@link IWifiChip#createBridgedApIface()} + */ + @Nullable + public WifiApIface createBridgedApIface() { + return validateAndCall("createBridgedApIface", null, + () -> mWifiChip.createBridgedApIface()); + } + + /** + * See comments for {@link IWifiChip#createNanIface()} + */ + @Nullable + public WifiNanIface createNanIface() { + return validateAndCall("createNanIface", null, + () -> mWifiChip.createNanIface()); + } + + /** + * See comments for {@link IWifiChip#createP2pIface()} + */ + @Nullable + public WifiP2pIface createP2pIface() { + return validateAndCall("createP2pIface", null, + () -> mWifiChip.createP2pIface()); + } + + /** + * See comments for {@link IWifiChip#createRttController()} + */ + @Nullable + public WifiRttController createRttController() { + return validateAndCall("createRttController", null, + () -> mWifiChip.createRttController()); + } + + /** + * See comments for {@link IWifiChip#createStaIface()} + */ + @Nullable + public WifiStaIface createStaIface() { + return validateAndCall("createStaIface", null, + () -> mWifiChip.createStaIface()); + } + + /** + * See comments for {@link IWifiChip#enableDebugErrorAlerts(boolean)} + */ + public boolean enableDebugErrorAlerts(boolean enable) { + return validateAndCall("enableDebugErrorAlerts", false, + () -> mWifiChip.enableDebugErrorAlerts(enable)); + } + + /** + * See comments for {@link IWifiChip#flushRingBufferToFile()} + */ + public boolean flushRingBufferToFile() { + return validateAndCall("flushRingBufferToFile", false, + () -> mWifiChip.flushRingBufferToFile()); + } + + /** + * See comments for {@link IWifiChip#forceDumpToDebugRingBuffer(String)} + */ + public boolean forceDumpToDebugRingBuffer(String ringName) { + return validateAndCall("forceDumpToDebugRingBuffer", false, + () -> mWifiChip.forceDumpToDebugRingBuffer(ringName)); + } + + /** + * See comments for {@link IWifiChip#getApIface(String)} + */ + @Nullable + public WifiApIface getApIface(String ifaceName) { + return validateAndCall("getApIface", null, + () -> mWifiChip.getApIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getApIfaceNames()} + */ + @Nullable + public List<String> getApIfaceNames() { + return validateAndCall("getApIfaceNames", null, + () -> mWifiChip.getApIfaceNames()); + } + + /** + * See comments for {@link IWifiChip#getAvailableModes()} + */ + @Nullable + public List<WifiChip.ChipMode> getAvailableModes() { + return validateAndCall("getAvailableModes", null, + () -> mWifiChip.getAvailableModes()); + } + + /** + * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()} + */ + public Response<Long> getCapabilitiesBeforeIfacesExist() { + return validateAndCall("getCapabilitiesBeforeIfacesExist", new Response<>(0L), + () -> mWifiChip.getCapabilitiesBeforeIfacesExist()); + } + + /** + * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()} + */ + public Response<Long> getCapabilitiesAfterIfacesExist() { + return validateAndCall("getCapabilitiesAfterIfacesExist", new Response<>(0L), + () -> mWifiChip.getCapabilitiesAfterIfacesExist()); + } + + /** + * See comments for {@link IWifiChip#getDebugHostWakeReasonStats()} + */ + @Nullable + public WlanWakeReasonAndCounts getDebugHostWakeReasonStats() { + return validateAndCall("getDebugHostWakeReasonStats", null, + () -> mWifiChip.getDebugHostWakeReasonStats()); + } + + /** + * See comments for {@link IWifiChip#getDebugRingBuffersStatus()} + */ + @Nullable + public List<WifiNative.RingBufferStatus> getDebugRingBuffersStatus() { + return validateAndCall("getDebugRingBuffersStatus", null, + () -> mWifiChip.getDebugRingBuffersStatus()); + } + + /** + * See comments for {@link IWifiChip#getId()} + */ + public int getId() { + return validateAndCall("getId", -1, () -> mWifiChip.getId()); + } + + /** + * See comments for {@link IWifiChip#getMode()} + */ + public Response<Integer> getMode() { + return validateAndCall("getMode", new Response<>(0), () -> mWifiChip.getMode()); + } + + /** + * See comments for {@link IWifiChip#getNanIface(String)} + */ + @Nullable + public WifiNanIface getNanIface(String ifaceName) { + return validateAndCall("getNanIface", null, + () -> mWifiChip.getNanIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getNanIfaceNames()} + */ + @Nullable + public List<String> getNanIfaceNames() { + return validateAndCall("getNanIfaceNames", null, + () -> mWifiChip.getNanIfaceNames()); + } + + /** + * See comments for {@link IWifiChip#getP2pIface(String)} + */ + @Nullable + public WifiP2pIface getP2pIface(String ifaceName) { + return validateAndCall("getP2pIface", null, + () -> mWifiChip.getP2pIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getP2pIfaceNames()} + */ + @Nullable + public List<String> getP2pIfaceNames() { + return validateAndCall("getP2pIfaceNames", null, + () -> mWifiChip.getP2pIfaceNames()); + } + + /** + * See comments for {@link IWifiChip#getStaIface(String)} + */ + @Nullable + public WifiStaIface getStaIface(String ifaceName) { + return validateAndCall("getStaIface", null, + () -> mWifiChip.getStaIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getStaIfaceNames()} + */ + @Nullable + public List<String> getStaIfaceNames() { + return validateAndCall("getStaIfaceNames", null, + () -> mWifiChip.getStaIfaceNames()); + } + + /** + * See comments for {@link IWifiChip#getSupportedRadioCombinationsMatrix()} + */ + @Nullable + public WifiChip.WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix() { + return validateAndCall("getSupportedRadioCombinationsMatrix", null, + () -> mWifiChip.getSupportedRadioCombinationsMatrix()); + } + + /** + * See comments for {@link IWifiChip#getUsableChannels(int, int, int)} + */ + @Nullable + public List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band, + @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) { + return validateAndCall("getUsableChannels", null, + () -> mWifiChip.getUsableChannels(band, mode, filter)); + } + + /** + * See comments for {@link IWifiChip#registerCallback(Callback)} + */ + public boolean registerCallback(WifiChip.Callback callback) { + return validateAndCall("registerCallback", false, + () -> mWifiChip.registerCallback(callback)); + } + + /** + * See comments for {@link IWifiChip#removeApIface(String)} + */ + public boolean removeApIface(String ifaceName) { + return validateAndCall("removeApIface", false, + () -> mWifiChip.removeApIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeIfaceInstanceFromBridgedApIface(String, String)} + */ + public boolean removeIfaceInstanceFromBridgedApIface(String brIfaceName, String ifaceName) { + return validateAndCall("removeIfaceInstanceFromBridgedApIface", false, + () -> mWifiChip.removeIfaceInstanceFromBridgedApIface(brIfaceName, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeNanIface(String)} + */ + public boolean removeNanIface(String ifaceName) { + return validateAndCall("removeNanIface", false, + () -> mWifiChip.removeNanIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeP2pIface(String)} + */ + public boolean removeP2pIface(String ifaceName) { + return validateAndCall("removeP2pIface", false, + () -> mWifiChip.removeP2pIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeStaIface(String)} + */ + public boolean removeStaIface(String ifaceName) { + return validateAndCall("removeStaIface", false, + () -> mWifiChip.removeStaIface(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#requestChipDebugInfo()} + */ + @Nullable + public WifiChip.ChipDebugInfo requestChipDebugInfo() { + return validateAndCall("requestChipDebugInfo", null, + () -> mWifiChip.requestChipDebugInfo()); + } + + /** + * See comments for {@link IWifiChip#requestDriverDebugDump()} + */ + @Nullable + public byte[] requestDriverDebugDump() { + return validateAndCall("requestDriverDebugDump", null, + () -> mWifiChip.requestDriverDebugDump()); + } + + /** + * See comments for {@link IWifiChip#requestFirmwareDebugDump()} + */ + @Nullable + public byte[] requestFirmwareDebugDump() { + return validateAndCall("requestFirmwareDebugDump", null, + () -> mWifiChip.requestFirmwareDebugDump()); + } + + /** + * See comments for {@link IWifiChip#resetTxPowerScenario()} + */ + public boolean resetTxPowerScenario() { + return validateAndCall("resetTxPowerScenario", false, + () -> mWifiChip.resetTxPowerScenario()); + } + + /** + * See comments for {@link IWifiChip#selectTxPowerScenario(SarInfo)} + */ + public boolean selectTxPowerScenario(SarInfo sarInfo) { + return validateAndCall("selectTxPowerScenario", false, + () -> mWifiChip.selectTxPowerScenario(sarInfo)); + } + + /** + * See comments for {@link IWifiChip#setCoexUnsafeChannels(List, int)} + */ + public boolean setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions) { + return validateAndCall("setCoexUnsafeChannels", false, + () -> mWifiChip.setCoexUnsafeChannels(unsafeChannels, restrictions)); + } + + /** + * See comments for {@link IWifiChip#setCountryCode(byte[])} + */ + public boolean setCountryCode(String countryCode) { + if (countryCode == null || countryCode.length() != 2) { + Log.e(TAG, "Invalid country code " + countryCode); + return false; + } + try { + final byte[] code = NativeUtil.stringToByteArray(countryCode); + return validateAndCall("setCountryCode", false, + () -> mWifiChip.setCountryCode(code)); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid country code " + countryCode + ", error: " + e); + return false; + } + } + + /** + * See comments for {@link IWifiChip#setLowLatencyMode(boolean)} + */ + public boolean setLowLatencyMode(boolean enable) { + return validateAndCall("setLowLatencyMode", false, + () -> mWifiChip.setLowLatencyMode(enable)); + } + + /** + * See comments for {@link IWifiChip#setMultiStaPrimaryConnection(String)} + */ + public boolean setMultiStaPrimaryConnection(String ifaceName) { + return validateAndCall("setMultiStaPrimaryConnection", false, + () -> mWifiChip.setMultiStaPrimaryConnection(ifaceName)); + } + + /** + * See comments for {@link IWifiChip#setMultiStaUseCase(int)} + */ + public boolean setMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase) { + return validateAndCall("setMultiStaUseCase", false, + () -> mWifiChip.setMultiStaUseCase(useCase)); + } + + /** + * See comments for {@link IWifiChip#startLoggingToDebugRingBuffer(String, int, int, int)} + */ + public boolean startLoggingToDebugRingBuffer(String ringName, int verboseLevel, + int maxIntervalInSec, int minDataSizeInBytes) { + return validateAndCall("startLoggingToDebugRingBuffer", false, + () -> mWifiChip.startLoggingToDebugRingBuffer(ringName, verboseLevel, + maxIntervalInSec, minDataSizeInBytes)); + } + + /** + * See comments for {@link IWifiChip#stopLoggingToDebugRingBuffer()} + */ + public boolean stopLoggingToDebugRingBuffer() { + return validateAndCall("stopLoggingToDebugRingBuffer", false, + () -> mWifiChip.stopLoggingToDebugRingBuffer()); + } + + /** + * See comments for {@link IWifiChip#triggerSubsystemRestart()} + */ + public boolean triggerSubsystemRestart() { + return validateAndCall("triggerSubsystemRestart", false, + () -> mWifiChip.triggerSubsystemRestart()); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java new file mode 100644 index 0000000000..4d24379d18 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java @@ -0,0 +1,1623 @@ +/* + * Copyright (C) 2022 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.hal; + +import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.wifi.IWifiApIface; +import android.hardware.wifi.IWifiChip.ChipCapabilityMask; +import android.hardware.wifi.IWifiChip.CoexRestriction; +import android.hardware.wifi.IWifiChip.LatencyMode; +import android.hardware.wifi.IWifiChip.MultiStaUseCase; +import android.hardware.wifi.IWifiChip.TxPowerScenario; +import android.hardware.wifi.IWifiChip.UsableChannelFilter; +import android.hardware.wifi.IWifiChipEventCallback; +import android.hardware.wifi.IWifiNanIface; +import android.hardware.wifi.IWifiP2pIface; +import android.hardware.wifi.IWifiRttController; +import android.hardware.wifi.IWifiStaIface; +import android.hardware.wifi.IfaceConcurrencyType; +import android.hardware.wifi.IfaceType; +import android.hardware.wifi.WifiAntennaMode; +import android.hardware.wifi.WifiBand; +import android.hardware.wifi.WifiDebugHostWakeReasonStats; +import android.hardware.wifi.WifiDebugRingBufferFlags; +import android.hardware.wifi.WifiDebugRingBufferStatus; +import android.hardware.wifi.WifiIfaceMode; +import android.hardware.wifi.WifiRadioCombination; +import android.hardware.wifi.WifiRadioCombinationMatrix; +import android.hardware.wifi.WifiRadioConfiguration; +import android.hardware.wifi.WifiUsableChannel; +import android.net.wifi.CoexUnsafeChannel; +import android.net.wifi.WifiAvailableChannel; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiScanner; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.build.SdkLevel; +import com.android.server.wifi.SarInfo; +import com.android.server.wifi.SsidTranslator; +import com.android.server.wifi.WifiNative; +import com.android.server.wifi.WlanWakeReasonAndCounts; +import com.android.server.wifi.util.BitMask; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * AIDL implementation of the WifiChip interface. + */ +public class WifiChipAidlImpl implements IWifiChip { + private static final String TAG = "WifiChipAidlImpl"; + private android.hardware.wifi.IWifiChip mWifiChip; + private android.hardware.wifi.IWifiChipEventCallback mHalCallback; + private WifiChip.Callback mFrameworkCallback; + private final Object mLock = new Object(); + private Context mContext; + private SsidTranslator mSsidTranslator; + + public WifiChipAidlImpl(@NonNull android.hardware.wifi.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiChip = chip; + mContext = context; + mSsidTranslator = ssidTranslator; + } + + /** + * See comments for {@link IWifiChip#configureChip(int)} + */ + @Override + public boolean configureChip(int modeId) { + final String methodStr = "configureChip"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.configureChip(modeId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#createApIface()} + */ + @Override + @Nullable + public WifiApIface createApIface() { + final String methodStr = "createApIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiApIface iface = mWifiChip.createApIface(); + return new WifiApIface(iface); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#createBridgedApIface()} + */ + @Override + @Nullable + public WifiApIface createBridgedApIface() { + final String methodStr = "createBridgedApIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiApIface iface = mWifiChip.createBridgedApIface(); + return new WifiApIface(iface); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#createNanIface()} + */ + @Override + @Nullable + public WifiNanIface createNanIface() { + final String methodStr = "createNanIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiNanIface iface = mWifiChip.createNanIface(); + return new WifiNanIface(iface); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#createP2pIface()} + */ + @Override + @Nullable + public WifiP2pIface createP2pIface() { + final String methodStr = "createP2pIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiP2pIface iface = mWifiChip.createP2pIface(); + return new WifiP2pIface(iface); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#createRttController()} + */ + @Override + @Nullable + public WifiRttController createRttController() { + final String methodStr = "createRttController"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiRttController rttController = mWifiChip.createRttController(null); + return new WifiRttController(rttController); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#createStaIface()} + */ + @Override + @Nullable + public WifiStaIface createStaIface() { + final String methodStr = "createStaIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiStaIface iface = mWifiChip.createStaIface(); + return new WifiStaIface(iface, mContext, mSsidTranslator); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#enableDebugErrorAlerts(boolean)} + */ + @Override + public boolean enableDebugErrorAlerts(boolean enable) { + final String methodStr = "enableDebugErrorAlerts"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.enableDebugErrorAlerts(enable); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#flushRingBufferToFile()} + */ + @Override + public boolean flushRingBufferToFile() { + final String methodStr = "flushRingBufferToFile"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.flushRingBufferToFile(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#forceDumpToDebugRingBuffer(String)} + */ + @Override + public boolean forceDumpToDebugRingBuffer(String ringName) { + final String methodStr = "forceDumpToDebugRingBuffer"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.forceDumpToDebugRingBuffer(ringName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#getApIface(String)} + */ + @Override + @Nullable + public WifiApIface getApIface(String ifaceName) { + final String methodStr = "getApIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiApIface iface = mWifiChip.getApIface(ifaceName); + return new WifiApIface(iface); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getApIfaceNames()} + */ + @Override + @Nullable + public List<String> getApIfaceNames() { + final String methodStr = "getApIfaceNames"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + String[] ifaceNames = mWifiChip.getApIfaceNames(); + return Arrays.asList(ifaceNames); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getAvailableModes()} + */ + @Override + @Nullable + public List<WifiChip.ChipMode> getAvailableModes() { + final String methodStr = "getAvailableModes"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + android.hardware.wifi.IWifiChip.ChipMode[] halModes = mWifiChip.getAvailableModes(); + return halToFrameworkChipModeList(halModes); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()} + */ + @Override + public WifiChip.Response<Long> getCapabilitiesBeforeIfacesExist() { + final String methodStr = "getCapabilitiesBeforeIfacesExist"; + return getCapabilitiesInternal(methodStr); + } + + /** + * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()} + */ + @Override + public WifiChip.Response<Long> getCapabilitiesAfterIfacesExist() { + final String methodStr = "getCapabilitiesAfterIfacesExist"; + return getCapabilitiesInternal(methodStr); + } + + private WifiChip.Response<Long> 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> capsResp = new WifiChip.Response<>(0L); + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return capsResp; + long halCaps = mWifiChip.getCapabilities(); + capsResp.setValue(halToFrameworkChipCapabilityMask(halCaps)); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + // TODO: convert to framework status code once WifiHalAidlImpl exists + capsResp.setStatusCode(e.errorCode); + } + return capsResp; + } + } + + /** + * See comments for {@link IWifiChip#getDebugHostWakeReasonStats()} + */ + @Override + @Nullable + public WlanWakeReasonAndCounts getDebugHostWakeReasonStats() { + final String methodStr = "getDebugHostWakeReasonStats"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + WifiDebugHostWakeReasonStats stats = mWifiChip.getDebugHostWakeReasonStats(); + return halToFrameworkWakeReasons(stats); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getDebugRingBuffersStatus()} + */ + @Override + @Nullable + public List<WifiNative.RingBufferStatus> getDebugRingBuffersStatus() { + final String methodStr = "getDebugRingBuffersStatus"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + WifiDebugRingBufferStatus[] stats = mWifiChip.getDebugRingBuffersStatus(); + return halToFrameworkRingBufferStatusList(stats); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getId()} + */ + @Override + public int getId() { + final String methodStr = "getId"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return -1; + return mWifiChip.getId(); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return -1; + } + } + + /** + * See comments for {@link IWifiChip#getMode()} + */ + @Override + public WifiChip.Response<Integer> getMode() { + final String methodStr = "getMode"; + WifiChip.Response<Integer> modeResp = new WifiChip.Response<>(0); + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return modeResp; + int mode = mWifiChip.getMode(); + modeResp.setValue(mode); + modeResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + modeResp.setStatusCode(WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + // TODO: convert to framework status code once WifiHalAidlImpl exists + modeResp.setStatusCode(e.errorCode); + } + return modeResp; + } + } + + /** + * See comments for {@link IWifiChip#getNanIface(String)} + */ + @Override + @Nullable + public WifiNanIface getNanIface(String ifaceName) { + final String methodStr = "getNanIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiNanIface iface = mWifiChip.getNanIface(ifaceName); + return new WifiNanIface(iface); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getNanIfaceNames()} + */ + @Override + @Nullable + public List<String> getNanIfaceNames() { + final String methodStr = "getNanIfaceNames"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + String[] ifaceNames = mWifiChip.getNanIfaceNames(); + return Arrays.asList(ifaceNames); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getP2pIface(String)} + */ + @Override + @Nullable + public WifiP2pIface getP2pIface(String ifaceName) { + final String methodStr = "getP2pIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiP2pIface iface = mWifiChip.getP2pIface(ifaceName); + return new WifiP2pIface(iface); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getP2pIfaceNames()} + */ + @Override + @Nullable + public List<String> getP2pIfaceNames() { + final String methodStr = "getP2pIfaceNames"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + String[] ifaceNames = mWifiChip.getP2pIfaceNames(); + return Arrays.asList(ifaceNames); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getStaIface(String)} + */ + @Override + @Nullable + public WifiStaIface getStaIface(String ifaceName) { + final String methodStr = "getStaIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + IWifiStaIface iface = mWifiChip.getStaIface(ifaceName); + return new WifiStaIface(iface, mContext, mSsidTranslator); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getStaIfaceNames()} + */ + @Override + @Nullable + public List<String> getStaIfaceNames() { + final String methodStr = "getStaIfaceNames"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + String[] ifaceNames = mWifiChip.getStaIfaceNames(); + return Arrays.asList(ifaceNames); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getSupportedRadioCombinationsMatrix()} + */ + @Override + @Nullable + public WifiChip.WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix() { + final String methodStr = "getSupportedRadioCombinationsMatrix"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + WifiRadioCombinationMatrix halMatrix = + mWifiChip.getSupportedRadioCombinationsMatrix(); + return halToFrameworkRadioCombinationMatrix(halMatrix); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#getUsableChannels(int, int, int)} + */ + @Override + @Nullable + public List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band, + @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) { + final String methodStr = "getUsableChannels"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + WifiUsableChannel[] halChannels = mWifiChip.getUsableChannels( + frameworkToHalWifiBand(band), + frameworkToHalIfaceMode(mode), + frameworkToHalUsableFilter(filter)); + List<WifiAvailableChannel> frameworkChannels = new ArrayList<>(); + for (WifiUsableChannel ch : halChannels) { + frameworkChannels.add(new WifiAvailableChannel( + ch.channel, halToFrameworkIfaceMode(ch.ifaceModeMask))); + } + return frameworkChannels; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#registerCallback(WifiChip.Callback)} + */ + @Override + public boolean registerCallback(WifiChip.Callback callback) { + final String methodStr = "registerCallback"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return false; + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (callback == null) { + Log.e(TAG, "Cannot register a null callback"); + return false; + } + + try { + mHalCallback = new ChipEventCallback(); + mWifiChip.registerEventCallback(mHalCallback); + mFrameworkCallback = callback; + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#removeApIface(String)} + */ + @Override + public boolean removeApIface(String ifaceName) { + final String methodStr = "removeApIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.removeApIface(ifaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#removeIfaceInstanceFromBridgedApIface(String, String)} + */ + @Override + public boolean removeIfaceInstanceFromBridgedApIface(String brIfaceName, String ifaceName) { + final String methodStr = "removeIfaceInstanceFromBridgedApIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.removeIfaceInstanceFromBridgedApIface(brIfaceName, ifaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#removeNanIface(String)} + */ + @Override + public boolean removeNanIface(String ifaceName) { + final String methodStr = "removeNanIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.removeNanIface(ifaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#removeP2pIface(String)} + */ + @Override + public boolean removeP2pIface(String ifaceName) { + final String methodStr = "removeP2pIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.removeP2pIface(ifaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#removeStaIface(String)} + */ + @Override + public boolean removeStaIface(String ifaceName) { + final String methodStr = "removeStaIface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.removeStaIface(ifaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#requestChipDebugInfo()} + */ + @Override + @Nullable + public WifiChip.ChipDebugInfo requestChipDebugInfo() { + final String methodStr = "requestChipDebugInfo"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + android.hardware.wifi.IWifiChip.ChipDebugInfo info = + mWifiChip.requestChipDebugInfo(); + return new WifiChip.ChipDebugInfo(info.driverDescription, info.firmwareDescription); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#requestDriverDebugDump()} + */ + @Override + @Nullable + public byte[] requestDriverDebugDump() { + final String methodStr = "requestDriverDebugDump"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + return mWifiChip.requestDriverDebugDump(); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#requestFirmwareDebugDump()} + */ + @Override + @Nullable + public byte[] requestFirmwareDebugDump() { + final String methodStr = "requestFirmwareDebugDump"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + return mWifiChip.requestFirmwareDebugDump(); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiChip#resetTxPowerScenario()} + */ + @Override + public boolean resetTxPowerScenario() { + final String methodStr = "resetTxPowerScenario"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.resetTxPowerScenario(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#selectTxPowerScenario(SarInfo)} + */ + @Override + public boolean selectTxPowerScenario(SarInfo sarInfo) { + final String methodStr = "selectTxPowerScenario"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + if (sarPowerBackoffRequired(sarInfo)) { + // Power backoff is needed, so calculate and set the required scenario. + int halScenario = frameworkToHalTxPowerScenario(sarInfo); + if (sarInfo.setSarScenarioNeeded(halScenario)) { + Log.d(TAG, "Attempting to set SAR scenario to " + halScenario); + mWifiChip.selectTxPowerScenario(halScenario); + } + // Reaching here means that setting SAR scenario would be redundant, + // do nothing and return with success. + return true; + } + + // We don't need to perform power backoff, so attempt to reset the SAR scenario. + if (sarInfo.resetSarScenarioNeeded()) { + Log.d(TAG, "Attempting to reset the SAR scenario"); + mWifiChip.resetTxPowerScenario(); + } + + // If no if-statement was executed, then setting/resetting the SAR scenario would + // have been redundant. Do nothing and return with success. + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#setCoexUnsafeChannels(List, int)} + */ + @Override + public boolean setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions) { + final String methodStr = "setCoexUnsafeChannels"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + android.hardware.wifi.IWifiChip.CoexUnsafeChannel[] halChannels = + frameworkToHalCoexUnsafeChannels(unsafeChannels); + int halRestrictions = frameworkToHalCoexRestrictions(restrictions); + mWifiChip.setCoexUnsafeChannels(halChannels, halRestrictions); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#setCountryCode(byte[])} + */ + @Override + public boolean setCountryCode(byte[] code) { + final String methodStr = "setCountryCode"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.setCountryCode(code); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#setLowLatencyMode(boolean)} + */ + @Override + public boolean setLowLatencyMode(boolean enable) { + final String methodStr = "setLowLatencyMode"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + int mode = enable ? LatencyMode.LOW : LatencyMode.NORMAL; + mWifiChip.setLatencyMode(mode); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#setMultiStaPrimaryConnection(String)} + */ + @Override + public boolean setMultiStaPrimaryConnection(String ifaceName) { + final String methodStr = "setMultiStaPrimaryConnection"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.setMultiStaPrimaryConnection(ifaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#setMultiStaUseCase(int)} + */ + @Override + public boolean setMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase) { + final String methodStr = "setMultiStaUseCase"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.setMultiStaUseCase(frameworkToHalMultiStaUseCase(useCase)); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#startLoggingToDebugRingBuffer(String, int, int, int)} + */ + @Override + public boolean startLoggingToDebugRingBuffer(String ringName, int verboseLevel, + int maxIntervalInSec, int minDataSizeInBytes) { + final String methodStr = "startLoggingToDebugRingBuffer"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.startLoggingToDebugRingBuffer( + ringName, verboseLevel, maxIntervalInSec, minDataSizeInBytes); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#stopLoggingToDebugRingBuffer()} + */ + @Override + public boolean stopLoggingToDebugRingBuffer() { + final String methodStr = "stopLoggingToDebugRingBuffer"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.stopLoggingToDebugRingBuffer(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiChip#triggerSubsystemRestart()} + */ + @Override + public boolean triggerSubsystemRestart() { + final String methodStr = "triggerSubsystemRestart"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiChip.triggerSubsystemRestart(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + private class ChipEventCallback extends IWifiChipEventCallback.Stub { + @Override + public void onChipReconfigured(int modeId) throws RemoteException { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onChipReconfigured(modeId); + } + + @Override + public void onChipReconfigureFailure(int statusCode) { + if (mFrameworkCallback == null) return; + // TODO: convert to framework status code once WifiHalAidlImpl exists + mFrameworkCallback.onChipReconfigureFailure(statusCode); + } + + @Override + public void onIfaceAdded(int type, String name) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onIfaceAdded(halToFrameworkIfaceType(type), name); + } + + @Override + public void onIfaceRemoved(int type, String name) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onIfaceRemoved(halToFrameworkIfaceType(type), name); + } + + @Override + public void onDebugRingBufferDataAvailable(WifiDebugRingBufferStatus status, byte[] data) { + if (mFrameworkCallback == null) return; + try { + mFrameworkCallback.onDebugRingBufferDataAvailable( + halToFrameworkRingBufferStatus(status), data); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, "onDebugRingBufferDataAvailable"); + } + } + + @Override + public void onDebugErrorAlert(int errorCode, byte[] debugData) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onDebugErrorAlert(errorCode, debugData); + } + + @Override + public void onRadioModeChange(RadioModeInfo[] radioModeInfoList) { + if (mFrameworkCallback == null) return; + List<WifiChip.RadioModeInfo> frameworkRadioModeInfos = new ArrayList<>(); + for (RadioModeInfo radioInfo : radioModeInfoList) { + List<WifiChip.IfaceInfo> frameworkIfaceInfos = new ArrayList<>(); + for (IfaceInfo ifaceInfo : radioInfo.ifaceInfos) { + frameworkIfaceInfos.add( + new WifiChip.IfaceInfo(ifaceInfo.name, ifaceInfo.channel)); + } + frameworkRadioModeInfos.add( + new WifiChip.RadioModeInfo( + radioInfo.radioId, radioInfo.bandInfo, frameworkIfaceInfos)); + } + mFrameworkCallback.onRadioModeChange(frameworkRadioModeInfos); + } + + @Override + public String getInterfaceHash() { + return IWifiChipEventCallback.HASH; + } + + @Override + public int getInterfaceVersion() { + return IWifiChipEventCallback.VERSION; + } + } + + + // Utilities + + private static @WifiChip.IfaceConcurrencyType int halToFrameworkIfaceConcurrencyType(int type) { + switch (type) { + case IfaceConcurrencyType.STA: + return WifiChip.IFACE_CONCURRENCY_TYPE_STA; + case IfaceConcurrencyType.AP: + return WifiChip.IFACE_CONCURRENCY_TYPE_AP; + case IfaceConcurrencyType.AP_BRIDGED: + return WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED; + case IfaceConcurrencyType.P2P: + return WifiChip.IFACE_CONCURRENCY_TYPE_P2P; + case IfaceConcurrencyType.NAN_IFACE: + return WifiChip.IFACE_CONCURRENCY_TYPE_NAN; + default: + Log.e(TAG, "Invalid IfaceConcurrencyType received: " + type); + return -1; + } + } + + private static @WifiChip.IfaceType int halToFrameworkIfaceType(int type) { + switch (type) { + case IfaceType.STA: + return WifiChip.IFACE_TYPE_STA; + case IfaceType.AP: + return WifiChip.IFACE_TYPE_AP; + case IfaceType.P2P: + return WifiChip.IFACE_TYPE_P2P; + case IfaceType.NAN_IFACE: + return WifiChip.IFACE_TYPE_NAN; + default: + Log.e(TAG, "Invalid IfaceType received: " + type); + return -1; + } + } + + private static @Nullable List<WifiNative.RingBufferStatus> halToFrameworkRingBufferStatusList( + WifiDebugRingBufferStatus[] ringBuffers) throws IllegalArgumentException { + if (ringBuffers == null) return null; + List<WifiNative.RingBufferStatus> ans = new ArrayList<>(); + for (WifiDebugRingBufferStatus b : ringBuffers) { + ans.add(halToFrameworkRingBufferStatus(b)); + } + return ans; + } + + private static WifiNative.RingBufferStatus halToFrameworkRingBufferStatus( + WifiDebugRingBufferStatus h) throws IllegalArgumentException { + WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus(); + ans.name = h.ringName; + ans.flag = halToFrameworkRingBufferFlags(h.flags); + ans.ringBufferId = h.ringId; + ans.ringBufferByteSize = h.sizeInBytes; + ans.verboseLevel = h.verboseLevel; + // Remaining fields are unavailable + // writtenBytes; + // readBytes; + // writtenRecords; + return ans; + } + + private static int halToFrameworkRingBufferFlags(int wifiDebugRingBufferFlag) + throws IllegalArgumentException { + BitMask checkoff = new BitMask(wifiDebugRingBufferFlag); + int flags = 0; + if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) { + flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES; + } + if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) { + flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES; + } + if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) { + flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES; + } + if (checkoff.value != 0) { + throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value); + } + return flags; + } + + private static WlanWakeReasonAndCounts halToFrameworkWakeReasons( + WifiDebugHostWakeReasonStats h) { + if (h == null) return null; + WlanWakeReasonAndCounts ans = new WlanWakeReasonAndCounts(); + ans.totalCmdEventWake = h.totalCmdEventWakeCnt; + ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt; + ans.totalRxDataWake = h.totalRxPacketWakeCnt; + ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt; + ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt; + ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt; + ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt; + ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt; + ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra; + ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na; + ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns; + ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt; + ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt; + ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt; + ans.cmdEventWakeCntArray = h.cmdEventWakeCntPerType; + ans.driverFWLocalWakeCntArray = h.driverFwLocalWakeCntPerType; + return ans; + } + + private static byte frameworkToHalMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase) + throws IllegalArgumentException { + switch (useCase) { + case WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY: + return MultiStaUseCase.DUAL_STA_TRANSIENT_PREFER_PRIMARY; + case WifiNative.DUAL_STA_NON_TRANSIENT_UNBIASED: + return MultiStaUseCase.DUAL_STA_NON_TRANSIENT_UNBIASED; + default: + throw new IllegalArgumentException("Invalid use case " + useCase); + } + } + + private static @NonNull android.hardware.wifi.IWifiChip.CoexUnsafeChannel[] + frameworkToHalCoexUnsafeChannels( + @NonNull List<android.net.wifi.CoexUnsafeChannel> frameworkUnsafeChannels) { + final ArrayList<android.hardware.wifi.IWifiChip.CoexUnsafeChannel> halList = + new ArrayList<>(); + if (!SdkLevel.isAtLeastS()) { + return new android.hardware.wifi.IWifiChip.CoexUnsafeChannel[0]; + } + for (android.net.wifi.CoexUnsafeChannel frameworkUnsafeChannel : frameworkUnsafeChannels) { + final android.hardware.wifi.IWifiChip.CoexUnsafeChannel halUnsafeChannel = + new android.hardware.wifi.IWifiChip.CoexUnsafeChannel(); + switch (frameworkUnsafeChannel.getBand()) { + case (WifiScanner.WIFI_BAND_24_GHZ): + halUnsafeChannel.band = WifiBand.BAND_24GHZ; + break; + case (WifiScanner.WIFI_BAND_5_GHZ): + halUnsafeChannel.band = WifiBand.BAND_5GHZ; + break; + case (WifiScanner.WIFI_BAND_6_GHZ): + halUnsafeChannel.band = WifiBand.BAND_6GHZ; + break; + case (WifiScanner.WIFI_BAND_60_GHZ): + halUnsafeChannel.band = WifiBand.BAND_60GHZ; + break; + default: + Log.e(TAG, "Tried to set unsafe channel with unknown band: " + + frameworkUnsafeChannel.getBand()); + continue; + } + halUnsafeChannel.channel = frameworkUnsafeChannel.getChannel(); + final int powerCapDbm = frameworkUnsafeChannel.getPowerCapDbm(); + if (powerCapDbm != POWER_CAP_NONE) { + halUnsafeChannel.powerCapDbm = powerCapDbm; + } else { + halUnsafeChannel.powerCapDbm = + android.hardware.wifi.IWifiChip.NO_POWER_CAP_CONSTANT; + } + halList.add(halUnsafeChannel); + } + + android.hardware.wifi.IWifiChip.CoexUnsafeChannel[] halArray = + new android.hardware.wifi.IWifiChip.CoexUnsafeChannel[halList.size()]; + for (int i = 0; i < halList.size(); i++) { + halArray[i] = halList.get(i); + } + return halArray; + } + + private static int frameworkToHalCoexRestrictions( + @WifiManager.CoexRestriction int restrictions) { + int halRestrictions = 0; + if (!SdkLevel.isAtLeastS()) { + return halRestrictions; + } + if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_DIRECT) != 0) { + halRestrictions |= CoexRestriction.WIFI_DIRECT; + } + if ((restrictions & WifiManager.COEX_RESTRICTION_SOFTAP) != 0) { + halRestrictions |= CoexRestriction.SOFTAP; + } + if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_AWARE) != 0) { + halRestrictions |= CoexRestriction.WIFI_AWARE; + } + return halRestrictions; + } + + /** + * Check if we need to backoff wifi Tx power due to SAR requirements. + */ + private static boolean sarPowerBackoffRequired(SarInfo sarInfo) { + if (sarInfo.sarSapSupported && sarInfo.isWifiSapEnabled) { + return true; + } + if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) { + return true; + } + return false; + } + + /** + * Maps the information in the SarInfo instance to a TxPowerScenario. + * If SAR SoftAP input is supported, we make these assumptions: + * - All voice calls are treated as if device is near the head. + * - SoftAP scenario is treated as if device is near the body. + * If SoftAP is not supported, the only valid scenario is when a voice call is ongoing. + */ + private static int frameworkToHalTxPowerScenario(SarInfo sarInfo) + throws IllegalArgumentException { + if (sarInfo.sarSapSupported && sarInfo.sarVoiceCallSupported) { + if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { + return TxPowerScenario.ON_HEAD_CELL_ON; + } else if (sarInfo.isWifiSapEnabled) { + return TxPowerScenario.ON_BODY_CELL_ON; + } else { + throw new IllegalArgumentException("bad scenario: no voice call/softAP active"); + } + } else if (sarInfo.sarVoiceCallSupported) { + if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { + return TxPowerScenario.VOICE_CALL; + } else { + throw new IllegalArgumentException("bad scenario: voice call not active"); + } + } else { + throw new IllegalArgumentException("Invalid case: voice call not supported"); + } + } + + private static int frameworkToHalWifiBand(int frameworkBand) throws IllegalArgumentException { + switch (frameworkBand) { + case WifiScanner.WIFI_BAND_UNSPECIFIED: + return WifiBand.BAND_UNSPECIFIED; + case WifiScanner.WIFI_BAND_24_GHZ: + return WifiBand.BAND_24GHZ; + case WifiScanner.WIFI_BAND_5_GHZ: + return WifiBand.BAND_5GHZ; + case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: + return WifiBand.BAND_5GHZ_DFS; + case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: + return WifiBand.BAND_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_BOTH: + return WifiBand.BAND_24GHZ_5GHZ; + case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_6_GHZ: + return WifiBand.BAND_6GHZ; + case WifiScanner.WIFI_BAND_24_5_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ; + case WifiScanner.WIFI_BAND_60_GHZ: + return WifiBand.BAND_60GHZ; + case WifiScanner.WIFI_BAND_24_5_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS: + default: + throw new IllegalArgumentException("bad band " + frameworkBand); + } + } + + private static int frameworkToHalIfaceMode(@WifiAvailableChannel.OpMode int mode) { + int halMode = 0; + if ((mode & WifiAvailableChannel.OP_MODE_STA) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_STA; + } + if ((mode & WifiAvailableChannel.OP_MODE_SAP) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_SOFTAP; + } + if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_P2P_CLIENT; + } + if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_P2P_GO; + } + if ((mode & WifiAvailableChannel.OP_MODE_WIFI_AWARE) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_NAN; + } + if ((mode & WifiAvailableChannel.OP_MODE_TDLS) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_TDLS; + } + return halMode; + } + + private static @WifiAvailableChannel.OpMode int halToFrameworkIfaceMode(int halMode) { + int mode = 0; + if ((halMode & WifiIfaceMode.IFACE_MODE_STA) != 0) { + mode |= WifiAvailableChannel.OP_MODE_STA; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_SOFTAP) != 0) { + mode |= WifiAvailableChannel.OP_MODE_SAP; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_CLIENT) != 0) { + mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_GO) != 0) { + mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_NAN) != 0) { + mode |= WifiAvailableChannel.OP_MODE_WIFI_AWARE; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_TDLS) != 0) { + mode |= WifiAvailableChannel.OP_MODE_TDLS; + } + return mode; + } + + private static int frameworkToHalUsableFilter(@WifiAvailableChannel.Filter int filter) { + int halFilter = 0; // O implies no additional filter other than regulatory (default) + if ((filter & WifiAvailableChannel.FILTER_CONCURRENCY) != 0) { + halFilter |= UsableChannelFilter.CONCURRENCY; + } + if ((filter & WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE) != 0) { + halFilter |= UsableChannelFilter.CELLULAR_COEXISTENCE; + } + if ((filter & WifiAvailableChannel.FILTER_NAN_INSTANT_MODE) != 0) { + halFilter |= UsableChannelFilter.NAN_INSTANT_MODE; + } + + return halFilter; + } + + private static boolean bitmapContains(long bitmap, long expectedBit) { + return (bitmap & expectedBit) != 0; + } + + @VisibleForTesting + protected static long halToFrameworkChipCapabilityMask(long halCaps) { + long frameworkCaps = 0; + if (bitmapContains(halCaps, ChipCapabilityMask.SET_TX_POWER_LIMIT)) { + frameworkCaps |= WifiManager.WIFI_FEATURE_TX_POWER_LIMIT; + } + if (bitmapContains(halCaps, ChipCapabilityMask.D2D_RTT)) { + frameworkCaps |= WifiManager.WIFI_FEATURE_D2D_RTT; + } + if (bitmapContains(halCaps, ChipCapabilityMask.D2AP_RTT)) { + frameworkCaps |= WifiManager.WIFI_FEATURE_D2AP_RTT; + } + if (bitmapContains(halCaps, ChipCapabilityMask.SET_LATENCY_MODE)) { + frameworkCaps |= WifiManager.WIFI_FEATURE_LOW_LATENCY; + } + if (bitmapContains(halCaps, ChipCapabilityMask.P2P_RAND_MAC)) { + frameworkCaps |= WifiManager.WIFI_FEATURE_P2P_RAND_MAC; + } + if (bitmapContains(halCaps, ChipCapabilityMask.WIGIG)) { + frameworkCaps |= WifiManager.WIFI_FEATURE_INFRA_60G; + } + return frameworkCaps; + } + + private static int halToFrameworkWifiBand(int halBand) { + int frameworkBand = 0; + if (bitmapContains(halBand, WifiBand.BAND_24GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_24_GHZ; + } + if (bitmapContains(halBand, WifiBand.BAND_5GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_5_GHZ; + } + if (bitmapContains(halBand, WifiBand.BAND_5GHZ_DFS)) { + frameworkBand |= WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY; + } + if (bitmapContains(halBand, WifiBand.BAND_6GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_6_GHZ; + } + if (bitmapContains(halBand, WifiBand.BAND_60GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_60_GHZ; + } + return frameworkBand; + } + + private static @WifiChip.WifiAntennaMode int halToFrameworkAntennaMode(int mode) { + switch (mode) { + case WifiAntennaMode.WIFI_ANTENNA_MODE_UNSPECIFIED: + return WifiChip.WIFI_ANTENNA_MODE_UNSPECIFIED; + case WifiAntennaMode.WIFI_ANTENNA_MODE_1X1: + return WifiChip.WIFI_ANTENNA_MODE_1X1; + case WifiAntennaMode.WIFI_ANTENNA_MODE_2X2: + return WifiChip.WIFI_ANTENNA_MODE_2X2; + case WifiAntennaMode.WIFI_ANTENNA_MODE_3X3: + return WifiChip.WIFI_ANTENNA_MODE_3X3; + case WifiAntennaMode.WIFI_ANTENNA_MODE_4X4: + return WifiChip.WIFI_ANTENNA_MODE_4X4; + default: + Log.e(TAG, "Invalid WifiAntennaMode: " + mode); + return WifiChip.WIFI_ANTENNA_MODE_UNSPECIFIED; + } + } + + private static List<WifiChip.ChipMode> halToFrameworkChipModeList( + android.hardware.wifi.IWifiChip.ChipMode[] halModes) { + List<WifiChip.ChipMode> frameworkModes = new ArrayList<>(); + for (android.hardware.wifi.IWifiChip.ChipMode halMode : halModes) { + frameworkModes.add(halToFrameworkChipMode(halMode)); + } + return frameworkModes; + } + + private static WifiChip.ChipMode halToFrameworkChipMode( + android.hardware.wifi.IWifiChip.ChipMode halMode) { + List<WifiChip.ChipConcurrencyCombination> frameworkCombos = new ArrayList<>(); + for (android.hardware.wifi.IWifiChip.ChipConcurrencyCombination halCombo : + halMode.availableCombinations) { + frameworkCombos.add(halToFrameworkChipConcurrencyCombination(halCombo)); + } + return new WifiChip.ChipMode(halMode.id, frameworkCombos); + } + + private static WifiChip.ChipConcurrencyCombination halToFrameworkChipConcurrencyCombination( + android.hardware.wifi.IWifiChip.ChipConcurrencyCombination halCombo) { + List<WifiChip.ChipConcurrencyCombinationLimit> frameworkLimits = new ArrayList<>(); + for (android.hardware.wifi.IWifiChip.ChipConcurrencyCombinationLimit halLimit : + halCombo.limits) { + frameworkLimits.add(halToFrameworkChipConcurrencyCombinationLimit(halLimit)); + } + return new WifiChip.ChipConcurrencyCombination(frameworkLimits); + } + + private static WifiChip.ChipConcurrencyCombinationLimit + halToFrameworkChipConcurrencyCombinationLimit( + android.hardware.wifi.IWifiChip.ChipConcurrencyCombinationLimit halLimit) { + List<Integer> frameworkTypes = new ArrayList<>(); + for (int halType : halLimit.types) { + frameworkTypes.add(halToFrameworkIfaceConcurrencyType(halType)); + } + return new WifiChip.ChipConcurrencyCombinationLimit(halLimit.maxIfaces, frameworkTypes); + } + + private static WifiChip.WifiRadioCombinationMatrix halToFrameworkRadioCombinationMatrix( + WifiRadioCombinationMatrix halMatrix) { + List<WifiChip.WifiRadioCombination> frameworkCombos = new ArrayList<>(); + for (WifiRadioCombination combo : halMatrix.radioCombinations) { + frameworkCombos.add(halToFrameworkRadioCombination(combo)); + } + return new WifiChip.WifiRadioCombinationMatrix(frameworkCombos); + } + + private static WifiChip.WifiRadioCombination halToFrameworkRadioCombination( + WifiRadioCombination halCombo) { + List<WifiChip.WifiRadioConfiguration> frameworkConfigs = new ArrayList<>(); + for (WifiRadioConfiguration config : halCombo.radioConfigurations) { + frameworkConfigs.add(halToFrameworkRadioConfiguration(config)); + } + return new WifiChip.WifiRadioCombination(frameworkConfigs); + } + + private static WifiChip.WifiRadioConfiguration halToFrameworkRadioConfiguration( + WifiRadioConfiguration halConfig) { + return new WifiChip.WifiRadioConfiguration(halToFrameworkWifiBand(halConfig.bandInfo), + halToFrameworkAntennaMode(halConfig.antennaMode)); + } + + private boolean checkIfaceAndLogFailure(String methodStr) { + if (mWifiChip == null) { + Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); + return false; + } + return true; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + mWifiChip = null; + Log.e(TAG, methodStr + " failed with remote exception: " + e); + } + + private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { + Log.e(TAG, methodStr + " failed with service-specific exception: " + e); + } + + private void handleIllegalArgumentException(IllegalArgumentException e, String methodStr) { + Log.e(TAG, methodStr + " failed with illegal argument exception: " + e); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java new file mode 100644 index 0000000000..4110bd06ca --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java @@ -0,0 +1,2292 @@ +/* + * Copyright (C) 2022 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.hal; + +import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.Resources; +import android.hardware.wifi.V1_0.IWifiChipEventCallback; +import android.hardware.wifi.V1_0.IfaceType; +import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; +import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; +import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; +import android.hardware.wifi.V1_0.WifiStatus; +import android.hardware.wifi.V1_0.WifiStatusCode; +import android.hardware.wifi.V1_5.WifiBand; +import android.hardware.wifi.V1_5.WifiIfaceMode; +import android.hardware.wifi.V1_6.IfaceConcurrencyType; +import android.hardware.wifi.V1_6.WifiAntennaMode; +import android.hardware.wifi.V1_6.WifiRadioCombination; +import android.hardware.wifi.V1_6.WifiRadioCombinationMatrix; +import android.hardware.wifi.V1_6.WifiRadioConfiguration; +import android.net.wifi.CoexUnsafeChannel; +import android.net.wifi.WifiAvailableChannel; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiScanner; +import android.os.RemoteException; +import android.util.Log; +import android.util.SparseIntArray; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.build.SdkLevel; +import com.android.server.wifi.SarInfo; +import com.android.server.wifi.SsidTranslator; +import com.android.server.wifi.WifiNative; +import com.android.server.wifi.WlanWakeReasonAndCounts; +import com.android.server.wifi.util.BitMask; +import com.android.server.wifi.util.GeneralUtil.Mutable; +import com.android.server.wifi.util.NativeUtil; +import com.android.wifi.resources.R; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; + +/** + * HIDL implementation of the WifiChip interface. + */ +public class WifiChipHidlImpl implements IWifiChip { + private static final String TAG = "WifiChipHidlImpl"; + private android.hardware.wifi.V1_0.IWifiChip mWifiChip; + private android.hardware.wifi.V1_0.IWifiChipEventCallback mHalCallback10; + private android.hardware.wifi.V1_2.IWifiChipEventCallback mHalCallback12; + private android.hardware.wifi.V1_4.IWifiChipEventCallback mHalCallback14; + private WifiChip.Callback mFrameworkCallback; + private Context mContext; + private SsidTranslator mSsidTranslator; + private boolean mIsBridgedSoftApSupported; + private boolean mIsStaWithBridgedSoftApConcurrencySupported; + + public WifiChipHidlImpl(@NonNull android.hardware.wifi.V1_0.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiChip = chip; + mContext = context; + mSsidTranslator = ssidTranslator; + Resources res = context.getResources(); + mIsBridgedSoftApSupported = res.getBoolean(R.bool.config_wifiBridgedSoftApSupported); + mIsStaWithBridgedSoftApConcurrencySupported = + res.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported); + } + + /** + * See comments for {@link IWifiChip#configureChip(int)} + */ + @Override + public boolean configureChip(int modeId) { + String methodStr = "configureChip"; + return validateAndCall(methodStr, false, + () -> configureChipInternal(methodStr, modeId)); + } + + /** + * See comments for {@link IWifiChip#createApIface()} + */ + @Override + @Nullable + public WifiApIface createApIface() { + String methodStr = "createApIface"; + return validateAndCall(methodStr, null, + () -> createApIfaceInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#createBridgedApIface()} + */ + @Override + @Nullable + public WifiApIface createBridgedApIface() { + String methodStr = "createBridgedApIface"; + return validateAndCall(methodStr, null, + () -> createBridgedApIfaceInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#createNanIface()} + */ + @Override + @Nullable + public WifiNanIface createNanIface() { + String methodStr = "createNanIface"; + return validateAndCall(methodStr, null, + () -> createNanIfaceInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#createP2pIface()} + */ + @Override + @Nullable + public WifiP2pIface createP2pIface() { + String methodStr = "createP2pIface"; + return validateAndCall(methodStr, null, + () -> createP2pIfaceInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#createRttController()} + */ + @Override + @Nullable + public WifiRttController createRttController() { + String methodStr = "createRttController"; + return validateAndCall(methodStr, null, + () -> createRttControllerInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#createStaIface()} + */ + @Override + @Nullable + public WifiStaIface createStaIface() { + String methodStr = "createStaIface"; + return validateAndCall(methodStr, null, + () -> createStaIfaceInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#enableDebugErrorAlerts(boolean)} + */ + @Override + public boolean enableDebugErrorAlerts(boolean enable) { + String methodStr = "enableDebugErrorAlerts"; + return validateAndCall(methodStr, false, + () -> enableDebugErrorAlertsInternal(methodStr, enable)); + } + + /** + * See comments for {@link IWifiChip#flushRingBufferToFile()} + */ + @Override + public boolean flushRingBufferToFile() { + String methodStr = "flushRingBufferToFile"; + return validateAndCall(methodStr, false, + () -> flushRingBufferToFileInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#forceDumpToDebugRingBuffer(String)} + */ + @Override + public boolean forceDumpToDebugRingBuffer(String ringName) { + String methodStr = "forceDumpToDebugRingBuffer"; + return validateAndCall(methodStr, false, + () -> forceDumpToDebugRingBufferInternal(methodStr, ringName)); + } + + /** + * See comments for {@link IWifiChip#getApIface(String)} + */ + @Override + @Nullable + public WifiApIface getApIface(String ifaceName) { + String methodStr = "getApIface"; + return validateAndCall(methodStr, null, + () -> getApIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getApIfaceNames()} + */ + @Override + @Nullable + public List<String> getApIfaceNames() { + String methodStr = "getApIfaceNames"; + return validateAndCall(methodStr, null, + () -> getApIfaceNamesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getAvailableModes()} + */ + @Override + @Nullable + public List<WifiChip.ChipMode> getAvailableModes() { + String methodStr = "getAvailableModes"; + return validateAndCall(methodStr, null, + () -> getAvailableModesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()} + */ + @Override + public WifiChip.Response<Long> getCapabilitiesBeforeIfacesExist() { + String methodStr = "getCapabilitiesBeforeIfacesExist"; + return validateAndCall(methodStr, new WifiChip.Response<>(0L), + () -> getCapabilitiesBeforeIfacesExistInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()} + */ + @Override + public WifiChip.Response<Long> getCapabilitiesAfterIfacesExist() { + String methodStr = "getCapabilitiesAfterIfacesExist"; + return validateAndCall(methodStr, new WifiChip.Response<>(0L), + () -> getCapabilitiesAfterIfacesExistInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getDebugHostWakeReasonStats()} + */ + @Override + @Nullable + public WlanWakeReasonAndCounts getDebugHostWakeReasonStats() { + String methodStr = "getDebugHostWakeReasonStats"; + return validateAndCall(methodStr, null, + () -> getDebugHostWakeReasonStatsInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getDebugRingBuffersStatus()} + */ + @Override + @Nullable + public List<WifiNative.RingBufferStatus> getDebugRingBuffersStatus() { + String methodStr = "getDebugRingBuffersStatus"; + return validateAndCall(methodStr, null, + () -> getDebugRingBuffersStatusInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getId()} + */ + @Override + public int getId() { + String methodStr = "getId"; + return validateAndCall(methodStr, -1, () -> getIdInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getMode()} + */ + @Override + public WifiChip.Response<Integer> getMode() { + String methodStr = "getMode"; + return validateAndCall(methodStr, new WifiChip.Response<>(0), + () -> getModeInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getNanIface(String)} + */ + @Override + @Nullable + public WifiNanIface getNanIface(String ifaceName) { + String methodStr = "getNanIface"; + return validateAndCall(methodStr, null, + () -> getNanIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getNanIfaceNames()} + */ + @Override + @Nullable + public List<String> getNanIfaceNames() { + String methodStr = "getNanIfaceNames"; + return validateAndCall(methodStr, null, + () -> getNanIfaceNamesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getP2pIface(String)} + */ + @Override + @Nullable + public WifiP2pIface getP2pIface(String ifaceName) { + String methodStr = "getP2pIface"; + return validateAndCall(methodStr, null, + () -> getP2pIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getP2pIfaceNames()} + */ + @Override + @Nullable + public List<String> getP2pIfaceNames() { + String methodStr = "getP2pIfaceNames"; + return validateAndCall(methodStr, null, + () -> getP2pIfaceNamesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getStaIface(String)} + */ + @Override + @Nullable + public WifiStaIface getStaIface(String ifaceName) { + String methodStr = "getStaIface"; + return validateAndCall(methodStr, null, + () -> getStaIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#getStaIfaceNames()} + */ + @Override + @Nullable + public List<String> getStaIfaceNames() { + String methodStr = "getStaIfaceNames"; + return validateAndCall(methodStr, null, + () -> getStaIfaceNamesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getSupportedRadioCombinationsMatrix()} + */ + @Override + @Nullable + public WifiChip.WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrix() { + String methodStr = "getSupportedRadioCombinationsMatrix"; + return validateAndCall(methodStr, null, + () -> getSupportedRadioCombinationsMatrixInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#getUsableChannels(int, int, int)} + */ + @Override + @Nullable + public List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band, + @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) { + String methodStr = "getUsableChannels"; + return validateAndCall(methodStr, null, + () -> getUsableChannelsInternal(methodStr, band, mode, filter)); + } + + /** + * See comments for {@link IWifiChip#registerCallback(WifiChip.Callback)} + */ + @Override + public boolean registerCallback(WifiChip.Callback callback) { + String methodStr = "registerCallback"; + return validateAndCall(methodStr, false, + () -> registerCallbackInternal(methodStr, callback)); + } + + /** + * See comments for {@link IWifiChip#removeApIface(String)} + */ + @Override + public boolean removeApIface(String ifaceName) { + String methodStr = "removeApIface"; + return validateAndCall(methodStr, false, + () -> removeApIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeIfaceInstanceFromBridgedApIface(String, String)} + */ + @Override + public boolean removeIfaceInstanceFromBridgedApIface(String brIfaceName, String ifaceName) { + String methodStr = "removeIfaceInstanceFromBridgedApIface"; + return validateAndCall(methodStr, false, + () -> removeIfaceInstanceFromBridgedApIfaceInternal(methodStr, + brIfaceName, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeNanIface(String)} + */ + @Override + public boolean removeNanIface(String ifaceName) { + String methodStr = "removeNanIface"; + return validateAndCall(methodStr, false, + () -> removeNanIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeP2pIface(String)} + */ + @Override + public boolean removeP2pIface(String ifaceName) { + String methodStr = "removeP2pIface"; + return validateAndCall(methodStr, false, + () -> removeP2pIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#removeStaIface(String)} + */ + @Override + public boolean removeStaIface(String ifaceName) { + String methodStr = "removeStaIface"; + return validateAndCall(methodStr, false, + () -> removeStaIfaceInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#requestChipDebugInfo()} + */ + @Override + @Nullable + public WifiChip.ChipDebugInfo requestChipDebugInfo() { + String methodStr = "requestChipDebugInfo"; + return validateAndCall(methodStr, null, + () -> requestChipDebugInfoInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#requestDriverDebugDump()} + */ + @Override + @Nullable + public byte[] requestDriverDebugDump() { + String methodStr = "requestDriverDebugDump"; + return validateAndCall(methodStr, null, + () -> requestDriverDebugDumpInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#requestFirmwareDebugDump()} + */ + @Override + @Nullable + public byte[] requestFirmwareDebugDump() { + String methodStr = "requestFirmwareDebugDump"; + return validateAndCall(methodStr, null, + () -> requestFirmwareDebugDumpInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#resetTxPowerScenario()} + */ + @Override + public boolean resetTxPowerScenario() { + String methodStr = "resetTxPowerScenario"; + return validateAndCall(methodStr, false, + () -> resetTxPowerScenarioInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#selectTxPowerScenario(SarInfo)} + */ + @Override + public boolean selectTxPowerScenario(SarInfo sarInfo) { + String methodStr = "selectTxPowerScenario"; + return validateAndCall(methodStr, false, + () -> selectTxPowerScenarioInternal(methodStr, sarInfo)); + } + + /** + * See comments for {@link IWifiChip#setCoexUnsafeChannels(List, int)} + */ + @Override + public boolean setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions) { + String methodStr = "setCoexUnsafeChannels"; + return validateAndCall(methodStr, false, + () -> setCoexUnsafeChannelsInternal(methodStr, unsafeChannels, + restrictions)); + } + + /** + * See comments for {@link IWifiChip#setCountryCode(byte[])} + */ + @Override + public boolean setCountryCode(byte[] code) { + String methodStr = "setCountryCode"; + return validateAndCall(methodStr, false, + () -> setCountryCodeInternal(methodStr, code)); + } + + /** + * See comments for {@link IWifiChip#setLowLatencyMode(boolean)} + */ + @Override + public boolean setLowLatencyMode(boolean enable) { + String methodStr = "setLowLatencyMode"; + return validateAndCall(methodStr, false, + () -> setLowLatencyModeInternal(methodStr, enable)); + } + + /** + * See comments for {@link IWifiChip#setMultiStaPrimaryConnection(String)} + */ + @Override + public boolean setMultiStaPrimaryConnection(String ifaceName) { + String methodStr = "setMultiStaPrimaryConnection"; + return validateAndCall(methodStr, false, + () -> setMultiStaPrimaryConnectionInternal(methodStr, ifaceName)); + } + + /** + * See comments for {@link IWifiChip#setMultiStaUseCase(int)} + */ + @Override + public boolean setMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase) { + String methodStr = "setMultiStaUseCase"; + return validateAndCall(methodStr, false, + () -> setMultiStaUseCaseInternal(methodStr, useCase)); + } + + /** + * See comments for {@link IWifiChip#startLoggingToDebugRingBuffer(String, int, int, int)} + */ + @Override + public boolean startLoggingToDebugRingBuffer(String ringName, int verboseLevel, + int maxIntervalInSec, int minDataSizeInBytes) { + String methodStr = "startLoggingToDebugRingBuffer"; + return validateAndCall(methodStr, false, + () -> startLoggingToDebugRingBufferInternal(methodStr, ringName, + verboseLevel, maxIntervalInSec, minDataSizeInBytes)); + } + + /** + * See comments for {@link IWifiChip#stopLoggingToDebugRingBuffer()} + */ + @Override + public boolean stopLoggingToDebugRingBuffer() { + String methodStr = "stopLoggingToDebugRingBuffer"; + return validateAndCall(methodStr, false, + () -> stopLoggingToDebugRingBufferInternal(methodStr)); + } + + /** + * See comments for {@link IWifiChip#triggerSubsystemRestart()} + */ + @Override + public boolean triggerSubsystemRestart() { + String methodStr = "triggerSubsystemRestart"; + return validateAndCall(methodStr, false, + () -> triggerSubsystemRestartInternal(methodStr)); + } + + + // Internal Implementations + + private boolean configureChipInternal(String methodStr, int modeId) { + try { + WifiStatus status = mWifiChip.configureChip(modeId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private WifiApIface createApIfaceInternal(String methodStr) { + Mutable<WifiApIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.createApIface((status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiApIface(iface); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private WifiApIface createBridgedApIfaceInternal(String methodStr) { + Mutable<WifiApIface> ifaceResp = new Mutable<>(); + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 == null) return null; + chip15.createBridgedApIface((status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiApIface(iface); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private WifiNanIface createNanIfaceInternal(String methodStr) { + Mutable<WifiNanIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.createNanIface((status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiNanIface(iface); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private WifiP2pIface createP2pIfaceInternal(String methodStr) { + Mutable<WifiP2pIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.createP2pIface((status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiP2pIface(iface); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private WifiRttController createRttControllerInternal(String methodStr) { + Mutable<WifiRttController> controllerResp = new Mutable<>(); + try { + android.hardware.wifi.V1_6.IWifiChip chip16 = getWifiChipV1_6Mockable(); + android.hardware.wifi.V1_4.IWifiChip chip14 = getWifiChipV1_4Mockable(); + if (chip16 != null) { + chip16.createRttController_1_6(null, (status, controller) -> { + if (isOk(status, methodStr)) { + controllerResp.value = new WifiRttController(controller); + } + }); + } else if (chip14 != null) { + chip14.createRttController_1_4(null, (status, controller) -> { + if (isOk(status, methodStr)) { + controllerResp.value = new WifiRttController(controller); + } + }); + } else { + mWifiChip.createRttController(null, (status, controller) -> { + if (isOk(status, methodStr)) { + controllerResp.value = new WifiRttController(controller); + } + }); + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return controllerResp.value; + } + + private WifiStaIface createStaIfaceInternal(String methodStr) { + Mutable<WifiStaIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.createStaIface((status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiStaIface(iface, mContext, mSsidTranslator); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private boolean enableDebugErrorAlertsInternal(String methodStr, boolean enable) { + try { + WifiStatus status = mWifiChip.enableDebugErrorAlerts(enable); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean flushRingBufferToFileInternal(String methodStr) { + try { + android.hardware.wifi.V1_3.IWifiChip chip13 = getWifiChipV1_3Mockable(); + if (chip13 == null) return false; + WifiStatus status = chip13.flushRingBufferToFile(); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean forceDumpToDebugRingBufferInternal(String methodStr, String ringName) { + try { + WifiStatus status = mWifiChip.forceDumpToDebugRingBuffer(ringName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private WifiApIface getApIfaceInternal(String methodStr, String ifaceName) { + Mutable<WifiApIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.getApIface(ifaceName, (status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiApIface(iface); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private List<String> getApIfaceNamesInternal(String methodStr) { + Mutable<List<String>> ifaceNameResp = new Mutable<>(); + try { + mWifiChip.getApIfaceNames((status, ifaceNames) -> { + if (isOk(status, methodStr)) { + ifaceNameResp.value = ifaceNames; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceNameResp.value; + } + + private List<WifiChip.ChipMode> getAvailableModesInternal(String methodStr) { + Mutable<List<WifiChip.ChipMode>> modeResp = new Mutable<>(); + try { + android.hardware.wifi.V1_6.IWifiChip chip16 = getWifiChipV1_6Mockable(); + if (chip16 != null) { + chip16.getAvailableModes_1_6((status, modes) -> { + if (isOk(status, methodStr)) { + modeResp.value = halToFrameworkChipModeListV1_6(modes); + } + }); + } else { + mWifiChip.getAvailableModes((status, modes) -> { + if (isOk(status, methodStr)) { + modeResp.value = halToFrameworkChipModeListV1_0(modes); + } + }); + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return modeResp.value; + } + + private WifiChip.Response<Long> getCapabilitiesBeforeIfacesExistInternal(String methodStr) { + WifiChip.Response<Long> capsResp = new WifiChip.Response<>(0L); + try { + // HAL newer than v1.5 supports getting capabilities before creating an interface. + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 != null) { + chip15.getCapabilities_1_5((status, caps) -> { + if (isOk(status, methodStr)) { + capsResp.setValue(wifiFeatureMaskFromChipCapabilities_1_5(caps)); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + } else { + capsResp.setStatusCode( + WifiHalHidlImpl.halToFrameworkWifiStatusCode(status.code)); + } + }); + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION); + } + return capsResp; + } + + private WifiChip.Response<Long> getCapabilitiesAfterIfacesExistInternal(String methodStr) { + WifiChip.Response<Long> capsResp = new WifiChip.Response<>(0L); + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + android.hardware.wifi.V1_3.IWifiChip chip13 = getWifiChipV1_3Mockable(); + if (chip15 != null) { + chip15.getCapabilities_1_5((status, caps) -> { + if (isOk(status, methodStr)) { + capsResp.setValue(wifiFeatureMaskFromChipCapabilities_1_5(caps)); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + } else { + capsResp.setStatusCode( + WifiHalHidlImpl.halToFrameworkWifiStatusCode(status.code)); + } + }); + } else if (chip13 != null) { + chip13.getCapabilities_1_3((status, caps) -> { + if (isOk(status, methodStr)) { + capsResp.setValue(wifiFeatureMaskFromChipCapabilities_1_3(caps)); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + } else { + capsResp.setStatusCode( + WifiHalHidlImpl.halToFrameworkWifiStatusCode(status.code)); + } + }); + } else { + mWifiChip.getCapabilities((status, caps) -> { + if (isOk(status, methodStr)) { + capsResp.setValue((long) wifiFeatureMaskFromChipCapabilities(caps)); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + } else { + capsResp.setStatusCode( + WifiHalHidlImpl.halToFrameworkWifiStatusCode(status.code)); + } + }); + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + capsResp.setStatusCode(WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION); + } + return capsResp; + } + + private WlanWakeReasonAndCounts getDebugHostWakeReasonStatsInternal(String methodStr) { + Mutable<WlanWakeReasonAndCounts> debugResp = new Mutable<>(); + try { + mWifiChip.getDebugHostWakeReasonStats((status, debugStats) -> { + if (isOk(status, methodStr)) { + debugResp.value = halToFrameworkWakeReasons(debugStats); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return debugResp.value; + } + + private List<WifiNative.RingBufferStatus> getDebugRingBuffersStatusInternal(String methodStr) { + Mutable<List<WifiNative.RingBufferStatus>> ringBufResp = new Mutable<>(); + try { + mWifiChip.getDebugRingBuffersStatus((status, ringBuffers) -> { + if (isOk(status, methodStr)) { + WifiNative.RingBufferStatus[] ringBufArray = + makeRingBufferStatusArray(ringBuffers); + ringBufResp.value = Arrays.asList(ringBufArray); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ringBufResp.value; + } + + private int getIdInternal(String methodStr) { + Mutable<Integer> idResp = new Mutable<>(-1); + try { + mWifiChip.getId((status, id) -> { + if (isOk(status, methodStr)) { + idResp.value = id; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return idResp.value; + } + + private WifiChip.Response<Integer> getModeInternal(String methodStr) { + WifiChip.Response<Integer> modeResp = new WifiChip.Response<>(0); + try { + mWifiChip.getMode((status, mode) -> { + if (isOk(status, methodStr)) { + modeResp.setValue(mode); + modeResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + } else { + modeResp.setStatusCode( + WifiHalHidlImpl.halToFrameworkWifiStatusCode(status.code)); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + modeResp.setStatusCode(WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION); + } + return modeResp; + } + + private WifiNanIface getNanIfaceInternal(String methodStr, String ifaceName) { + Mutable<WifiNanIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.getNanIface(ifaceName, (status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiNanIface(iface); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private List<String> getNanIfaceNamesInternal(String methodStr) { + Mutable<List<String>> ifaceNameResp = new Mutable<>(); + try { + mWifiChip.getNanIfaceNames((status, ifaceNames) -> { + if (isOk(status, methodStr)) { + ifaceNameResp.value = ifaceNames; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceNameResp.value; + } + + private WifiP2pIface getP2pIfaceInternal(String methodStr, String ifaceName) { + Mutable<WifiP2pIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.getP2pIface(ifaceName, (status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiP2pIface(iface); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private List<String> getP2pIfaceNamesInternal(String methodStr) { + Mutable<List<String>> ifaceNameResp = new Mutable<>(); + try { + mWifiChip.getP2pIfaceNames((status, ifaceNames) -> { + if (isOk(status, methodStr)) { + ifaceNameResp.value = ifaceNames; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceNameResp.value; + } + + private WifiStaIface getStaIfaceInternal(String methodStr, String ifaceName) { + Mutable<WifiStaIface> ifaceResp = new Mutable<>(); + try { + mWifiChip.getStaIface(ifaceName, (status, iface) -> { + if (isOk(status, methodStr)) { + ifaceResp.value = new WifiStaIface(iface, mContext, mSsidTranslator); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceResp.value; + } + + private List<String> getStaIfaceNamesInternal(String methodStr) { + Mutable<List<String>> ifaceNameResp = new Mutable<>(); + try { + mWifiChip.getStaIfaceNames((status, ifaceNames) -> { + if (isOk(status, methodStr)) { + ifaceNameResp.value = ifaceNames; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return ifaceNameResp.value; + } + + private WifiChip.WifiRadioCombinationMatrix getSupportedRadioCombinationsMatrixInternal( + String methodStr) { + Mutable<WifiChip.WifiRadioCombinationMatrix> matrixResp = new Mutable<>(); + try { + android.hardware.wifi.V1_6.IWifiChip chip16 = getWifiChipV1_6Mockable(); + if (chip16 == null) return null; + chip16.getSupportedRadioCombinationsMatrix((status, matrix) -> { + matrixResp.value = halToFrameworkRadioCombinationMatrix(matrix); + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return matrixResp.value; + } + + private List<WifiAvailableChannel> getUsableChannelsInternal(String methodStr, + @WifiScanner.WifiBand int band, @WifiAvailableChannel.OpMode int mode, + @WifiAvailableChannel.Filter int filter) { + Mutable<List<WifiAvailableChannel>> channelResp = new Mutable<>(); + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + android.hardware.wifi.V1_6.IWifiChip chip16 = getWifiChipV1_6Mockable(); + if (chip15 == null && chip16 == null) return null; + if (chip16 != null) { + chip16.getUsableChannels_1_6( + frameworkToHalWifiBand(band), + frameworkToHalIfaceMode(mode), + frameworkToHalUsableFilter_1_6(filter), + (status, channels) -> { + if (isOk(status, methodStr)) { + channelResp.value = new ArrayList<>(); + for (android.hardware.wifi.V1_6.WifiUsableChannel ch : channels) { + channelResp.value.add(new WifiAvailableChannel(ch.channel, + halToFrameworkIfaceMode(ch.ifaceModeMask))); + } + } + }); + } else { + chip15.getUsableChannels( + frameworkToHalWifiBand(band), + frameworkToHalIfaceMode(mode), + frameworkToHalUsableFilter(filter), + (status, channels) -> { + if (isOk(status, methodStr)) { + channelResp.value = new ArrayList<>(); + for (android.hardware.wifi.V1_5.WifiUsableChannel ch : channels) { + channelResp.value.add(new WifiAvailableChannel(ch.channel, + halToFrameworkIfaceMode(ch.ifaceModeMask))); + } + } + }); + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return channelResp.value; + } + + private boolean registerCallbackInternal(String methodStr, WifiChip.Callback callback) { + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (callback == null) { + Log.e(TAG, "Cannot register a null callback"); + return false; + } + + try { + android.hardware.wifi.V1_2.IWifiChip chip12 = getWifiChipV1_2Mockable(); + android.hardware.wifi.V1_4.IWifiChip chip14 = getWifiChipV1_4Mockable(); + mHalCallback10 = new ChipEventCallback(); + WifiStatus status; + if (chip14 != null) { + mHalCallback12 = new ChipEventCallbackV12(); + mHalCallback14 = new ChipEventCallbackV14(); + status = chip14.registerEventCallback_1_4(mHalCallback14); + } else if (chip12 != null) { + mHalCallback12 = new ChipEventCallbackV12(); + status = chip12.registerEventCallback_1_2(mHalCallback12); + } else { + status = mWifiChip.registerEventCallback(mHalCallback10); + } + if (!isOk(status, methodStr)) return false; + mFrameworkCallback = callback; + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean removeApIfaceInternal(String methodStr, String ifaceName) { + try { + WifiStatus status = mWifiChip.removeApIface(ifaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean removeIfaceInstanceFromBridgedApIfaceInternal(String methodStr, + String brIfaceName, String ifaceName) { + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 == null) return false; + WifiStatus status = + chip15.removeIfaceInstanceFromBridgedApIface(brIfaceName, ifaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean removeNanIfaceInternal(String methodStr, String ifaceName) { + try { + WifiStatus status = mWifiChip.removeNanIface(ifaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean removeP2pIfaceInternal(String methodStr, String ifaceName) { + try { + WifiStatus status = mWifiChip.removeP2pIface(ifaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean removeStaIfaceInternal(String methodStr, String ifaceName) { + try { + WifiStatus status = mWifiChip.removeStaIface(ifaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private WifiChip.ChipDebugInfo requestChipDebugInfoInternal(String methodStr) { + Mutable<WifiChip.ChipDebugInfo> debugResp = new Mutable<>(); + try { + mWifiChip.requestChipDebugInfo((status, halInfo) -> { + if (isOk(status, methodStr)) { + debugResp.value = new WifiChip.ChipDebugInfo( + halInfo.driverDescription, halInfo.firmwareDescription); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return debugResp.value; + } + + private byte[] requestDriverDebugDumpInternal(String methodStr) { + Mutable<byte[]> debugResp = new Mutable<>(); + try { + mWifiChip.requestDriverDebugDump((status, blob) -> { + if (isOk(status, methodStr)) { + debugResp.value = NativeUtil.byteArrayFromArrayList(blob); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return debugResp.value; + } + + private byte[] requestFirmwareDebugDumpInternal(String methodStr) { + Mutable<byte[]> debugResp = new Mutable<>(); + try { + mWifiChip.requestFirmwareDebugDump((status, blob) -> { + if (isOk(status, methodStr)) { + debugResp.value = NativeUtil.byteArrayFromArrayList(blob); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return debugResp.value; + } + + private boolean resetTxPowerScenarioInternal(String methodStr) { + try { + android.hardware.wifi.V1_1.IWifiChip chip11 = getWifiChipV1_1Mockable(); + android.hardware.wifi.V1_2.IWifiChip chip12 = getWifiChipV1_2Mockable(); + if (chip11 == null && chip12 == null) return false; + WifiStatus status; + if (chip12 != null) { + status = chip12.resetTxPowerScenario(); + } else { + status = chip11.resetTxPowerScenario(); + } + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean selectTxPowerScenarioInternal(String methodStr, SarInfo sarInfo) { + if (getWifiChipV1_2Mockable() != null) { + return selectTxPowerScenarioInternal_1_2(methodStr, sarInfo); + } else if (getWifiChipV1_1Mockable() != null) { + return selectTxPowerScenarioInternal_1_1(methodStr, sarInfo); + } + return false; + } + + private boolean selectTxPowerScenarioInternal_1_1(String methodStr, SarInfo sarInfo) { + methodStr += "_1_1"; + try { + WifiStatus status; + android.hardware.wifi.V1_1.IWifiChip chip11 = getWifiChipV1_1Mockable(); + + if (sarPowerBackoffRequired_1_1(sarInfo)) { + // Power backoff is needed, so calculate the required scenario + // and attempt to set it. + int halScenario = frameworkToHalTxPowerScenario_1_1(sarInfo); + if (sarInfo.setSarScenarioNeeded(halScenario)) { + Log.d(TAG, "Attempting to set SAR scenario to " + halScenario); + status = chip11.selectTxPowerScenario(halScenario); + return isOk(status, methodStr); + } + // Reaching here means setting SAR scenario would be redundant, + // do nothing and return with success. + return true; + } + + // We don't need to perform power backoff, so attempt to reset the SAR scenario. + if (sarInfo.resetSarScenarioNeeded()) { + status = chip11.resetTxPowerScenario(); + Log.d(TAG, "Attempting to reset the SAR scenario"); + return isOk(status, methodStr); + } + + // Resetting SAR scenario would be redundant; do nothing and return with success. + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } catch (IllegalArgumentException e) { + Log.e(TAG, "IllegalArgumentException in " + methodStr); + return false; + } + } + + private boolean selectTxPowerScenarioInternal_1_2(String methodStr, SarInfo sarInfo) { + methodStr += "_1_2"; + try { + WifiStatus status; + android.hardware.wifi.V1_2.IWifiChip chip12 = getWifiChipV1_2Mockable(); + + if (sarPowerBackoffRequired_1_2(sarInfo)) { + // Power backoff is needed, so calculate the required scenario + // and attempt to set it. + int halScenario = frameworkToHalTxPowerScenario_1_2(sarInfo); + if (sarInfo.setSarScenarioNeeded(halScenario)) { + Log.d(TAG, "Attempting to set SAR scenario to " + halScenario); + status = chip12.selectTxPowerScenario_1_2(halScenario); + return isOk(status, methodStr); + } + // Reaching here means setting SAR scenario would be redundant, + // do nothing and return with success. + return true; + } + + // We don't need to perform power backoff, so attempt to reset the SAR scenario. + if (sarInfo.resetSarScenarioNeeded()) { + status = chip12.resetTxPowerScenario(); + Log.d(TAG, "Attempting to reset the SAR scenario"); + return isOk(status, methodStr); + } + + // Resetting SAR scenario would be redundant; do nothing and return with success. + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } catch (IllegalArgumentException e) { + Log.e(TAG, "IllegalArgumentException in " + methodStr); + return false; + } + } + + private boolean setCoexUnsafeChannelsInternal(String methodStr, + List<CoexUnsafeChannel> unsafeChannels, int restrictions) { + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 == null) return false; + WifiStatus status = chip15.setCoexUnsafeChannels( + frameworkCoexUnsafeChannelsToHidl(unsafeChannels), + frameworkCoexRestrictionsToHidl(restrictions)); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean setCountryCodeInternal(String methodStr, byte[] code) { + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 == null) return false; + WifiStatus status = chip15.setCountryCode(code); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean setLowLatencyModeInternal(String methodStr, boolean enable) { + try { + android.hardware.wifi.V1_3.IWifiChip chip13 = getWifiChipV1_3Mockable(); + if (chip13 == null) return false; + int mode; + if (enable) { + mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.LOW; + } else { + mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.NORMAL; + } + WifiStatus status = chip13.setLatencyMode(mode); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean setMultiStaPrimaryConnectionInternal(String methodStr, String ifaceName) { + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 == null) return false; + WifiStatus status = chip15.setMultiStaPrimaryConnection(ifaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean setMultiStaUseCaseInternal(String methodStr, + @WifiNative.MultiStaUseCase int useCase) { + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 == null) return false; + WifiStatus status = chip15.setMultiStaUseCase(frameworkMultiStaUseCaseToHidl(useCase)); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid argument " + useCase + " in " + methodStr); + } + return false; + } + + private boolean startLoggingToDebugRingBufferInternal(String methodStr, String ringName, + int verboseLevel, int maxIntervalInSec, int minDataSizeInBytes) { + try { + WifiStatus status = mWifiChip.startLoggingToDebugRingBuffer(ringName, verboseLevel, + maxIntervalInSec, minDataSizeInBytes); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean stopLoggingToDebugRingBufferInternal(String methodStr) { + try { + WifiStatus status = mWifiChip.stopLoggingToDebugRingBuffer(); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean triggerSubsystemRestartInternal(String methodStr) { + try { + android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); + if (chip15 == null) return false; + WifiStatus status = chip15.triggerSubsystemRestart(); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + /** + * Callback for events on the chip. + */ + private class ChipEventCallback extends IWifiChipEventCallback.Stub { + @Override + public void onChipReconfigured(int modeId) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onChipReconfigured(modeId); + } + + @Override + public void onChipReconfigureFailure(WifiStatus status) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onChipReconfigureFailure( + WifiHalHidlImpl.halToFrameworkWifiStatusCode(status.code)); + } + + @Override + public void onIfaceAdded(int type, String name) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onIfaceAdded(halToFrameworkIfaceType(type), name); + } + + @Override + public void onIfaceRemoved(int type, String name) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onIfaceRemoved(halToFrameworkIfaceType(type), name); + } + + @Override + public void onDebugRingBufferDataAvailable( + WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onDebugRingBufferDataAvailable( + halToFrameworkRingBufferStatus(status), + NativeUtil.byteArrayFromArrayList(data)); + } + + @Override + public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onDebugErrorAlert(errorCode, + NativeUtil.byteArrayFromArrayList(debugData)); + } + } + + /** + * Callback for events on the 1.2 chip. + */ + private class ChipEventCallbackV12 extends + android.hardware.wifi.V1_2.IWifiChipEventCallback.Stub { + @Override + public void onChipReconfigured(int modeId) throws RemoteException { + mHalCallback10.onChipReconfigured(modeId); + } + + @Override + public void onChipReconfigureFailure(WifiStatus status) throws RemoteException { + mHalCallback10.onChipReconfigureFailure(status); + } + + public void onIfaceAdded(int type, String name) throws RemoteException { + mHalCallback10.onIfaceAdded(type, name); + } + + @Override + public void onIfaceRemoved(int type, String name) throws RemoteException { + mHalCallback10.onIfaceRemoved(type, name); + } + + @Override + public void onDebugRingBufferDataAvailable( + WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) + throws RemoteException { + mHalCallback10.onDebugRingBufferDataAvailable(status, data); + } + + @Override + public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) + throws RemoteException { + mHalCallback10.onDebugErrorAlert(errorCode, debugData); + } + + @Override + public void onRadioModeChange(ArrayList<RadioModeInfo> radioModeInfoList) { + if (mFrameworkCallback == null) return; + List<WifiChip.RadioModeInfo> frameworkRadioModeInfos = new ArrayList<>(); + for (RadioModeInfo radioInfo : radioModeInfoList) { + List<WifiChip.IfaceInfo> frameworkIfaceInfos = new ArrayList<>(); + for (IfaceInfo ifaceInfo : radioInfo.ifaceInfos) { + frameworkIfaceInfos.add( + new WifiChip.IfaceInfo(ifaceInfo.name, ifaceInfo.channel)); + } + frameworkRadioModeInfos.add( + new WifiChip.RadioModeInfo( + radioInfo.radioId, radioInfo.bandInfo, frameworkIfaceInfos)); + } + mFrameworkCallback.onRadioModeChange(frameworkRadioModeInfos); + } + } + + /** + * Callback for events on the 1.4 chip. + */ + private class ChipEventCallbackV14 extends + android.hardware.wifi.V1_4.IWifiChipEventCallback.Stub { + @Override + public void onChipReconfigured(int modeId) throws RemoteException { + mHalCallback10.onChipReconfigured(modeId); + } + + @Override + public void onChipReconfigureFailure(WifiStatus status) throws RemoteException { + mHalCallback10.onChipReconfigureFailure(status); + } + + public void onIfaceAdded(int type, String name) throws RemoteException { + mHalCallback10.onIfaceAdded(type, name); + } + + @Override + public void onIfaceRemoved(int type, String name) throws RemoteException { + mHalCallback10.onIfaceRemoved(type, name); + } + + @Override + public void onDebugRingBufferDataAvailable( + WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) + throws RemoteException { + mHalCallback10.onDebugRingBufferDataAvailable(status, data); + } + + @Override + public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) + throws RemoteException { + mHalCallback10.onDebugErrorAlert(errorCode, debugData); + } + + @Override + public void onRadioModeChange( + ArrayList<android.hardware.wifi.V1_2.IWifiChipEventCallback.RadioModeInfo> + radioModeInfoList) throws RemoteException { + mHalCallback12.onRadioModeChange(radioModeInfoList); + } + + @Override + public void onRadioModeChange_1_4(ArrayList<RadioModeInfo> radioModeInfoList) { + if (mFrameworkCallback == null) return; + List<WifiChip.RadioModeInfo> frameworkRadioModeInfos = new ArrayList<>(); + for (RadioModeInfo radioInfo : radioModeInfoList) { + List<WifiChip.IfaceInfo> frameworkIfaceInfos = new ArrayList<>(); + for (IfaceInfo ifaceInfo : radioInfo.ifaceInfos) { + frameworkIfaceInfos.add( + new WifiChip.IfaceInfo(ifaceInfo.name, ifaceInfo.channel)); + } + frameworkRadioModeInfos.add( + new WifiChip.RadioModeInfo( + radioInfo.radioId, radioInfo.bandInfo, frameworkIfaceInfos)); + } + mFrameworkCallback.onRadioModeChange(frameworkRadioModeInfos); + } + } + + + // Helper Functions + + protected boolean isBridgedSoftApSupportedMockable() { + return mIsBridgedSoftApSupported; + } + + protected boolean isStaWithBridgedSoftApConcurrencySupportedMockable() { + return mIsStaWithBridgedSoftApConcurrencySupported; + } + + private static final SparseIntArray IFACE_TYPE_TO_CONCURRENCY_TYPE_MAP = new SparseIntArray() {{ + put(IfaceType.STA, android.hardware.wifi.V1_6.IfaceConcurrencyType.STA); + put(IfaceType.AP, android.hardware.wifi.V1_6.IfaceConcurrencyType.AP); + put(IfaceType.P2P, android.hardware.wifi.V1_6.IfaceConcurrencyType.P2P); + put(IfaceType.NAN, android.hardware.wifi.V1_6.IfaceConcurrencyType.NAN); + }}; + + private List<android.hardware.wifi.V1_6.IWifiChip.ChipMode> upgradeV1_0ChipModesToV1_6( + List<android.hardware.wifi.V1_0.IWifiChip.ChipMode> oldChipModes) { + ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> newChipModes = new ArrayList<>(); + for (android.hardware.wifi.V1_0.IWifiChip.ChipMode oldChipMode : oldChipModes) { + android.hardware.wifi.V1_6.IWifiChip.ChipMode newChipMode = + new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); + newChipMode.id = oldChipMode.id; + newChipMode.availableCombinations = new ArrayList<>(); + for (android.hardware.wifi.V1_0.IWifiChip.ChipIfaceCombination oldCombo + : oldChipMode.availableCombinations) { + android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination + newCombo = new android.hardware.wifi.V1_6.IWifiChip + .ChipConcurrencyCombination(); + newCombo.limits = new ArrayList<>(); + // Define a duplicate combination list with AP converted to AP_BRIDGED + android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination + newComboWithBridgedAp = + new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); + newComboWithBridgedAp.limits = new ArrayList<>(); + android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit + bridgedApLimit = new android.hardware.wifi.V1_6.IWifiChip + .ChipConcurrencyCombinationLimit(); + bridgedApLimit.maxIfaces = 1; + bridgedApLimit.types = new ArrayList<>(); + bridgedApLimit.types.add(IfaceConcurrencyType.AP_BRIDGED); + newComboWithBridgedAp.limits.add(bridgedApLimit); + + boolean apInCombo = false; + // Populate both the combo with AP_BRIDGED and the combo without AP_BRIDGED + for (android.hardware.wifi.V1_0.IWifiChip.ChipIfaceCombinationLimit oldLimit + : oldCombo.limits) { + android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit newLimit = + new android.hardware.wifi.V1_6 + .IWifiChip.ChipConcurrencyCombinationLimit(); + newLimit.types = new ArrayList<>(); + newLimit.maxIfaces = oldLimit.maxIfaces; + for (int oldType : oldLimit.types) { + newLimit.types.add(IFACE_TYPE_TO_CONCURRENCY_TYPE_MAP.get(oldType)); + } + newCombo.limits.add(newLimit); + + android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit + newLimitForBridgedApCombo = new android.hardware.wifi.V1_6.IWifiChip + .ChipConcurrencyCombinationLimit(); + newLimitForBridgedApCombo.types = new ArrayList<>(newLimit.types); + newLimitForBridgedApCombo.maxIfaces = newLimit.maxIfaces; + if (newLimitForBridgedApCombo.types.contains(IfaceConcurrencyType.AP)) { + // Skip the limit if it contains AP, since this corresponds to the + // AP_BRIDGED in the duplicate AP_BRIDGED combo. + apInCombo = true; + } else if (!isStaWithBridgedSoftApConcurrencySupportedMockable() + && newLimitForBridgedApCombo.types.contains(IfaceConcurrencyType.STA)) { + // Don't include STA in the AP_BRIDGED combo if STA + AP_BRIDGED is not + // supported. + newLimitForBridgedApCombo.types.remove((Integer) IfaceConcurrencyType.STA); + if (!newLimitForBridgedApCombo.types.isEmpty()) { + newComboWithBridgedAp.limits.add(newLimitForBridgedApCombo); + } + } else { + newComboWithBridgedAp.limits.add(newLimitForBridgedApCombo); + } + } + newChipMode.availableCombinations.add(newCombo); + if (isBridgedSoftApSupportedMockable() && apInCombo) { + newChipMode.availableCombinations.add(newComboWithBridgedAp); + } + } + newChipModes.add(newChipMode); + } + return newChipModes; + } + + private List<WifiChip.ChipMode> halToFrameworkChipModeListV1_0( + List<android.hardware.wifi.V1_0.IWifiChip.ChipMode> halModes) { + List<android.hardware.wifi.V1_6.IWifiChip.ChipMode> modes16 = + upgradeV1_0ChipModesToV1_6(halModes); + return halToFrameworkChipModeListV1_6(modes16); + } + + private static List<WifiChip.ChipMode> halToFrameworkChipModeListV1_6( + List<android.hardware.wifi.V1_6.IWifiChip.ChipMode> halModes) { + List<WifiChip.ChipMode> frameworkModes = new ArrayList<>(); + for (android.hardware.wifi.V1_6.IWifiChip.ChipMode halMode : halModes) { + frameworkModes.add(halToFrameworkChipModeV1_6(halMode)); + } + return frameworkModes; + } + + private static WifiChip.ChipMode halToFrameworkChipModeV1_6( + android.hardware.wifi.V1_6.IWifiChip.ChipMode halMode) { + List<WifiChip.ChipConcurrencyCombination> frameworkCombos = new ArrayList<>(); + for (android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination halCombo : + halMode.availableCombinations) { + frameworkCombos.add(halToFrameworkChipConcurrencyCombinationV1_6(halCombo)); + } + return new WifiChip.ChipMode(halMode.id, frameworkCombos); + } + + private static WifiChip.ChipConcurrencyCombination halToFrameworkChipConcurrencyCombinationV1_6( + android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination halCombo) { + List<WifiChip.ChipConcurrencyCombinationLimit> frameworkLimits = new ArrayList<>(); + for (android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit halLimit : + halCombo.limits) { + frameworkLimits.add(halToFrameworkChipConcurrencyCombinationLimitV1_6(halLimit)); + } + return new WifiChip.ChipConcurrencyCombination(frameworkLimits); + } + + private static WifiChip.ChipConcurrencyCombinationLimit + halToFrameworkChipConcurrencyCombinationLimitV1_6( + android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit halLimit) { + List<Integer> frameworkTypes = new ArrayList<>(); + for (int halType : halLimit.types) { + frameworkTypes.add(halToFrameworkIfaceConcurrencyType(halType)); + } + return new WifiChip.ChipConcurrencyCombinationLimit(halLimit.maxIfaces, frameworkTypes); + } + + private static @WifiChip.IfaceConcurrencyType int halToFrameworkIfaceConcurrencyType(int type) { + switch (type) { + case IfaceConcurrencyType.STA: + return WifiChip.IFACE_CONCURRENCY_TYPE_STA; + case IfaceConcurrencyType.AP: + return WifiChip.IFACE_CONCURRENCY_TYPE_AP; + case IfaceConcurrencyType.AP_BRIDGED: + return WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED; + case IfaceConcurrencyType.P2P: + return WifiChip.IFACE_CONCURRENCY_TYPE_P2P; + case IfaceConcurrencyType.NAN: + return WifiChip.IFACE_CONCURRENCY_TYPE_NAN; + default: + Log.e(TAG, "Invalid IfaceConcurrencyType received: " + type); + return -1; + } + } + + private static @WifiChip.IfaceType int halToFrameworkIfaceType(int type) { + switch (type) { + case IfaceType.STA: + return WifiChip.IFACE_TYPE_STA; + case IfaceType.AP: + return WifiChip.IFACE_TYPE_AP; + case IfaceType.P2P: + return WifiChip.IFACE_TYPE_P2P; + case IfaceType.NAN: + return WifiChip.IFACE_TYPE_NAN; + default: + Log.e(TAG, "Invalid IfaceType received: " + type); + return -1; + } + } + + private static final long[][] sChipFeatureCapabilityTranslation = { + {WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, + android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT + }, + {WifiManager.WIFI_FEATURE_D2D_RTT, + android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT + }, + {WifiManager.WIFI_FEATURE_D2AP_RTT, + android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT + } + }; + + /** + * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for + * additional capabilities introduced in V1.5 + */ + private static final long[][] sChipFeatureCapabilityTranslation15 = { + {WifiManager.WIFI_FEATURE_INFRA_60G, + android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG + } + }; + + /** + * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for + * additional capabilities introduced in V1.3 + */ + private static final long[][] sChipFeatureCapabilityTranslation13 = { + {WifiManager.WIFI_FEATURE_LOW_LATENCY, + android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE + }, + {WifiManager.WIFI_FEATURE_P2P_RAND_MAC, + android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.P2P_RAND_MAC + } + + }; + + /** + * Feature bit mask translation for Chip V1.1 + * + * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask + * @return bitmask defined by WifiManager.WIFI_FEATURE_* + */ + @VisibleForTesting + int wifiFeatureMaskFromChipCapabilities(int capabilities) { + int features = 0; + for (int i = 0; i < sChipFeatureCapabilityTranslation.length; i++) { + if ((capabilities & sChipFeatureCapabilityTranslation[i][1]) != 0) { + features |= sChipFeatureCapabilityTranslation[i][0]; + } + } + return features; + } + + /** + * Feature bit mask translation for Chip V1.5 + * + * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask + * @return bitmask defined by WifiManager.WIFI_FEATURE_* + */ + @VisibleForTesting + long wifiFeatureMaskFromChipCapabilities_1_5(int capabilities) { + // First collect features from previous versions + long 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]; + } + } + return features; + } + + /** + * Feature bit mask translation for Chip V1.3 + * + * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask + * @return bitmask defined by WifiManager.WIFI_FEATURE_* + */ + @VisibleForTesting + long wifiFeatureMaskFromChipCapabilities_1_3(int capabilities) { + // First collect features from previous versions + long 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]; + } + } + return features; + } + + /** + * Translates from Hal version of wake reason stats to the framework version of same + * + * @param h - Hal version of wake reason stats + * @return framework version of same + */ + private static WlanWakeReasonAndCounts halToFrameworkWakeReasons( + WifiDebugHostWakeReasonStats h) { + if (h == null) return null; + WlanWakeReasonAndCounts ans = new WlanWakeReasonAndCounts(); + ans.totalCmdEventWake = h.totalCmdEventWakeCnt; + ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt; + ans.totalRxDataWake = h.totalRxPacketWakeCnt; + ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt; + ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt; + ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt; + ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt; + ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt; + ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra; + ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na; + ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns; + ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt; + ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt; + ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt; + ans.cmdEventWakeCntArray = intsFromArrayList(h.cmdEventWakeCntPerType); + ans.driverFWLocalWakeCntArray = intsFromArrayList(h.driverFwLocalWakeCntPerType); + return ans; + } + + /** + * Creates array of RingBufferStatus from the Hal version + */ + private static WifiNative.RingBufferStatus[] makeRingBufferStatusArray( + ArrayList<WifiDebugRingBufferStatus> ringBuffers) { + WifiNative.RingBufferStatus[] ans = new WifiNative.RingBufferStatus[ringBuffers.size()]; + int i = 0; + for (WifiDebugRingBufferStatus b : ringBuffers) { + ans[i++] = halToFrameworkRingBufferStatus(b); + } + return ans; + } + + /** + * Creates RingBufferStatus from the Hal version + */ + private static WifiNative.RingBufferStatus halToFrameworkRingBufferStatus( + WifiDebugRingBufferStatus h) { + WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus(); + ans.name = h.ringName; + ans.flag = frameworkRingBufferFlagsFromHal(h.flags); + ans.ringBufferId = h.ringId; + ans.ringBufferByteSize = h.sizeInBytes; + ans.verboseLevel = h.verboseLevel; + // Remaining fields are unavailable + // writtenBytes; + // readBytes; + // writtenRecords; + return ans; + } + + /** + * Translates a hal wifiDebugRingBufferFlag to the WifiNative version + */ + private static int frameworkRingBufferFlagsFromHal(int wifiDebugRingBufferFlag) { + BitMask checkoff = new BitMask(wifiDebugRingBufferFlag); + int flags = 0; + if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) { + flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES; + } + if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) { + flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES; + } + if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) { + flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES; + } + if (checkoff.value != 0) { + throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value); + } + return flags; + } + + private static WifiChip.WifiRadioCombinationMatrix halToFrameworkRadioCombinationMatrix( + WifiRadioCombinationMatrix halMatrix) { + List<WifiChip.WifiRadioCombination> frameworkCombos = new ArrayList<>(); + for (WifiRadioCombination combo : halMatrix.radioCombinations) { + frameworkCombos.add(halToFrameworkRadioCombination(combo)); + } + return new WifiChip.WifiRadioCombinationMatrix(frameworkCombos); + } + + private static WifiChip.WifiRadioCombination halToFrameworkRadioCombination( + WifiRadioCombination halCombo) { + List<WifiChip.WifiRadioConfiguration> frameworkConfigs = new ArrayList<>(); + for (WifiRadioConfiguration config : halCombo.radioConfigurations) { + frameworkConfigs.add(halToFrameworkRadioConfiguration(config)); + } + return new WifiChip.WifiRadioCombination(frameworkConfigs); + } + + private static WifiChip.WifiRadioConfiguration halToFrameworkRadioConfiguration( + WifiRadioConfiguration halConfig) { + return new WifiChip.WifiRadioConfiguration(halToFrameworkWifiBand(halConfig.bandInfo), + halToFrameworkAntennaMode(halConfig.antennaMode)); + } + + /** + * Makes the Hal flavor of WifiScanner's band indication + * + * Note: This method is only used by background scan which does not + * support 6GHz, hence band combinations including 6GHz are considered invalid + * + * @param frameworkBand one of WifiScanner.WIFI_BAND_* + * @return A WifiBand value + * @throws IllegalArgumentException if frameworkBand is not recognized + */ + private static int frameworkToHalWifiBand(int frameworkBand) { + switch (frameworkBand) { + case WifiScanner.WIFI_BAND_UNSPECIFIED: + return WifiBand.BAND_UNSPECIFIED; + case WifiScanner.WIFI_BAND_24_GHZ: + return WifiBand.BAND_24GHZ; + case WifiScanner.WIFI_BAND_5_GHZ: + return WifiBand.BAND_5GHZ; + case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: + return WifiBand.BAND_5GHZ_DFS; + case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: + return WifiBand.BAND_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_BOTH: + return WifiBand.BAND_24GHZ_5GHZ; + case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_6_GHZ: + return WifiBand.BAND_6GHZ; + case WifiScanner.WIFI_BAND_24_5_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ; + case WifiScanner.WIFI_BAND_60_GHZ: + return WifiBand.BAND_60GHZ; + case WifiScanner.WIFI_BAND_24_5_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS: + default: + throw new IllegalArgumentException("bad band " + frameworkBand); + } + } + + private static boolean bitmapContains(int bitmap, int expectedBit) { + return (bitmap & expectedBit) != 0; + } + + private static int halToFrameworkWifiBand(int halBand) { + int frameworkBand = 0; + if (bitmapContains(halBand, WifiBand.BAND_24GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_24_GHZ; + } + if (bitmapContains(halBand, WifiBand.BAND_5GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_5_GHZ; + } + if (bitmapContains(halBand, WifiBand.BAND_5GHZ_DFS)) { + frameworkBand |= WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY; + } + if (bitmapContains(halBand, WifiBand.BAND_6GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_6_GHZ; + } + if (bitmapContains(halBand, WifiBand.BAND_60GHZ)) { + frameworkBand |= WifiScanner.WIFI_BAND_60_GHZ; + } + return frameworkBand; + } + + private static @WifiChip.WifiAntennaMode int halToFrameworkAntennaMode(int mode) { + switch (mode) { + case WifiAntennaMode.WIFI_ANTENNA_MODE_UNSPECIFIED: + return WifiChip.WIFI_ANTENNA_MODE_UNSPECIFIED; + case WifiAntennaMode.WIFI_ANTENNA_MODE_1X1: + return WifiChip.WIFI_ANTENNA_MODE_1X1; + case WifiAntennaMode.WIFI_ANTENNA_MODE_2X2: + return WifiChip.WIFI_ANTENNA_MODE_2X2; + case WifiAntennaMode.WIFI_ANTENNA_MODE_3X3: + return WifiChip.WIFI_ANTENNA_MODE_3X3; + case WifiAntennaMode.WIFI_ANTENNA_MODE_4X4: + return WifiChip.WIFI_ANTENNA_MODE_4X4; + default: + Log.e(TAG, "Invalid WifiAntennaMode: " + mode); + return -1; + } + } + + /** + * Convert framework's operational mode to HAL's operational mode. + */ + private int frameworkToHalIfaceMode(@WifiAvailableChannel.OpMode int mode) { + int halMode = 0; + if ((mode & WifiAvailableChannel.OP_MODE_STA) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_STA; + } + if ((mode & WifiAvailableChannel.OP_MODE_SAP) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_SOFTAP; + } + if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_P2P_CLIENT; + } + if ((mode & WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_P2P_GO; + } + if ((mode & WifiAvailableChannel.OP_MODE_WIFI_AWARE) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_NAN; + } + if ((mode & WifiAvailableChannel.OP_MODE_TDLS) != 0) { + halMode |= WifiIfaceMode.IFACE_MODE_TDLS; + } + return halMode; + } + + /** + * Convert framework's WifiAvailableChannel.FILTER_* to HAL's UsableChannelFilter. + */ + private int frameworkToHalUsableFilter(@WifiAvailableChannel.Filter int filter) { + int halFilter = 0; // O implies no additional filter other than regulatory (default) + + if ((filter & WifiAvailableChannel.FILTER_CONCURRENCY) != 0) { + halFilter |= android.hardware.wifi.V1_6.IWifiChip.UsableChannelFilter.CONCURRENCY; + } + if ((filter & WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE) != 0) { + halFilter |= android.hardware.wifi.V1_6.IWifiChip.UsableChannelFilter + .CELLULAR_COEXISTENCE; + } + + return halFilter; + } + + /** + * Convert framework's WifiAvailableChannel.FILTER_* to HAL's UsableChannelFilter 1.6. + */ + private int frameworkToHalUsableFilter_1_6(@WifiAvailableChannel.Filter int filter) { + int halFilter = 0; // O implies no additional filter other than regulatory (default) + + if ((filter & WifiAvailableChannel.FILTER_CONCURRENCY) != 0) { + halFilter |= android.hardware.wifi.V1_6.IWifiChip.UsableChannelFilter.CONCURRENCY; + } + if ((filter & WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE) != 0) { + halFilter |= android.hardware.wifi.V1_6.IWifiChip.UsableChannelFilter + .CELLULAR_COEXISTENCE; + } + if ((filter & WifiAvailableChannel.FILTER_NAN_INSTANT_MODE) != 0) { + halFilter |= android.hardware.wifi.V1_6.IWifiChip.UsableChannelFilter.NAN_INSTANT_MODE; + } + + return halFilter; + } + + /** + * Convert from HAL's operational mode to framework's operational mode. + */ + private @WifiAvailableChannel.OpMode int halToFrameworkIfaceMode(int halMode) { + int mode = 0; + if ((halMode & WifiIfaceMode.IFACE_MODE_STA) != 0) { + mode |= WifiAvailableChannel.OP_MODE_STA; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_SOFTAP) != 0) { + mode |= WifiAvailableChannel.OP_MODE_SAP; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_CLIENT) != 0) { + mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_P2P_GO) != 0) { + mode |= WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_NAN) != 0) { + mode |= WifiAvailableChannel.OP_MODE_WIFI_AWARE; + } + if ((halMode & WifiIfaceMode.IFACE_MODE_TDLS) != 0) { + mode |= WifiAvailableChannel.OP_MODE_TDLS; + } + return mode; + } + + @NonNull + private ArrayList<android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel> + frameworkCoexUnsafeChannelsToHidl( + @NonNull List<android.net.wifi.CoexUnsafeChannel> frameworkUnsafeChannels) { + final ArrayList<android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel> hidlList = + new ArrayList<>(); + if (!SdkLevel.isAtLeastS()) { + return hidlList; + } + for (android.net.wifi.CoexUnsafeChannel frameworkUnsafeChannel : frameworkUnsafeChannels) { + final android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel hidlUnsafeChannel = + new android.hardware.wifi.V1_5.IWifiChip.CoexUnsafeChannel(); + switch (frameworkUnsafeChannel.getBand()) { + case (WifiScanner.WIFI_BAND_24_GHZ): + hidlUnsafeChannel.band = WifiBand.BAND_24GHZ; + break; + case (WifiScanner.WIFI_BAND_5_GHZ): + hidlUnsafeChannel.band = WifiBand.BAND_5GHZ; + break; + case (WifiScanner.WIFI_BAND_6_GHZ): + hidlUnsafeChannel.band = WifiBand.BAND_6GHZ; + break; + case (WifiScanner.WIFI_BAND_60_GHZ): + hidlUnsafeChannel.band = WifiBand.BAND_60GHZ; + break; + default: + Log.e(TAG, "Tried to set unsafe channel with unknown band: " + + frameworkUnsafeChannel.getBand()); + continue; + } + hidlUnsafeChannel.channel = frameworkUnsafeChannel.getChannel(); + final int powerCapDbm = frameworkUnsafeChannel.getPowerCapDbm(); + if (powerCapDbm != POWER_CAP_NONE) { + hidlUnsafeChannel.powerCapDbm = powerCapDbm; + } else { + hidlUnsafeChannel.powerCapDbm = + android.hardware.wifi.V1_5.IWifiChip.PowerCapConstant.NO_POWER_CAP; + } + hidlList.add(hidlUnsafeChannel); + } + return hidlList; + } + + private int frameworkCoexRestrictionsToHidl(@WifiManager.CoexRestriction int restrictions) { + int hidlRestrictions = 0; + if (!SdkLevel.isAtLeastS()) { + return hidlRestrictions; + } + if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_DIRECT) != 0) { + hidlRestrictions |= android.hardware.wifi.V1_5.IWifiChip.CoexRestriction.WIFI_DIRECT; + } + if ((restrictions & WifiManager.COEX_RESTRICTION_SOFTAP) != 0) { + hidlRestrictions |= android.hardware.wifi.V1_5.IWifiChip.CoexRestriction.SOFTAP; + } + if ((restrictions & WifiManager.COEX_RESTRICTION_WIFI_AWARE) != 0) { + hidlRestrictions |= android.hardware.wifi.V1_5.IWifiChip.CoexRestriction.WIFI_AWARE; + } + return hidlRestrictions; + } + + private byte frameworkMultiStaUseCaseToHidl(@WifiNative.MultiStaUseCase int useCase) + throws IllegalArgumentException { + switch (useCase) { + case WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY: + return android.hardware.wifi.V1_5.IWifiChip + .MultiStaUseCase.DUAL_STA_TRANSIENT_PREFER_PRIMARY; + case WifiNative.DUAL_STA_NON_TRANSIENT_UNBIASED: + return android.hardware.wifi.V1_5.IWifiChip + .MultiStaUseCase.DUAL_STA_NON_TRANSIENT_UNBIASED; + default: + throw new IllegalArgumentException("Invalid use case " + useCase); + } + } + + /** + * This method checks if we need to backoff wifi Tx power due to SAR requirements. + * It handles the case when the device is running the V1_1 version of WifiChip HAL + * In that HAL version, it is required to perform wifi Tx power backoff only if + * a voice call is ongoing. + */ + private static boolean sarPowerBackoffRequired_1_1(SarInfo sarInfo) { + /* As long as no voice call is active (in case voice call is supported), + * no backoff is needed + */ + if (sarInfo.sarVoiceCallSupported) { + return (sarInfo.isVoiceCall || sarInfo.isEarPieceActive); + } else { + return false; + } + } + + /** + * This method maps the information inside the SarInfo instance into a SAR scenario + * when device is running the V1_1 version of WifiChip HAL. + * In this HAL version, only one scenario is defined which is for VOICE_CALL (if voice call is + * supported). + * Otherwise, an exception is thrown. + */ + private static int frameworkToHalTxPowerScenario_1_1(SarInfo sarInfo) { + if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) { + return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL; + } else { + throw new IllegalArgumentException("bad scenario: voice call not active/supported"); + } + } + + /** + * This method checks if we need to backoff wifi Tx power due to SAR requirements. + * It handles the case when the device is running the V1_2 version of WifiChip HAL + */ + private static boolean sarPowerBackoffRequired_1_2(SarInfo sarInfo) { + if (sarInfo.sarSapSupported && sarInfo.isWifiSapEnabled) { + return true; + } + if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) { + return true; + } + return false; + } + + /** + * This method maps the information inside the SarInfo instance into a SAR scenario + * when device is running the V1_2 version of WifiChip HAL. + * If SAR SoftAP input is supported, + * we make these assumptions: + * - All voice calls are treated as if device is near the head. + * - SoftAP scenario is treated as if device is near the body. + * In case SoftAP is not supported, then we should revert to the V1_1 HAL + * behavior, and the only valid scenario would be when a voice call is ongoing. + */ + private static int frameworkToHalTxPowerScenario_1_2(SarInfo sarInfo) { + if (sarInfo.sarSapSupported && sarInfo.sarVoiceCallSupported) { + if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { + return android.hardware.wifi.V1_2.IWifiChip + .TxPowerScenario.ON_HEAD_CELL_ON; + } else if (sarInfo.isWifiSapEnabled) { + return android.hardware.wifi.V1_2.IWifiChip + .TxPowerScenario.ON_BODY_CELL_ON; + } else { + throw new IllegalArgumentException("bad scenario: no voice call/softAP active"); + } + } else if (sarInfo.sarVoiceCallSupported) { + /* SAR SoftAP input not supported, act like V1_1 */ + if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) { + return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL; + } else { + throw new IllegalArgumentException("bad scenario: voice call not active"); + } + } else { + throw new IllegalArgumentException("Invalid case: voice call not supported"); + } + } + + protected android.hardware.wifi.V1_1.IWifiChip getWifiChipV1_1Mockable() { + return android.hardware.wifi.V1_1.IWifiChip.castFrom(mWifiChip); + } + + protected android.hardware.wifi.V1_2.IWifiChip getWifiChipV1_2Mockable() { + return android.hardware.wifi.V1_2.IWifiChip.castFrom(mWifiChip); + } + + protected android.hardware.wifi.V1_3.IWifiChip getWifiChipV1_3Mockable() { + return android.hardware.wifi.V1_3.IWifiChip.castFrom(mWifiChip); + } + + protected android.hardware.wifi.V1_4.IWifiChip getWifiChipV1_4Mockable() { + return android.hardware.wifi.V1_4.IWifiChip.castFrom(mWifiChip); + } + + protected android.hardware.wifi.V1_5.IWifiChip getWifiChipV1_5Mockable() { + return android.hardware.wifi.V1_5.IWifiChip.castFrom(mWifiChip); + } + + protected android.hardware.wifi.V1_6.IWifiChip getWifiChipV1_6Mockable() { + return android.hardware.wifi.V1_6.IWifiChip.castFrom(mWifiChip); + } + + private static int[] intsFromArrayList(ArrayList<Integer> a) { + if (a == null) return null; + int[] b = new int[a.size()]; + int i = 0; + for (Integer e : a) b[i++] = e; + return b; + } + + private boolean isOk(WifiStatus status, String methodStr) { + if (status.code == WifiStatusCode.SUCCESS) return true; + Log.e(TAG, methodStr + " failed with status: " + status); + return false; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + Log.e(TAG, methodStr + " failed with remote exception: " + e); + mWifiChip = null; + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiChip == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiChip is null"); + return defaultVal; + } + return supplier.get(); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiHal.java b/service/java/com/android/server/wifi/hal/WifiHal.java new file mode 100644 index 0000000000..05203d48bd --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiHal.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wifi.SsidTranslator; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; +import java.util.function.Supplier; + +/** + * Wrapper around the root Wifi HAL. + * Depending on the service available, may initialize using HIDL or AIDL. + */ +public class WifiHal { + private static final String TAG = "WifiHal"; + private IWifiHal mWifiHal; + + /** + * Wifi operation status codes. + */ + public static final int WIFI_STATUS_SUCCESS = 0; + public static final int WIFI_STATUS_ERROR_WIFI_CHIP_INVALID = 1; + public static final int WIFI_STATUS_ERROR_WIFI_IFACE_INVALID = 2; + public static final int WIFI_STATUS_ERROR_WIFI_RTT_CONTROLLER_INVALID = 3; + public static final int WIFI_STATUS_ERROR_NOT_SUPPORTED = 4; + public static final int WIFI_STATUS_ERROR_NOT_AVAILABLE = 5; + public static final int WIFI_STATUS_ERROR_NOT_STARTED = 6; + public static final int WIFI_STATUS_ERROR_INVALID_ARGS = 7; + public static final int WIFI_STATUS_ERROR_BUSY = 8; + public static final int WIFI_STATUS_ERROR_UNKNOWN = 9; + public static final int WIFI_STATUS_ERROR_REMOTE_EXCEPTION = 10; + + @IntDef(prefix = { "WIFI_STATUS_" }, value = { + WIFI_STATUS_SUCCESS, + WIFI_STATUS_ERROR_WIFI_CHIP_INVALID, + WIFI_STATUS_ERROR_WIFI_IFACE_INVALID, + WIFI_STATUS_ERROR_WIFI_RTT_CONTROLLER_INVALID, + WIFI_STATUS_ERROR_NOT_SUPPORTED, + WIFI_STATUS_ERROR_NOT_AVAILABLE, + WIFI_STATUS_ERROR_NOT_STARTED, + WIFI_STATUS_ERROR_INVALID_ARGS, + WIFI_STATUS_ERROR_BUSY, + WIFI_STATUS_ERROR_UNKNOWN, + WIFI_STATUS_ERROR_REMOTE_EXCEPTION, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WifiStatusCode {} + + /** + * Interface that can be created by the Wi-Fi HAL. + */ + public interface WifiInterface { + /** + * Get the name of this interface. + */ + String getName(); + } + + /** + * Framework callback object. Will get called when the equivalent events are received + * from the HAL. + */ + public interface Callback { + /** + * Called when the Wi-Fi system failed in a way that caused it be disabled. + * Calling start again must restart Wi-Fi as if stop then start was called + * (full state reset). When this event is received, all WifiChip & WifiIface + * objects retrieved after the last call to start will be considered invalid. + * + * @param status Failure reason code. + */ + void onFailure(@WifiStatusCode int status); + + /** + * Called in response to a call to start, indicating that the operation + * completed. After this callback the HAL must be fully operational. + */ + void onStart(); + + /** + * Called in response to a call to stop, indicating that the operation + * completed. When this event is received, all WifiChip objects retrieved + * after the last call to start will be considered invalid. + */ + void onStop(); + + /** + * Must be called when the Wi-Fi subsystem restart completes. + * Once this event is received, the framework must fully reset the Wi-Fi stack state. + * + * @param status Status code. + */ + void onSubsystemRestart(@WifiStatusCode int status); + } + + /** + * Framework death recipient object. Called if the death recipient registered with the HAL + * indicates that the service died. + */ + public interface DeathRecipient { + /** + * Called on service death. + */ + void onDeath(); + } + + public WifiHal(@NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiHal = createWifiHalMockable(context, ssidTranslator); + } + + @VisibleForTesting + protected IWifiHal createWifiHalMockable(@NonNull Context context, + @NonNull SsidTranslator ssidTranslator) { + if (WifiHalAidlImpl.serviceDeclared()) { + return new WifiHalAidlImpl(context, ssidTranslator); + } else if (WifiHalHidlImpl.serviceDeclared()) { + return new WifiHalHidlImpl(context, ssidTranslator); + } else { + Log.e(TAG, "No HIDL or AIDL service available for the Wifi Vendor HAL."); + return null; + } + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiHal == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiHal is null"); + return defaultVal; + } + return supplier.get(); + } + + /** + * See comments for {@link IWifiHal#getChip(int)} + */ + @Nullable + public WifiChip getChip(int chipId) { + return validateAndCall("getChip", null, + () -> mWifiHal.getChip(chipId)); + } + + /** + * See comments for {@link IWifiHal#getChipIds()} + */ + @Nullable + public List<Integer> getChipIds() { + return validateAndCall("getChipIds", null, + () -> mWifiHal.getChipIds()); + } + + /** + * See comments for {@link IWifiHal#registerEventCallback(Callback)} + */ + public boolean registerEventCallback(Callback callback) { + return validateAndCall("registerEventCallback", false, + () -> mWifiHal.registerEventCallback(callback)); + } + + /** + * See comments for {@link IWifiHal#initialize(DeathRecipient)} + */ + public void initialize(WifiHal.DeathRecipient deathRecipient) { + if (mWifiHal != null) { + mWifiHal.initialize(deathRecipient); + } + } + + /** + * See comments for {@link IWifiHal#isInitializationComplete()} + */ + public boolean isInitializationComplete() { + return validateAndCall("isInitializationComplete", false, + () -> mWifiHal.isInitializationComplete()); + } + + /** + * See comments for {@link IWifiHal#isSupported()} + */ + public boolean isSupported() { + return validateAndCall("isSupported", false, + () -> mWifiHal.isSupported()); + } + + /** + * See comments for {@link IWifiHal#start()} + */ + public @WifiStatusCode int start() { + return validateAndCall("start", WIFI_STATUS_ERROR_UNKNOWN, + () -> mWifiHal.start()); + } + + /** + * See comments for {@link IWifiHal#isStarted()} + */ + public boolean isStarted() { + return validateAndCall("isStarted", false, + () -> mWifiHal.isStarted()); + } + + /** + * See comments for {@link IWifiHal#stop()} + */ + public boolean stop() { + return validateAndCall("stop", false, + () -> mWifiHal.stop()); + } + + /** + * See comments for {@link IWifiHal#invalidate()} + */ + public void invalidate() { + if (mWifiHal != null) { + mWifiHal.invalidate(); + } + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiHalAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiHalAidlImpl.java new file mode 100644 index 0000000000..1ba9a79c6a --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiHalAidlImpl.java @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.wifi.IWifiChip; +import android.hardware.wifi.IWifiEventCallback; +import android.hardware.wifi.WifiStatusCode; +import android.os.IBinder; +import android.os.IBinder.DeathRecipient; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ServiceSpecificException; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.build.SdkLevel; +import com.android.server.wifi.SsidTranslator; + +import java.util.ArrayList; +import java.util.List; + +/** + * AIDL implementation of the IWifiHal interface. + */ +public class WifiHalAidlImpl implements IWifiHal { + private static final String TAG = "WifiHalAidlImpl"; + private static final String HAL_INSTANCE_NAME = + android.hardware.wifi.IWifi.DESCRIPTOR + "/default"; + + private android.hardware.wifi.IWifi mWifi; + private Context mContext; + private SsidTranslator mSsidTranslator; + private IWifiEventCallback mHalCallback; + private WifiHal.Callback mFrameworkCallback; + private DeathRecipient mServiceDeathRecipient; + private WifiHal.DeathRecipient mFrameworkDeathRecipient; + private final Object mLock = new Object(); + + public WifiHalAidlImpl(@NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + Log.i(TAG, "Creating the Wifi HAL using the AIDL implementation"); + mContext = context; + mSsidTranslator = ssidTranslator; + mServiceDeathRecipient = new WifiDeathRecipient(); + mHalCallback = new WifiEventCallback(); + } + + /** + * See comments for {@link IWifiHal#getChip(int)} + */ + @Override + @Nullable + public WifiChip getChip(int chipId) { + final String methodStr = "getChip"; + synchronized (mLock) { + try { + if (!checkWifiAndLogFailure(methodStr)) return null; + IWifiChip chip = mWifi.getChip(chipId); + return new WifiChip(chip, mContext, mSsidTranslator); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiHal#getChipIds()} + */ + @Override + @Nullable + public List<Integer> getChipIds() { + final String methodStr = "getChipIds"; + synchronized (mLock) { + try { + if (!checkWifiAndLogFailure(methodStr)) return null; + int[] chipIdArray = mWifi.getChipIds(); + List<Integer> chipIdList = new ArrayList<>(); + for (int id : chipIdArray) { + chipIdList.add(id); + } + return chipIdList; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiHal#registerEventCallback(WifiHal.Callback)} + */ + @Override + public boolean registerEventCallback(WifiHal.Callback callback) { + synchronized (mLock) { + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (callback == null) { + Log.e(TAG, "Cannot register a null callback"); + return false; + } + if (!registerHalCallback()) return false; + mFrameworkCallback = callback; + return true; + } + } + + private boolean registerHalCallback() { + final String methodStr = "registerHalCallback"; + try { + mWifi.registerEventCallback(mHalCallback); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + + /** + * See comments for {@link IWifiHal#isInitializationComplete()} + */ + @Override + public boolean isInitializationComplete() { + synchronized (mLock) { + return mWifi != null; + } + } + + /** + * See comments for {@link IWifiHal#isSupported()} + */ + @Override + public boolean isSupported() { + return serviceDeclared(); + } + + /** + * Indicates whether the AIDL service is declared. + */ + protected static boolean serviceDeclared() { + // Service Manager API ServiceManager#isDeclared is supported after U. + return SdkLevel.isAtLeastU() ? ServiceManager.isDeclared(HAL_INSTANCE_NAME) : false; + } + + /** + * See comments for {@link IWifiHal#start()} + */ + @Override + public @WifiHal.WifiStatusCode int start() { + final String methodStr = "start"; + synchronized (mLock) { + try { + if (!checkWifiAndLogFailure(methodStr)) return WifiHal.WIFI_STATUS_ERROR_UNKNOWN; + mWifi.start(); + return WifiHal.WIFI_STATUS_SUCCESS; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION; + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + return halToFrameworkWifiStatusCode(e.errorCode); + } + } + } + + /** + * See comments for {@link IWifiHal#isStarted()} + */ + @Override + public boolean isStarted() { + final String methodStr = "isStarted"; + synchronized (mLock) { + try { + if (!checkWifiAndLogFailure(methodStr)) return false; + return mWifi.isStarted(); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiHal#stop()} + */ + @Override + public boolean stop() { + synchronized (mLock) { + if (!checkWifiAndLogFailure("stop")) return false; + boolean result = stopInternal(); + return result; + } + } + + private boolean stopInternal() { + final String methodStr = "stopInternal"; + try { + mWifi.stop(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + + /** + * See comments for {@link IWifiHal#initialize(WifiHal.DeathRecipient)} + */ + @Override + public void initialize(WifiHal.DeathRecipient deathRecipient) { + final String methodStr = "initialize"; + synchronized (mLock) { + if (mWifi != null) { + Log.i(TAG, "Service is already initialized"); + return; + } + + mWifi = getWifiServiceMockable(); + if (mWifi == null) { + Log.e(TAG, "Unable to obtain the IWifi binder"); + return; + } + Log.i(TAG, "Obtained the IWifi binder. Local Version: " + + android.hardware.wifi.IWifi.VERSION); + + try { + Log.i(TAG, "Remote Version: " + mWifi.getInterfaceVersion()); + IBinder serviceBinder = getServiceBinderMockable(); + if (serviceBinder == null) { + Log.e(TAG, "Unable to obtain the service binder"); + return; + } + serviceBinder.linkToDeath(mServiceDeathRecipient, /* flags= */ 0); + mFrameworkDeathRecipient = deathRecipient; + + // Stop wifi just in case. Stop will invalidate the callbacks, so re-register them. + stopInternal(); + registerHalCallback(); + Log.i(TAG, "Initialization was successful"); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + } + } + + /** + * See comments for {@link IWifiHal#invalidate()} + */ + public void invalidate() { + synchronized (mLock) { + mWifi = null; + } + } + + private class WifiEventCallback extends IWifiEventCallback.Stub { + @Override + public void onStart() throws RemoteException { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onStart(); + } + + @Override + public void onStop() throws RemoteException { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onStop(); + } + + @Override + public void onFailure(int statusCode) throws RemoteException { + synchronized (mLock) { + mWifi = null; + } + if (mFrameworkCallback == null) return; + mFrameworkCallback.onFailure(halToFrameworkWifiStatusCode(statusCode)); + } + + @Override + public void onSubsystemRestart(int statusCode) throws RemoteException { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onSubsystemRestart(halToFrameworkWifiStatusCode(statusCode)); + } + + @Override + public String getInterfaceHash() { + return IWifiEventCallback.HASH; + } + + @Override + public int getInterfaceVersion() { + return IWifiEventCallback.VERSION; + } + } + + private class WifiDeathRecipient implements DeathRecipient { + @Override + public void binderDied() { + synchronized (mLock) { + Log.w(TAG, "IWifi binder died."); + mWifi = null; + if (mFrameworkDeathRecipient != null) { + mFrameworkDeathRecipient.onDeath(); + } + } + } + } + + + // Utilities + + protected static @WifiHal.WifiStatusCode int halToFrameworkWifiStatusCode(int code) { + switch (code) { + case WifiStatusCode.SUCCESS: + return WifiHal.WIFI_STATUS_SUCCESS; + case WifiStatusCode.ERROR_WIFI_CHIP_INVALID: + return WifiHal.WIFI_STATUS_ERROR_WIFI_CHIP_INVALID; + case WifiStatusCode.ERROR_WIFI_IFACE_INVALID: + return WifiHal.WIFI_STATUS_ERROR_WIFI_IFACE_INVALID; + case WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID: + return WifiHal.WIFI_STATUS_ERROR_WIFI_RTT_CONTROLLER_INVALID; + case WifiStatusCode.ERROR_NOT_SUPPORTED: + return WifiHal.WIFI_STATUS_ERROR_NOT_SUPPORTED; + case WifiStatusCode.ERROR_NOT_AVAILABLE: + return WifiHal.WIFI_STATUS_ERROR_NOT_AVAILABLE; + case WifiStatusCode.ERROR_NOT_STARTED: + return WifiHal.WIFI_STATUS_ERROR_NOT_STARTED; + case WifiStatusCode.ERROR_INVALID_ARGS: + return WifiHal.WIFI_STATUS_ERROR_INVALID_ARGS; + case WifiStatusCode.ERROR_BUSY: + return WifiHal.WIFI_STATUS_ERROR_BUSY; + case WifiStatusCode.ERROR_UNKNOWN: + return WifiHal.WIFI_STATUS_ERROR_UNKNOWN; + default: + Log.e(TAG, "Invalid WifiStatusCode received: " + code); + return WifiHal.WIFI_STATUS_ERROR_UNKNOWN; + } + } + + @VisibleForTesting + protected android.hardware.wifi.IWifi getWifiServiceMockable() { + try { + return android.hardware.wifi.IWifi.Stub.asInterface( + ServiceManager.waitForDeclaredService(HAL_INSTANCE_NAME)); + } catch (Exception e) { + Log.e(TAG, "Unable to get IWifi service, " + e); + return null; + } + } + + @VisibleForTesting + protected IBinder getServiceBinderMockable() { + if (mWifi == null) return null; + return mWifi.asBinder(); + } + + private boolean checkWifiAndLogFailure(String methodStr) { + if (mWifi == null) { + Log.e(TAG, "Unable to call " + methodStr + " because IWifi is null."); + return false; + } + return true; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + mWifi = null; + Log.e(TAG, methodStr + " failed with remote exception: " + e); + } + + private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { + Log.e(TAG, methodStr + " failed with service-specific exception: " + e); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiHalHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiHalHidlImpl.java new file mode 100644 index 0000000000..f9fe456211 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiHalHidlImpl.java @@ -0,0 +1,591 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.wifi.V1_0.IWifi; +import android.hardware.wifi.V1_0.WifiStatus; +import android.hardware.wifi.V1_0.WifiStatusCode; +import android.hidl.manager.V1_0.IServiceNotification; +import android.hidl.manager.V1_2.IServiceManager; +import android.os.IHwBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.android.server.wifi.SsidTranslator; +import com.android.server.wifi.util.GeneralUtil.Mutable; + +import java.util.List; +import java.util.function.Supplier; + +/** + * HIDL implementation of the IWifiHal interface. + */ +public class WifiHalHidlImpl implements IWifiHal { + private static final String TAG = "WifiHalHidlImpl"; + private IServiceManager mServiceManager; + private android.hardware.wifi.V1_0.IWifi mWifi; + private Context mContext; + private SsidTranslator mSsidTranslator; + private android.hardware.wifi.V1_0.IWifiEventCallback mHalCallback10; + private android.hardware.wifi.V1_5.IWifiEventCallback mHalCallback15; + private WifiHal.Callback mFrameworkCallback; + private ServiceManagerDeathRecipient mServiceManagerDeathRecipient; + private WifiDeathRecipient mWifiDeathRecipient; + private WifiHal.DeathRecipient mFrameworkDeathRecipient; + private boolean mIsVendorHalSupported; + + private final Object mLock = new Object(); + + public WifiHalHidlImpl(@NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + Log.i(TAG, "Creating the Wifi HAL using the HIDL implementation"); + mContext = context; + mSsidTranslator = ssidTranslator; + mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient(); + mWifiDeathRecipient = new WifiDeathRecipient(); + mHalCallback10 = new WifiEventCallback(); + mHalCallback15 = new WifiEventCallbackV15(); + } + + /** + * See comments for {@link IWifiHal#getChip(int)} + */ + @Override + @Nullable + public WifiChip getChip(int chipId) { + synchronized (mLock) { + final String methodStr = "getChip"; + return validateAndCall(methodStr, null, + () -> getChipInternal(methodStr, chipId)); + } + } + + /** + * See comments for {@link IWifiHal#getChipIds()} + */ + @Override + @Nullable + public List<Integer> getChipIds() { + synchronized (mLock) { + final String methodStr = "getChipIds"; + return validateAndCall(methodStr, null, + () -> getChipIdsInternal(methodStr)); + } + } + + /** + * See comments for {@link IWifiHal#registerEventCallback(WifiHal.Callback)} + */ + @Override + public boolean registerEventCallback(WifiHal.Callback callback) { + synchronized (mLock) { + final String methodStr = "registerEventCallback"; + return validateAndCall(methodStr, false, + () -> registerEventCallbackInternal(callback)); + } + } + + /** + * See comments for {@link IWifiHal#isInitializationComplete()} + */ + @Override + public boolean isInitializationComplete() { + synchronized (mLock) { + return mWifi != null; + } + } + + /** + * See comments for {@link IWifiHal#isSupported()} + */ + @Override + public boolean isSupported() { + synchronized (mLock) { + return mIsVendorHalSupported; + } + } + + /** + * See comments for {@link IWifiHal#start()} + */ + @Override + public @WifiHal.WifiStatusCode int start() { + synchronized (mLock) { + final String methodStr = "start"; + return validateAndCall(methodStr, WifiHal.WIFI_STATUS_ERROR_UNKNOWN, + () -> startInternal(methodStr)); + } + } + + /** + * See comments for {@link IWifiHal#isStarted()} + */ + @Override + public boolean isStarted() { + synchronized (mLock) { + final String methodStr = "isStarted"; + return validateAndCall(methodStr, false, + () -> isStartedInternal(methodStr)); + } + } + + /** + * See comments for {@link IWifiHal#stop()} + */ + @Override + public boolean stop() { + synchronized (mLock) { + final String methodStr = "stop"; + boolean result = validateAndCall(methodStr, false, + () -> stopInternal(methodStr)); + return result; + } + } + + /** + * See comments for {@link IWifiHal#initialize(WifiHal.DeathRecipient)} + */ + @Override + public void initialize(WifiHal.DeathRecipient deathRecipient) { + synchronized (mLock) { + Log.i(TAG, "Initializing the WiFi HAL"); + mFrameworkDeathRecipient = deathRecipient; + initServiceManagerIfNecessaryLocked(); + if (mIsVendorHalSupported) { + initWifiIfNecessaryLocked(); + } + } + } + + /** + * See comments for {@link IWifiHal#invalidate()} + */ + public void invalidate() { + synchronized (mLock) { + mWifi = null; + } + } + + + // Internal Implementations + + private WifiChip getChipInternal(String methodStr, int chipId) { + Mutable<WifiChip> chipResp = new Mutable<>(); + try { + mWifi.getChip(chipId, (status, chip) -> { + if (isOk(status, methodStr)) { + chipResp.value = new WifiChip(chip, mContext, mSsidTranslator); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return chipResp.value; + } + + private List<Integer> getChipIdsInternal(String methodStr) { + Mutable<List<Integer>> chipIdResp = new Mutable<>(); + try { + mWifi.getChipIds((status, chipIds) -> { + if (isOk(status, methodStr)) { + chipIdResp.value = chipIds; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return chipIdResp.value; + } + + private boolean registerEventCallbackInternal(WifiHal.Callback callback) { + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (callback == null) { + Log.e(TAG, "Cannot register a null callback"); + return false; + } + + if (!registerHalCallback()) return false; + mFrameworkCallback = callback; + return true; + } + + private boolean registerHalCallback() { + final String methodStr = "registerHalCallback"; + try { + android.hardware.wifi.V1_5.IWifi wifi15 = getWifiV1_5Mockable(); + WifiStatus status; + if (wifi15 != null) { + status = wifi15.registerEventCallback_1_5(mHalCallback15); + } else { + status = mWifi.registerEventCallback(mHalCallback10); + } + + if (!isOk(status, methodStr)) { + Log.e(TAG, "Unable to register HAL callback"); + mWifi = null; + return false; + } + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private @WifiHal.WifiStatusCode int startInternal(String methodStr) { + try { + WifiStatus status = mWifi.start(); + return halToFrameworkWifiStatusCode(status.code); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return WifiHal.WIFI_STATUS_ERROR_UNKNOWN; + } + } + + private boolean isStartedInternal(String methodStr) { + try { + return mWifi.isStarted(); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean stopInternal(String methodStr) { + try { + WifiStatus status = mWifi.stop(); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private class WifiEventCallback extends android.hardware.wifi.V1_0.IWifiEventCallback.Stub { + @Override + public void onStart() throws RemoteException { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onStart(); + } + + @Override + public void onStop() throws RemoteException { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onStop(); + } + + @Override + public void onFailure(WifiStatus status) throws RemoteException { + synchronized (mLock) { + mWifi = null; + if (mFrameworkCallback == null) return; + mFrameworkCallback.onFailure(halToFrameworkWifiStatusCode(status.code)); + } + } + } + + private class WifiEventCallbackV15 extends android.hardware.wifi.V1_5.IWifiEventCallback.Stub { + @Override + public void onStart() throws RemoteException { + if (mFrameworkCallback == null) return; + mHalCallback10.onStart(); + } + + @Override + public void onStop() throws RemoteException { + if (mFrameworkCallback == null) return; + mHalCallback10.onStop(); + } + + @Override + public void onFailure(WifiStatus status) throws RemoteException { + if (mFrameworkCallback == null) return; + mHalCallback10.onFailure(status); + } + + @Override + public void onSubsystemRestart(WifiStatus status) throws RemoteException { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onSubsystemRestart(halToFrameworkWifiStatusCode(status.code)); + } + } + + private class ServiceManagerDeathRecipient implements IHwBinder.DeathRecipient { + @Override + public void serviceDied(long cookie) { + Log.wtf(TAG, "IServiceManager died: cookie=" + cookie); + mServiceManager = null; + // theoretically can call initServiceManager again here - but + // there's no point since most likely system is going to reboot + } + } + + private class WifiDeathRecipient implements IHwBinder.DeathRecipient { + @Override + public void serviceDied(long cookie) { + synchronized (mLock) { + Log.e(TAG, "IWifi HAL service died! Have a listener for it ... cookie=" + + cookie); + mWifi = null; + if (mFrameworkDeathRecipient != null) { + mFrameworkDeathRecipient.onDeath(); + } + // don't restart: wait for registration notification + } + } + } + + private final IServiceNotification mServiceNotificationCallback = + new IServiceNotification.Stub() { + @Override + public void onRegistration(String fqName, String name, boolean preexisting) { + synchronized (mLock) { + Log.d(TAG, "IWifi registration notification: fqName=" + fqName + + ", name=" + name + ", preexisting=" + preexisting); + initWifiIfNecessaryLocked(); + } + } + }; + + + // Helper Functions + + private void initServiceManagerIfNecessaryLocked() { + if (mServiceManager != null) { + Log.i(TAG, "mServiceManager already exists"); + return; + } + Log.i(TAG, "initServiceManagerIfNecessaryLocked"); + + // Failures of IServiceManager are most likely system breaking. + // Behavior here will be to WTF and continue. + mServiceManager = getServiceManagerMockable(); + if (mServiceManager == null) { + Log.wtf(TAG, "Failed to get IServiceManager instance"); + return; + } + + try { + if (!mServiceManager.linkToDeath(mServiceManagerDeathRecipient, 0)) { + Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); + mServiceManager = null; + return; + } + if (!mServiceManager.registerForNotifications(IWifi.kInterfaceName, "", + mServiceNotificationCallback)) { + Log.wtf(TAG, "Failed to register a listener for IWifi service"); + mServiceManager = null; + } + } catch (RemoteException e) { + Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); + mServiceManager = null; + return; + } + mIsVendorHalSupported = isSupportedInternal(); + } + + private void initWifiIfNecessaryLocked() { + if (mWifi != null) { + Log.i(TAG, "mWifi already exists"); + return; + } + Log.i(TAG, "initWifiIfNecessaryLocked"); + + try { + mWifi = getWifiServiceMockable(); + if (mWifi == null) { + Log.e(TAG, "IWifi not (yet) available - but have a listener for it ..."); + return; + } + + if (!mWifi.linkToDeath(mWifiDeathRecipient, /* don't care */ 0)) { + Log.e(TAG, "Error on linkToDeath on IWifi - will retry later"); + return; + } + + // Stop wifi just in case. Stop will invalidate the callbacks, so re-register them. + stopInternal("stop"); + registerHalCallback(); + Log.i(TAG, "mWifi was retrieved. HAL is running version " + getVersion()); + } catch (RemoteException e) { + Log.e(TAG, "Exception while operating on IWifi: " + e); + } + } + + /** + * Uses the IServiceManager to query if the vendor HAL is present in the VINTF for the device + * or not. + * @return true if supported, false otherwise. + */ + private boolean isSupportedInternal() { + if (mServiceManager == null) { + Log.e(TAG, "isSupported: called but mServiceManager is null!?"); + return false; + } + try { + List<String> wifiServices = + mServiceManager.listManifestByInterface(IWifi.kInterfaceName); + return !wifiServices.isEmpty(); + } catch (RemoteException e) { + Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); + return false; + } + } + + /** + * Indicates whether the HIDL service is declared. Uses the IServiceManager to check + * if the device is running a version >= V1_0 of the HAL from the VINTF for the device. + */ + protected static boolean serviceDeclared() { + try { + IServiceManager serviceManager = getServiceManagerMockable(); + if (serviceManager == null) { + Log.e(TAG, "Unable to get service manager to check for service."); + return false; + } + String interfaceName = android.hardware.wifi.V1_0.IWifi.kInterfaceName; + if (serviceManager.getTransport(interfaceName, "default") + != IServiceManager.Transport.EMPTY) { + return true; + } + return false; + } catch (RemoteException e) { + Log.e(TAG, "Unable to check for existence of HIDL service."); + return false; + } + } + + private String getVersion() { + if (checkHalVersionByInterfaceName( + android.hardware.wifi.V1_6.IWifi.kInterfaceName)) { + return "1.6"; + } else if (checkHalVersionByInterfaceName( + android.hardware.wifi.V1_5.IWifi.kInterfaceName)) { + return "1.5"; + } else if (checkHalVersionByInterfaceName( + android.hardware.wifi.V1_4.IWifi.kInterfaceName)) { + return "1.4"; + } else if (checkHalVersionByInterfaceName( + android.hardware.wifi.V1_3.IWifi.kInterfaceName)) { + return "1.3"; + } else if (checkHalVersionByInterfaceName( + android.hardware.wifi.V1_2.IWifi.kInterfaceName)) { + return "1.2"; + } else if (checkHalVersionByInterfaceName( + android.hardware.wifi.V1_1.IWifi.kInterfaceName)) { + return "1.1"; + } else { + // Service exists, so at least V1_0 is supported + return "1.0"; + } + } + + /** + * Use the IServiceManager to check if the device is running V1_X of the HAL + * from the VINTF for the device. + * + * @return true if HAL version is V1_X, false otherwise. + */ + private boolean checkHalVersionByInterfaceName(String interfaceName) { + if (interfaceName == null) return false; + if (mServiceManager == null) { + Log.e(TAG, "checkHalVersionByInterfaceName called but mServiceManager is null!?"); + return false; + } + try { + return (mServiceManager.getTransport(interfaceName, "default") + != IServiceManager.Transport.EMPTY); + } catch (RemoteException e) { + Log.e(TAG, "Exception while operating on IServiceManager: " + e); + handleRemoteException(e, "getTransport"); + return false; + } + } + + protected static @WifiHal.WifiStatusCode int halToFrameworkWifiStatusCode(int code) { + switch (code) { + case WifiStatusCode.SUCCESS: + return WifiHal.WIFI_STATUS_SUCCESS; + case WifiStatusCode.ERROR_WIFI_CHIP_INVALID: + return WifiHal.WIFI_STATUS_ERROR_WIFI_CHIP_INVALID; + case WifiStatusCode.ERROR_WIFI_IFACE_INVALID: + return WifiHal.WIFI_STATUS_ERROR_WIFI_IFACE_INVALID; + case WifiStatusCode.ERROR_WIFI_RTT_CONTROLLER_INVALID: + return WifiHal.WIFI_STATUS_ERROR_WIFI_RTT_CONTROLLER_INVALID; + case WifiStatusCode.ERROR_NOT_SUPPORTED: + return WifiHal.WIFI_STATUS_ERROR_NOT_SUPPORTED; + case WifiStatusCode.ERROR_NOT_AVAILABLE: + return WifiHal.WIFI_STATUS_ERROR_NOT_AVAILABLE; + case WifiStatusCode.ERROR_NOT_STARTED: + return WifiHal.WIFI_STATUS_ERROR_NOT_STARTED; + case WifiStatusCode.ERROR_INVALID_ARGS: + return WifiHal.WIFI_STATUS_ERROR_INVALID_ARGS; + case WifiStatusCode.ERROR_BUSY: + return WifiHal.WIFI_STATUS_ERROR_BUSY; + case WifiStatusCode.ERROR_UNKNOWN: + return WifiHal.WIFI_STATUS_ERROR_UNKNOWN; + default: + Log.e(TAG, "Invalid WifiStatusCode received: " + code); + return WifiHal.WIFI_STATUS_ERROR_UNKNOWN; + } + } + + protected android.hardware.wifi.V1_5.IWifi getWifiV1_5Mockable() { + return android.hardware.wifi.V1_5.IWifi.castFrom(mWifi); + } + + protected static IServiceManager getServiceManagerMockable() { + try { + return IServiceManager.getService(); + } catch (RemoteException e) { + Log.e(TAG, "Exception getting IServiceManager: " + e); + return null; + } + } + + protected IWifi getWifiServiceMockable() { + try { + return IWifi.getService(true /* retry */); + } catch (RemoteException e) { + Log.e(TAG, "Exception getting IWifi service: " + e); + return null; + } + } + + private boolean isOk(WifiStatus status, String methodStr) { + if (status.code == WifiStatusCode.SUCCESS) return true; + Log.e(TAG, methodStr + " failed with status: " + status); + return false; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + Log.e(TAG, methodStr + " failed with remote exception: " + e); + mWifi = null; + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifi == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifi is null"); + return defaultVal; + } + return supplier.get(); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiNanIface.java b/service/java/com/android/server/wifi/hal/WifiNanIface.java new file mode 100644 index 0000000000..1f89a9c96a --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiNanIface.java @@ -0,0 +1,701 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.MacAddress; +import android.net.wifi.aware.ConfigRequest; +import android.net.wifi.aware.PublishConfig; +import android.net.wifi.aware.SubscribeConfig; +import android.net.wifi.aware.WifiAwareChannelInfo; +import android.net.wifi.aware.WifiAwareDataPathSecurityConfig; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wifi.aware.Capabilities; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * Wrapper class for IWifiNanIface HAL calls. + */ +public class WifiNanIface implements WifiHal.WifiInterface { + private static final String TAG = "WifiNanIface"; + private IWifiNanIface mWifiNanIface; + + @VisibleForTesting + static final String SERVICE_NAME_FOR_OOB_DATA_PATH = "Wi-Fi Aware Data Path"; + + /** + * Event types for a cluster event indication. + */ + public static class NanClusterEventType { + public static final int DISCOVERY_MAC_ADDRESS_CHANGED = 0; + public static final int STARTED_CLUSTER = 1; + public static final int JOINED_CLUSTER = 2; + + /** + * Convert NanClusterEventType from HIDL to framework. + */ + public static int fromHidl(int code) { + switch (code) { + case android.hardware.wifi.V1_0.NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED: + return DISCOVERY_MAC_ADDRESS_CHANGED; + case android.hardware.wifi.V1_0.NanClusterEventType.STARTED_CLUSTER: + return STARTED_CLUSTER; + case android.hardware.wifi.V1_0.NanClusterEventType.JOINED_CLUSTER: + return JOINED_CLUSTER; + default: + Log.e(TAG, "Unknown NanClusterEventType received from HIDL: " + code); + return -1; + } + } + + /** + * Convert NanClusterEventType from AIDL to framework. + */ + public static int fromAidl(int code) { + switch (code) { + case android.hardware.wifi.NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED: + return DISCOVERY_MAC_ADDRESS_CHANGED; + case android.hardware.wifi.NanClusterEventType.STARTED_CLUSTER: + return STARTED_CLUSTER; + case android.hardware.wifi.NanClusterEventType.JOINED_CLUSTER: + return JOINED_CLUSTER; + default: + Log.e(TAG, "Unknown NanClusterEventType received from HIDL: " + code); + return -1; + } + } + } + + /** + * NAN DP (data-path) channel config options. + */ + public static class NanDataPathChannelCfg { + public static final int CHANNEL_NOT_REQUESTED = 0; + public static final int REQUEST_CHANNEL_SETUP = 1; + public static final int FORCE_CHANNEL_SETUP = 2; + + /** + * Convert NanDataPathChannelCfg from framework to HIDL. + */ + public static int toHidl(int code) { + switch (code) { + case CHANNEL_NOT_REQUESTED: + return android.hardware.wifi.V1_0.NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED; + case REQUEST_CHANNEL_SETUP: + return android.hardware.wifi.V1_0.NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP; + case FORCE_CHANNEL_SETUP: + return android.hardware.wifi.V1_0.NanDataPathChannelCfg.FORCE_CHANNEL_SETUP; + default: + Log.e(TAG, "Unknown NanDataPathChannelCfg received from framework: " + code); + return -1; + } + } + + /** + * Convert NanDataPathChannelCfg from framework to AIDL. + */ + public static int toAidl(int code) { + switch (code) { + case CHANNEL_NOT_REQUESTED: + return android.hardware.wifi.NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED; + case REQUEST_CHANNEL_SETUP: + return android.hardware.wifi.NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP; + case FORCE_CHANNEL_SETUP: + return android.hardware.wifi.NanDataPathChannelCfg.FORCE_CHANNEL_SETUP; + default: + Log.e(TAG, "Unknown NanDataPathChannelCfg received from framework: " + code); + return -1; + } + } + } + + /** + * Ranging in the context of discovery session indication controls. + */ + public static class NanRangingIndication { + public static final int CONTINUOUS_INDICATION_MASK = 1 << 0; + public static final int INGRESS_MET_MASK = 1 << 1; + public static final int EGRESS_MET_MASK = 1 << 2; + + /** + * Convert NanRangingIndication from HIDL to framework. + */ + public static int fromHidl(int rangingInd) { + int frameworkRangingInd = 0; + if ((android.hardware.wifi.V1_0.NanRangingIndication.CONTINUOUS_INDICATION_MASK + & rangingInd) != 0) { + frameworkRangingInd |= CONTINUOUS_INDICATION_MASK; + } + if ((android.hardware.wifi.V1_0.NanRangingIndication.INGRESS_MET_MASK + & rangingInd) != 0) { + frameworkRangingInd |= INGRESS_MET_MASK; + } + if ((android.hardware.wifi.V1_0.NanRangingIndication.EGRESS_MET_MASK + & rangingInd) != 0) { + frameworkRangingInd |= EGRESS_MET_MASK; + } + return frameworkRangingInd; + } + + /** + * Convert NanRangingIndication from AIDL to framework. + */ + public static int fromAidl(int rangingInd) { + int frameworkRangingInd = 0; + if ((android.hardware.wifi.NanRangingIndication.CONTINUOUS_INDICATION_MASK + & rangingInd) != 0) { + frameworkRangingInd |= CONTINUOUS_INDICATION_MASK; + } + if ((android.hardware.wifi.NanRangingIndication.INGRESS_MET_MASK + & rangingInd) != 0) { + frameworkRangingInd |= INGRESS_MET_MASK; + } + if ((android.hardware.wifi.NanRangingIndication.EGRESS_MET_MASK + & rangingInd) != 0) { + frameworkRangingInd |= EGRESS_MET_MASK; + } + return frameworkRangingInd; + } + } + + /** + * NAN API response codes used in request notifications and events. + */ + public static class NanStatusCode { + public static final int SUCCESS = 0; + public static final int INTERNAL_FAILURE = 1; + public static final int PROTOCOL_FAILURE = 2; + public static final int INVALID_SESSION_ID = 3; + public static final int NO_RESOURCES_AVAILABLE = 4; + public static final int INVALID_ARGS = 5; + public static final int INVALID_PEER_ID = 6; + public static final int INVALID_NDP_ID = 7; + public static final int NAN_NOT_ALLOWED = 8; + public static final int NO_OTA_ACK = 9; + public static final int ALREADY_ENABLED = 10; + public static final int FOLLOWUP_TX_QUEUE_FULL = 11; + public static final int UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12; + + /** + * Convert NanStatusCode from HIDL to framework. + */ + public static int fromHidl(int code) { + switch (code) { + case android.hardware.wifi.V1_0.NanStatusType.SUCCESS: + return SUCCESS; + case android.hardware.wifi.V1_0.NanStatusType.INTERNAL_FAILURE: + return INTERNAL_FAILURE; + case android.hardware.wifi.V1_0.NanStatusType.PROTOCOL_FAILURE: + return PROTOCOL_FAILURE; + case android.hardware.wifi.V1_0.NanStatusType.INVALID_SESSION_ID: + return INVALID_SESSION_ID; + case android.hardware.wifi.V1_0.NanStatusType.NO_RESOURCES_AVAILABLE: + return NO_RESOURCES_AVAILABLE; + case android.hardware.wifi.V1_0.NanStatusType.INVALID_ARGS: + return INVALID_ARGS; + case android.hardware.wifi.V1_0.NanStatusType.INVALID_PEER_ID: + return INVALID_PEER_ID; + case android.hardware.wifi.V1_0.NanStatusType.INVALID_NDP_ID: + return INVALID_NDP_ID; + case android.hardware.wifi.V1_0.NanStatusType.NAN_NOT_ALLOWED: + return NAN_NOT_ALLOWED; + case android.hardware.wifi.V1_0.NanStatusType.NO_OTA_ACK: + return NO_OTA_ACK; + case android.hardware.wifi.V1_0.NanStatusType.ALREADY_ENABLED: + return ALREADY_ENABLED; + case android.hardware.wifi.V1_0.NanStatusType.FOLLOWUP_TX_QUEUE_FULL: + return FOLLOWUP_TX_QUEUE_FULL; + case android.hardware.wifi.V1_0.NanStatusType.UNSUPPORTED_CONCURRENCY_NAN_DISABLED: + return UNSUPPORTED_CONCURRENCY_NAN_DISABLED; + default: + Log.e(TAG, "Unknown NanStatusType received from HIDL: " + code); + return -1; + } + } + + /** + * Convert NanStatusCode from AIDL to framework. + */ + public static int fromAidl(int code) { + switch (code) { + case android.hardware.wifi.NanStatusCode.SUCCESS: + return SUCCESS; + case android.hardware.wifi.NanStatusCode.INTERNAL_FAILURE: + return INTERNAL_FAILURE; + case android.hardware.wifi.NanStatusCode.PROTOCOL_FAILURE: + return PROTOCOL_FAILURE; + case android.hardware.wifi.NanStatusCode.INVALID_SESSION_ID: + return INVALID_SESSION_ID; + case android.hardware.wifi.NanStatusCode.NO_RESOURCES_AVAILABLE: + return NO_RESOURCES_AVAILABLE; + case android.hardware.wifi.NanStatusCode.INVALID_ARGS: + return INVALID_ARGS; + case android.hardware.wifi.NanStatusCode.INVALID_PEER_ID: + return INVALID_PEER_ID; + case android.hardware.wifi.NanStatusCode.INVALID_NDP_ID: + return INVALID_NDP_ID; + case android.hardware.wifi.NanStatusCode.NAN_NOT_ALLOWED: + return NAN_NOT_ALLOWED; + case android.hardware.wifi.NanStatusCode.NO_OTA_ACK: + return NO_OTA_ACK; + case android.hardware.wifi.NanStatusCode.ALREADY_ENABLED: + return ALREADY_ENABLED; + case android.hardware.wifi.NanStatusCode.FOLLOWUP_TX_QUEUE_FULL: + return FOLLOWUP_TX_QUEUE_FULL; + case android.hardware.wifi.NanStatusCode.UNSUPPORTED_CONCURRENCY_NAN_DISABLED: + return UNSUPPORTED_CONCURRENCY_NAN_DISABLED; + default: + Log.e(TAG, "Unknown NanStatusType received from AIDL: " + code); + return -1; + } + } + } + + /** + * Configuration parameters used in the call to enableAndConfigure. + */ + public static class PowerParameters { + public int discoveryWindow24Ghz; + public int discoveryWindow5Ghz; + public int discoveryWindow6Ghz; + public int discoveryBeaconIntervalMs; + public int numberOfSpatialStreamsInDiscovery; + public boolean enableDiscoveryWindowEarlyTermination; + } + + public WifiNanIface(@NonNull android.hardware.wifi.V1_0.IWifiNanIface nanIface) { + Log.i(TAG, "Creating WifiNanIface using the HIDL implementation"); + mWifiNanIface = createWifiNanIfaceHidlImplMockable(nanIface); + } + + public WifiNanIface(@NonNull android.hardware.wifi.IWifiNanIface nanIface) { + mWifiNanIface = createWifiNanIfaceAidlImplMockable(nanIface); + } + + protected WifiNanIfaceHidlImpl createWifiNanIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiNanIface nanIface) { + return new WifiNanIfaceHidlImpl(nanIface); + } + + protected WifiNanIfaceAidlImpl createWifiNanIfaceAidlImplMockable( + android.hardware.wifi.IWifiNanIface nanIface) { + return new WifiNanIfaceAidlImpl(nanIface); + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiNanIface == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiNanIface is null"); + return defaultVal; + } + return supplier.get(); + } + + /** + * Enable verbose logging. + */ + public void enableVerboseLogging(boolean verbose) { + if (mWifiNanIface != null) { + mWifiNanIface.enableVerboseLogging(verbose); + } + } + + /** + * See comments for {@link IWifiNanIface#getNanIface()} + * + * TODO: Remove this API. Will only be used temporarily until HalDeviceManager is refactored. + */ + public android.hardware.wifi.V1_0.IWifiNanIface getNanIface() { + return validateAndCall("getNanIface", null, + () -> mWifiNanIface.getNanIface()); + } + + /** + * See comments for {@link IWifiNanIface#registerFrameworkCallback(Callback)} + */ + public boolean registerFrameworkCallback(Callback cb) { + return validateAndCall("registerFrameworkCallback", false, + () -> mWifiNanIface.registerFrameworkCallback(cb)); + } + + /** + * See comments for {@link IWifiNanIface#getName()} + */ + @Override + @Nullable + public String getName() { + return validateAndCall("getName", null, + () -> mWifiNanIface.getName()); + } + + /** + * See comments for {@link IWifiNanIface#getCapabilities(short)} + */ + public boolean getCapabilities(short transactionId) { + return validateAndCall("getCapabilities", false, + () -> mWifiNanIface.getCapabilities(transactionId)); + } + + /** + * See comments for {@link IWifiNanIface#enableAndConfigure(short, ConfigRequest, boolean, + * boolean, boolean, boolean, int, int, PowerParameters)} + */ + public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest, + boolean notifyIdentityChange, boolean initialConfiguration, boolean rangingEnabled, + boolean isInstantCommunicationEnabled, int instantModeChannel, + int macAddressRandomizationIntervalSec, PowerParameters powerParameters) { + return validateAndCall("enableAndConfigure", false, + () -> mWifiNanIface.enableAndConfigure(transactionId, configRequest, + notifyIdentityChange, initialConfiguration, rangingEnabled, + isInstantCommunicationEnabled, instantModeChannel, + macAddressRandomizationIntervalSec, powerParameters)); + } + + /** + * See comments for {@link IWifiNanIface#disable(short)} + */ + public boolean disable(short transactionId) { + return validateAndCall("disable", false, + () -> mWifiNanIface.disable(transactionId)); + } + + /** + * See comments for {@link IWifiNanIface#publish(short, byte, PublishConfig)} + */ + public boolean publish(short transactionId, byte publishId, PublishConfig publishConfig) { + return validateAndCall("publish", false, + () -> mWifiNanIface.publish(transactionId, publishId, publishConfig)); + } + + /** + * See comments for {@link IWifiNanIface#subscribe(short, byte, SubscribeConfig)} + */ + public boolean subscribe(short transactionId, byte subscribeId, + SubscribeConfig subscribeConfig) { + return validateAndCall("subscribe", false, + () -> mWifiNanIface.subscribe(transactionId, subscribeId, subscribeConfig)); + } + + /** + * See comments for {@link IWifiNanIface#sendMessage(short, byte, int, MacAddress, byte[])} + */ + public boolean sendMessage(short transactionId, byte pubSubId, int requestorInstanceId, + MacAddress dest, byte[] message) { + return validateAndCall("sendMessage", false, + () -> mWifiNanIface.sendMessage(transactionId, pubSubId, requestorInstanceId, + dest, message)); + } + + /** + * See comments for {@link IWifiNanIface#stopPublish(short, byte)} + */ + public boolean stopPublish(short transactionId, byte pubSubId) { + return validateAndCall("stopPublish", false, + () -> mWifiNanIface.stopPublish(transactionId, pubSubId)); + } + + /** + * See comments for {@link IWifiNanIface#stopSubscribe(short, byte)} + */ + public boolean stopSubscribe(short transactionId, byte pubSubId) { + return validateAndCall("stopSubscribe", false, + () -> mWifiNanIface.stopSubscribe(transactionId, pubSubId)); + } + + /** + * See comments for {@link IWifiNanIface#createAwareNetworkInterface(short, String)} + */ + public boolean createAwareNetworkInterface(short transactionId, String interfaceName) { + return validateAndCall("createAwareNetworkInterface", false, + () -> mWifiNanIface.createAwareNetworkInterface(transactionId, interfaceName)); + } + + /** + * See comments for {@link IWifiNanIface#deleteAwareNetworkInterface(short, String)} + */ + public boolean deleteAwareNetworkInterface(short transactionId, String interfaceName) { + return validateAndCall("deleteAwareNetworkInterface", false, + () -> mWifiNanIface.deleteAwareNetworkInterface(transactionId, interfaceName)); + } + + /** + * See comments for {@link IWifiNanIface#initiateDataPath(short, int, int, int, MacAddress, + * String, boolean, byte[], Capabilities, + * WifiAwareDataPathSecurityConfig)} + */ + public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, + int channel, MacAddress peer, String interfaceName, + boolean isOutOfBand, byte[] appInfo, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig) { + return validateAndCall("initiateDataPath", false, + () -> mWifiNanIface.initiateDataPath(transactionId, peerId, channelRequestType, + channel, peer, interfaceName, isOutOfBand, appInfo, capabilities, + securityConfig)); + } + + /** + * See comments for {@link IWifiNanIface#respondToDataPathRequest(short, boolean, int, String, + * byte[], boolean, Capabilities, WifiAwareDataPathSecurityConfig)} + */ + public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, + String interfaceName, byte[] appInfo, + boolean isOutOfBand, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig) { + return validateAndCall("respondToDataPathRequest", false, + () -> mWifiNanIface.respondToDataPathRequest(transactionId, accept, ndpId, + interfaceName, appInfo, isOutOfBand, capabilities, securityConfig)); + } + + /** + * See comments for {@link IWifiNanIface#endDataPath(short, int)} + */ + public boolean endDataPath(short transactionId, int ndpId) { + return validateAndCall("endDataPath", false, + () -> mWifiNanIface.endDataPath(transactionId, ndpId)); + } + + /** + * Framework callback object. Will get called when the equivalent events are received + * from the HAL. + */ + public interface Callback { + /** + * Invoked in response to a capability request. + * @param id ID corresponding to the original request. + * @param capabilities Capability data. + */ + void notifyCapabilitiesResponse(short id, Capabilities capabilities); + + /** + * Invoked in response to an enable request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyEnableResponse(short id, int status); + + /** + * Invoked in response to a config request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyConfigResponse(short id, int status); + + /** + * Invoked in response to a disable request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyDisableResponse(short id, int status); + + /** + * Invoked to notify the status of the start publish request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + * @param publishId + */ + void notifyStartPublishResponse(short id, int status, byte publishId); + + /** + * Invoked to notify the status of the start subscribe request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + * @param subscribeId ID of the new subscribe session (if successfully created). + */ + void notifyStartSubscribeResponse(short id, int status, byte subscribeId); + + /** + * Invoked in response to a transmit followup request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyTransmitFollowupResponse(short id, int status); + + /** + * Invoked in response to a create data interface request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyCreateDataInterfaceResponse(short id, int status); + + /** + * Invoked in response to a delete data interface request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyDeleteDataInterfaceResponse(short id, int status); + + /** + * Invoked in response to a delete data interface request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + * @param ndpInstanceId + */ + void notifyInitiateDataPathResponse(short id, int status, int ndpInstanceId); + + /** + * Invoked in response to a respond to data path indication request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyRespondToDataPathIndicationResponse(short id, int status); + + /** + * Invoked in response to a terminate data path request. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void notifyTerminateDataPathResponse(short id, int status); + + /** + * Indicates that a cluster event has been received. + * @param eventType Type of the cluster event (see {@link NanClusterEventType}). + * @param addr MAC Address associated with the corresponding event. + */ + void eventClusterEvent(int eventType, byte[] addr); + + /** + * Indicates that a NAN has been disabled. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void eventDisabled(int status); + + /** + * Indicates that an active publish session has terminated. + * @param sessionId Discovery session ID of the terminated session. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void eventPublishTerminated(byte sessionId, int status); + + /** + * Indicates that an active subscribe session has terminated. + * @param sessionId Discovery session ID of the terminated session. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void eventSubscribeTerminated(byte sessionId, int status); + + /** + * Indicates that a match has occurred - i.e. a service has been discovered. + * @param discoverySessionId Publish or subscribe discovery session ID of an existing + * discovery session. + * @param peerId Unique ID of the peer. Can be used subsequently in sendMessage() + * or to set up a data-path. + * @param addr NAN Discovery (management) MAC address of the peer. + * @param serviceSpecificInfo The arbitrary information contained in the + * |NanDiscoveryCommonConfig.serviceSpecificInfo| of + * the peer's discovery session configuration. + * @param matchFilter The match filter from the discovery packet (publish or subscribe) + * which caused service discovery. Matches the + * |NanDiscoveryCommonConfig.txMatchFilter| of the peer's unsolicited + * publish message or of the local device's Active subscribe message. + * @param rangingIndicationType The ranging event(s) which triggered the ranging. Ex. can + * indicate that continuous ranging was requested, or else that + * an ingress event occurred. See {@link NanRangingIndication}. + * @param rangingMeasurementInMm If ranging was required and executed, contains the + * distance to the peer in mm. + * @param scid Security Context Identifier identifies the Security Context. + * For NAN Shared Key Cipher Suite, this field contains the 16 octet PMKID + * identifying the PMK used for setting up the Secure Data Path. + * @param peerCipherType Cipher type for data-paths constructed in the context of this + * discovery session. + */ + void eventMatch(byte discoverySessionId, int peerId, byte[] addr, + byte[] serviceSpecificInfo, byte[] matchFilter, int rangingIndicationType, + int rangingMeasurementInMm, byte[] scid, int peerCipherType); + + /** + * Indicates that a previously discovered match (service) has expired. + * @param discoverySessionId Discovery session ID of the expired match. + * @param peerId Peer ID of the expired match. + */ + void eventMatchExpired(byte discoverySessionId, int peerId); + + /** + * Indicates that a followup message has been received from a peer. + * @param discoverySessionId Discovery session (publish or subscribe) ID of a previously + * created discovery session. + * @param peerId Unique ID of the peer. + * @param addr NAN Discovery (management) MAC address of the peer. + * @param serviceSpecificInfo Received message from the peer. There is no semantic + * meaning to these bytes. They are passed-through from sender + * to receiver as-is with no parsing. + */ + void eventFollowupReceived(byte discoverySessionId, int peerId, byte[] addr, + byte[] serviceSpecificInfo); + + /** + * Provides status of a completed followup message transmit operation. + * @param id ID corresponding to the original request. + * @param status Status the operation (see {@link NanStatusCode}). + */ + void eventTransmitFollowup(short id, int status); + + /** + * Indicates that a data-path (NDP) setup has been requested by an initiator peer + * (received by the intended responder). + * @param discoverySessionId ID of an active publish or subscribe discovery session. + * @param peerDiscMacAddr MAC address of the Initiator peer. This is the MAC address of + * the peer's management/discovery NAN interface. + * @param ndpInstanceId ID of the data-path. Used to identify the data-path in further + * negotiation/APIs. + * @param appInfo Arbitrary information communicated from the peer as part of the + * data-path setup process. There is no semantic meaning to these bytes. + * They are passed from sender to receiver as-is with no parsing. + */ + void eventDataPathRequest(byte discoverySessionId, byte[] peerDiscMacAddr, + int ndpInstanceId, byte[] appInfo); + + /** + * Indicates that a data-path (NDP) setup has been completed. Received by both the + * Initiator and Responder. + * @param status Status the operation (see {@link NanStatusCode}). + * @param ndpInstanceId ID of the data-path. + * @param dataPathSetupSuccess Indicates whether the data-path setup succeeded (true) + * or failed (false). + * @param peerNdiMacAddr MAC address of the peer's data-interface (not its + * management/discovery interface). + * @param appInfo Arbitrary information communicated from the peer as part of the + * data-path setup process. There is no semantic meaning to these bytes. + * They are passed from sender to receiver as-is with no parsing. + * @param channelInfos + */ + void eventDataPathConfirm(int status, int ndpInstanceId, boolean dataPathSetupSuccess, + byte[] peerNdiMacAddr, byte[] appInfo, List<WifiAwareChannelInfo> channelInfos); + + /** + * Indicates that a data-path (NDP) schedule has been updated (ex. channels + * have been changed). + * @param peerDiscoveryAddress Discovery address (NMI) of the peer to which the NDP + * is connected. + * @param ndpInstanceIds List of NDPs to which this update applies. + * @param channelInfo Updated channel(s) information. + */ + void eventDataPathScheduleUpdate(byte[] peerDiscoveryAddress, + ArrayList<Integer> ndpInstanceIds, List<WifiAwareChannelInfo> channelInfo); + + /** + * Indicates that a list of data-paths (NDP) have been terminated. Received by both the + * Initiator and Responder. + * @param ndpInstanceId Data-path ID of the terminated data-path. + */ + void eventDataPathTerminated(int ndpInstanceId); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java new file mode 100644 index 0000000000..656dfd3685 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java @@ -0,0 +1,843 @@ +/* + * Copyright (C) 2022 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.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_SK_128; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.hardware.wifi.NanBandIndex; +import android.hardware.wifi.NanBandSpecificConfig; +import android.hardware.wifi.NanCipherSuiteType; +import android.hardware.wifi.NanConfigRequest; +import android.hardware.wifi.NanConfigRequestSupplemental; +import android.hardware.wifi.NanDataPathSecurityConfig; +import android.hardware.wifi.NanDataPathSecurityType; +import android.hardware.wifi.NanDebugConfig; +import android.hardware.wifi.NanDiscoveryCommonConfig; +import android.hardware.wifi.NanEnableRequest; +import android.hardware.wifi.NanInitiateDataPathRequest; +import android.hardware.wifi.NanMatchAlg; +import android.hardware.wifi.NanPublishRequest; +import android.hardware.wifi.NanRangingIndication; +import android.hardware.wifi.NanRespondToDataPathIndicationRequest; +import android.hardware.wifi.NanSubscribeRequest; +import android.hardware.wifi.NanTransmitFollowupRequest; +import android.hardware.wifi.NanTxType; +import android.net.MacAddress; +import android.net.wifi.aware.ConfigRequest; +import android.net.wifi.aware.PublishConfig; +import android.net.wifi.aware.SubscribeConfig; +import android.net.wifi.aware.WifiAwareDataPathSecurityConfig; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.util.Log; + +import com.android.server.wifi.aware.Capabilities; + +import java.nio.charset.StandardCharsets; + +/** + * AIDL implementation of the IWifiNanIface interface. + */ +public class WifiNanIfaceAidlImpl implements IWifiNanIface { + private static final String TAG = "WifiNanIfaceAidlImpl"; + private android.hardware.wifi.IWifiNanIface mWifiNanIface; + private String mIfaceName; + private final Object mLock = new Object(); + private WifiNanIfaceCallbackAidlImpl mHalCallback; + private WifiNanIface.Callback mFrameworkCallback; + + public WifiNanIfaceAidlImpl(@NonNull android.hardware.wifi.IWifiNanIface nanIface) { + mWifiNanIface = nanIface; + mHalCallback = new WifiNanIfaceCallbackAidlImpl(this); + } + + /** + * Enable verbose logging. + */ + @Override + public void enableVerboseLogging(boolean verbose) { + synchronized (mLock) { + if (mHalCallback != null) { + mHalCallback.enableVerboseLogging(verbose); + } + } + } + + protected WifiNanIface.Callback getFrameworkCallback() { + return mFrameworkCallback; + } + + /** + * See comments for {@link IWifiNanIface#getNanIface()} + * + * TODO: Remove this API. Will only be used temporarily until HalDeviceManager is refactored. + */ + @Override + public android.hardware.wifi.V1_0.IWifiNanIface getNanIface() { + return null; + } + + /** + * See comments for {@link IWifiNanIface#registerFrameworkCallback(WifiNanIface.Callback)} + */ + @Override + public boolean registerFrameworkCallback(WifiNanIface.Callback callback) { + final String methodStr = "registerFrameworkCallback"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return false; + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (callback == null) { + Log.e(TAG, "Cannot register a null framework callback"); + return false; + } + + try { + mWifiNanIface.registerEventCallback(mHalCallback); + mFrameworkCallback = callback; + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#getName()} + */ + @Override + @Nullable + public String getName() { + final String methodStr = "getName"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return null; + if (mIfaceName != null) return mIfaceName; + try { + String ifaceName = mWifiNanIface.getName(); + mIfaceName = ifaceName; + return mIfaceName; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiNanIface#getCapabilities(short)} + */ + @Override + public boolean getCapabilities(short transactionId) { + final String methodStr = "getCapabilities"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiNanIface.getCapabilitiesRequest((char) transactionId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#enableAndConfigure(short, ConfigRequest, boolean, + * boolean, boolean, boolean, int, int, WifiNanIface.PowerParameters)} + */ + @Override + public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest, + boolean notifyIdentityChange, boolean initialConfiguration, boolean rangingEnabled, + boolean isInstantCommunicationEnabled, int instantModeChannel, + int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) { + final String methodStr = "enableAndConfigure"; + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + NanConfigRequestSupplemental supplemental = createNanConfigRequestSupplemental( + rangingEnabled, isInstantCommunicationEnabled, instantModeChannel); + if (initialConfiguration) { + NanEnableRequest req = createNanEnableRequest( + configRequest, notifyIdentityChange, supplemental, + macAddressRandomizationIntervalSec, powerParameters); + mWifiNanIface.enableRequest((char) transactionId, req, supplemental); + } else { + NanConfigRequest req = createNanConfigRequest( + configRequest, notifyIdentityChange, supplemental, + macAddressRandomizationIntervalSec, powerParameters); + mWifiNanIface.configRequest((char) transactionId, req, supplemental); + } + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + + /** + * See comments for {@link IWifiNanIface#disable(short)} + */ + @Override + public boolean disable(short transactionId) { + final String methodStr = "disable"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiNanIface.disableRequest((char) transactionId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#publish(short, byte, PublishConfig)} + */ + @Override + public boolean publish(short transactionId, byte publishId, PublishConfig publishConfig) { + final String methodStr = "publish"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + NanPublishRequest req = createNanPublishRequest(publishId, publishConfig); + mWifiNanIface.startPublishRequest((char) transactionId, req); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#subscribe(short, byte, SubscribeConfig)} + */ + @Override + public boolean subscribe(short transactionId, byte subscribeId, + SubscribeConfig subscribeConfig) { + final String methodStr = "subscribe"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + NanSubscribeRequest req = createNanSubscribeRequest(subscribeId, subscribeConfig); + mWifiNanIface.startSubscribeRequest((char) transactionId, req); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#sendMessage(short, byte, int, MacAddress, byte[])} + */ + @Override + public boolean sendMessage(short transactionId, byte pubSubId, int requesterInstanceId, + MacAddress dest, byte[] message) { + final String methodStr = "sendMessage"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + NanTransmitFollowupRequest req = createNanTransmitFollowupRequest( + pubSubId, requesterInstanceId, dest, message); + mWifiNanIface.transmitFollowupRequest((char) transactionId, req); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#stopPublish(short, byte)} + */ + @Override + public boolean stopPublish(short transactionId, byte pubSubId) { + final String methodStr = "stopPublish"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiNanIface.stopPublishRequest((char) transactionId, pubSubId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#stopSubscribe(short, byte)} + */ + @Override + public boolean stopSubscribe(short transactionId, byte pubSubId) { + final String methodStr = "stopSubscribe"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiNanIface.stopSubscribeRequest((char) transactionId, pubSubId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#createAwareNetworkInterface(short, String)} + */ + @Override + public boolean createAwareNetworkInterface(short transactionId, String interfaceName) { + final String methodStr = "createAwareNetworkInterface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiNanIface.createDataInterfaceRequest((char) transactionId, interfaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#deleteAwareNetworkInterface(short, String)} + */ + @Override + public boolean deleteAwareNetworkInterface(short transactionId, String interfaceName) { + final String methodStr = "deleteAwareNetworkInterface"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiNanIface.deleteDataInterfaceRequest((char) transactionId, interfaceName); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#initiateDataPath(short, int, int, int, MacAddress, + * String, boolean, byte[], Capabilities, + * WifiAwareDataPathSecurityConfig)} + */ + @Override + public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, + int channel, MacAddress peer, String interfaceName, + boolean isOutOfBand, byte[] appInfo, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig) { + final String methodStr = "initiateDataPath"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + NanInitiateDataPathRequest req = createNanInitiateDataPathRequest( + peerId, channelRequestType, channel, peer, interfaceName, isOutOfBand, + appInfo, securityConfig); + mWifiNanIface.initiateDataPathRequest((char) transactionId, req); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#respondToDataPathRequest(short, boolean, int, String, + * byte[], boolean, Capabilities, WifiAwareDataPathSecurityConfig)} + */ + @Override + public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, + String interfaceName, byte[] appInfo, boolean isOutOfBand, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig) { + final String methodStr = "respondToDataPathRequest"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + NanRespondToDataPathIndicationRequest req = + createNanRespondToDataPathIndicationRequest( + accept, ndpId, interfaceName, appInfo, isOutOfBand, + securityConfig); + mWifiNanIface.respondToDataPathIndicationRequest((char) transactionId, req); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiNanIface#endDataPath(short, int)} + */ + @Override + public boolean endDataPath(short transactionId, int ndpId) { + final String methodStr = "endDataPath"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiNanIface.terminateDataPathRequest((char) transactionId, ndpId); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + + // Utilities + + private static NanConfigRequestSupplemental createNanConfigRequestSupplemental( + boolean rangingEnabled, boolean isInstantCommunicationEnabled, int instantModeChannel) { + NanConfigRequestSupplemental out = new NanConfigRequestSupplemental(); + out.discoveryBeaconIntervalMs = 0; + out.numberOfSpatialStreamsInDiscovery = 0; + out.enableDiscoveryWindowEarlyTermination = false; + out.enableRanging = rangingEnabled; + out.enableInstantCommunicationMode = isInstantCommunicationEnabled; + out.instantModeChannel = instantModeChannel; + return out; + } + + private static NanBandSpecificConfig[] createNanBandSpecificConfigs( + ConfigRequest configRequest) { + NanBandSpecificConfig config24 = new NanBandSpecificConfig(); + config24.rssiClose = 60; + config24.rssiMiddle = 70; + config24.rssiCloseProximity = 60; + config24.dwellTimeMs = 200; + config24.scanPeriodSec = 20; + if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ] + == ConfigRequest.DW_INTERVAL_NOT_INIT) { + config24.validDiscoveryWindowIntervalVal = false; + } else { + config24.validDiscoveryWindowIntervalVal = true; + config24.discoveryWindowIntervalVal = + (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ]; + } + + NanBandSpecificConfig config5 = new NanBandSpecificConfig(); + config5.rssiClose = 60; + config5.rssiMiddle = 75; + config5.rssiCloseProximity = 60; + config5.dwellTimeMs = 200; + config5.scanPeriodSec = 20; + if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ] + == ConfigRequest.DW_INTERVAL_NOT_INIT) { + config5.validDiscoveryWindowIntervalVal = false; + } else { + config5.validDiscoveryWindowIntervalVal = true; + config5.discoveryWindowIntervalVal = + (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ]; + } + + NanBandSpecificConfig config6 = new NanBandSpecificConfig(); + config6.rssiClose = 60; + config6.rssiMiddle = 75; + config6.rssiCloseProximity = 60; + config6.dwellTimeMs = 200; + config6.scanPeriodSec = 20; + if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_6GHZ] + == ConfigRequest.DW_INTERVAL_NOT_INIT) { + config6.validDiscoveryWindowIntervalVal = false; + } else { + config6.validDiscoveryWindowIntervalVal = true; + config6.discoveryWindowIntervalVal = + (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_6GHZ]; + } + + return new NanBandSpecificConfig[]{config24, config5, config6}; + } + + private static NanEnableRequest createNanEnableRequest( + ConfigRequest configRequest, boolean notifyIdentityChange, + NanConfigRequestSupplemental configSupplemental, + int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) { + NanEnableRequest req = new NanEnableRequest(); + NanBandSpecificConfig[] nanBandSpecificConfigs = + createNanBandSpecificConfigs(configRequest); + + req.operateInBand = new boolean[3]; + req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; + req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; + req.operateInBand[NanBandIndex.NAN_BAND_6GHZ] = configRequest.mSupport6gBand; + req.hopCountMax = 2; + req.configParams = new NanConfigRequest(); + req.configParams.masterPref = (byte) configRequest.mMasterPreference; + req.configParams.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; + req.configParams.disableStartedClusterIndication = !notifyIdentityChange; + req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; + req.configParams.includePublishServiceIdsInBeacon = true; + req.configParams.numberOfPublishServiceIdsInBeacon = 0; + req.configParams.includeSubscribeServiceIdsInBeacon = true; + req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; + req.configParams.rssiWindowSize = 8; + req.configParams.macAddressRandomizationIntervalSec = macAddressRandomizationIntervalSec; + + req.configParams.bandSpecificConfig = new NanBandSpecificConfig[3]; + req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = + nanBandSpecificConfigs[0]; + req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = nanBandSpecificConfigs[1]; + req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_6GHZ] = nanBandSpecificConfigs[2]; + + req.debugConfigs = new NanDebugConfig(); + req.debugConfigs.validClusterIdVals = true; + req.debugConfigs.clusterIdTopRangeVal = (char) configRequest.mClusterHigh; + req.debugConfigs.clusterIdBottomRangeVal = (char) configRequest.mClusterLow; + req.debugConfigs.validIntfAddrVal = false; + req.debugConfigs.validOuiVal = false; + req.debugConfigs.ouiVal = 0; + req.debugConfigs.validRandomFactorForceVal = false; + req.debugConfigs.randomFactorForceVal = 0; + req.debugConfigs.validHopCountForceVal = false; + req.debugConfigs.hopCountForceVal = 0; + req.debugConfigs.validDiscoveryChannelVal = false; + req.debugConfigs.discoveryChannelMhzVal = new int[3]; + req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; + req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; + req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_6GHZ] = 0; + req.debugConfigs.validUseBeaconsInBandVal = false; + req.debugConfigs.useBeaconsInBandVal = new boolean[3]; + req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; + req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; + req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_6GHZ] = true; + req.debugConfigs.validUseSdfInBandVal = false; + req.debugConfigs.useSdfInBandVal = new boolean[3]; + req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; + req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; + req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_6GHZ] = true; + updateConfigForPowerSettings(req.configParams, configSupplemental, powerParameters); + return req; + } + + private static NanConfigRequest createNanConfigRequest( + ConfigRequest configRequest, boolean notifyIdentityChange, + NanConfigRequestSupplemental configSupplemental, + int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) { + NanConfigRequest req = new NanConfigRequest(); + NanBandSpecificConfig[] nanBandSpecificConfigs = + createNanBandSpecificConfigs(configRequest); + + req.masterPref = (byte) configRequest.mMasterPreference; + req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; + req.disableStartedClusterIndication = !notifyIdentityChange; + req.disableJoinedClusterIndication = !notifyIdentityChange; + req.includePublishServiceIdsInBeacon = true; + req.numberOfPublishServiceIdsInBeacon = 0; + req.includeSubscribeServiceIdsInBeacon = true; + req.numberOfSubscribeServiceIdsInBeacon = 0; + req.rssiWindowSize = 8; + req.macAddressRandomizationIntervalSec = macAddressRandomizationIntervalSec; + + req.bandSpecificConfig = new NanBandSpecificConfig[3]; + req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = nanBandSpecificConfigs[0]; + req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = nanBandSpecificConfigs[1]; + req.bandSpecificConfig[NanBandIndex.NAN_BAND_6GHZ] = nanBandSpecificConfigs[2]; + updateConfigForPowerSettings(req, configSupplemental, powerParameters); + return req; + } + + /** + * Update the NAN configuration to reflect the current power settings + */ + private static void updateConfigForPowerSettings(NanConfigRequest req, + NanConfigRequestSupplemental configSupplemental, + WifiNanIface.PowerParameters powerParameters) { + updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], + powerParameters.discoveryWindow5Ghz); + updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], + powerParameters.discoveryWindow24Ghz); + updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_6GHZ], + powerParameters.discoveryWindow6Ghz); + + configSupplemental.discoveryBeaconIntervalMs = powerParameters.discoveryBeaconIntervalMs; + configSupplemental.numberOfSpatialStreamsInDiscovery = + powerParameters.numberOfSpatialStreamsInDiscovery; + configSupplemental.enableDiscoveryWindowEarlyTermination = + powerParameters.enableDiscoveryWindowEarlyTermination; + } + + private static void updateSingleConfigForPowerSettings( + NanBandSpecificConfig cfg, int override) { + if (override != -1) { + cfg.validDiscoveryWindowIntervalVal = true; + cfg.discoveryWindowIntervalVal = (byte) override; + } + } + + private static NanPublishRequest createNanPublishRequest( + byte publishId, PublishConfig publishConfig) { + NanPublishRequest req = new NanPublishRequest(); + req.baseConfigs = new NanDiscoveryCommonConfig(); + req.baseConfigs.sessionId = publishId; + req.baseConfigs.ttlSec = (char) publishConfig.mTtlSec; + req.baseConfigs.discoveryWindowPeriod = 1; + req.baseConfigs.discoveryCount = 0; + req.baseConfigs.serviceName = publishConfig.mServiceName; + req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER; + req.baseConfigs.serviceSpecificInfo = publishConfig.mServiceSpecificInfo; + if (publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED) { + req.baseConfigs.txMatchFilter = publishConfig.mMatchFilter; + req.baseConfigs.rxMatchFilter = new byte[0]; + } else { + req.baseConfigs.rxMatchFilter = publishConfig.mMatchFilter; + req.baseConfigs.txMatchFilter = new byte[0]; + } + req.baseConfigs.useRssiThreshold = false; + req.baseConfigs.disableDiscoveryTerminationIndication = + !publishConfig.mEnableTerminateNotification; + req.baseConfigs.disableMatchExpirationIndication = true; + req.baseConfigs.disableFollowupReceivedIndication = false; + + req.autoAcceptDataPathRequests = false; + + req.baseConfigs.rangingRequired = publishConfig.mEnableRanging; + + req.baseConfigs.securityConfig = new NanDataPathSecurityConfig(); + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; + WifiAwareDataPathSecurityConfig securityConfig = publishConfig.getSecurityConfig(); + if (securityConfig != null) { + req.baseConfigs.securityConfig.cipherType = getHalCipherSuiteType( + securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PMK; + req.baseConfigs.securityConfig.pmk = copyArray(securityConfig.getPmk()); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; + req.baseConfigs.securityConfig.passphrase = + securityConfig.getPskPassphrase().getBytes(); + } + if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { + req.baseConfigs.securityConfig.scid = copyArray(securityConfig.getPmkId()); + } + } + + req.publishType = publishConfig.mPublishType; + req.txType = NanTxType.BROADCAST; + return req; + } + + private static NanSubscribeRequest createNanSubscribeRequest( + byte subscribeId, SubscribeConfig subscribeConfig) { + NanSubscribeRequest req = new NanSubscribeRequest(); + req.baseConfigs = new NanDiscoveryCommonConfig(); + req.baseConfigs.sessionId = subscribeId; + req.baseConfigs.ttlSec = (char) subscribeConfig.mTtlSec; + req.baseConfigs.discoveryWindowPeriod = 1; + req.baseConfigs.discoveryCount = 0; + req.baseConfigs.serviceName = subscribeConfig.mServiceName; + req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_ONCE; + req.baseConfigs.serviceSpecificInfo = subscribeConfig.mServiceSpecificInfo; + if (subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE) { + req.baseConfigs.txMatchFilter = subscribeConfig.mMatchFilter; + req.baseConfigs.rxMatchFilter = new byte[0]; + } else { + req.baseConfigs.rxMatchFilter = subscribeConfig.mMatchFilter; + req.baseConfigs.txMatchFilter = new byte[0]; + } + req.baseConfigs.useRssiThreshold = false; + req.baseConfigs.disableDiscoveryTerminationIndication = + !subscribeConfig.mEnableTerminateNotification; + req.baseConfigs.disableMatchExpirationIndication = false; + req.baseConfigs.disableFollowupReceivedIndication = false; + + req.baseConfigs.rangingRequired = + subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet; + req.baseConfigs.configRangingIndications = 0; + if (subscribeConfig.mMinDistanceMmSet) { + req.baseConfigs.distanceEgressCm = (char) Math.min( + subscribeConfig.mMinDistanceMm / 10, Short.MAX_VALUE); + req.baseConfigs.configRangingIndications |= NanRangingIndication.EGRESS_MET_MASK; + } + if (subscribeConfig.mMaxDistanceMmSet) { + req.baseConfigs.distanceIngressCm = (char) Math.min( + subscribeConfig.mMaxDistanceMm / 10, Short.MAX_VALUE); + req.baseConfigs.configRangingIndications |= NanRangingIndication.INGRESS_MET_MASK; + } + + // TODO: configure security + req.baseConfigs.securityConfig = new NanDataPathSecurityConfig(); + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; + + req.subscribeType = subscribeConfig.mSubscribeType; + return req; + } + + private static NanTransmitFollowupRequest createNanTransmitFollowupRequest( + byte pubSubId, int requesterInstanceId, MacAddress dest, byte[] message) { + NanTransmitFollowupRequest req = new NanTransmitFollowupRequest(); + req.discoverySessionId = pubSubId; + req.peerId = requesterInstanceId; + req.addr = dest.toByteArray(); + req.isHighPriority = false; + req.shouldUseDiscoveryWindow = true; + req.serviceSpecificInfo = message; + req.disableFollowupResultIndication = false; + return req; + } + + private static NanInitiateDataPathRequest createNanInitiateDataPathRequest( + int peerId, int channelRequestType, int channel, MacAddress peer, String interfaceName, + boolean isOutOfBand, byte[] appInfo, WifiAwareDataPathSecurityConfig securityConfig) { + NanInitiateDataPathRequest req = new NanInitiateDataPathRequest(); + req.peerId = peerId; + req.peerDiscMacAddr = peer.toByteArray(); + req.channelRequestType = WifiNanIface.NanDataPathChannelCfg.toAidl(channelRequestType); + req.channel = channel; + req.ifaceName = interfaceName; + req.securityConfig = new NanDataPathSecurityConfig(); + req.securityConfig.securityType = NanDataPathSecurityType.OPEN; + if (securityConfig != null) { + req.securityConfig.cipherType = getHalCipherSuiteType(securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PMK; + req.securityConfig.pmk = copyArray(securityConfig.getPmk()); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; + req.securityConfig.passphrase = securityConfig.getPskPassphrase().getBytes(); + } + if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { + req.securityConfig.scid = copyArray(securityConfig.getPmkId()); + } + } + + if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { + req.serviceNameOutOfBand = WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH + .getBytes(StandardCharsets.UTF_8); + } + req.appInfo = appInfo; + return req; + } + + private static NanRespondToDataPathIndicationRequest + createNanRespondToDataPathIndicationRequest(boolean accept, int ndpId, + String interfaceName, byte[] appInfo, boolean isOutOfBand, + WifiAwareDataPathSecurityConfig securityConfig) { + NanRespondToDataPathIndicationRequest req = new NanRespondToDataPathIndicationRequest(); + req.acceptRequest = accept; + req.ndpInstanceId = ndpId; + req.ifaceName = interfaceName; + req.securityConfig = new NanDataPathSecurityConfig(); + req.securityConfig.securityType = NanDataPathSecurityType.OPEN; + if (securityConfig != null) { + req.securityConfig.cipherType = getHalCipherSuiteType(securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PMK; + req.securityConfig.pmk = copyArray(securityConfig.getPmk()); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; + req.securityConfig.passphrase = securityConfig.getPskPassphrase().getBytes(); + } + if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { + req.securityConfig.scid = copyArray(securityConfig.getPmkId()); + } + } + + if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { + req.serviceNameOutOfBand = WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH + .getBytes(StandardCharsets.UTF_8); + } + req.appInfo = appInfo; + 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_128_MASK; + case WIFI_AWARE_CIPHER_SUITE_NCS_PK_256: + return NanCipherSuiteType.PUBLIC_KEY_256_MASK; + } + return NanCipherSuiteType.NONE; + } + + private static byte[] copyArray(byte[] source) { + return source != null ? source.clone() : new byte[0]; + } + + private boolean checkIfaceAndLogFailure(String methodStr) { + if (mWifiNanIface == null) { + Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); + return false; + } + return true; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + mWifiNanIface = null; + mIfaceName = null; + Log.e(TAG, methodStr + " failed with remote exception: " + e); + } + + private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { + Log.e(TAG, methodStr + " failed with service-specific exception: " + e); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java new file mode 100644 index 0000000000..80cfe43ae6 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java @@ -0,0 +1,514 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.hardware.wifi.IWifiNanIfaceEventCallback; +import android.hardware.wifi.NanCapabilities; +import android.hardware.wifi.NanCipherSuiteType; +import android.hardware.wifi.NanClusterEventInd; +import android.hardware.wifi.NanDataPathChannelInfo; +import android.hardware.wifi.NanDataPathConfirmInd; +import android.hardware.wifi.NanDataPathRequestInd; +import android.hardware.wifi.NanDataPathScheduleUpdateInd; +import android.hardware.wifi.NanFollowupReceivedInd; +import android.hardware.wifi.NanMatchInd; +import android.hardware.wifi.NanStatus; +import android.hardware.wifi.NanStatusCode; +import android.hardware.wifi.WifiChannelWidthInMhz; +import android.net.MacAddress; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiAnnotations; +import android.net.wifi.aware.Characteristics; +import android.net.wifi.aware.WifiAwareChannelInfo; +import android.net.wifi.util.HexEncoding; +import android.util.Log; + +import com.android.server.wifi.aware.Capabilities; +import com.android.server.wifi.hal.WifiNanIface.NanClusterEventType; +import com.android.server.wifi.hal.WifiNanIface.NanRangingIndication; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Callback registered with the Vendor HAL service. On events, converts arguments + * to their framework equivalents and calls the registered framework callback. + */ +public class WifiNanIfaceCallbackAidlImpl extends IWifiNanIfaceEventCallback.Stub { + private static final String TAG = "WifiNanIfaceCallbackAidlImpl"; + + private boolean mVerboseLoggingEnabled; + private WifiNanIfaceAidlImpl mWifiNanIface; + + public WifiNanIfaceCallbackAidlImpl(WifiNanIfaceAidlImpl wifiNanIface) { + mWifiNanIface = wifiNanIface; + } + + /** + * Enable verbose logging. + */ + public void enableVerboseLogging(boolean verbose) { + mVerboseLoggingEnabled = verbose; + } + + @Override + public void notifyCapabilitiesResponse(char id, NanStatus status, + NanCapabilities capabilities) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyCapabilitiesResponse: id=" + id + ", status=" + + statusString(status) + ", capabilities=" + capabilities); + } + + if (status.status == NanStatusCode.SUCCESS) { + Capabilities frameworkCapabilities = toFrameworkCapability(capabilities); + mWifiNanIface.getFrameworkCallback().notifyCapabilitiesResponse( + (short) id, frameworkCapabilities); + } else { + Log.e(TAG, "notifyCapabilitiesResponse: error code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyEnableResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyEnableResponse: id=" + id + ", status=" + statusString(status)); + } + + if (status.status == NanStatusCode.ALREADY_ENABLED) { + Log.wtf(TAG, "notifyEnableResponse: id=" + id + ", already enabled!?"); + } + mWifiNanIface.getFrameworkCallback().notifyEnableResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void notifyConfigResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyConfigResponse: id=" + id + ", status=" + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyConfigResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void notifyDisableResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyDisableResponse: id=" + id + ", status=" + statusString(status)); + } + + if (status.status != NanStatusCode.SUCCESS) { + Log.e(TAG, "notifyDisableResponse: failure - code=" + status.status + " (" + + status.description + ")"); + } + mWifiNanIface.getFrameworkCallback().notifyDisableResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void notifyStartPublishResponse(char id, NanStatus status, byte publishId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStartPublishResponse: id=" + id + ", status=" + statusString(status) + + ", publishId=" + publishId); + } + mWifiNanIface.getFrameworkCallback().notifyStartPublishResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status), publishId); + } + + @Override + public void notifyStopPublishResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStopPublishResponse: id=" + id + ", status=" + statusString(status)); + } + + if (status.status == NanStatusCode.SUCCESS) { + // NOP + } else { + Log.e(TAG, "notifyStopPublishResponse: failure - code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyStartSubscribeResponse(char id, NanStatus status, byte subscribeId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStartSubscribeResponse: id=" + id + ", status=" + statusString(status) + + ", subscribeId=" + subscribeId); + } + mWifiNanIface.getFrameworkCallback().notifyStartSubscribeResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status), subscribeId); + } + + @Override + public void notifyStopSubscribeResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStopSubscribeResponse: id=" + id + ", status=" + + statusString(status)); + } + + if (status.status == NanStatusCode.SUCCESS) { + // NOP + } else { + Log.e(TAG, "notifyStopSubscribeResponse: failure - code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyTransmitFollowupResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyTransmitFollowupResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyTransmitFollowupResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void notifyCreateDataInterfaceResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyCreateDataInterfaceResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyCreateDataInterfaceResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void notifyDeleteDataInterfaceResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyDeleteDataInterfaceResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyDeleteDataInterfaceResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void notifyInitiateDataPathResponse(char id, NanStatus status, + int ndpInstanceId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyInitiateDataPathResponse: id=" + id + ", status=" + + statusString(status) + ", ndpInstanceId=" + ndpInstanceId); + } + mWifiNanIface.getFrameworkCallback().notifyInitiateDataPathResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status), ndpInstanceId); + } + + @Override + public void notifyRespondToDataPathIndicationResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyRespondToDataPathIndicationResponse: id=" + id + + ", status=" + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyRespondToDataPathIndicationResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void notifyTerminateDataPathResponse(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyTerminateDataPathResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyTerminateDataPathResponse( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void eventClusterEvent(NanClusterEventInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventClusterEvent: eventType=" + event.eventType + ", addr=" + + String.valueOf(HexEncoding.encode(event.addr))); + } + mWifiNanIface.getFrameworkCallback().eventClusterEvent( + NanClusterEventType.fromAidl(event.eventType), event.addr); + } + + @Override + public void eventDisabled(NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) Log.v(TAG, "eventDisabled: status=" + statusString(status)); + mWifiNanIface.getFrameworkCallback().eventDisabled( + WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void eventPublishTerminated(byte sessionId, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventPublishTerminated: sessionId=" + sessionId + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().eventPublishTerminated( + sessionId, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void eventSubscribeTerminated(byte sessionId, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventSubscribeTerminated: sessionId=" + sessionId + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().eventSubscribeTerminated( + sessionId, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void eventMatch(NanMatchInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventMatch: discoverySessionId=" + event.discoverySessionId + + ", peerId=" + event.peerId + + ", addr=" + String.valueOf(HexEncoding.encode(event.addr)) + + ", serviceSpecificInfo=" + Arrays.toString(event.serviceSpecificInfo) + + ", ssi.size()=" + (event.serviceSpecificInfo == null + ? 0 : event.serviceSpecificInfo.length) + + ", matchFilter=" + Arrays.toString(event.matchFilter) + + ", mf.size()=" + (event.matchFilter == null ? 0 : event.matchFilter.length) + + ", rangingIndicationType=" + event.rangingIndicationType + + ", rangingMeasurementInMm=" + event.rangingMeasurementInMm + ", " + + "scid=" + Arrays.toString(event.scid)); + } + mWifiNanIface.getFrameworkCallback().eventMatch(event.discoverySessionId, event.peerId, + event.addr, event.serviceSpecificInfo, event.matchFilter, + NanRangingIndication.fromAidl(event.rangingIndicationType), + event.rangingMeasurementInMm, event.scid, + toPublicCipherSuites(event.peerCipherType)); + } + + @Override + public void eventMatchExpired(byte discoverySessionId, int peerId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventMatchExpired: discoverySessionId=" + discoverySessionId + + ", peerId=" + peerId); + } + mWifiNanIface.getFrameworkCallback().eventMatchExpired(discoverySessionId, peerId); + } + + @Override + public void eventFollowupReceived(NanFollowupReceivedInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventFollowupReceived: discoverySessionId=" + event.discoverySessionId + + ", peerId=" + event.peerId + ", addr=" + String.valueOf( + HexEncoding.encode(event.addr)) + ", serviceSpecificInfo=" + Arrays.toString( + event.serviceSpecificInfo) + ", ssi.size()=" + + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.length)); + } + mWifiNanIface.getFrameworkCallback().eventFollowupReceived( + event.discoverySessionId, event.peerId, event.addr, event.serviceSpecificInfo); + } + + @Override + public void eventTransmitFollowup(char id, NanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventTransmitFollowup: id=" + id + ", status=" + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().eventTransmitFollowup( + (short) id, WifiNanIface.NanStatusCode.fromAidl(status.status)); + } + + @Override + public void eventDataPathRequest(NanDataPathRequestInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathRequest: discoverySessionId=" + event.discoverySessionId + + ", peerDiscMacAddr=" + String.valueOf( + HexEncoding.encode(event.peerDiscMacAddr)) + ", ndpInstanceId=" + + event.ndpInstanceId + ", appInfo.size()=" + event.appInfo.length); + } + mWifiNanIface.getFrameworkCallback().eventDataPathRequest(event.discoverySessionId, + event.peerDiscMacAddr, event.ndpInstanceId, event.appInfo); + } + + @Override + public void eventDataPathConfirm(NanDataPathConfirmInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathConfirm: ndpInstanceId=" + event.ndpInstanceId + + ", peerNdiMacAddr=" + String.valueOf( + HexEncoding.encode(event.peerNdiMacAddr)) + ", dataPathSetupSuccess=" + + event.dataPathSetupSuccess + ", reason=" + event.status.status + + ", appInfo.size()=" + event.appInfo.length + + ", channelInfo" + Arrays.toString(event.channelInfo)); + } + List<WifiAwareChannelInfo> wifiAwareChannelInfos = convertHalChannelInfo(event.channelInfo); + mWifiNanIface.getFrameworkCallback().eventDataPathConfirm( + WifiNanIface.NanStatusCode.fromAidl(event.status.status), event.ndpInstanceId, + event.dataPathSetupSuccess, event.peerNdiMacAddr, event.appInfo, + wifiAwareChannelInfos); + } + + @Override + public void eventDataPathScheduleUpdate(NanDataPathScheduleUpdateInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathScheduleUpdate: peerMac=" + + MacAddress.fromBytes(event.peerDiscoveryAddress) + + ", ndpIds=" + Arrays.toString(event.ndpInstanceIds) + + ", channelInfo=" + Arrays.toString(event.channelInfo)); + } + List<WifiAwareChannelInfo> wifiAwareChannelInfos = convertHalChannelInfo(event.channelInfo); + ArrayList<Integer> ndpInstanceIds = new ArrayList<>(); + for (int i : event.ndpInstanceIds) { + ndpInstanceIds.add(i); + } + mWifiNanIface.getFrameworkCallback().eventDataPathScheduleUpdate( + event.peerDiscoveryAddress, ndpInstanceIds, wifiAwareChannelInfos); + } + + @Override + public void eventDataPathTerminated(int ndpInstanceId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathTerminated: ndpInstanceId=" + ndpInstanceId); + } + mWifiNanIface.getFrameworkCallback().eventDataPathTerminated(ndpInstanceId); + } + + @Override + public String getInterfaceHash() { + return IWifiNanIfaceEventCallback.HASH; + } + + @Override + public int getInterfaceVersion() { + return IWifiNanIfaceEventCallback.VERSION; + } + + private Capabilities toFrameworkCapability(NanCapabilities capabilities) { + Capabilities frameworkCapabilities = new Capabilities(); + frameworkCapabilities.maxConcurrentAwareClusters = capabilities.maxConcurrentClusters; + frameworkCapabilities.maxPublishes = capabilities.maxPublishes; + frameworkCapabilities.maxSubscribes = capabilities.maxSubscribes; + frameworkCapabilities.maxServiceNameLen = capabilities.maxServiceNameLen; + frameworkCapabilities.maxMatchFilterLen = capabilities.maxMatchFilterLen; + frameworkCapabilities.maxTotalMatchFilterLen = capabilities.maxTotalMatchFilterLen; + frameworkCapabilities.maxServiceSpecificInfoLen = + capabilities.maxServiceSpecificInfoLen; + frameworkCapabilities.maxExtendedServiceSpecificInfoLen = + capabilities.maxExtendedServiceSpecificInfoLen; + frameworkCapabilities.maxNdiInterfaces = capabilities.maxNdiInterfaces; + frameworkCapabilities.maxNdpSessions = capabilities.maxNdpSessions; + frameworkCapabilities.maxAppInfoLen = capabilities.maxAppInfoLen; + frameworkCapabilities.maxQueuedTransmitMessages = + capabilities.maxQueuedTransmitFollowupMsgs; + frameworkCapabilities.maxSubscribeInterfaceAddresses = + capabilities.maxSubscribeInterfaceAddresses; + frameworkCapabilities.supportedCipherSuites = toPublicCipherSuites( + capabilities.supportedCipherSuites); + frameworkCapabilities.isInstantCommunicationModeSupported = + capabilities.instantCommunicationModeSupportFlag; + return frameworkCapabilities; + } + + private int toPublicCipherSuites(int nativeCipherSuites) { + int publicCipherSuites = 0; + + if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_128_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; + } + if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_256_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; + } + if ((nativeCipherSuites & NanCipherSuiteType.PUBLIC_KEY_128_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_128; + } + if ((nativeCipherSuites & NanCipherSuiteType.PUBLIC_KEY_256_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_256; + } + + return publicCipherSuites; + } + + private static String statusString(NanStatus status) { + if (status == null) { + return "status=null"; + } + StringBuilder sb = new StringBuilder(); + sb.append(status.status).append(" (").append(status.description).append(")"); + return sb.toString(); + } + + /** + * Convert HAL channelBandwidth to framework enum + */ + private @WifiAnnotations.ChannelWidth int getChannelBandwidthFromHal(int channelBandwidth) { + switch(channelBandwidth) { + case WifiChannelWidthInMhz.WIDTH_40: + return ScanResult.CHANNEL_WIDTH_40MHZ; + case WifiChannelWidthInMhz.WIDTH_80: + return ScanResult.CHANNEL_WIDTH_80MHZ; + case WifiChannelWidthInMhz.WIDTH_160: + return ScanResult.CHANNEL_WIDTH_160MHZ; + case WifiChannelWidthInMhz.WIDTH_80P80: + return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; + case WifiChannelWidthInMhz.WIDTH_320: + return ScanResult.CHANNEL_WIDTH_320MHZ; + default: + return ScanResult.CHANNEL_WIDTH_20MHZ; + } + } + + /** + * Convert HAL NanDataPathChannelInfo to WifiAwareChannelInfo + */ + private List<WifiAwareChannelInfo> convertHalChannelInfo( + NanDataPathChannelInfo[] channelInfos) { + List<WifiAwareChannelInfo> wifiAwareChannelInfos = new ArrayList<>(); + if (channelInfos == null) { + return null; + } + for (android.hardware.wifi.NanDataPathChannelInfo channelInfo : channelInfos) { + wifiAwareChannelInfos.add(new WifiAwareChannelInfo(channelInfo.channelFreq, + getChannelBandwidthFromHal(channelInfo.channelBandwidth), + channelInfo.numSpatialStreams)); + } + return wifiAwareChannelInfos; + } + + private boolean checkFrameworkCallback() { + if (mWifiNanIface == null) { + Log.e(TAG, "mWifiNanIface is null"); + return false; + } else if (mWifiNanIface.getFrameworkCallback() == null) { + Log.e(TAG, "Framework callback is null"); + return false; + } + return true; + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackHidlImpl.java new file mode 100644 index 0000000000..721a340992 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackHidlImpl.java @@ -0,0 +1,678 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.hardware.wifi.V1_0.NanClusterEventInd; +import android.hardware.wifi.V1_0.NanDataPathConfirmInd; +import android.hardware.wifi.V1_0.NanDataPathRequestInd; +import android.hardware.wifi.V1_0.NanFollowupReceivedInd; +import android.hardware.wifi.V1_0.NanMatchInd; +import android.hardware.wifi.V1_0.NanStatusType; +import android.hardware.wifi.V1_0.WifiNanStatus; +import android.hardware.wifi.V1_2.NanDataPathScheduleUpdateInd; +import android.hardware.wifi.V1_6.IWifiNanIfaceEventCallback; +import android.hardware.wifi.V1_6.NanCipherSuiteType; +import android.hardware.wifi.V1_6.WifiChannelWidthInMhz; +import android.net.MacAddress; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiAnnotations; +import android.net.wifi.aware.Characteristics; +import android.net.wifi.aware.WifiAwareChannelInfo; +import android.net.wifi.util.HexEncoding; +import android.util.Log; + +import com.android.server.wifi.aware.Capabilities; +import com.android.server.wifi.hal.WifiNanIface.NanClusterEventType; +import com.android.server.wifi.hal.WifiNanIface.NanRangingIndication; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Callback registered with the Vendor HAL service. On events, converts arguments + * to their framework equivalents and calls the registered framework callback. + */ +public class WifiNanIfaceCallbackHidlImpl extends IWifiNanIfaceEventCallback.Stub { + private static final String TAG = "WifiNanIfaceCallbackHidlImpl"; + + private boolean mVerboseLoggingEnabled; + private WifiNanIfaceHidlImpl mWifiNanIface; + + public WifiNanIfaceCallbackHidlImpl(WifiNanIfaceHidlImpl wifiNanIface) { + mWifiNanIface = wifiNanIface; + } + + /** + * Enable verbose logging. + */ + public void enableVerboseLogging(boolean verbose) { + mVerboseLoggingEnabled = verbose; + } + + @Override + public void notifyCapabilitiesResponse(short id, WifiNanStatus status, + android.hardware.wifi.V1_0.NanCapabilities capabilities) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyCapabilitiesResponse: id=" + id + ", status=" + statusString(status) + + ", capabilities=" + capabilities); + } + + if (status.status == NanStatusType.SUCCESS) { + Capabilities frameworkCapabilities = toFrameworkCapability10(capabilities); + mWifiNanIface.getFrameworkCallback().notifyCapabilitiesResponse( + id, frameworkCapabilities); + } else { + Log.e(TAG, "notifyCapabilitiesResponse: error code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyCapabilitiesResponse_1_5(short id, WifiNanStatus status, + android.hardware.wifi.V1_5.NanCapabilities capabilities) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyCapabilitiesResponse_1_5: id=" + id + ", status=" + + statusString(status) + ", capabilities=" + capabilities); + } + + if (status.status == NanStatusType.SUCCESS) { + Capabilities frameworkCapabilities = toFrameworkCapability10(capabilities.V1_0); + frameworkCapabilities.isInstantCommunicationModeSupported = + capabilities.instantCommunicationModeSupportFlag; + mWifiNanIface.getFrameworkCallback().notifyCapabilitiesResponse( + id, frameworkCapabilities); + } else { + Log.e(TAG, "notifyCapabilitiesResponse_1_5: error code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyCapabilitiesResponse_1_6(short id, WifiNanStatus status, + android.hardware.wifi.V1_6.NanCapabilities capabilities) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyCapabilitiesResponse_1_6: id=" + id + ", status=" + + statusString(status) + ", capabilities=" + capabilities); + } + + if (status.status == NanStatusType.SUCCESS) { + Capabilities frameworkCapabilities = toFrameworkCapability1_6(capabilities); + mWifiNanIface.getFrameworkCallback().notifyCapabilitiesResponse( + id, frameworkCapabilities); + } else { + Log.e(TAG, "notifyCapabilitiesResponse_1_6: error code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyEnableResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyEnableResponse: id=" + id + ", status=" + statusString(status)); + } + + if (status.status == NanStatusType.ALREADY_ENABLED) { + Log.wtf(TAG, "notifyEnableResponse: id=" + id + ", already enabled!?"); + } + mWifiNanIface.getFrameworkCallback().notifyEnableResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void notifyConfigResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyConfigResponse: id=" + id + ", status=" + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyConfigResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void notifyDisableResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyDisableResponse: id=" + id + ", status=" + statusString(status)); + } + + if (status.status != NanStatusType.SUCCESS) { + Log.e(TAG, "notifyDisableResponse: failure - code=" + status.status + " (" + + status.description + ")"); + } + mWifiNanIface.getFrameworkCallback().notifyDisableResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void notifyStartPublishResponse(short id, WifiNanStatus status, byte publishId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStartPublishResponse: id=" + id + ", status=" + statusString(status) + + ", publishId=" + publishId); + } + mWifiNanIface.getFrameworkCallback().notifyStartPublishResponse( + id, NanStatusCode.fromHidl(status.status), publishId); + } + + @Override + public void notifyStopPublishResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStopPublishResponse: id=" + id + ", status=" + statusString(status)); + } + + if (status.status == NanStatusType.SUCCESS) { + // NOP + } else { + Log.e(TAG, "notifyStopPublishResponse: failure - code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyStartSubscribeResponse(short id, WifiNanStatus status, byte subscribeId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStartSubscribeResponse: id=" + id + ", status=" + statusString(status) + + ", subscribeId=" + subscribeId); + } + mWifiNanIface.getFrameworkCallback().notifyStartSubscribeResponse( + id, NanStatusCode.fromHidl(status.status), subscribeId); + } + + @Override + public void notifyStopSubscribeResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyStopSubscribeResponse: id=" + id + ", status=" + + statusString(status)); + } + + if (status.status == NanStatusType.SUCCESS) { + // NOP + } else { + Log.e(TAG, "notifyStopSubscribeResponse: failure - code=" + status.status + " (" + + status.description + ")"); + } + } + + @Override + public void notifyTransmitFollowupResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyTransmitFollowupResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyTransmitFollowupResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void notifyCreateDataInterfaceResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyCreateDataInterfaceResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyCreateDataInterfaceResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void notifyDeleteDataInterfaceResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyDeleteDataInterfaceResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyDeleteDataInterfaceResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void notifyInitiateDataPathResponse(short id, WifiNanStatus status, + int ndpInstanceId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyInitiateDataPathResponse: id=" + id + ", status=" + + statusString(status) + ", ndpInstanceId=" + ndpInstanceId); + } + mWifiNanIface.getFrameworkCallback().notifyInitiateDataPathResponse( + id, NanStatusCode.fromHidl(status.status), ndpInstanceId); + } + + @Override + public void notifyRespondToDataPathIndicationResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyRespondToDataPathIndicationResponse: id=" + id + + ", status=" + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyRespondToDataPathIndicationResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void notifyTerminateDataPathResponse(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "notifyTerminateDataPathResponse: id=" + id + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().notifyTerminateDataPathResponse( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void eventClusterEvent(NanClusterEventInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventClusterEvent: eventType=" + event.eventType + ", addr=" + + String.valueOf(HexEncoding.encode(event.addr))); + } + mWifiNanIface.getFrameworkCallback().eventClusterEvent( + NanClusterEventType.fromHidl(event.eventType), event.addr); + } + + @Override + public void eventDisabled(WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) Log.v(TAG, "eventDisabled: status=" + statusString(status)); + mWifiNanIface.getFrameworkCallback().eventDisabled( + NanStatusCode.fromHidl(status.status)); + } + + @Override + public void eventPublishTerminated(byte sessionId, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventPublishTerminated: sessionId=" + sessionId + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().eventPublishTerminated( + sessionId, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void eventSubscribeTerminated(byte sessionId, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventSubscribeTerminated: sessionId=" + sessionId + ", status=" + + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().eventSubscribeTerminated( + sessionId, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void eventMatch(NanMatchInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventMatch: discoverySessionId=" + event.discoverySessionId + ", peerId=" + + event.peerId + ", addr=" + String.valueOf(HexEncoding.encode(event.addr)) + + ", serviceSpecificInfo=" + Arrays.toString( + convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" + + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size()) + + ", matchFilter=" + Arrays.toString( + convertArrayListToNativeByteArray(event.matchFilter)) + ", mf.size()=" + ( + event.matchFilter == null ? 0 : event.matchFilter.size()) + + ", rangingIndicationType=" + event.rangingIndicationType + + ", rangingMeasurementInCm=" + event.rangingMeasurementInCm); + } + mWifiNanIface.getFrameworkCallback().eventMatch(event.discoverySessionId, event.peerId, + event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo), + convertArrayListToNativeByteArray(event.matchFilter), + NanRangingIndication.fromHidl(event.rangingIndicationType), + event.rangingMeasurementInCm * 10, new byte[0], 0); + } + + @Override + public void eventMatch_1_6(android.hardware.wifi.V1_6.NanMatchInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventMatch_1_6: discoverySessionId=" + event.discoverySessionId + + ", peerId=" + event.peerId + + ", addr=" + String.valueOf(HexEncoding.encode(event.addr)) + + ", serviceSpecificInfo=" + Arrays.toString( + convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" + + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size()) + + ", matchFilter=" + Arrays.toString( + convertArrayListToNativeByteArray(event.matchFilter)) + ", mf.size()=" + ( + event.matchFilter == null ? 0 : event.matchFilter.size()) + + ", rangingIndicationType=" + event.rangingIndicationType + + ", rangingMeasurementInCm=" + event.rangingMeasurementInMm + ", " + + "scid=" + Arrays.toString(convertArrayListToNativeByteArray(event.scid))); + } + mWifiNanIface.getFrameworkCallback().eventMatch(event.discoverySessionId, event.peerId, + event.addr, convertArrayListToNativeByteArray(event.serviceSpecificInfo), + convertArrayListToNativeByteArray(event.matchFilter), + NanRangingIndication.fromHidl(event.rangingIndicationType), + event.rangingMeasurementInMm, convertArrayListToNativeByteArray(event.scid), + toPublicCipherSuites(event.peerCipherType)); + } + + @Override + public void eventMatchExpired(byte discoverySessionId, int peerId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventMatchExpired: discoverySessionId=" + discoverySessionId + + ", peerId=" + peerId); + } + mWifiNanIface.getFrameworkCallback().eventMatchExpired(discoverySessionId, peerId); + } + + @Override + public void eventFollowupReceived(NanFollowupReceivedInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventFollowupReceived: discoverySessionId=" + event.discoverySessionId + + ", peerId=" + event.peerId + ", addr=" + String.valueOf( + HexEncoding.encode(event.addr)) + ", serviceSpecificInfo=" + Arrays.toString( + convertArrayListToNativeByteArray(event.serviceSpecificInfo)) + ", ssi.size()=" + + (event.serviceSpecificInfo == null ? 0 : event.serviceSpecificInfo.size())); + } + mWifiNanIface.getFrameworkCallback().eventFollowupReceived( + event.discoverySessionId, event.peerId, event.addr, + convertArrayListToNativeByteArray(event.serviceSpecificInfo)); + } + + @Override + public void eventTransmitFollowup(short id, WifiNanStatus status) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventTransmitFollowup: id=" + id + ", status=" + statusString(status)); + } + mWifiNanIface.getFrameworkCallback().eventTransmitFollowup( + id, NanStatusCode.fromHidl(status.status)); + } + + @Override + public void eventDataPathRequest(NanDataPathRequestInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathRequest: discoverySessionId=" + event.discoverySessionId + + ", peerDiscMacAddr=" + String.valueOf( + HexEncoding.encode(event.peerDiscMacAddr)) + ", ndpInstanceId=" + + event.ndpInstanceId + ", appInfo.size()=" + event.appInfo.size()); + } + mWifiNanIface.getFrameworkCallback().eventDataPathRequest(event.discoverySessionId, + event.peerDiscMacAddr, event.ndpInstanceId, + convertArrayListToNativeByteArray(event.appInfo)); + } + + @Override + public void eventDataPathConfirm(NanDataPathConfirmInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "onDataPathConfirm: ndpInstanceId=" + event.ndpInstanceId + + ", peerNdiMacAddr=" + String.valueOf(HexEncoding.encode(event.peerNdiMacAddr)) + + ", dataPathSetupSuccess=" + event.dataPathSetupSuccess + ", reason=" + + event.status.status + ", appInfo.size()=" + event.appInfo.size()); + } + mWifiNanIface.getFrameworkCallback().eventDataPathConfirm( + NanStatusCode.fromHidl(event.status.status), event.ndpInstanceId, + event.dataPathSetupSuccess, event.peerNdiMacAddr, + convertArrayListToNativeByteArray(event.appInfo), null); + } + + @Override + public void eventDataPathConfirm_1_2(android.hardware.wifi.V1_2.NanDataPathConfirmInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathConfirm_1_2: ndpInstanceId=" + event.V1_0.ndpInstanceId + + ", peerNdiMacAddr=" + String.valueOf( + HexEncoding.encode(event.V1_0.peerNdiMacAddr)) + ", dataPathSetupSuccess=" + + event.V1_0.dataPathSetupSuccess + ", reason=" + event.V1_0.status.status + + ", appInfo.size()=" + event.V1_0.appInfo.size() + + ", channelInfo" + event.channelInfo); + } + List<WifiAwareChannelInfo> wifiAwareChannelInfos = + convertHalChannelInfo_1_2(event.channelInfo); + mWifiNanIface.getFrameworkCallback().eventDataPathConfirm( + NanStatusCode.fromHidl(event.V1_0.status.status), event.V1_0.ndpInstanceId, + event.V1_0.dataPathSetupSuccess, event.V1_0.peerNdiMacAddr, + convertArrayListToNativeByteArray(event.V1_0.appInfo), wifiAwareChannelInfos); + } + + @Override + public void eventDataPathConfirm_1_6(android.hardware.wifi.V1_6.NanDataPathConfirmInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathConfirm_1_6: ndpInstanceId=" + event.V1_0.ndpInstanceId + + ", peerNdiMacAddr=" + String.valueOf( + HexEncoding.encode(event.V1_0.peerNdiMacAddr)) + ", dataPathSetupSuccess=" + + event.V1_0.dataPathSetupSuccess + ", reason=" + event.V1_0.status.status + + ", appInfo.size()=" + event.V1_0.appInfo.size() + + ", channelInfo" + event.channelInfo); + } + List<WifiAwareChannelInfo> wifiAwareChannelInfos = + convertHalChannelInfo_1_6(event.channelInfo); + mWifiNanIface.getFrameworkCallback().eventDataPathConfirm( + NanStatusCode.fromHidl(event.V1_0.status.status), event.V1_0.ndpInstanceId, + event.V1_0.dataPathSetupSuccess, event.V1_0.peerNdiMacAddr, + convertArrayListToNativeByteArray(event.V1_0.appInfo), wifiAwareChannelInfos); + } + + @Override + public void eventDataPathScheduleUpdate(NanDataPathScheduleUpdateInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathScheduleUpdate: peerMac=" + + MacAddress.fromBytes(event.peerDiscoveryAddress) + + ", ndpIds=" + event.ndpInstanceIds + ", channelInfo=" + event.channelInfo); + } + List<WifiAwareChannelInfo> wifiAwareChannelInfos = + convertHalChannelInfo_1_2(event.channelInfo); + mWifiNanIface.getFrameworkCallback().eventDataPathScheduleUpdate( + event.peerDiscoveryAddress, event.ndpInstanceIds, wifiAwareChannelInfos); + } + + @Override + public void eventDataPathScheduleUpdate_1_6( + android.hardware.wifi.V1_6.NanDataPathScheduleUpdateInd event) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathScheduleUpdate_1_6: peerMac=" + + MacAddress.fromBytes(event.peerDiscoveryAddress) + + ", ndpIds=" + event.ndpInstanceIds + ", channelInfo=" + event.channelInfo); + } + List<WifiAwareChannelInfo> wifiAwareChannelInfos = + convertHalChannelInfo_1_6(event.channelInfo); + mWifiNanIface.getFrameworkCallback().eventDataPathScheduleUpdate( + event.peerDiscoveryAddress, event.ndpInstanceIds, wifiAwareChannelInfos); + } + + @Override + public void eventDataPathTerminated(int ndpInstanceId) { + if (!checkFrameworkCallback()) return; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "eventDataPathTerminated: ndpInstanceId=" + ndpInstanceId); + } + mWifiNanIface.getFrameworkCallback().eventDataPathTerminated(ndpInstanceId); + } + + private Capabilities toFrameworkCapability10( + android.hardware.wifi.V1_0.NanCapabilities capabilities) { + Capabilities frameworkCapabilities = new Capabilities(); + frameworkCapabilities.maxConcurrentAwareClusters = capabilities.maxConcurrentClusters; + frameworkCapabilities.maxPublishes = capabilities.maxPublishes; + frameworkCapabilities.maxSubscribes = capabilities.maxSubscribes; + frameworkCapabilities.maxServiceNameLen = capabilities.maxServiceNameLen; + frameworkCapabilities.maxMatchFilterLen = capabilities.maxMatchFilterLen; + frameworkCapabilities.maxTotalMatchFilterLen = capabilities.maxTotalMatchFilterLen; + frameworkCapabilities.maxServiceSpecificInfoLen = + capabilities.maxServiceSpecificInfoLen; + frameworkCapabilities.maxExtendedServiceSpecificInfoLen = + capabilities.maxExtendedServiceSpecificInfoLen; + frameworkCapabilities.maxNdiInterfaces = capabilities.maxNdiInterfaces; + frameworkCapabilities.maxNdpSessions = capabilities.maxNdpSessions; + frameworkCapabilities.maxAppInfoLen = capabilities.maxAppInfoLen; + frameworkCapabilities.maxQueuedTransmitMessages = + capabilities.maxQueuedTransmitFollowupMsgs; + frameworkCapabilities.maxSubscribeInterfaceAddresses = + capabilities.maxSubscribeInterfaceAddresses; + frameworkCapabilities.supportedCipherSuites = toPublicCipherSuites( + capabilities.supportedCipherSuites); + frameworkCapabilities.isInstantCommunicationModeSupported = false; + return frameworkCapabilities; + } + + private Capabilities toFrameworkCapability1_6( + android.hardware.wifi.V1_6.NanCapabilities capabilities) { + Capabilities frameworkCapabilities = new Capabilities(); + frameworkCapabilities.maxConcurrentAwareClusters = capabilities.maxConcurrentClusters; + frameworkCapabilities.maxPublishes = capabilities.maxPublishes; + frameworkCapabilities.maxSubscribes = capabilities.maxSubscribes; + frameworkCapabilities.maxServiceNameLen = capabilities.maxServiceNameLen; + frameworkCapabilities.maxMatchFilterLen = capabilities.maxMatchFilterLen; + frameworkCapabilities.maxTotalMatchFilterLen = capabilities.maxTotalMatchFilterLen; + frameworkCapabilities.maxServiceSpecificInfoLen = + capabilities.maxServiceSpecificInfoLen; + frameworkCapabilities.maxExtendedServiceSpecificInfoLen = + capabilities.maxExtendedServiceSpecificInfoLen; + frameworkCapabilities.maxNdiInterfaces = capabilities.maxNdiInterfaces; + frameworkCapabilities.maxNdpSessions = capabilities.maxNdpSessions; + frameworkCapabilities.maxAppInfoLen = capabilities.maxAppInfoLen; + frameworkCapabilities.maxQueuedTransmitMessages = + capabilities.maxQueuedTransmitFollowupMsgs; + frameworkCapabilities.maxSubscribeInterfaceAddresses = + capabilities.maxSubscribeInterfaceAddresses; + frameworkCapabilities.supportedCipherSuites = toPublicCipherSuites( + capabilities.supportedCipherSuites); + frameworkCapabilities.isInstantCommunicationModeSupported = + capabilities.instantCommunicationModeSupportFlag; + return frameworkCapabilities; + } + + private int toPublicCipherSuites(int nativeCipherSuites) { + int publicCipherSuites = 0; + + if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_128_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; + } + if ((nativeCipherSuites & NanCipherSuiteType.SHARED_KEY_256_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; + } + if ((nativeCipherSuites & NanCipherSuiteType.PUBLIC_KEY_128_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_128; + } + if ((nativeCipherSuites & NanCipherSuiteType.PUBLIC_KEY_256_MASK) != 0) { + publicCipherSuites |= Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_256; + } + + return publicCipherSuites; + } + + /** + * Converts an ArrayList<Byte> to a byte[]. + * + * @param from The input ArrayList<Byte></Byte> to convert from. + * + * @return A newly allocated byte[]. + */ + private byte[] convertArrayListToNativeByteArray(ArrayList<Byte> from) { + if (from == null) { + return null; + } + + byte[] to = new byte[from.size()]; + for (int i = 0; i < from.size(); ++i) { + to[i] = from.get(i); + } + return to; + } + + private static String statusString(WifiNanStatus status) { + if (status == null) { + return "status=null"; + } + StringBuilder sb = new StringBuilder(); + sb.append(status.status).append(" (").append(status.description).append(")"); + return sb.toString(); + } + + /** + * Convert HAL channelBandwidth to framework enum + */ + private @WifiAnnotations.ChannelWidth int getChannelBandwidthFromHal(int channelBandwidth) { + switch(channelBandwidth) { + case WifiChannelWidthInMhz.WIDTH_40: + return ScanResult.CHANNEL_WIDTH_40MHZ; + case WifiChannelWidthInMhz.WIDTH_80: + return ScanResult.CHANNEL_WIDTH_80MHZ; + case WifiChannelWidthInMhz.WIDTH_160: + return ScanResult.CHANNEL_WIDTH_160MHZ; + case WifiChannelWidthInMhz.WIDTH_80P80: + return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; + case WifiChannelWidthInMhz.WIDTH_320: + return ScanResult.CHANNEL_WIDTH_320MHZ; + default: + return ScanResult.CHANNEL_WIDTH_20MHZ; + } + } + + /** + * Convert HAL V1_2 NanDataPathChannelInfo to WifiAwareChannelInfo + */ + private List<WifiAwareChannelInfo> convertHalChannelInfo_1_2( + List<android.hardware.wifi.V1_2.NanDataPathChannelInfo> channelInfos) { + List<WifiAwareChannelInfo> wifiAwareChannelInfos = new ArrayList<>(); + if (channelInfos == null) { + return null; + } + for (android.hardware.wifi.V1_2.NanDataPathChannelInfo channelInfo : channelInfos) { + wifiAwareChannelInfos.add(new WifiAwareChannelInfo(channelInfo.channelFreq, + getChannelBandwidthFromHal(channelInfo.channelBandwidth), + channelInfo.numSpatialStreams)); + } + return wifiAwareChannelInfos; + } + + /** + * Convert HAL V1_6 NanDataPathChannelInfo to WifiAwareChannelInfo + */ + private List<WifiAwareChannelInfo> convertHalChannelInfo_1_6( + List<android.hardware.wifi.V1_6.NanDataPathChannelInfo> channelInfos) { + List<WifiAwareChannelInfo> wifiAwareChannelInfos = new ArrayList<>(); + if (channelInfos == null) { + return null; + } + for (android.hardware.wifi.V1_6.NanDataPathChannelInfo channelInfo : channelInfos) { + wifiAwareChannelInfos.add(new WifiAwareChannelInfo(channelInfo.channelFreq, + getChannelBandwidthFromHal(channelInfo.channelBandwidth), + channelInfo.numSpatialStreams)); + } + return wifiAwareChannelInfos; + } + + private boolean checkFrameworkCallback() { + if (mWifiNanIface == null) { + Log.e(TAG, "mWifiNanIface is null"); + return false; + } else if (mWifiNanIface.getFrameworkCallback() == null) { + Log.e(TAG, "Framework callback is null"); + return false; + } + return true; + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceHidlImpl.java new file mode 100644 index 0000000000..8869031a0c --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceHidlImpl.java @@ -0,0 +1,1149 @@ +/* + * Copyright (C) 2022 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.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_SK_128; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; + +import android.annotation.NonNull; +import android.hardware.wifi.V1_0.NanBandIndex; +import android.hardware.wifi.V1_0.NanBandSpecificConfig; +import android.hardware.wifi.V1_0.NanConfigRequest; +import android.hardware.wifi.V1_0.NanDataPathSecurityType; +import android.hardware.wifi.V1_0.NanEnableRequest; +import android.hardware.wifi.V1_0.NanInitiateDataPathRequest; +import android.hardware.wifi.V1_0.NanMatchAlg; +import android.hardware.wifi.V1_0.NanPublishRequest; +import android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest; +import android.hardware.wifi.V1_0.NanSubscribeRequest; +import android.hardware.wifi.V1_0.NanTransmitFollowupRequest; +import android.hardware.wifi.V1_0.NanTxType; +import android.hardware.wifi.V1_0.WifiStatus; +import android.hardware.wifi.V1_0.WifiStatusCode; +import android.hardware.wifi.V1_6.NanCipherSuiteType; +import android.net.MacAddress; +import android.net.wifi.aware.ConfigRequest; +import android.net.wifi.aware.PublishConfig; +import android.net.wifi.aware.SubscribeConfig; +import android.net.wifi.aware.WifiAwareDataPathSecurityConfig; +import android.os.RemoteException; +import android.util.Log; + +import com.android.server.wifi.aware.Capabilities; +import com.android.server.wifi.util.GeneralUtil.Mutable; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.function.Supplier; + +/** + * HIDL implementation of the IWifiNanIface interface. + */ +public class WifiNanIfaceHidlImpl implements IWifiNanIface { + private static final String TAG = "WifiNanIfaceHidlImpl"; + private android.hardware.wifi.V1_0.IWifiNanIface mWifiNanIface; + private String mIfaceName; + private WifiNanIfaceCallbackHidlImpl mHalCallback; + private WifiNanIface.Callback mFrameworkCallback; + + public WifiNanIfaceHidlImpl(@NonNull android.hardware.wifi.V1_0.IWifiNanIface nanIface) { + mWifiNanIface = nanIface; + mHalCallback = new WifiNanIfaceCallbackHidlImpl(this); + } + + /** + * Enable verbose logging. + */ + public void enableVerboseLogging(boolean verbose) { + if (mHalCallback != null) { + mHalCallback.enableVerboseLogging(verbose); + } + } + + protected WifiNanIface.Callback getFrameworkCallback() { + return mFrameworkCallback; + } + + /** + * See comments for {@link IWifiNanIface#getNanIface()} + * + * TODO: Remove this API. Will only be used temporarily until HalDeviceManager is refactored. + */ + public android.hardware.wifi.V1_0.IWifiNanIface getNanIface() { + return mWifiNanIface; + } + + /** + * See comments for {@link IWifiNanIface#registerFrameworkCallback(WifiNanIface.Callback)} + */ + public boolean registerFrameworkCallback(WifiNanIface.Callback callback) { + final String methodStr = "registerFrameworkCallback"; + return validateAndCall(methodStr, false, + () -> registerFrameworkCallbackInternal(methodStr, callback)); + } + + /** + * See comments for {@link IWifiNanIface#getName()} + */ + public String getName() { + final String methodStr = "getName"; + return validateAndCall(methodStr, null, + () -> getNameInternal(methodStr)); + } + + /** + * See comments for {@link IWifiNanIface#getCapabilities(short)} + */ + public boolean getCapabilities(short transactionId) { + final String methodStr = "getCapabilities"; + return validateAndCall(methodStr, false, + () -> getCapabilitiesInternal(methodStr, transactionId)); + } + + /** + * See comments for {@link IWifiNanIface#enableAndConfigure(short, ConfigRequest, boolean, + * boolean, boolean, boolean, int, int, WifiNanIface.PowerParameters)} + */ + public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest, + boolean notifyIdentityChange, boolean initialConfiguration, boolean rangingEnabled, + boolean isInstantCommunicationEnabled, int instantModeChannel, + int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) { + final String methodStr = "enableAndConfigure"; + return validateAndCall(methodStr, false, + () -> enableAndConfigureInternal(methodStr, transactionId, configRequest, + notifyIdentityChange, initialConfiguration, rangingEnabled, + isInstantCommunicationEnabled, instantModeChannel, + macAddressRandomizationIntervalSec, powerParameters)); + } + + /** + * See comments for {@link IWifiNanIface#disable(short)} + */ + public boolean disable(short transactionId) { + final String methodStr = "disable"; + return validateAndCall(methodStr, false, + () -> disableInternal(methodStr, transactionId)); + } + + /** + * See comments for {@link IWifiNanIface#publish(short, byte, PublishConfig)} + */ + public boolean publish(short transactionId, byte publishId, PublishConfig publishConfig) { + final String methodStr = "publish"; + return validateAndCall(methodStr, false, + () -> publishInternal(methodStr, transactionId, publishId, publishConfig)); + } + + /** + * See comments for {@link IWifiNanIface#subscribe(short, byte, SubscribeConfig)} + */ + public boolean subscribe(short transactionId, byte subscribeId, + SubscribeConfig subscribeConfig) { + final String methodStr = "subscribe"; + return validateAndCall(methodStr, false, + () -> subscribeInternal(methodStr, transactionId, subscribeId, subscribeConfig)); + } + + /** + * See comments for {@link IWifiNanIface#sendMessage(short, byte, int, MacAddress, byte[])} + */ + public boolean sendMessage(short transactionId, byte pubSubId, int requestorInstanceId, + MacAddress dest, byte[] message) { + final String methodStr = "sendMessage"; + return validateAndCall(methodStr, false, + () -> sendMessageInternal(methodStr, transactionId, pubSubId, requestorInstanceId, + dest, message)); + } + + /** + * See comments for {@link IWifiNanIface#stopPublish(short, byte)} + */ + public boolean stopPublish(short transactionId, byte pubSubId) { + final String methodStr = "stopPublish"; + return validateAndCall(methodStr, false, + () -> stopPublishInternal(methodStr, transactionId, pubSubId)); + } + + /** + * See comments for {@link IWifiNanIface#stopSubscribe(short, byte)} + */ + public boolean stopSubscribe(short transactionId, byte pubSubId) { + final String methodStr = "stopSubscribe"; + return validateAndCall(methodStr, false, + () -> stopSubscribeInternal(methodStr, transactionId, pubSubId)); + } + + /** + * See comments for {@link IWifiNanIface#createAwareNetworkInterface(short, String)} + */ + public boolean createAwareNetworkInterface(short transactionId, String interfaceName) { + final String methodStr = "createAwareNetworkInterface"; + return validateAndCall(methodStr, false, + () -> createAwareNetworkInterfaceInternal(methodStr, transactionId, interfaceName)); + } + + /** + * See comments for {@link IWifiNanIface#deleteAwareNetworkInterface(short, String)} + */ + public boolean deleteAwareNetworkInterface(short transactionId, String interfaceName) { + final String methodStr = "deleteAwareNetworkInterface"; + return validateAndCall(methodStr, false, + () -> deleteAwareNetworkInterfaceInternal(methodStr, transactionId, interfaceName)); + } + + /** + * See comments for {@link IWifiNanIface#initiateDataPath(short, int, int, int, MacAddress, + * String, boolean, byte[], Capabilities, + * WifiAwareDataPathSecurityConfig)} + */ + public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, + int channel, MacAddress peer, String interfaceName, + boolean isOutOfBand, byte[] appInfo, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig) { + final String methodStr = "initiateDataPath"; + return validateAndCall(methodStr, false, + () -> initiateDataPathInternal(methodStr, transactionId, peerId, channelRequestType, + channel, peer, interfaceName, isOutOfBand, appInfo, capabilities, + securityConfig)); + } + + /** + * See comments for {@link IWifiNanIface#respondToDataPathRequest(short, boolean, int, String, + * byte[], boolean, Capabilities, WifiAwareDataPathSecurityConfig)} + */ + public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, + String interfaceName, byte[] appInfo, boolean isOutOfBand, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig) { + final String methodStr = "respondToDataPathRequest"; + return validateAndCall(methodStr, false, + () -> respondToDataPathRequestInternal(methodStr, transactionId, accept, ndpId, + interfaceName, appInfo, isOutOfBand, capabilities, securityConfig)); + } + + /** + * See comments for {@link IWifiNanIface#endDataPath(short, int)} + */ + public boolean endDataPath(short transactionId, int ndpId) { + final String methodStr = "endDataPath"; + return validateAndCall(methodStr, false, + () -> endDataPathInternal(methodStr, transactionId, ndpId)); + } + + + // Internal Implementations + + private boolean registerFrameworkCallbackInternal(String methodStr, WifiNanIface.Callback cb) { + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (cb == null) { + Log.e(TAG, "Cannot register a null framework callback"); + return false; + } + + WifiStatus status; + try { + android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(); + android.hardware.wifi.V1_5.IWifiNanIface iface15 = mockableCastTo_1_5(); + android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(); + if (iface16 != null) { + status = iface16.registerEventCallback_1_6(mHalCallback); + } else if (iface15 != null) { + status = iface15.registerEventCallback_1_5(mHalCallback); + } else if (iface12 != null) { + status = iface12.registerEventCallback_1_2(mHalCallback); + } else { + status = mWifiNanIface.registerEventCallback(mHalCallback); + } + if (!isOk(status, methodStr)) return false; + mFrameworkCallback = cb; + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private String getNameInternal(String methodStr) { + if (mIfaceName != null) return mIfaceName; + Mutable<String> nameResp = new Mutable<>(); + try { + mWifiNanIface.getName((WifiStatus status, String name) -> { + if (isOk(status, methodStr)) { + nameResp.value = name; + mIfaceName = name; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return nameResp.value; + } + + private boolean getCapabilitiesInternal(String methodStr, short transactionId) { + android.hardware.wifi.V1_5.IWifiNanIface iface15 = mockableCastTo_1_5(); + try { + WifiStatus status; + if (iface15 == null) { + status = mWifiNanIface.getCapabilitiesRequest(transactionId); + } else { + status = iface15.getCapabilitiesRequest_1_5(transactionId); + } + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + boolean enableAndConfigureInternal( + String methodStr, short transactionId, ConfigRequest configRequest, + boolean notifyIdentityChange, boolean initialConfiguration, boolean rangingEnabled, + boolean isInstantCommunicationEnabled, int instantModeChannel, + int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) { + android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(); + android.hardware.wifi.V1_4.IWifiNanIface iface14 = mockableCastTo_1_4(); + android.hardware.wifi.V1_5.IWifiNanIface iface15 = mockableCastTo_1_5(); + android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(); + android.hardware.wifi.V1_2.NanConfigRequestSupplemental configSupplemental12 = + new android.hardware.wifi.V1_2.NanConfigRequestSupplemental(); + android.hardware.wifi.V1_5.NanConfigRequestSupplemental configSupplemental15 = + new android.hardware.wifi.V1_5.NanConfigRequestSupplemental(); + android.hardware.wifi.V1_6.NanConfigRequestSupplemental configSupplemental16 = + new android.hardware.wifi.V1_6.NanConfigRequestSupplemental(); + if (iface12 != null || iface14 != null) { + configSupplemental12.discoveryBeaconIntervalMs = 0; + configSupplemental12.numberOfSpatialStreamsInDiscovery = 0; + configSupplemental12.enableDiscoveryWindowEarlyTermination = false; + configSupplemental12.enableRanging = rangingEnabled; + } + + if (iface15 != null) { + configSupplemental15.V1_2 = configSupplemental12; + configSupplemental15.enableInstantCommunicationMode = isInstantCommunicationEnabled; + } + if (iface16 != null) { + configSupplemental16.V1_5 = configSupplemental15; + configSupplemental16.instantModeChannel = instantModeChannel; + } + + NanBandSpecificConfig config24 = new NanBandSpecificConfig(); + config24.rssiClose = 60; + config24.rssiMiddle = 70; + config24.rssiCloseProximity = 60; + config24.dwellTimeMs = (byte) 200; + config24.scanPeriodSec = 20; + if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ] + == ConfigRequest.DW_INTERVAL_NOT_INIT) { + config24.validDiscoveryWindowIntervalVal = false; + } else { + config24.validDiscoveryWindowIntervalVal = true; + config24.discoveryWindowIntervalVal = + (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest + .NAN_BAND_24GHZ]; + } + + NanBandSpecificConfig config5 = new NanBandSpecificConfig(); + config5.rssiClose = 60; + config5.rssiMiddle = 75; + config5.rssiCloseProximity = 60; + config5.dwellTimeMs = (byte) 200; + config5.scanPeriodSec = 20; + if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ] + == ConfigRequest.DW_INTERVAL_NOT_INIT) { + config5.validDiscoveryWindowIntervalVal = false; + } else { + config5.validDiscoveryWindowIntervalVal = true; + config5.discoveryWindowIntervalVal = + (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest + .NAN_BAND_5GHZ]; + } + + NanBandSpecificConfig config6 = new NanBandSpecificConfig(); + config6.rssiClose = 60; + config6.rssiMiddle = 75; + config6.rssiCloseProximity = 60; + config6.dwellTimeMs = (byte) 200; + config6.scanPeriodSec = 20; + if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_6GHZ] + == ConfigRequest.DW_INTERVAL_NOT_INIT) { + config6.validDiscoveryWindowIntervalVal = false; + } else { + config6.validDiscoveryWindowIntervalVal = true; + config6.discoveryWindowIntervalVal = + (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest + .NAN_BAND_6GHZ]; + } + + try { + WifiStatus status; + if (initialConfiguration) { + if (iface14 != null || iface15 != null || iface16 != null) { + // translate framework to HIDL configuration (V_1.4) + android.hardware.wifi.V1_4.NanEnableRequest req = + new android.hardware.wifi.V1_4.NanEnableRequest(); + + req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; + req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; + req.operateInBand[android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = + configRequest.mSupport6gBand; + req.hopCountMax = 2; + req.configParams.masterPref = (byte) configRequest.mMasterPreference; + req.configParams.disableDiscoveryAddressChangeIndication = + !notifyIdentityChange; + req.configParams.disableStartedClusterIndication = !notifyIdentityChange; + req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; + req.configParams.includePublishServiceIdsInBeacon = true; + req.configParams.numberOfPublishServiceIdsInBeacon = 0; + req.configParams.includeSubscribeServiceIdsInBeacon = true; + req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; + req.configParams.rssiWindowSize = 8; + req.configParams.macAddressRandomizationIntervalSec = + macAddressRandomizationIntervalSec; + + req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; + req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; + req.configParams.bandSpecificConfig[ + android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = config6; + + req.debugConfigs.validClusterIdVals = true; + req.debugConfigs.clusterIdTopRangeVal = (short) configRequest.mClusterHigh; + req.debugConfigs.clusterIdBottomRangeVal = (short) configRequest.mClusterLow; + req.debugConfigs.validIntfAddrVal = false; + req.debugConfigs.validOuiVal = false; + req.debugConfigs.ouiVal = 0; + req.debugConfigs.validRandomFactorForceVal = false; + req.debugConfigs.randomFactorForceVal = 0; + req.debugConfigs.validHopCountForceVal = false; + req.debugConfigs.hopCountForceVal = 0; + req.debugConfigs.validDiscoveryChannelVal = false; + req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; + req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; + req.debugConfigs.discoveryChannelMhzVal[ + android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = 0; + req.debugConfigs.validUseBeaconsInBandVal = false; + req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; + req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; + req.debugConfigs.useBeaconsInBandVal[ + android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = true; + req.debugConfigs.validUseSdfInBandVal = false; + req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; + req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; + req.debugConfigs.useSdfInBandVal[ + android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = true; + updateConfigForPowerSettings14(req.configParams, configSupplemental12, + powerParameters); + + if (iface16 != null) { + status = iface16.enableRequest_1_6(transactionId, req, + configSupplemental16); + } else if (iface15 != null) { + status = iface15.enableRequest_1_5(transactionId, req, + configSupplemental15); + } else { + status = iface14.enableRequest_1_4(transactionId, req, + configSupplemental12); + } + } else { + // translate framework to HIDL configuration (before V_1.4) + NanEnableRequest req = new NanEnableRequest(); + + req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; + req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; + req.hopCountMax = 2; + req.configParams.masterPref = (byte) configRequest.mMasterPreference; + req.configParams.disableDiscoveryAddressChangeIndication = + !notifyIdentityChange; + req.configParams.disableStartedClusterIndication = !notifyIdentityChange; + req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; + req.configParams.includePublishServiceIdsInBeacon = true; + req.configParams.numberOfPublishServiceIdsInBeacon = 0; + req.configParams.includeSubscribeServiceIdsInBeacon = true; + req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; + req.configParams.rssiWindowSize = 8; + req.configParams.macAddressRandomizationIntervalSec = + macAddressRandomizationIntervalSec; + + req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; + req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; + + req.debugConfigs.validClusterIdVals = true; + req.debugConfigs.clusterIdTopRangeVal = (short) configRequest.mClusterHigh; + req.debugConfigs.clusterIdBottomRangeVal = (short) configRequest.mClusterLow; + req.debugConfigs.validIntfAddrVal = false; + req.debugConfigs.validOuiVal = false; + req.debugConfigs.ouiVal = 0; + req.debugConfigs.validRandomFactorForceVal = false; + req.debugConfigs.randomFactorForceVal = 0; + req.debugConfigs.validHopCountForceVal = false; + req.debugConfigs.hopCountForceVal = 0; + req.debugConfigs.validDiscoveryChannelVal = false; + req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; + req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; + req.debugConfigs.validUseBeaconsInBandVal = false; + req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; + req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; + req.debugConfigs.validUseSdfInBandVal = false; + req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; + req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; + + updateConfigForPowerSettings(req.configParams, configSupplemental12, + powerParameters); + + if (iface12 != null) { + status = iface12.enableRequest_1_2(transactionId, req, + configSupplemental12); + } else { + status = mWifiNanIface.enableRequest(transactionId, req); + } + } + } else { + if (iface14 != null || iface15 != null || iface16 != null) { + android.hardware.wifi.V1_4.NanConfigRequest req = + new android.hardware.wifi.V1_4.NanConfigRequest(); + req.masterPref = (byte) configRequest.mMasterPreference; + req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; + req.disableStartedClusterIndication = !notifyIdentityChange; + req.disableJoinedClusterIndication = !notifyIdentityChange; + req.includePublishServiceIdsInBeacon = true; + req.numberOfPublishServiceIdsInBeacon = 0; + req.includeSubscribeServiceIdsInBeacon = true; + req.numberOfSubscribeServiceIdsInBeacon = 0; + req.rssiWindowSize = 8; + req.macAddressRandomizationIntervalSec = + macAddressRandomizationIntervalSec; + + req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; + req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; + req.bandSpecificConfig[android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ] = + config6; + + updateConfigForPowerSettings14(req, configSupplemental12, + powerParameters); + if (iface16 != null) { + status = iface16.configRequest_1_6(transactionId, req, + configSupplemental16); + } else if (iface15 != null) { + status = iface15.configRequest_1_5(transactionId, req, + configSupplemental15); + } else { + status = iface14.configRequest_1_4(transactionId, req, + configSupplemental12); + } + } else { + NanConfigRequest req = new NanConfigRequest(); + req.masterPref = (byte) configRequest.mMasterPreference; + req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; + req.disableStartedClusterIndication = !notifyIdentityChange; + req.disableJoinedClusterIndication = !notifyIdentityChange; + req.includePublishServiceIdsInBeacon = true; + req.numberOfPublishServiceIdsInBeacon = 0; + req.includeSubscribeServiceIdsInBeacon = true; + req.numberOfSubscribeServiceIdsInBeacon = 0; + req.rssiWindowSize = 8; + req.macAddressRandomizationIntervalSec = + macAddressRandomizationIntervalSec; + + req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; + req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; + + updateConfigForPowerSettings(req, configSupplemental12, powerParameters); + + if (iface12 != null) { + status = iface12.configRequest_1_2(transactionId, req, + configSupplemental12); + } else { + status = mWifiNanIface.configRequest(transactionId, req); + } + } + } + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean disableInternal(String methodStr, short transactionId) { + try { + WifiStatus status = mWifiNanIface.disableRequest(transactionId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean publishInternal(String methodStr, short transactionId, byte publishId, + PublishConfig publishConfig) { + android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(); + if (iface16 == null) { + NanPublishRequest req = new NanPublishRequest(); + req.baseConfigs.sessionId = publishId; + req.baseConfigs.ttlSec = (short) publishConfig.mTtlSec; + req.baseConfigs.discoveryWindowPeriod = 1; + req.baseConfigs.discoveryCount = 0; + convertNativeByteArrayToArrayList(publishConfig.mServiceName, + req.baseConfigs.serviceName); + req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER; + convertNativeByteArrayToArrayList(publishConfig.mServiceSpecificInfo, + req.baseConfigs.serviceSpecificInfo); + convertNativeByteArrayToArrayList(publishConfig.mMatchFilter, + publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED + ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); + req.baseConfigs.useRssiThreshold = false; + req.baseConfigs.disableDiscoveryTerminationIndication = + !publishConfig.mEnableTerminateNotification; + req.baseConfigs.disableMatchExpirationIndication = true; + req.baseConfigs.disableFollowupReceivedIndication = false; + + req.autoAcceptDataPathRequests = false; + + req.baseConfigs.rangingRequired = publishConfig.mEnableRanging; + + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; + WifiAwareDataPathSecurityConfig securityConfig = publishConfig.getSecurityConfig(); + if (securityConfig != null) { + req.baseConfigs.securityConfig.cipherType = getHalCipherSuiteType( + securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PMK; + copyArray(securityConfig.getPmk(), req.baseConfigs.securityConfig.pmk); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.baseConfigs.securityConfig.securityType = + NanDataPathSecurityType.PASSPHRASE; + convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), + req.baseConfigs.securityConfig.passphrase); + } + } + + req.publishType = publishConfig.mPublishType; + req.txType = NanTxType.BROADCAST; + + try { + WifiStatus status = mWifiNanIface.startPublishRequest(transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } else { + android.hardware.wifi.V1_6.NanPublishRequest req = + new android.hardware.wifi.V1_6.NanPublishRequest(); + req.baseConfigs.sessionId = publishId; + req.baseConfigs.ttlSec = (short) publishConfig.mTtlSec; + req.baseConfigs.discoveryWindowPeriod = 1; + req.baseConfigs.discoveryCount = 0; + convertNativeByteArrayToArrayList(publishConfig.mServiceName, + req.baseConfigs.serviceName); + req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER; + convertNativeByteArrayToArrayList(publishConfig.mServiceSpecificInfo, + req.baseConfigs.serviceSpecificInfo); + convertNativeByteArrayToArrayList(publishConfig.mMatchFilter, + publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED + ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); + req.baseConfigs.useRssiThreshold = false; + req.baseConfigs.disableDiscoveryTerminationIndication = + !publishConfig.mEnableTerminateNotification; + req.baseConfigs.disableMatchExpirationIndication = true; + req.baseConfigs.disableFollowupReceivedIndication = false; + + req.autoAcceptDataPathRequests = false; + + req.baseConfigs.rangingRequired = publishConfig.mEnableRanging; + + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; + WifiAwareDataPathSecurityConfig securityConfig = publishConfig.getSecurityConfig(); + if (securityConfig != null) { + req.baseConfigs.securityConfig.cipherType = getHalCipherSuiteType( + securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PMK; + copyArray(securityConfig.getPmk(), req.baseConfigs.securityConfig.pmk); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.baseConfigs.securityConfig.securityType = + NanDataPathSecurityType.PASSPHRASE; + convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), + req.baseConfigs.securityConfig.passphrase); + } + if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { + copyArray(securityConfig.getPmkId(), req.baseConfigs.securityConfig.scid); + } + } + + req.publishType = publishConfig.mPublishType; + req.txType = NanTxType.BROADCAST; + + try { + WifiStatus status = iface16.startPublishRequest_1_6(transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + } + + private boolean subscribeInternal(String methodStr, short transactionId, byte subscribeId, + SubscribeConfig subscribeConfig) { + NanSubscribeRequest req = new NanSubscribeRequest(); + req.baseConfigs.sessionId = subscribeId; + req.baseConfigs.ttlSec = (short) subscribeConfig.mTtlSec; + req.baseConfigs.discoveryWindowPeriod = 1; + req.baseConfigs.discoveryCount = 0; + convertNativeByteArrayToArrayList(subscribeConfig.mServiceName, + req.baseConfigs.serviceName); + req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_ONCE; + convertNativeByteArrayToArrayList(subscribeConfig.mServiceSpecificInfo, + req.baseConfigs.serviceSpecificInfo); + convertNativeByteArrayToArrayList(subscribeConfig.mMatchFilter, + subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE + ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); + req.baseConfigs.useRssiThreshold = false; + req.baseConfigs.disableDiscoveryTerminationIndication = + !subscribeConfig.mEnableTerminateNotification; + req.baseConfigs.disableMatchExpirationIndication = false; + req.baseConfigs.disableFollowupReceivedIndication = false; + + req.baseConfigs.rangingRequired = + subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet; + req.baseConfigs.configRangingIndications = 0; + if (subscribeConfig.mMinDistanceMmSet) { + req.baseConfigs.distanceEgressCm = (short) Math.min( + subscribeConfig.mMinDistanceMm / 10, Short.MAX_VALUE); + req.baseConfigs.configRangingIndications |= + android.hardware.wifi.V1_0.NanRangingIndication.EGRESS_MET_MASK; + } + if (subscribeConfig.mMaxDistanceMmSet) { + req.baseConfigs.distanceIngressCm = (short) Math.min( + subscribeConfig.mMaxDistanceMm / 10, Short.MAX_VALUE); + req.baseConfigs.configRangingIndications |= + android.hardware.wifi.V1_0.NanRangingIndication.INGRESS_MET_MASK; + } + + // TODO: configure security + req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; + + req.subscribeType = subscribeConfig.mSubscribeType; + + try { + WifiStatus status = mWifiNanIface.startSubscribeRequest(transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean sendMessageInternal(String methodStr, short transactionId, byte pubSubId, + int requestorInstanceId, MacAddress dest, byte[] message) { + NanTransmitFollowupRequest req = new NanTransmitFollowupRequest(); + req.discoverySessionId = pubSubId; + req.peerId = requestorInstanceId; + req.addr = dest.toByteArray(); + req.isHighPriority = false; + req.shouldUseDiscoveryWindow = true; + convertNativeByteArrayToArrayList(message, req.serviceSpecificInfo); + req.disableFollowupResultIndication = false; + + try { + WifiStatus status = mWifiNanIface.transmitFollowupRequest(transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean stopPublishInternal(String methodStr, short transactionId, byte pubSubId) { + try { + WifiStatus status = mWifiNanIface.stopPublishRequest(transactionId, pubSubId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean stopSubscribeInternal(String methodStr, short transactionId, byte pubSubId) { + try { + WifiStatus status = mWifiNanIface.stopSubscribeRequest(transactionId, pubSubId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean createAwareNetworkInterfaceInternal(String methodStr, short transactionId, + String interfaceName) { + try { + WifiStatus status = + mWifiNanIface.createDataInterfaceRequest(transactionId, interfaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean deleteAwareNetworkInterfaceInternal(String methodStr, short transactionId, + String interfaceName) { + try { + WifiStatus status = + mWifiNanIface.deleteDataInterfaceRequest(transactionId, interfaceName); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean initiateDataPathInternal(String methodStr, short transactionId, int peerId, + int channelRequestType, int channel, MacAddress peer, String interfaceName, + boolean isOutOfBand, byte[] appInfo, Capabilities capabilities, + WifiAwareDataPathSecurityConfig securityConfig) { + if (capabilities == null) { + Log.e(TAG, "Null capabilities were received"); + return false; + } + + android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(); + + if (iface16 == null) { + NanInitiateDataPathRequest req = new NanInitiateDataPathRequest(); + req.peerId = peerId; + req.peerDiscMacAddr = peer.toByteArray(); + req.channelRequestType = WifiNanIface.NanDataPathChannelCfg.toHidl(channelRequestType); + req.channel = channel; + req.ifaceName = interfaceName; + req.securityConfig.securityType = NanDataPathSecurityType.OPEN; + if (securityConfig != null) { + req.securityConfig.cipherType = getHalCipherSuiteType( + securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + + req.securityConfig.securityType = NanDataPathSecurityType.PMK; + copyArray(securityConfig.getPmk(), req.securityConfig.pmk); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; + convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), + req.securityConfig.passphrase); + } + } + + if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { + convertNativeByteArrayToArrayList(WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH + .getBytes(StandardCharsets.UTF_8), req.serviceNameOutOfBand); + } + convertNativeByteArrayToArrayList(appInfo, req.appInfo); + + try { + WifiStatus status = mWifiNanIface.initiateDataPathRequest(transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + Log.e(TAG, "initiateDataPath: exception: " + e); + return false; + } + } else { + android.hardware.wifi.V1_6.NanInitiateDataPathRequest req = + new android.hardware.wifi.V1_6.NanInitiateDataPathRequest(); + req.peerId = peerId; + req.peerDiscMacAddr = peer.toByteArray(); + req.channelRequestType = WifiNanIface.NanDataPathChannelCfg.toHidl(channelRequestType); + req.channel = channel; + req.ifaceName = interfaceName; + req.securityConfig.securityType = NanDataPathSecurityType.OPEN; + if (securityConfig != null) { + req.securityConfig.cipherType = getHalCipherSuiteType( + securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PMK; + copyArray(securityConfig.getPmk(), req.securityConfig.pmk); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; + convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), + req.securityConfig.passphrase); + } + if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { + copyArray(securityConfig.getPmkId(), req.securityConfig.scid); + } + } + + if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { + convertNativeByteArrayToArrayList(WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH + .getBytes(StandardCharsets.UTF_8), req.serviceNameOutOfBand); + } + convertNativeByteArrayToArrayList(appInfo, req.appInfo); + + try { + WifiStatus status = iface16.initiateDataPathRequest_1_6(transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + } + + private boolean respondToDataPathRequestInternal(String methodStr, short transactionId, + boolean accept, int ndpId, String interfaceName, byte[] appInfo, boolean isOutOfBand, + Capabilities capabilities, WifiAwareDataPathSecurityConfig securityConfig) { + if (capabilities == null) { + Log.e(TAG, "Null capabilities were received"); + return false; + } + + android.hardware.wifi.V1_6.IWifiNanIface iface16 = mockableCastTo_1_6(); + + if (iface16 == null) { + NanRespondToDataPathIndicationRequest req = new NanRespondToDataPathIndicationRequest(); + req.acceptRequest = accept; + req.ndpInstanceId = ndpId; + req.ifaceName = interfaceName; + req.securityConfig.securityType = NanDataPathSecurityType.OPEN; + if (securityConfig != null) { + req.securityConfig.cipherType = getHalCipherSuiteType( + securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + + req.securityConfig.securityType = NanDataPathSecurityType.PMK; + copyArray(securityConfig.getPmk(), req.securityConfig.pmk); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; + convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), + req.securityConfig.passphrase); + } + } + + if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { + convertNativeByteArrayToArrayList(WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH + .getBytes(StandardCharsets.UTF_8), req.serviceNameOutOfBand); + } + convertNativeByteArrayToArrayList(appInfo, req.appInfo); + + try { + WifiStatus status = mWifiNanIface.respondToDataPathIndicationRequest( + transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } else { + android.hardware.wifi.V1_6.NanRespondToDataPathIndicationRequest req = + new android.hardware.wifi.V1_6.NanRespondToDataPathIndicationRequest(); + req.acceptRequest = accept; + req.ndpInstanceId = ndpId; + req.ifaceName = interfaceName; + req.securityConfig.securityType = NanDataPathSecurityType.OPEN; + if (securityConfig != null) { + req.securityConfig.cipherType = getHalCipherSuiteType( + securityConfig.getCipherSuite()); + if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { + + req.securityConfig.securityType = NanDataPathSecurityType.PMK; + copyArray(securityConfig.getPmk(), req.securityConfig.pmk); + } + if (securityConfig.getPskPassphrase() != null + && securityConfig.getPskPassphrase().length() != 0) { + req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; + convertNativeByteArrayToArrayList(securityConfig.getPskPassphrase().getBytes(), + req.securityConfig.passphrase); + } + if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) { + copyArray(securityConfig.getPmkId(), req.securityConfig.scid); + } + } + + if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { + convertNativeByteArrayToArrayList(WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH + .getBytes(StandardCharsets.UTF_8), req.serviceNameOutOfBand); + } + convertNativeByteArrayToArrayList(appInfo, req.appInfo); + + try { + WifiStatus status = iface16 + .respondToDataPathIndicationRequest_1_6(transactionId, req); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + } + + private boolean endDataPathInternal(String methodStr, short transactionId, int ndpId) { + try { + WifiStatus status = mWifiNanIface.terminateDataPathRequest(transactionId, ndpId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + + // Helper Functions + + /** + * Update the NAN configuration to reflect the current power settings (before V1.4) + */ + private void updateConfigForPowerSettings(NanConfigRequest req, + android.hardware.wifi.V1_2.NanConfigRequestSupplemental configSupplemental12, + WifiNanIface.PowerParameters powerParameters) { + updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], + powerParameters.discoveryWindow5Ghz); + updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], + powerParameters.discoveryWindow24Ghz); + + configSupplemental12.discoveryBeaconIntervalMs = powerParameters.discoveryBeaconIntervalMs; + configSupplemental12.numberOfSpatialStreamsInDiscovery = + powerParameters.numberOfSpatialStreamsInDiscovery; + configSupplemental12.enableDiscoveryWindowEarlyTermination = + powerParameters.enableDiscoveryWindowEarlyTermination; + } + + /** + * Update the NAN configuration to reflect the current power settings (V1.4) + */ + private void updateConfigForPowerSettings14(android.hardware.wifi.V1_4.NanConfigRequest req, + android.hardware.wifi.V1_2.NanConfigRequestSupplemental configSupplemental12, + WifiNanIface.PowerParameters powerParameters) { + updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], + powerParameters.discoveryWindow5Ghz); + updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], + powerParameters.discoveryWindow24Ghz); + updateSingleConfigForPowerSettings(req.bandSpecificConfig[ + android.hardware.wifi.V1_4.NanBandIndex.NAN_BAND_6GHZ], + powerParameters.discoveryWindow6Ghz); + + configSupplemental12.discoveryBeaconIntervalMs = powerParameters.discoveryBeaconIntervalMs; + configSupplemental12.numberOfSpatialStreamsInDiscovery = + powerParameters.numberOfSpatialStreamsInDiscovery; + configSupplemental12.enableDiscoveryWindowEarlyTermination = + powerParameters.enableDiscoveryWindowEarlyTermination; + } + + private void updateSingleConfigForPowerSettings(NanBandSpecificConfig cfg, int override) { + if (override != -1) { + cfg.validDiscoveryWindowIntervalVal = true; + cfg.discoveryWindowIntervalVal = (byte) override; + } + } + + /** + * Returns the HAL cipher suite. + */ + private 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_128_MASK; + case WIFI_AWARE_CIPHER_SUITE_NCS_PK_256: + return NanCipherSuiteType.PUBLIC_KEY_256_MASK; + } + return NanCipherSuiteType.NONE; + } + + /** + * Converts a byte[] to an ArrayList<Byte>. Fills in the entries of the 'to' array if + * provided (non-null), otherwise creates and returns a new ArrayList<>. + * + * @param from The input byte[] to convert from. + * @param to An optional ArrayList<> to fill in from 'from'. + * + * @return A newly allocated ArrayList<> if 'to' is null, otherwise null. + */ + private ArrayList<Byte> convertNativeByteArrayToArrayList(byte[] from, ArrayList<Byte> to) { + if (from == null) { + from = new byte[0]; + } + + if (to == null) { + to = new ArrayList<>(from.length); + } else { + to.ensureCapacity(from.length); + } + for (int i = 0; i < from.length; ++i) { + to.add(from[i]); + } + return to; + } + + private void copyArray(byte[] from, byte[] to) { + if (from == null || to == null || from.length != to.length) { + Log.e(TAG, "copyArray error: from=" + Arrays.toString(from) + ", to=" + + Arrays.toString(to)); + return; + } + for (int i = 0; i < from.length; ++i) { + to[i] = from[i]; + } + } + + protected android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2() { + return android.hardware.wifi.V1_2.IWifiNanIface.castFrom(mWifiNanIface); + } + + protected android.hardware.wifi.V1_4.IWifiNanIface mockableCastTo_1_4() { + return android.hardware.wifi.V1_4.IWifiNanIface.castFrom(mWifiNanIface); + } + + protected android.hardware.wifi.V1_5.IWifiNanIface mockableCastTo_1_5() { + return android.hardware.wifi.V1_5.IWifiNanIface.castFrom(mWifiNanIface); + } + + protected android.hardware.wifi.V1_6.IWifiNanIface mockableCastTo_1_6() { + return android.hardware.wifi.V1_6.IWifiNanIface.castFrom(mWifiNanIface); + } + + private boolean isOk(WifiStatus status, String methodStr) { + if (status.code == WifiStatusCode.SUCCESS) return true; + Log.e(TAG, methodStr + " failed with status: " + status); + return false; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + Log.e(TAG, methodStr + " failed with remote exception: " + e); + mWifiNanIface = null; + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiNanIface == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiNanIface is null"); + return defaultVal; + } + return supplier.get(); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiP2pIface.java b/service/java/com/android/server/wifi/hal/WifiP2pIface.java new file mode 100644 index 0000000000..26414283b1 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiP2pIface.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.Log; + +/** + * Wrapper around a WifiP2pIface. + * May be initialized using a HIDL or AIDL WifiP2pIface. + */ +public class WifiP2pIface implements WifiHal.WifiInterface { + private static final String TAG = "WifiP2pIface"; + private final IWifiP2pIface mWifiP2pIface; + + public WifiP2pIface(@NonNull android.hardware.wifi.V1_0.IWifiP2pIface p2pIface) { + mWifiP2pIface = createWifiP2pIfaceHidlImplMockable(p2pIface); + } + + public WifiP2pIface(@NonNull android.hardware.wifi.IWifiP2pIface p2pIface) { + mWifiP2pIface = createWifiP2pIfaceAidlImplMockable(p2pIface); + } + + protected WifiP2pIfaceHidlImpl createWifiP2pIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiP2pIface p2pIface) { + return new WifiP2pIfaceHidlImpl(p2pIface); + } + + protected WifiP2pIfaceAidlImpl createWifiP2pIfaceAidlImplMockable( + android.hardware.wifi.IWifiP2pIface p2pIface) { + return new WifiP2pIfaceAidlImpl(p2pIface); + } + + private void handleNullIface(String methodStr) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiP2pIface is null"); + } + + /** + * See comments for {@link IWifiP2pIface#getName()} + */ + @Override + @Nullable + public String getName() { + final String methodStr = "getName"; + if (mWifiP2pIface == null) { + handleNullIface(methodStr); + return null; + } + return mWifiP2pIface.getName(); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiP2pIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiP2pIfaceAidlImpl.java new file mode 100644 index 0000000000..9ae33f6cc7 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiP2pIfaceAidlImpl.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 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.hal; + + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.util.Log; + +/** + * AIDL implementation of the IWifiP2pIface interface. + */ +public class WifiP2pIfaceAidlImpl implements IWifiP2pIface { + private static final String TAG = "WifiP2pIfaceAidlImpl"; + private android.hardware.wifi.IWifiP2pIface mWifiP2pIface; + private final Object mLock = new Object(); + private String mIfaceName; + + public WifiP2pIfaceAidlImpl(@NonNull android.hardware.wifi.IWifiP2pIface p2pIface) { + mWifiP2pIface = p2pIface; + } + + /** + * See comments for {@link com.android.server.wifi.hal.IWifiP2pIface#getName()} + */ + @Override + @Nullable + public String getName() { + final String methodStr = "getName"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return null; + if (mIfaceName != null) return mIfaceName; + try { + String ifaceName = mWifiP2pIface.getName(); + mIfaceName = ifaceName; + return mIfaceName; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + private boolean checkIfaceAndLogFailure(String methodStr) { + if (mWifiP2pIface == null) { + Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); + return false; + } + return true; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + mWifiP2pIface = null; + Log.e(TAG, methodStr + " failed with remote exception: " + e); + } + + private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { + Log.e(TAG, methodStr + " failed with service-specific exception: " + e); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiP2pIfaceHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiP2pIfaceHidlImpl.java new file mode 100644 index 0000000000..cb63e18940 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiP2pIfaceHidlImpl.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.hardware.wifi.V1_0.WifiStatus; +import android.hardware.wifi.V1_0.WifiStatusCode; +import android.os.RemoteException; +import android.util.Log; + +import com.android.server.wifi.util.GeneralUtil.Mutable; + +/** + * HIDL implementation of the IWifiP2pIface interface. + */ +public class WifiP2pIfaceHidlImpl implements IWifiP2pIface { + private static final String TAG = "WifiP2pIfaceHidlImpl"; + private android.hardware.wifi.V1_0.IWifiP2pIface mWifiP2pIface; + private String mIfaceName; + + public WifiP2pIfaceHidlImpl(@NonNull android.hardware.wifi.V1_0.IWifiP2pIface p2pIface) { + mWifiP2pIface = p2pIface; + } + + /** + * See comments for {@link com.android.server.wifi.hal.IWifiP2pIface#getName()} + */ + public String getName() { + final String methodStr = "getName"; + if (mWifiP2pIface == null) { + handleNullIface(methodStr); + return null; + } + if (mIfaceName != null) return mIfaceName; + Mutable<String> nameResp = new Mutable<>(); + try { + mWifiP2pIface.getName((WifiStatus status, String name) -> { + if (isOk(status, methodStr)) { + nameResp.value = name; + mIfaceName = name; + } + }); + } catch (RemoteException e) { + Log.e(TAG, "Exception in " + methodStr + ": " + e); + } + return nameResp.value; + } + + private boolean isOk(WifiStatus status, String methodStr) { + if (status.code == WifiStatusCode.SUCCESS) return true; + Log.e(TAG, methodStr + " failed with status: " + status); + return false; + } + + private void handleNullIface(String methodStr) { + Log.e(TAG, "Cannot call " + methodStr + " because mWifiP2pIface is null"); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiRttController.java b/service/java/com/android/server/wifi/hal/WifiRttController.java new file mode 100644 index 0000000000..2a0f7a6281 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiRttController.java @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.MacAddress; +import android.net.wifi.rtt.RangingRequest; +import android.net.wifi.rtt.RangingResult; +import android.util.Log; + +import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * Wrapper around a WifiRttController. + * May be initialized using a HIDL or AIDL WifiRttController. + */ +public class WifiRttController { + private static final String TAG = "WifiRttController"; + protected static final int CONVERSION_US_TO_MS = 1_000; + + private IWifiRttController mWifiRttController; + + /** Unknown status */ + public static final int FRAMEWORK_RTT_STATUS_UNKNOWN = -1; + /** Success */ + public static final int FRAMEWORK_RTT_STATUS_SUCCESS = 0; + /** General failure status */ + public static final int FRAMEWORK_RTT_STATUS_FAILURE = 1; + /** Target STA does not respond to request */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_RSP = 2; + /** Request rejected. Applies to 2-sided RTT only */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_REJECTED = 3; + public static final int FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; + /** Timing measurement times out */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT = 5; + /** Target on different channel, cannot range */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; + /** Ranging not supported */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY = 7; + /** Request aborted for unknown reason */ + public static final int FRAMEWORK_RTT_STATUS_ABORTED = 8; + /** Invalid T1-T4 timestamp */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS = 9; + /** 11mc protocol failed */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL = 10; + /** Request could not be scheduled */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE = 11; + /** Responder cannot collaborate at time of request */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; + /** Bad request args */ + public static final int FRAMEWORK_RTT_STATUS_INVALID_REQ = 13; + /** WiFi not enabled. */ + public static final int FRAMEWORK_RTT_STATUS_NO_WIFI = 14; + /** Responder overrides param info, cannot range with new params */ + public static final int FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; + + /** @hide */ + @IntDef(prefix = "FRAMEWORK_RTT_STATUS_", value = {FRAMEWORK_RTT_STATUS_UNKNOWN, + FRAMEWORK_RTT_STATUS_SUCCESS, FRAMEWORK_RTT_STATUS_FAILURE, + FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, FRAMEWORK_RTT_STATUS_FAIL_REJECTED, + FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, + FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, + FRAMEWORK_RTT_STATUS_ABORTED, FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, + FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, + FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, FRAMEWORK_RTT_STATUS_INVALID_REQ, + FRAMEWORK_RTT_STATUS_NO_WIFI, FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE}) + @Retention(RetentionPolicy.SOURCE) + public @interface FrameworkRttStatus {} + + /** + * Framework representation of RTT capabilities. + */ + public static class Capabilities { + // 1-sided rtt measurement is supported. + public boolean oneSidedRttSupported; + // Location configuration information supported. + public boolean lciSupported; + // Location civic records supported. + public boolean lcrSupported; + // Preamble supported, see bit mask definition above. + public int preambleSupported; + // RTT bandwidth supported. + public int bwSupported; + // Whether STA responder role is supported. + public boolean responderSupported; + // Draft 11mc version supported, including major and minor version. e.g., draft 4.3 is 43. + public byte mcVersion; + // Whether ftm rtt data collection is supported. + public boolean rttFtmSupported; + + public Capabilities() { + } + + public Capabilities(android.hardware.wifi.V1_0.RttCapabilities rttHalCapabilities) { + oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; + lciSupported = rttHalCapabilities.lciSupported; + lcrSupported = rttHalCapabilities.lcrSupported; + responderSupported = rttHalCapabilities.responderSupported; + preambleSupported = rttHalCapabilities.preambleSupport; + mcVersion = rttHalCapabilities.mcVersion; + bwSupported = rttHalCapabilities.bwSupport; + rttFtmSupported = rttHalCapabilities.rttFtmSupported; + } + + public Capabilities(android.hardware.wifi.V1_4.RttCapabilities rttHalCapabilities) { + oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; + lciSupported = rttHalCapabilities.lciSupported; + lcrSupported = rttHalCapabilities.lcrSupported; + responderSupported = rttHalCapabilities.responderSupported; + preambleSupported = rttHalCapabilities.preambleSupport; + mcVersion = rttHalCapabilities.mcVersion; + bwSupported = rttHalCapabilities.bwSupport; + rttFtmSupported = rttHalCapabilities.rttFtmSupported; + } + + public Capabilities(android.hardware.wifi.V1_6.RttCapabilities rttHalCapabilities) { + oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; + lciSupported = rttHalCapabilities.lciSupported; + lcrSupported = rttHalCapabilities.lcrSupported; + responderSupported = rttHalCapabilities.responderSupported; + preambleSupported = rttHalCapabilities.preambleSupport; + mcVersion = rttHalCapabilities.mcVersion; + bwSupported = rttHalCapabilities.bwSupport; + rttFtmSupported = rttHalCapabilities.rttFtmSupported; + } + + public Capabilities(android.hardware.wifi.RttCapabilities rttHalCapabilities) { + oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; + lciSupported = rttHalCapabilities.lciSupported; + lcrSupported = rttHalCapabilities.lcrSupported; + responderSupported = rttHalCapabilities.responderSupported; + preambleSupported = rttHalCapabilities.preambleSupport; + mcVersion = rttHalCapabilities.mcVersion; + bwSupported = rttHalCapabilities.bwSupport; + rttFtmSupported = rttHalCapabilities.rttFtmSupported; + } + } + + /** + * Callback to receive ranging results. + */ + public interface RttControllerRangingResultsCallback { + /** + * Called when ranging results are received from the HAL. + * + * @param cmdId Command ID specified in the original request. + * @param rangingResults A list of range results. + */ + void onRangingResults(int cmdId, List<RangingResult> rangingResults); + } + + public WifiRttController(@NonNull android.hardware.wifi.V1_0.IWifiRttController rttController) { + mWifiRttController = createWifiRttControllerHidlImplMockable(rttController); + } + + public WifiRttController(@NonNull android.hardware.wifi.IWifiRttController rttController) { + mWifiRttController = createWifiRttControllerAidlImplMockable(rttController); + } + + protected WifiRttControllerHidlImpl createWifiRttControllerHidlImplMockable( + @NonNull android.hardware.wifi.V1_0.IWifiRttController rttController) { + return new WifiRttControllerHidlImpl(rttController); + } + + protected WifiRttControllerAidlImpl createWifiRttControllerAidlImplMockable( + @NonNull android.hardware.wifi.IWifiRttController rttController) { + return new WifiRttControllerAidlImpl(rttController); + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiRttController == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiRttController is null"); + return defaultVal; + } + return supplier.get(); + } + + /** + * See comments for {@link IWifiRttController#setup()} + */ + public boolean setup() { + return validateAndCall("setup", false, + () -> mWifiRttController.setup()); + } + + /** + * See comments for {@link IWifiRttController#enableVerboseLogging(boolean)} + */ + public void enableVerboseLogging(boolean verbose) { + if (mWifiRttController != null) { + mWifiRttController.enableVerboseLogging(verbose); + } + } + + /** + * See comments for {@link IWifiRttController#registerRangingResultsCallback( + * RttControllerRangingResultsCallback)} + */ + public void registerRangingResultsCallback(RttControllerRangingResultsCallback callback) { + if (mWifiRttController != null) { + mWifiRttController.registerRangingResultsCallback(callback); + } + } + + /** + * See comments for {@link IWifiRttController#validate()} + */ + public boolean validate() { + return validateAndCall("validate", false, + () -> mWifiRttController.validate()); + } + + /** + * See comments for {@link IWifiRttController#getRttCapabilities()} + */ + @Nullable + public Capabilities getRttCapabilities() { + return validateAndCall("getRttCapabilities", null, + () -> mWifiRttController.getRttCapabilities()); + } + + /** + * See comments for {@link IWifiRttController#rangeRequest(int, RangingRequest)} + */ + public boolean rangeRequest(int cmdId, RangingRequest request) { + return validateAndCall("rangeRequest", false, + () -> mWifiRttController.rangeRequest(cmdId, request)); + } + + /** + * See comments for {@link IWifiRttController#rangeCancel(int, List)} + */ + public boolean rangeCancel(int cmdId, ArrayList<MacAddress> macAddresses) { + return validateAndCall("rangeCancel", false, + () -> mWifiRttController.rangeCancel(cmdId, macAddresses)); + } + + /** + * See comments for {@link IWifiRttController#dump(PrintWriter)} + */ + public void dump(PrintWriter pw) { + if (mWifiRttController != null) { + mWifiRttController.dump(pw); + } + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java new file mode 100644 index 0000000000..8629b088d8 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java @@ -0,0 +1,579 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.hardware.wifi.IWifiRttControllerEventCallback; +import android.hardware.wifi.RttBw; +import android.hardware.wifi.RttCapabilities; +import android.hardware.wifi.RttConfig; +import android.hardware.wifi.RttPeerType; +import android.hardware.wifi.RttPreamble; +import android.hardware.wifi.RttResult; +import android.hardware.wifi.RttStatus; +import android.hardware.wifi.RttType; +import android.hardware.wifi.WifiChannelInfo; +import android.hardware.wifi.WifiChannelWidthInMhz; +import android.net.MacAddress; +import android.net.wifi.rtt.RangingRequest; +import android.net.wifi.rtt.RangingResult; +import android.net.wifi.rtt.ResponderConfig; +import android.net.wifi.rtt.ResponderLocation; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.util.Log; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * AIDL implementation of the IWifiRttController interface. + */ +public class WifiRttControllerAidlImpl implements IWifiRttController { + private static final String TAG = "WifiRttControllerAidl"; + private boolean mVerboseLoggingEnabled = false; + + private android.hardware.wifi.IWifiRttController mWifiRttController; + private WifiRttController.Capabilities mRttCapabilities; + private WifiRttControllerEventCallback mHalCallback; + private Set<WifiRttController.RttControllerRangingResultsCallback> mRangingResultsCallbacks = + new HashSet<>(); + private final Object mLock = new Object(); + + public WifiRttControllerAidlImpl( + @NonNull android.hardware.wifi.IWifiRttController rttController) { + mWifiRttController = rttController; + mHalCallback = new WifiRttControllerEventCallback(); + } + + /** + * See comments for {@link IWifiRttController#setup()} + */ + @Override + public boolean setup() { + final String methodStr = "setup"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return false; + try { + mWifiRttController.registerEventCallback(mHalCallback); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + updateRttCapabilities(); + return true; + } + } + + /** + * See comments for {@link IWifiRttController#enableVerboseLogging(boolean)} + */ + @Override + public void enableVerboseLogging(boolean verbose) { + synchronized (mLock) { + mVerboseLoggingEnabled = verbose; + } + } + + /** + * See comments for {@link IWifiRttController#registerRangingResultsCallback( + * WifiRttController.RttControllerRangingResultsCallback)} + */ + @Override + public void registerRangingResultsCallback( + WifiRttController.RttControllerRangingResultsCallback callback) { + synchronized (mLock) { + if (!mRangingResultsCallbacks.add(callback)) { + Log.e(TAG, "Ranging results callback was already registered"); + } + } + } + + /** + * See comments for {@link IWifiRttController#validate()} + */ + @Override + public boolean validate() { + final String methodStr = "validate"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return false; + try { + // Just check that we can call this method successfully. + mWifiRttController.getBoundIface(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiRttController#getRttCapabilities()} + */ + @Override + @Nullable + public WifiRttController.Capabilities getRttCapabilities() { + synchronized (mLock) { + return mRttCapabilities; + } + } + + /** + * See comments for {@link IWifiRttController#rangeRequest(int, RangingRequest)} + */ + @Override + public boolean rangeRequest(int cmdId, RangingRequest request) { + final String methodStr = "rangeRequest"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return false; + if (mVerboseLoggingEnabled) { + Log.v(TAG, "rangeRequest: cmdId=" + cmdId + ", # of requests=" + + request.mRttPeers.size() + ", request=" + request); + } + + updateRttCapabilities(); + try { + RttConfig[] rttConfigs = + convertRangingRequestToRttConfigs(request, mRttCapabilities); + if (rttConfigs == null) { + Log.e(TAG, methodStr + " received invalid request parameters"); + return false; + } else if (rttConfigs.length == 0) { + Log.e(TAG, methodStr + " invalidated all requests"); + dispatchOnRangingResults(cmdId, new ArrayList<>()); + return true; + } + mWifiRttController.rangeRequest(cmdId, rttConfigs); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiRttController#rangeCancel(int, List)} + */ + @Override + public boolean rangeCancel(int cmdId, List<MacAddress> macAddresses) { + final String methodStr = "rangeCancel"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return false; + try { + android.hardware.wifi.MacAddress[] halAddresses = + new android.hardware.wifi.MacAddress[macAddresses.size()]; + for (int i = 0; i < macAddresses.size(); i++) { + android.hardware.wifi.MacAddress halAddress = + new android.hardware.wifi.MacAddress(); + halAddress.data = macAddresses.get(i).toByteArray(); + halAddresses[i] = halAddress; + } + mWifiRttController.rangeCancel(cmdId, halAddresses); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiRttController#dump(PrintWriter)} + */ + @Override + public void dump(PrintWriter pw) { + pw.println("WifiRttController:"); + pw.println(" mIWifiRttController: " + mWifiRttController); + pw.println(" mRttCapabilities: " + mRttCapabilities); + } + + /** + * Callback for HAL events on the WifiRttController + */ + private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub { + @Override + public void onResults(int cmdId, RttResult[] halResults) { + if (mVerboseLoggingEnabled) { + int numResults = halResults != null ? halResults.length : -1; + Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + numResults); + } + if (halResults == null) { + halResults = new RttResult[0]; + } + ArrayList<RangingResult> rangingResults = halToFrameworkRangingResults(halResults); + dispatchOnRangingResults(cmdId, rangingResults); + } + + @Override + public String getInterfaceHash() { + return IWifiRttControllerEventCallback.HASH; + } + + @Override + public int getInterfaceVersion() { + return IWifiRttControllerEventCallback.VERSION; + } + } + + + // Utilities + + private ArrayList<RangingResult> halToFrameworkRangingResults(RttResult[] halResults) { + ArrayList<RangingResult> rangingResults = new ArrayList(); + for (RttResult rttResult : halResults) { + if (rttResult == null) continue; + byte[] lci = rttResult.lci.data; + byte[] lcr = rttResult.lcr.data; + ResponderLocation responderLocation; + try { + responderLocation = new ResponderLocation(lci, lcr); + if (!responderLocation.isValid()) { + responderLocation = null; + } + } catch (Exception e) { + responderLocation = null; + Log.e(TAG, "ResponderLocation: lci/lcr parser failed exception -- " + e); + } + if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { + if (mVerboseLoggingEnabled) { + Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " + + "samples!? result=" + rttResult); + } + rttResult.distanceSdInMm = 0; + } + rangingResults.add(new RangingResult( + halToFrameworkRttStatus(rttResult.status), + MacAddress.fromBytes(rttResult.addr), + rttResult.distanceInMm, rttResult.distanceSdInMm, + rttResult.rssi / -2, rttResult.numberPerBurstPeer, + rttResult.successNumber, lci, lcr, responderLocation, + rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS, + rttResult.type == RttType.TWO_SIDED)); + } + return rangingResults; + } + + private static @WifiRttController.FrameworkRttStatus int halToFrameworkRttStatus( + int halStatus) { + switch (halStatus) { + case RttStatus.SUCCESS: + return WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS; + case RttStatus.FAILURE: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE; + case RttStatus.FAIL_NO_RSP: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP; + case RttStatus.FAIL_REJECTED: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED; + case RttStatus.FAIL_NOT_SCHEDULED_YET: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET; + case RttStatus.FAIL_TM_TIMEOUT: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT; + case RttStatus.FAIL_AP_ON_DIFF_CHANNEL: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; + case RttStatus.FAIL_NO_CAPABILITY: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY; + case RttStatus.ABORTED: + return WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED; + case RttStatus.FAIL_INVALID_TS: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS; + case RttStatus.FAIL_PROTOCOL: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL; + case RttStatus.FAIL_SCHEDULE: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE; + case RttStatus.FAIL_BUSY_TRY_LATER: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER; + case RttStatus.INVALID_REQ: + return WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ; + case RttStatus.NO_WIFI: + return WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI; + case RttStatus.FAIL_FTM_PARAM_OVERRIDE: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; + default: + Log.e(TAG, "Unrecognized RttStatus: " + halStatus); + return WifiRttController.FRAMEWORK_RTT_STATUS_UNKNOWN; + } + } + + private void updateRttCapabilities() { + final String methodStr = "updateRttCapabilities"; + if (mRttCapabilities != null) return; + if (mVerboseLoggingEnabled) Log.v(TAG, "updateRttCapabilities"); + + try { + RttCapabilities halCapabilities = mWifiRttController.getCapabilities(); + mRttCapabilities = new WifiRttController.Capabilities(halCapabilities); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + + if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { + Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - " + + "ignored!?"); + } + } + + private static RttConfig[] convertRangingRequestToRttConfigs(RangingRequest request, + WifiRttController.Capabilities cap) { + ArrayList<RttConfig> rttConfigs = new ArrayList<>(); + + // Skip any configurations which have an error (just print out a message). + // The caller will only get results for valid configurations. + for (ResponderConfig responder: request.mRttPeers) { + RttConfig config = new RttConfig(); + config.addr = responder.macAddress.toByteArray(); + + try { + config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; + if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { + Log.w(TAG, "Device does not support one-sided RTT"); + continue; + } + + config.peer = frameworkToHalRttPeerType(responder.responderType); + config.channel = new WifiChannelInfo(); + config.channel.width = frameworkToHalChannelWidth( + responder.channelWidth); + config.channel.centerFreq = responder.frequency; + config.channel.centerFreq0 = responder.centerFreq0; + config.channel.centerFreq1 = responder.centerFreq1; + config.bw = frameworkToHalChannelBandwidth(responder.channelWidth); + config.preamble = frameworkToHalResponderPreamble(responder.preamble); + validateBwAndPreambleCombination(config.bw, config.preamble); + + if (config.peer == RttPeerType.NAN_TYPE) { + config.mustRequestLci = false; + config.mustRequestLcr = false; + config.burstPeriod = 0; + config.numBurst = 0; + config.numFramesPerBurst = request.mRttBurstSize; + config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT + config.numRetriesPerFtmr = 3; + config.burstDuration = 9; + } else { // AP + all non-NAN requests + config.mustRequestLci = true; + config.mustRequestLcr = true; + config.burstPeriod = 0; + config.numBurst = 0; + config.numFramesPerBurst = request.mRttBurstSize; + config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); + config.numRetriesPerFtmr = 3; + config.burstDuration = 9; + + if (cap != null) { // constrain parameters per device capabilities + config.mustRequestLci = config.mustRequestLci && cap.lciSupported; + config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; + config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); + config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); + } + } + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid configuration: " + e.getMessage()); + continue; + } + + rttConfigs.add(config); + } + + RttConfig[] configArray = new RttConfig[rttConfigs.size()]; + for (int i = 0; i < rttConfigs.size(); i++) { + configArray[i] = rttConfigs.get(i); + } + return configArray; + } + + private static void validateBwAndPreambleCombination(int bw, int preamble) { + if (bw <= RttBw.BW_20MHZ) { + return; + } + if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) { + return; + } + if (bw == RttBw.BW_320MHZ && preamble == RttPreamble.EHT) { + return; + } + if (bw >= RttBw.BW_80MHZ && bw < RttBw.BW_320MHZ && preamble >= RttPreamble.VHT) { + return; + } + throw new IllegalArgumentException( + "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble); + } + + private static int frameworkToHalRttPeerType(int responderType) + throws IllegalArgumentException { + switch (responderType) { + case ResponderConfig.RESPONDER_AP: + return RttPeerType.AP; + case ResponderConfig.RESPONDER_STA: + return RttPeerType.STA; + case ResponderConfig.RESPONDER_P2P_GO: + return RttPeerType.P2P_GO; + case ResponderConfig.RESPONDER_P2P_CLIENT: + return RttPeerType.P2P_CLIENT; + case ResponderConfig.RESPONDER_AWARE: + return RttPeerType.NAN_TYPE; + default: + throw new IllegalArgumentException( + "frameworkToHalRttPeerType: bad " + responderType); + } + } + + private static int frameworkToHalChannelWidth(int responderChannelWidth) + throws IllegalArgumentException { + switch (responderChannelWidth) { + case ResponderConfig.CHANNEL_WIDTH_20MHZ: + return WifiChannelWidthInMhz.WIDTH_20; + case ResponderConfig.CHANNEL_WIDTH_40MHZ: + return WifiChannelWidthInMhz.WIDTH_40; + case ResponderConfig.CHANNEL_WIDTH_80MHZ: + return WifiChannelWidthInMhz.WIDTH_80; + case ResponderConfig.CHANNEL_WIDTH_160MHZ: + return WifiChannelWidthInMhz.WIDTH_160; + case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: + return WifiChannelWidthInMhz.WIDTH_80P80; + case ResponderConfig.CHANNEL_WIDTH_320MHZ: + return WifiChannelWidthInMhz.WIDTH_320; + default: + throw new IllegalArgumentException( + "frameworkToHalChannelWidth: bad " + responderChannelWidth); + } + } + + private static int frameworkToHalChannelBandwidth(int responderChannelWidth) + throws IllegalArgumentException { + switch (responderChannelWidth) { + case ResponderConfig.CHANNEL_WIDTH_20MHZ: + return RttBw.BW_20MHZ; + case ResponderConfig.CHANNEL_WIDTH_40MHZ: + return RttBw.BW_40MHZ; + case ResponderConfig.CHANNEL_WIDTH_80MHZ: + return RttBw.BW_80MHZ; + case ResponderConfig.CHANNEL_WIDTH_160MHZ: + case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: + return RttBw.BW_160MHZ; + case ResponderConfig.CHANNEL_WIDTH_320MHZ: + return RttBw.BW_320MHZ; + default: + throw new IllegalArgumentException( + "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth); + } + } + + private static int frameworkToHalResponderPreamble(int responderPreamble) + throws IllegalArgumentException { + switch (responderPreamble) { + case ResponderConfig.PREAMBLE_LEGACY: + return RttPreamble.LEGACY; + case ResponderConfig.PREAMBLE_HT: + return RttPreamble.HT; + case ResponderConfig.PREAMBLE_VHT: + return RttPreamble.VHT; + case ResponderConfig.PREAMBLE_HE: + return RttPreamble.HE; + default: + throw new IllegalArgumentException( + "frameworkToHalResponderPreamble: bad " + responderPreamble); + } + } + + /** + * Check whether the selected RTT channel bandwidth is supported by the device. + * If supported, return the requested bandwidth. + * If not supported, return the next lower bandwidth which is supported. + * If none, throw an IllegalArgumentException. + * + * Note: the halRttChannelBandwidth is a single bit flag from the HAL RttBw type. + */ + private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, + WifiRttController.Capabilities cap) throws IllegalArgumentException { + int requestedBandwidth = halRttChannelBandwidth; + while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & cap.bwSupported) == 0)) { + halRttChannelBandwidth >>= 1; + } + + if (halRttChannelBandwidth != 0) { + return halRttChannelBandwidth; + } + + throw new IllegalArgumentException( + "RTT BW=" + requestedBandwidth + ", not supported by device capabilities=" + cap + + " - and no supported alternative"); + } + + /** + * Check whether the selected RTT preamble is supported by the device. + * If supported, return the requested preamble. + * If not supported, return the next "lower" preamble which is supported. + * If none, throw an IllegalArgumentException. + * + * Note: the halRttPreamble is a single bit flag from the HAL RttPreamble type. + */ + private static int halRttPreambleCapabilityLimiter(int halRttPreamble, + WifiRttController.Capabilities cap) throws IllegalArgumentException { + int requestedPreamble = halRttPreamble; + while ((halRttPreamble != 0) && ((halRttPreamble & cap.preambleSupported) == 0)) { + halRttPreamble >>= 1; + } + + if (halRttPreamble != 0) { + return halRttPreamble; + } + + throw new IllegalArgumentException( + "RTT Preamble=" + requestedPreamble + ", not supported by device capabilities=" + + cap + " - and no supported alternative"); + } + + private void dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults) { + for (WifiRttController.RttControllerRangingResultsCallback + callback : mRangingResultsCallbacks) { + callback.onRangingResults(cmdId, rangingResults); + } + } + + private boolean checkIfaceAndLogFailure(String methodStr) { + if (mWifiRttController == null) { + Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); + return false; + } + return true; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + mWifiRttController = null; + Log.e(TAG, methodStr + " failed with remote exception: " + e); + } + + private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { + Log.e(TAG, methodStr + " failed with service-specific exception: " + e); + } +} diff --git a/service/java/com/android/server/wifi/rtt/RttNative.java b/service/java/com/android/server/wifi/hal/WifiRttControllerHidlImpl.java index a4fd9e7516..6ef2eaabff 100644 --- a/service/java/com/android/server/wifi/rtt/RttNative.java +++ b/service/java/com/android/server/wifi/hal/WifiRttControllerHidlImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2022 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. @@ -14,13 +14,11 @@ * limitations under the License. */ -package com.android.server.wifi.rtt; +package com.android.server.wifi.hal; -import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.wifi.V1_0.IWifiRttController; import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback; -import android.hardware.wifi.V1_0.RttCapabilities; import android.hardware.wifi.V1_0.RttConfig; import android.hardware.wifi.V1_0.RttPeerType; import android.hardware.wifi.V1_0.RttResult; @@ -36,425 +34,560 @@ import android.net.wifi.rtt.RangingRequest; import android.net.wifi.rtt.RangingResult; import android.net.wifi.rtt.ResponderConfig; import android.net.wifi.rtt.ResponderLocation; -import android.os.Handler; import android.os.RemoteException; import android.util.Log; -import com.android.server.wifi.HalDeviceManager; +import com.android.server.wifi.util.GeneralUtil.Mutable; import com.android.server.wifi.util.NativeUtil; -import java.io.FileDescriptor; import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.function.Supplier; /** - * TBD + * HIDL implementation of the IWifiRttController interface. */ -public class RttNative { - private static final String TAG = "RttNative"; - private static final boolean VDBG = false; // STOPSHIP if true +public class WifiRttControllerHidlImpl implements IWifiRttController { + private static final String TAG = "WifiRttControllerHidl"; private boolean mVerboseLoggingEnabled = false; - /** Unknown status */ - public static final int FRAMEWORK_RTT_STATUS_UNKNOWN = -1; - /** Success */ - public static final int FRAMEWORK_RTT_STATUS_SUCCESS = 0; - /** General failure status */ - public static final int FRAMEWORK_RTT_STATUS_FAILURE = 1; - /** Target STA does not respond to request */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_RSP = 2; - /** Request rejected. Applies to 2-sided RTT only */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_REJECTED = 3; - public static final int FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; - /** Timing measurement times out */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT = 5; - /** Target on different channel, cannot range */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; - /** Ranging not supported */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY = 7; - /** Request aborted for unknown reason */ - public static final int FRAMEWORK_RTT_STATUS_ABORTED = 8; - /** Invalid T1-T4 timestamp */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS = 9; - /** 11mc protocol failed */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL = 10; - /** Request could not be scheduled */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE = 11; - /** Responder cannot collaborate at time of request */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; - /** Bad request args */ - public static final int FRAMEWORK_RTT_STATUS_INVALID_REQ = 13; - /** WiFi not enabled. */ - public static final int FRAMEWORK_RTT_STATUS_NO_WIFI = 14; - /** Responder overrides param info, cannot range with new params */ - public static final int FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; - - /** @hide */ - @IntDef(prefix = "FRAMEWORK_RTT_STATUS_", value = {FRAMEWORK_RTT_STATUS_UNKNOWN, - FRAMEWORK_RTT_STATUS_SUCCESS, FRAMEWORK_RTT_STATUS_FAILURE, - FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, FRAMEWORK_RTT_STATUS_FAIL_REJECTED, - FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, - FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, - FRAMEWORK_RTT_STATUS_ABORTED, FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, - FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, - FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, FRAMEWORK_RTT_STATUS_INVALID_REQ, - FRAMEWORK_RTT_STATUS_NO_WIFI, FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE}) - @Retention(RetentionPolicy.SOURCE) - public @interface FrameworkRttStatus {} - - - private final RttServiceImpl mRttService; - private final HalDeviceManager mHalDeviceManager; - - private Object mLock = new Object(); - - private volatile IWifiRttController mIWifiRttController; - private volatile Capabilities mRttCapabilities; + private android.hardware.wifi.V1_0.IWifiRttController mWifiRttController; + private android.hardware.wifi.V1_4.IWifiRttController mWifiRttController14; + private android.hardware.wifi.V1_6.IWifiRttController mWifiRttController16; private final WifiRttControllerEventCallback mWifiRttControllerEventCallback; - private volatile android.hardware.wifi.V1_4.IWifiRttController mIWifiRttController14; - private volatile android.hardware.wifi.V1_6.IWifiRttController mIWifiRttController16; private final WifiRttControllerEventCallback14 mWifiRttControllerEventCallback14; private final WifiRttControllerEventCallback16 mWifiRttControllerEventCallback16; - private static final int CONVERSION_US_TO_MS = 1_000; - - private final HalDeviceManager.InterfaceRttControllerLifecycleCallback mRttLifecycleCb = - new HalDeviceManager.InterfaceRttControllerLifecycleCallback() { - @Override - public void onNewRttController(IWifiRttController controller) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, - "onNewRttController: controller=" + controller); - } - boolean changed = mIWifiRttController == null; - synchronized (mLock) { - mIWifiRttController = controller; - mIWifiRttController14 = getWifiRttControllerV1_4(); - mIWifiRttController16 = getWifiRttControllerV1_6(); - try { - if (mIWifiRttController16 != null) { - mIWifiRttController16.registerEventCallback_1_6( - mWifiRttControllerEventCallback16); - } else if (mIWifiRttController14 != null) { - mIWifiRttController14.registerEventCallback_1_4( - mWifiRttControllerEventCallback14); - } else { - mIWifiRttController.registerEventCallback( - mWifiRttControllerEventCallback); - } - } catch (RemoteException e) { - Log.e(TAG, "onNewRttController: exception registering callback: " + e); - if (mIWifiRttController != null) { - mIWifiRttController = null; - mIWifiRttController14 = null; - mIWifiRttController16 = null; - mRttService.disable(); - } - return; - } - if (changed) { - mRttService.enableIfPossible(); - } - updateRttCapabilities(); - } - } - - @Override - public void onRttControllerDestroyed() { - if (mVerboseLoggingEnabled) Log.d(TAG, "onRttControllerDestroyed"); - synchronized (mLock) { - mIWifiRttController = null; - mIWifiRttController14 = null; - mIWifiRttController16 = null; - mRttCapabilities = null; - mRttService.disable(); - } - } - }; - - public RttNative(RttServiceImpl rttService, HalDeviceManager halDeviceManager) { - mRttService = rttService; - mHalDeviceManager = halDeviceManager; + private WifiRttController.Capabilities mRttCapabilities; + private Set<WifiRttController.RttControllerRangingResultsCallback> mRangingResultsCallbacks = + new HashSet<>(); + + public WifiRttControllerHidlImpl( + @NonNull android.hardware.wifi.V1_0.IWifiRttController rttController) { + mWifiRttController = rttController; + mWifiRttController14 = + android.hardware.wifi.V1_4.IWifiRttController.castFrom(mWifiRttController); + mWifiRttController16 = + android.hardware.wifi.V1_6.IWifiRttController.castFrom(mWifiRttController); mWifiRttControllerEventCallback = new WifiRttControllerEventCallback(); mWifiRttControllerEventCallback14 = new WifiRttControllerEventCallback14(); mWifiRttControllerEventCallback16 = new WifiRttControllerEventCallback16(); } /** - * Initialize the object - registering with the HAL device manager. + * See comments for {@link IWifiRttController#setup()} */ - public void start(Handler handler) { - synchronized (mLock) { - mHalDeviceManager.initialize(); - mHalDeviceManager.registerStatusListener(() -> { - if (VDBG) Log.d(TAG, "hdm.onStatusChanged"); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, - handler); - } - }, handler); - if (mHalDeviceManager.isStarted()) { - mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, handler); - } - } + public boolean setup() { + final String methodStr = "setup"; + return validateAndCall(methodStr, false, + () -> setupInternal(methodStr)); } /** - * Enable/Disable verbose logging. - * + * See comments for {@link IWifiRttController#enableVerboseLogging(boolean)} */ - public void enableVerboseLogging(boolean verboseEnabled) { - mVerboseLoggingEnabled = verboseEnabled; + public void enableVerboseLogging(boolean verbose) { + mVerboseLoggingEnabled = verbose; } /** - * Returns true if Wi-Fi is ready for RTT requests, false otherwise. + * See comments for {@link IWifiRttController#registerRangingResultsCallback( + * WifiRttController.RttControllerRangingResultsCallback)} */ - public boolean isReady() { - return mIWifiRttController != null; + public void registerRangingResultsCallback( + WifiRttController.RttControllerRangingResultsCallback callback) { + if (!mRangingResultsCallbacks.add(callback)) { + Log.e(TAG, "Ranging results callback was already registered"); + } } /** - * Returns the RTT capabilities. Will only be null when disabled (e.g. no STA interface - * available - not necessarily up). + * See comments for {@link IWifiRttController#validate()} */ - public @Nullable Capabilities getRttCapabilities() { + public boolean validate() { + final String methodStr = "validate"; + return validateAndCall(methodStr, false, + () -> validateInternal(methodStr)); + } + + /** + * See comments for {@link IWifiRttController#getRttCapabilities()} + */ + @Nullable + public WifiRttController.Capabilities getRttCapabilities() { return mRttCapabilities; } /** - * Updates the RTT capabilities. + * See comments for {@link IWifiRttController#rangeRequest(int, RangingRequest)} */ - void updateRttCapabilities() { - if (mIWifiRttController == null) { - Log.e(TAG, "updateRttCapabilities: but a RTT controller is NULL!?"); - return; - } - if (mRttCapabilities != null) { - return; - } - if (mVerboseLoggingEnabled) Log.v(TAG, "updateRttCapabilities"); + public boolean rangeRequest(int cmdId, RangingRequest request) { + final String methodStr = "rangeRequest"; + return validateAndCall(methodStr, false, + () -> rangeRequestInternal(methodStr, cmdId, request)); + } - synchronized (mLock) { - try { - if (mIWifiRttController16 != null) { - mIWifiRttController16.getCapabilities_1_6( - (status, capabilities16) -> { - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "updateRttCapabilities:" - + " error requesting capabilities " - + "-- code=" + status.code); - return; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateRttCapabilities: RTT capabilities=" - + capabilities16); - } - mRttCapabilities = new Capabilities(capabilities16); - }); - } else if (mIWifiRttController14 != null) { - mIWifiRttController14.getCapabilities_1_4( - (status, capabilities14) -> { - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "updateRttCapabilities:" - + " error requesting capabilities " - + "-- code=" + status.code); - return; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateRttCapabilities: RTT capabilities=" - + capabilities14); - } - mRttCapabilities = new Capabilities(capabilities14); - }); - } else { - mIWifiRttController.getCapabilities( - (status, capabilities) -> { - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "updateRttCapabilities:" - + " error requesting capabilities " - + "-- code=" + status.code); - return; - } - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateRttCapabilities: RTT capabilities=" - + capabilities); - } - mRttCapabilities = new Capabilities(capabilities); - }); - } - } catch (RemoteException e) { - Log.e(TAG, "updateRttCapabilities: exception requesting capabilities: " + e); - } + /** + * See comments for {@link IWifiRttController#rangeCancel(int, List)} + */ + public boolean rangeCancel(int cmdId, List<MacAddress> macAddresses) { + final String methodStr = "rangeCancel"; + return validateAndCall(methodStr, false, + () -> rangeCancelInternal(methodStr, cmdId, macAddresses)); + } + + /** + * See comments for {@link IWifiRttController#dump(PrintWriter)} + */ + public void dump(PrintWriter pw) { + pw.println("WifiRttController:"); + pw.println(" mIWifiRttController: " + mWifiRttController); + pw.println(" mRttCapabilities: " + mRttCapabilities); + } + + + // Internal Implementations - if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { - Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - " - + "ignored!?"); + private boolean setupInternal(String methodStr) { + try { + if (mWifiRttController16 != null) { + mWifiRttController16.registerEventCallback_1_6(mWifiRttControllerEventCallback16); + } else if (mWifiRttController14 != null) { + mWifiRttController14.registerEventCallback_1_4(mWifiRttControllerEventCallback14); + } else { + mWifiRttController.registerEventCallback(mWifiRttControllerEventCallback); } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; } + updateRttCapabilities(); + return true; } - /** - * Issue a range request to the HAL. - * - * @param cmdId Command ID for the request. Will be used in the corresponding - * {@link WifiRttControllerEventCallback#onResults(int, ArrayList)}. - * @param request Range request. - * @param isCalledFromPrivilegedContext Indicates whether privileged APIs are permitted, - * initially: support for one-sided RTT. - * - * @return Success status: true for success, false for failure. - */ - public boolean rangeRequest(int cmdId, RangingRequest request, - boolean isCalledFromPrivilegedContext) { + private boolean validateInternal(String methodStr) { + Mutable<Boolean> isRttControllerValid = new Mutable<>(false); + try { + mWifiRttController.getBoundIface( + (status, iface) -> { + if (isOk(status, methodStr)) { + isRttControllerValid.value = true; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return isRttControllerValid.value; + } + + private boolean rangeRequestInternal(String methodStr, int cmdId, RangingRequest request) { if (mVerboseLoggingEnabled) { - Log.v(TAG, - "rangeRequest: cmdId=" + cmdId + ", # of requests=" + request.mRttPeers.size()); + Log.v(TAG, "rangeRequest: cmdId=" + cmdId + ", # of requests=" + + request.mRttPeers.size() + ", request=" + request); } - if (VDBG) Log.v(TAG, "rangeRequest: request=" + request); - synchronized (mLock) { - if (!isReady()) { - Log.e(TAG, "rangeRequest: RttController is null"); - return false; - } - updateRttCapabilities(); - if (mIWifiRttController16 != null) { - return sendRangeRequest16(cmdId, request, isCalledFromPrivilegedContext); - } else if (mIWifiRttController14 != null) { - return sendRangeRequest14(cmdId, request, isCalledFromPrivilegedContext); - } else { - return sendRangeRequest(cmdId, request, isCalledFromPrivilegedContext); - } + updateRttCapabilities(); + if (mWifiRttController16 != null) { + return sendRangeRequest16(cmdId, request); + } else if (mWifiRttController14 != null) { + return sendRangeRequest14(cmdId, request); + } else { + return sendRangeRequest(cmdId, request); } } - private boolean sendRangeRequest(int cmdId, RangingRequest request, - boolean isCalledFromPrivilegedContext) { - ArrayList<RttConfig> rttConfig = convertRangingRequestToRttConfigs(request, - isCalledFromPrivilegedContext, mRttCapabilities); + private boolean sendRangeRequest(int cmdId, RangingRequest request) { + final String methodStr = "sendRangeRequest"; + ArrayList<RttConfig> rttConfig = + convertRangingRequestToRttConfigs(request, mRttCapabilities); if (rttConfig == null) { Log.e(TAG, "sendRangeRequest: invalid request parameters"); return false; } if (rttConfig.size() == 0) { Log.e(TAG, "sendRangeRequest: all requests invalidated"); - mRttService.onRangingResults(cmdId, new ArrayList<>()); + dispatchOnRangingResults(cmdId, new ArrayList<>()); return true; } try { - WifiStatus status = mIWifiRttController.rangeRequest(cmdId, rttConfig); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "sendRangeRequest: cannot issue range request -- code=" + status.code); - return false; - } + WifiStatus status = mWifiRttController.rangeRequest(cmdId, rttConfig); + return isOk(status, methodStr); } catch (RemoteException e) { - Log.e(TAG, "sendRangeRequest: exception issuing range request: " + e); + handleRemoteException(e, methodStr); return false; } - - return true; } - private boolean sendRangeRequest14(int cmdId, RangingRequest request, - boolean isCalledFromPrivilegedContext) { + private boolean sendRangeRequest14(int cmdId, RangingRequest request) { + final String methodStr = "sendRangeRequest14"; ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfig = - convertRangingRequestToRttConfigs14(request, - isCalledFromPrivilegedContext, mRttCapabilities); + convertRangingRequestToRttConfigs14(request, mRttCapabilities); if (rttConfig == null) { Log.e(TAG, "sendRangeRequest14: invalid request parameters"); return false; } if (rttConfig.size() == 0) { Log.e(TAG, "sendRangeRequest14: all requests invalidated"); - mRttService.onRangingResults(cmdId, new ArrayList<>()); + dispatchOnRangingResults(cmdId, new ArrayList<>()); return true; } try { - WifiStatus status = mIWifiRttController14.rangeRequest_1_4(cmdId, rttConfig); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "sendRangeRequest14: cannot issue range request -- code=" - + status.code); - return false; - } + WifiStatus status = mWifiRttController14.rangeRequest_1_4(cmdId, rttConfig); + return isOk(status, methodStr); } catch (RemoteException e) { - Log.e(TAG, "sendRangeRequest14: exception issuing range request: " + e); + handleRemoteException(e, methodStr); return false; } - - return true; } - private boolean sendRangeRequest16(int cmdId, RangingRequest request, - boolean isCalledFromPrivilegedContext) { + private boolean sendRangeRequest16(int cmdId, RangingRequest request) { + final String methodStr = "sendRangeRequest16"; ArrayList<android.hardware.wifi.V1_6.RttConfig> rttConfig = - convertRangingRequestToRttConfigs16(request, - isCalledFromPrivilegedContext, mRttCapabilities); + convertRangingRequestToRttConfigs16(request, mRttCapabilities); if (rttConfig == null) { Log.e(TAG, "sendRangeRequest16: invalid request parameters"); return false; } if (rttConfig.size() == 0) { Log.e(TAG, "sendRangeRequest16: all requests invalidated"); - mRttService.onRangingResults(cmdId, new ArrayList<>()); + dispatchOnRangingResults(cmdId, new ArrayList<>()); return true; } try { - WifiStatus status = mIWifiRttController16.rangeRequest_1_6(cmdId, rttConfig); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "sendRangeRequest16: cannot issue range request -- code=" - + status.code); - return false; + WifiStatus status = mWifiRttController16.rangeRequest_1_6(cmdId, rttConfig); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + boolean rangeCancelInternal(String methodStr, int cmdId, List<MacAddress> macAddresses) { + if (mVerboseLoggingEnabled) Log.v(TAG, "rangeCancel: cmdId=" + cmdId); + try { + ArrayList<byte[]> macBytes = new ArrayList<>(); + for (MacAddress mac : macAddresses) { + macBytes.add(mac.toByteArray()); } + WifiStatus status = mWifiRttController.rangeCancel(cmdId, macBytes); + return isOk(status, methodStr); } catch (RemoteException e) { - Log.e(TAG, "sendRangeRequest16: exception issuing range request: " + e); + handleRemoteException(e, methodStr); return false; } + } - return true; + /** + * Callback for HAL events on 1.0 WifiRttController + */ + private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub { + /** + * Callback from the HAL with range results. + * + * @param cmdId Command ID specified in the original request. + * @param halResults A list of range results. + */ + @Override + public void onResults(int cmdId, ArrayList<RttResult> halResults) { + if (mVerboseLoggingEnabled) { + int numResults = halResults != null ? halResults.size() : -1; + Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + numResults); + } + if (halResults == null) { + halResults = new ArrayList<>(); + } + halResults.removeIf(Objects::isNull); + ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults(halResults); + dispatchOnRangingResults(cmdId, rangingResults); + } } /** - * Cancel an outstanding ranging request: no guarantees of execution - we will ignore any - * results which are returned for the canceled request. - * - * @param cmdId The cmdId issued with the original rangeRequest command. - * @param macAddresses A list of MAC addresses for which to cancel the operation. - * @return Success status: true for success, false for failure. + * Callback for HAL events on 1.4 WifiRttController */ - public boolean rangeCancel(int cmdId, ArrayList<byte[]> macAddresses) { - if (mVerboseLoggingEnabled) Log.v(TAG, "rangeCancel: cmdId=" + cmdId); - synchronized (mLock) { - if (!isReady()) { - Log.e(TAG, "rangeCancel: RttController is null"); - return false; + private class WifiRttControllerEventCallback14 extends + android.hardware.wifi.V1_4.IWifiRttControllerEventCallback.Stub { + @Override + public void onResults(int cmdId, ArrayList<RttResult> halResults) { + // This callback is not supported on this version of the interface. + return; + } + + @Override + public void onResults_1_4(int cmdId, + ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { + if (mVerboseLoggingEnabled) { + int numResults = halResults != null ? halResults.size() : -1; + Log.v(TAG, "onResults_1_4: cmdId=" + cmdId + ", # of results=" + numResults); + } + if (halResults == null) { + halResults = new ArrayList<>(); } + halResults.removeIf(Objects::isNull); + ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults14(halResults); + dispatchOnRangingResults(cmdId, rangingResults); + } + } + /** + * Callback for HAL events on 1.6 WifiRttController + */ + private class WifiRttControllerEventCallback16 extends + android.hardware.wifi.V1_6.IWifiRttControllerEventCallback.Stub { + @Override + public void onResults(int cmdId, ArrayList<RttResult> halResults) { + // This callback is not supported on this version of the interface. + return; + } + + @Override + public void onResults_1_4(int cmdId, + ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { + // This callback is not supported on this version of the interface. + return; + } + + @Override + public void onResults_1_6(int cmdId, + ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) { + if (mVerboseLoggingEnabled) { + int numResults = halResults != null ? halResults.size() : -1; + Log.v(TAG, "onResults_1_6: cmdId=" + cmdId + ", # of results=" + numResults); + } + if (halResults == null) { + halResults = new ArrayList<>(); + } + halResults.removeIf(Objects::isNull); + ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults16(halResults); + dispatchOnRangingResults(cmdId, rangingResults); + } + } + + + // Helper Functions + + private ArrayList<RangingResult> convertHalResultsRangingResults( + ArrayList<RttResult> halResults) { + ArrayList<RangingResult> rangingResults = new ArrayList<>(); + for (RttResult rttResult : halResults) { + byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); + byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); + ResponderLocation responderLocation; try { - WifiStatus status = mIWifiRttController.rangeCancel(cmdId, macAddresses); - if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, "rangeCancel: cannot issue range cancel -- code=" + status.code); - return false; + responderLocation = new ResponderLocation(lci, lcr); + if (!responderLocation.isValid()) { + responderLocation = null; } - } catch (RemoteException e) { - Log.e(TAG, "rangeCancel: exception issuing range cancel: " + e); - return false; + } catch (Exception e) { + responderLocation = null; + Log.e(TAG, + "ResponderLocation: lci/lcr parser failed exception -- " + e); } + if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { + if (mVerboseLoggingEnabled) { + Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " + + "samples!? result=" + rttResult); + } + rttResult.distanceSdInMm = 0; + } + rangingResults.add(new RangingResult( + convertHalStatusToFrameworkStatus(rttResult.status), + MacAddress.fromBytes(rttResult.addr), + rttResult.distanceInMm, rttResult.distanceSdInMm, + rttResult.rssi / -2, rttResult.numberPerBurstPeer, + rttResult.successNumber, lci, lcr, responderLocation, + rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS, + rttResult.type == RttType.TWO_SIDED)); + } + return rangingResults; + } - return true; + private ArrayList<RangingResult> convertHalResultsRangingResults14( + ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { + ArrayList<RangingResult> rangingResults = new ArrayList<>(); + for (android.hardware.wifi.V1_4.RttResult rttResult : halResults) { + byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); + byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); + ResponderLocation responderLocation; + try { + responderLocation = new ResponderLocation(lci, lcr); + if (!responderLocation.isValid()) { + responderLocation = null; + } + } catch (Exception e) { + responderLocation = null; + Log.e(TAG, + "ResponderLocation: lci/lcr parser failed exception -- " + e); + } + if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { + if (mVerboseLoggingEnabled) { + Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " + + "samples!? result=" + rttResult); + } + rttResult.distanceSdInMm = 0; + } + rangingResults.add(new RangingResult( + convertHalStatusToFrameworkStatus(rttResult.status), + MacAddress.fromBytes(rttResult.addr), + rttResult.distanceInMm, rttResult.distanceSdInMm, + rttResult.rssi / -2, rttResult.numberPerBurstPeer, + rttResult.successNumber, lci, lcr, responderLocation, + rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS, + rttResult.type == RttType.TWO_SIDED)); } + return rangingResults; } - private static ArrayList<RttConfig> convertRangingRequestToRttConfigs(RangingRequest request, - boolean isCalledFromPrivilegedContext, Capabilities cap) { + private ArrayList<RangingResult> convertHalResultsRangingResults16( + ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) { + ArrayList<RangingResult> rangingResults = new ArrayList<>(); + for (android.hardware.wifi.V1_6.RttResult rttResult : halResults) { + byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); + byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); + ResponderLocation responderLocation; + try { + responderLocation = new ResponderLocation(lci, lcr); + if (!responderLocation.isValid()) { + responderLocation = null; + } + } catch (Exception e) { + responderLocation = null; + Log.e(TAG, + "ResponderLocation: lci/lcr parser failed exception -- " + e); + } + if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { + if (mVerboseLoggingEnabled) { + Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " + + "samples!? result=" + rttResult); + } + rttResult.distanceSdInMm = 0; + } + rangingResults.add(new RangingResult( + convertHalStatusToFrameworkStatus(rttResult.status), + MacAddress.fromBytes(rttResult.addr), + rttResult.distanceInMm, rttResult.distanceSdInMm, + rttResult.rssi / -2, rttResult.numberPerBurstPeer, + rttResult.successNumber, lci, lcr, responderLocation, + rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS, + rttResult.type == RttType.TWO_SIDED)); + } + return rangingResults; + } + + private @WifiRttController.FrameworkRttStatus + int convertHalStatusToFrameworkStatus(int halStatus) { + switch (halStatus) { + case RttStatus.SUCCESS: + return WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS; + case RttStatus.FAILURE: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE; + case RttStatus.FAIL_NO_RSP: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP; + case RttStatus.FAIL_REJECTED: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED; + case RttStatus.FAIL_NOT_SCHEDULED_YET: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET; + case RttStatus.FAIL_TM_TIMEOUT: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT; + case RttStatus.FAIL_AP_ON_DIFF_CHANNEL: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; + case RttStatus.FAIL_NO_CAPABILITY: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY; + case RttStatus.ABORTED: + return WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED; + case RttStatus.FAIL_INVALID_TS: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS; + case RttStatus.FAIL_PROTOCOL: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL; + case RttStatus.FAIL_SCHEDULE: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE; + case RttStatus.FAIL_BUSY_TRY_LATER: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER; + case RttStatus.INVALID_REQ: + return WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ; + case RttStatus.NO_WIFI: + return WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI; + case RttStatus.FAIL_FTM_PARAM_OVERRIDE: + return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; + default: + Log.e(TAG, "Unrecognized RttStatus: " + halStatus); + return WifiRttController.FRAMEWORK_RTT_STATUS_UNKNOWN; + } + } + + private void updateRttCapabilities() { + if (mRttCapabilities != null) return; + if (mVerboseLoggingEnabled) Log.v(TAG, "updateRttCapabilities"); + + try { + if (mWifiRttController16 != null) { + mWifiRttController16.getCapabilities_1_6( + (status, capabilities16) -> { + if (status.code != WifiStatusCode.SUCCESS) { + Log.e(TAG, "updateRttCapabilities:" + + " error requesting capabilities " + + "-- code=" + status.code); + return; + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "updateRttCapabilities: RTT capabilities=" + + capabilities16); + } + mRttCapabilities = new WifiRttController.Capabilities(capabilities16); + }); + } else if (mWifiRttController14 != null) { + mWifiRttController14.getCapabilities_1_4( + (status, capabilities14) -> { + if (status.code != WifiStatusCode.SUCCESS) { + Log.e(TAG, "updateRttCapabilities:" + + " error requesting capabilities " + + "-- code=" + status.code); + return; + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "updateRttCapabilities: RTT capabilities=" + + capabilities14); + } + mRttCapabilities = new WifiRttController.Capabilities(capabilities14); + }); + } else { + mWifiRttController.getCapabilities( + (status, capabilities) -> { + if (status.code != WifiStatusCode.SUCCESS) { + Log.e(TAG, "updateRttCapabilities:" + + " error requesting capabilities " + + "-- code=" + status.code); + return; + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "updateRttCapabilities: RTT capabilities=" + + capabilities); + } + mRttCapabilities = new WifiRttController.Capabilities(capabilities); + }); + + } + } catch (RemoteException e) { + handleRemoteException(e, "updateRttCapabilities"); + } + + if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { + Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - " + + "ignored!?"); + } + } + + private static ArrayList<RttConfig> convertRangingRequestToRttConfigs( + RangingRequest request, WifiRttController.Capabilities cap) { ArrayList<RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size()); - // Skipping any configurations which have an error (printing out a message). + // Skip any configurations which have an error (just print out a message). // The caller will only get results for valid configurations. for (ResponderConfig responder: request.mRttPeers) { RttConfig config = new RttConfig(); @@ -534,18 +667,16 @@ public class RttNative { } private static ArrayList<android.hardware.wifi.V1_4.RttConfig> - convertRangingRequestToRttConfigs14( - RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap) { + convertRangingRequestToRttConfigs14(RangingRequest request, + WifiRttController.Capabilities cap) { ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size()); - // Skipping any configurations which have an error (printing out a message). + // Skip any configurations which have an error (just print out a message). // The caller will only get results for valid configurations. for (ResponderConfig responder: request.mRttPeers) { - android.hardware.wifi.V1_4.RttConfig config = new android.hardware.wifi.V1_4.RttConfig(); - System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, config.addr.length); @@ -603,18 +734,16 @@ public class RttNative { } private static ArrayList<android.hardware.wifi.V1_6.RttConfig> - convertRangingRequestToRttConfigs16( - RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap) { + convertRangingRequestToRttConfigs16(RangingRequest request, + WifiRttController.Capabilities cap) { ArrayList<android.hardware.wifi.V1_6.RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size()); - // Skipping any configurations which have an error (printing out a message). + // Skip any configurations which have an error (just print out a message). // The caller will only get results for valid configurations. for (ResponderConfig responder: request.mRttPeers) { - android.hardware.wifi.V1_6.RttConfig config = new android.hardware.wifi.V1_6.RttConfig(); - System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, config.addr.length); @@ -763,15 +892,16 @@ public class RttNative { } /** - * Check to see whether the selected RTT channel bandwidth is supported by the device. - * If not supported: return the next lower bandwidth which is supported - * If none: throw an IllegalArgumentException. + * Check whether the selected RTT channel bandwidth is supported by the device. + * If supported, return the requested bandwidth. + * If not supported, return the next lower bandwidth which is supported. + * If none, throw an IllegalArgumentException. * - * Note: the halRttChannelBandwidth is a single bit flag of the ones used in cap.bwSupport (HAL - * specifications). + * Note: the halRttChannelBandwidth is a single bit flag from the HAL RttBw type. */ private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, - Capabilities cap) { + WifiRttController.Capabilities cap) { + int requestedBandwidth = halRttChannelBandwidth; while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & cap.bwSupported) == 0)) { halRttChannelBandwidth >>= 1; } @@ -781,19 +911,21 @@ public class RttNative { } throw new IllegalArgumentException( - "RTT BW=" + halRttChannelBandwidth + ", not supported by device capabilities=" + cap + "RTT BW=" + requestedBandwidth + ", not supported by device capabilities=" + cap + " - and no supported alternative"); } /** - * Check to see whether the selected RTT preamble is supported by the device. - * If not supported: return the next "lower" preamble which is supported - * If none: throw an IllegalArgumentException. + * Check whether the selected RTT preamble is supported by the device. + * If supported, return the requested preamble. + * If not supported, return the next "lower" preamble which is supported. + * If none, throw an IllegalArgumentException. * - * Note: the halRttPreamble is a single bit flag of the ones used in cap.preambleSupport (HAL - * specifications). + * Note: the halRttPreamble is a single bit flag from the HAL RttPreamble type. */ - private static int halRttPreambleCapabilityLimiter(int halRttPreamble, Capabilities cap) { + private static int halRttPreambleCapabilityLimiter(int halRttPreamble, + WifiRttController.Capabilities cap) { + int requestedPreamble = halRttPreamble; while ((halRttPreamble != 0) && ((halRttPreamble & cap.preambleSupported) == 0)) { halRttPreamble >>= 1; } @@ -803,338 +935,33 @@ public class RttNative { } throw new IllegalArgumentException( - "RTT Preamble=" + halRttPreamble + ", not supported by device capabilities=" + cap - + " - and no supported alternative"); - } - - /** - * Check if HAL Interface 1.4 is running - * - * @return 1.4 IWifiRttController object if the device is running the 1.4 hal service, null - * otherwise - */ - private android.hardware.wifi.V1_4.IWifiRttController getWifiRttControllerV1_4() { - if (mIWifiRttController == null) { - return null; - } - return android.hardware.wifi.V1_4.IWifiRttController.castFrom(mIWifiRttController); - } - - /** - * Check if HAL Interface 1.6 is running - * - * @return 1.6 IWifiRttController object if the device is running the 1.6 hal service, null - * otherwise - */ - private android.hardware.wifi.V1_6.IWifiRttController getWifiRttControllerV1_6() { - if (mIWifiRttController == null) { - return null; - } - return android.hardware.wifi.V1_6.IWifiRttController.castFrom(mIWifiRttController); - } - - /** - * Dump the internal state of the class. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("RttNative:"); - pw.println(" mHalDeviceManager: " + mHalDeviceManager); - pw.println(" mIWifiRttController: " + mIWifiRttController); - pw.println(" mRttCapabilities: " + mRttCapabilities); - } - - /** - * Callback for events on 1.0 WifiRttController - */ - private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub { - /** - * Callback from HAL with range results. - * - * @param cmdId Command ID specified in the original request - * {@link #rangeRequest(int, RangingRequest, boolean)}. - * @param halResults A list of range results. - */ - @Override - public void onResults(int cmdId, ArrayList<RttResult> halResults) { - // sanitize HAL results - if (halResults == null) { - halResults = new ArrayList<>(); - } - halResults.removeIf(Objects::isNull); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + halResults.size()); - } - ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults(halResults); - mRttService.onRangingResults(cmdId, rangingResults); - } - } - - /** - * Callback for events on 1.4 WifiRttController - */ - private class WifiRttControllerEventCallback14 extends - android.hardware.wifi.V1_4.IWifiRttControllerEventCallback.Stub { - @Override - public void onResults(int cmdId, ArrayList<RttResult> halResults) { - // This callback is not supported on this version of the interface - return; - } - - @Override - public void onResults_1_4(int cmdId, - ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, - "onResults_1_4: cmdId=" + cmdId + ", # of results=" + halResults.size()); - } - // sanitize HAL results - if (halResults == null) { - halResults = new ArrayList<>(); - } - halResults.removeIf(Objects::isNull); - ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults14(halResults); - mRttService.onRangingResults(cmdId, rangingResults); - } - } - - /** - * Callback for events on 1.6 WifiRttController - */ - private class WifiRttControllerEventCallback16 extends - android.hardware.wifi.V1_6.IWifiRttControllerEventCallback.Stub { - @Override - public void onResults(int cmdId, ArrayList<RttResult> halResults) { - // This callback is not supported on this version of the interface - return; - } - - @Override - public void onResults_1_4(int cmdId, - ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { - // This callback is not supported on this version of the interface - return; - } - - @Override - public void onResults_1_6(int cmdId, - ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, - "onResults_1_6: cmdId=" + cmdId + ", # of results=" + halResults.size()); - } - // sanitize HAL results - if (halResults == null) { - halResults = new ArrayList<>(); - } - halResults.removeIf(Objects::isNull); - ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults16(halResults); - mRttService.onRangingResults(cmdId, rangingResults); - } - } - - private ArrayList<RangingResult> convertHalResultsRangingResults( - ArrayList<RttResult> halResults) { - ArrayList<RangingResult> rangingResults = new ArrayList<>(); - for (RttResult rttResult : halResults) { - byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); - byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); - ResponderLocation responderLocation; - try { - responderLocation = new ResponderLocation(lci, lcr); - if (!responderLocation.isValid()) { - responderLocation = null; - } - } catch (Exception e) { - responderLocation = null; - Log.e(TAG, - "ResponderLocation: lci/lcr parser failed exception -- " + e); - } - if (rttResult.successNumber <= 1 - && rttResult.distanceSdInMm != 0) { - if (mVerboseLoggingEnabled) { - Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " - + "samples!? result=" + rttResult); - } - rttResult.distanceSdInMm = 0; - } - rangingResults.add(new RangingResult( - convertHalStatusToFrameworkStatus(rttResult.status), - MacAddress.fromBytes(rttResult.addr), - rttResult.distanceInMm, rttResult.distanceSdInMm, - rttResult.rssi / -2, rttResult.numberPerBurstPeer, - rttResult.successNumber, lci, lcr, responderLocation, - rttResult.timeStampInUs / CONVERSION_US_TO_MS, - rttResult.type == RttType.TWO_SIDED)); - } - return rangingResults; + "RTT Preamble=" + requestedPreamble + ", not supported by device capabilities=" + + cap + " - and no supported alternative"); } - private ArrayList<RangingResult> convertHalResultsRangingResults14( - ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { - ArrayList<RangingResult> rangingResults = new ArrayList<>(); - for (android.hardware.wifi.V1_4.RttResult rttResult : halResults) { - byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); - byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); - ResponderLocation responderLocation; - try { - responderLocation = new ResponderLocation(lci, lcr); - if (!responderLocation.isValid()) { - responderLocation = null; - } - } catch (Exception e) { - responderLocation = null; - Log.e(TAG, - "ResponderLocation: lci/lcr parser failed exception -- " + e); - } - if (rttResult.successNumber <= 1 - && rttResult.distanceSdInMm != 0) { - if (mVerboseLoggingEnabled) { - Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " - + "samples!? result=" + rttResult); - } - rttResult.distanceSdInMm = 0; - } - rangingResults.add(new RangingResult( - convertHalStatusToFrameworkStatus(rttResult.status), - MacAddress.fromBytes(rttResult.addr), - rttResult.distanceInMm, rttResult.distanceSdInMm, - rttResult.rssi / -2, rttResult.numberPerBurstPeer, - rttResult.successNumber, lci, lcr, responderLocation, - rttResult.timeStampInUs / CONVERSION_US_TO_MS, - rttResult.type == RttType.TWO_SIDED)); + private void dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults) { + for (WifiRttController.RttControllerRangingResultsCallback + callback : mRangingResultsCallbacks) { + callback.onRangingResults(cmdId, rangingResults); } - return rangingResults; } - private ArrayList<RangingResult> convertHalResultsRangingResults16( - ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) { - ArrayList<RangingResult> rangingResults = new ArrayList<>(); - for (android.hardware.wifi.V1_6.RttResult rttResult : halResults) { - byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); - byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); - ResponderLocation responderLocation; - try { - responderLocation = new ResponderLocation(lci, lcr); - if (!responderLocation.isValid()) { - responderLocation = null; - } - } catch (Exception e) { - responderLocation = null; - Log.e(TAG, - "ResponderLocation: lci/lcr parser failed exception -- " + e); - } - if (rttResult.successNumber <= 1 - && rttResult.distanceSdInMm != 0) { - if (mVerboseLoggingEnabled) { - Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " - + "samples!? result=" + rttResult); - } - rttResult.distanceSdInMm = 0; - } - rangingResults.add(new RangingResult( - convertHalStatusToFrameworkStatus(rttResult.status), - MacAddress.fromBytes(rttResult.addr), - rttResult.distanceInMm, rttResult.distanceSdInMm, - rttResult.rssi / -2, rttResult.numberPerBurstPeer, - rttResult.successNumber, lci, lcr, responderLocation, - rttResult.timeStampInUs / CONVERSION_US_TO_MS, - rttResult.type == RttType.TWO_SIDED)); - } - return rangingResults; + private boolean isOk(WifiStatus status, String methodStr) { + if (status.code == WifiStatusCode.SUCCESS) return true; + Log.e(TAG, methodStr + " failed with status: " + status); + return false; } - private @FrameworkRttStatus int convertHalStatusToFrameworkStatus(int halStatus) { - switch (halStatus) { - case RttStatus.SUCCESS: - return FRAMEWORK_RTT_STATUS_SUCCESS; - case RttStatus.FAILURE: - return FRAMEWORK_RTT_STATUS_FAILURE; - case RttStatus.FAIL_NO_RSP: - return FRAMEWORK_RTT_STATUS_FAIL_NO_RSP; - case RttStatus.FAIL_REJECTED: - return FRAMEWORK_RTT_STATUS_FAIL_REJECTED; - case RttStatus.FAIL_NOT_SCHEDULED_YET: - return FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET; - case RttStatus.FAIL_TM_TIMEOUT: - return FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT; - case RttStatus.FAIL_AP_ON_DIFF_CHANNEL: - return FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; - case RttStatus.FAIL_NO_CAPABILITY: - return FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY; - case RttStatus.ABORTED: - return FRAMEWORK_RTT_STATUS_ABORTED; - case RttStatus.FAIL_INVALID_TS: - return FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS; - case RttStatus.FAIL_PROTOCOL: - return FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL; - case RttStatus.FAIL_SCHEDULE: - return FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE; - case RttStatus.FAIL_BUSY_TRY_LATER: - return FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER; - case RttStatus.INVALID_REQ: - return FRAMEWORK_RTT_STATUS_INVALID_REQ; - case RttStatus.NO_WIFI: - return FRAMEWORK_RTT_STATUS_NO_WIFI; - case RttStatus.FAIL_FTM_PARAM_OVERRIDE: - return FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; - default: - Log.e(TAG, "Unrecognized RttStatus: " + halStatus); - return FRAMEWORK_RTT_STATUS_UNKNOWN; - } + private void handleRemoteException(RemoteException e, String methodStr) { + Log.e(TAG, methodStr + " failed with remote exception: " + e); + mWifiRttController = null; } - /** - * Rtt capabilities inside framework - */ - public class Capabilities { - //1-sided rtt measurement is supported - public boolean oneSidedRttSupported; - //location configuration information supported - public boolean lciSupported; - //location civic records supported - public boolean lcrSupported; - //preamble supported, see bit mask definition above - public int preambleSupported; - //RTT bandwidth supported - public int bwSupported; - // Whether STA responder role is supported. - public boolean responderSupported; - //Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43. - public byte mcVersion; - //if ftm rtt data collection is supported. - public boolean rttFtmSupported; - - public Capabilities(RttCapabilities rttHalCapabilities) { - oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; - lciSupported = rttHalCapabilities.lciSupported; - lcrSupported = rttHalCapabilities.lcrSupported; - responderSupported = rttHalCapabilities.responderSupported; - preambleSupported = rttHalCapabilities.preambleSupport; - mcVersion = rttHalCapabilities.mcVersion; - bwSupported = rttHalCapabilities.bwSupport; - rttFtmSupported = rttHalCapabilities.rttFtmSupported; - } - - public Capabilities(android.hardware.wifi.V1_4.RttCapabilities rttHalCapabilities) { - oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; - lciSupported = rttHalCapabilities.lciSupported; - lcrSupported = rttHalCapabilities.lcrSupported; - responderSupported = rttHalCapabilities.responderSupported; - preambleSupported = rttHalCapabilities.preambleSupport; - mcVersion = rttHalCapabilities.mcVersion; - bwSupported = rttHalCapabilities.bwSupport; - rttFtmSupported = rttHalCapabilities.rttFtmSupported; - } - - public Capabilities(android.hardware.wifi.V1_6.RttCapabilities rttHalCapabilities) { - oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; - lciSupported = rttHalCapabilities.lciSupported; - lcrSupported = rttHalCapabilities.lcrSupported; - responderSupported = rttHalCapabilities.responderSupported; - preambleSupported = rttHalCapabilities.preambleSupport; - mcVersion = rttHalCapabilities.mcVersion; - bwSupported = rttHalCapabilities.bwSupport; - rttFtmSupported = rttHalCapabilities.rttFtmSupported; + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiRttController == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiRttController is null"); + return defaultVal; } + return supplier.get(); } } diff --git a/service/java/com/android/server/wifi/hal/WifiStaIface.java b/service/java/com/android/server/wifi/hal/WifiStaIface.java new file mode 100644 index 0000000000..1a04c2ff3e --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiStaIface.java @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.net.MacAddress; +import android.net.apf.ApfCapabilities; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiScanner; +import android.util.Log; + +import com.android.server.wifi.SsidTranslator; +import com.android.server.wifi.WifiLinkLayerStats; +import com.android.server.wifi.WifiNative; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * Wrapper around a WifiStaIface. + * May be initialized using a HIDL or AIDL WifiStaIface. + */ +public class WifiStaIface implements WifiHal.WifiInterface { + private static final String TAG = "WifiStaIface"; + private final IWifiStaIface mWifiStaIface; + + public static final int SET_ROAMING_STATE_FAILURE_CODE = + WifiNative.SET_FIRMWARE_ROAMING_FAILURE; + + /** + * Parameters for a background scan request. + */ + public static class StaBackgroundScanParameters { + public int basePeriodInMs; + public int maxApPerScan; + public int reportThresholdPercent; + public int reportThresholdNumScans; + public List<WifiNative.BucketSettings> buckets; + + public StaBackgroundScanParameters(int inBasePeriodInMs, int inMaxApPerScan, + int inReportThresholdPercent, int inReportThresholdNumScans, + List<WifiNative.BucketSettings> inBuckets) { + basePeriodInMs = inBasePeriodInMs; + maxApPerScan = inMaxApPerScan; + reportThresholdPercent = inReportThresholdPercent; + reportThresholdNumScans = inReportThresholdNumScans; + buckets = inBuckets; + } + } + + /** + * Framework callback object. Will get called when the equivalent events are received + * from the HAL. + */ + public interface Callback { + /** + * Called for each received beacon/probe response for a scan with the + * |REPORT_EVENTS_FULL_RESULTS| flag set in + * |StaBackgroundScanBucketParameters.eventReportScheme|. + * + * @param cmdId Command ID corresponding to the request. + * @param bucketsScanned Bitset where each bit indicates if the bucket with + * that index (starting at 0) was scanned. + * @param result Full scan result for an AP. + */ + void onBackgroundFullScanResult(int cmdId, int bucketsScanned, ScanResult result); + + /** + * Callback indicating that an ongoing background scan request has failed. + * The background scan needs to be restarted to continue scanning. + * + * @param cmdId Command ID corresponding to the request. + */ + void onBackgroundScanFailure(int cmdId); + + /** + * Called when the |StaBackgroundScanBucketParameters.eventReportScheme| flags + * for at least one bucket that was just scanned was |REPORT_EVENTS_EACH_SCAN|, + * or one of the configured thresholds was breached. + * + * @param cmdId Command ID corresponding to the request. + * @param scanDatas List of scan results for all APs seen since the last callback. + */ + void onBackgroundScanResults(int cmdId, WifiScanner.ScanData[] scanDatas); + + /** + * Called when the RSSI of the currently connected access point goes beyond the + * thresholds set via + * {@link IWifiStaIface#startRssiMonitoring(int, int, int)} + * + * @param cmdId Command ID corresponding to the request. + * @param currBssid BSSID of the currently connected access point. + * @param currRssi RSSI of the currently connected access point. + */ + void onRssiThresholdBreached(int cmdId, byte[] currBssid, int currRssi); + } + + public WifiStaIface(@NonNull android.hardware.wifi.V1_0.IWifiStaIface staIface, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiStaIface = createWifiStaIfaceHidlImplMockable(staIface, context, ssidTranslator); + } + + public WifiStaIface(@NonNull android.hardware.wifi.IWifiStaIface staIface, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiStaIface = createWifiStaIfaceAidlImplMockable(staIface, context, ssidTranslator); + } + + protected WifiStaIfaceHidlImpl createWifiStaIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiStaIface staIface, @NonNull Context context, + @NonNull SsidTranslator ssidTranslator) { + return new WifiStaIfaceHidlImpl(staIface, context, ssidTranslator); + } + + protected WifiStaIfaceAidlImpl createWifiStaIfaceAidlImplMockable( + android.hardware.wifi.IWifiStaIface staIface, @NonNull Context context, + @NonNull SsidTranslator ssidTranslator) { + return new WifiStaIfaceAidlImpl(staIface, context, ssidTranslator); + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiStaIface == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiStaIface is null"); + return defaultVal; + } + return supplier.get(); + } + + /** + * See comments for {@link IWifiStaIface#registerFrameworkCallback(Callback)} + */ + public boolean registerFrameworkCallback(Callback callback) { + return validateAndCall("registerFrameworkCallback", false, + () -> mWifiStaIface.registerFrameworkCallback(callback)); + } + + /** + * See comments for {@link IWifiStaIface#getName()} + */ + @Override + @Nullable + public String getName() { + return validateAndCall("getName", null, + () -> mWifiStaIface.getName()); + } + + /** + * See comments for {@link IWifiStaIface#configureRoaming(List, List)} + */ + public boolean configureRoaming(List<MacAddress> bssidBlocklist, + List<byte[]> ssidAllowlist) { + return validateAndCall("configureRoaming", false, + () -> mWifiStaIface.configureRoaming(bssidBlocklist, ssidAllowlist)); + } + + /** + * See comments for {@link IWifiStaIface#enableLinkLayerStatsCollection(boolean)} + */ + public boolean enableLinkLayerStatsCollection(boolean debug) { + return validateAndCall("enableLinkLayerStatsCollection", false, + () -> mWifiStaIface.enableLinkLayerStatsCollection(debug)); + } + + /** + * See comments for {@link IWifiStaIface#enableNdOffload(boolean)} + */ + public boolean enableNdOffload(boolean enable) { + return validateAndCall("enableNdOffload", false, + () -> mWifiStaIface.enableNdOffload(enable)); + } + + /** + * See comments for {@link IWifiStaIface#getApfPacketFilterCapabilities()} + */ + public ApfCapabilities getApfPacketFilterCapabilities() { + return validateAndCall("getApfPacketFilterCapabilities", new ApfCapabilities(0, 0, 0), + () -> mWifiStaIface.getApfPacketFilterCapabilities()); + } + + /** + * See comments for {@link IWifiStaIface#getBackgroundScanCapabilities()} + */ + @Nullable + public WifiNative.ScanCapabilities getBackgroundScanCapabilities() { + return validateAndCall("getBackgroundScanCapabilities", null, + () -> mWifiStaIface.getBackgroundScanCapabilities()); + } + + /** + * See comments for {@link IWifiStaIface#getCapabilities()} + */ + public long getCapabilities() { + return validateAndCall("getCapabilities", 0L, + () -> mWifiStaIface.getCapabilities()); + } + + /** + * See comments for {@link IWifiStaIface#getDebugRxPacketFates()} + */ + public List<WifiNative.RxFateReport> getDebugRxPacketFates() { + return validateAndCall("getDebugRxPacketFates", new ArrayList<>(), + () -> mWifiStaIface.getDebugRxPacketFates()); + } + + /** + * See comments for {@link IWifiStaIface#getDebugTxPacketFates()} + */ + public List<WifiNative.TxFateReport> getDebugTxPacketFates() { + return validateAndCall("getDebugTxPacketFates", new ArrayList<>(), + () -> mWifiStaIface.getDebugTxPacketFates()); + } + + /** + * See comments for {@link IWifiStaIface#getFactoryMacAddress()} + */ + @Nullable + public MacAddress getFactoryMacAddress() { + return validateAndCall("getFactoryMacAddress", null, + () -> mWifiStaIface.getFactoryMacAddress()); + } + + /** + * See comments for {@link IWifiStaIface#getLinkLayerStats()} + */ + @Nullable + public WifiLinkLayerStats getLinkLayerStats() { + return validateAndCall("getLinkLayerStats", null, + () -> mWifiStaIface.getLinkLayerStats()); + } + + /** + * See comments for {@link IWifiStaIface#getRoamingCapabilities()} + */ + @Nullable + public WifiNative.RoamingCapabilities getRoamingCapabilities() { + return validateAndCall("getRoamingCapabilities", null, + () -> mWifiStaIface.getRoamingCapabilities()); + } + + /** + * See comments for {@link IWifiStaIface#installApfPacketFilter(byte[])} + */ + public boolean installApfPacketFilter(byte[] program) { + return validateAndCall("installApfPacketFilter", false, + () -> mWifiStaIface.installApfPacketFilter(program)); + } + + /** + * See comments for {@link IWifiStaIface#readApfPacketFilterData()} + */ + @Nullable + public byte[] readApfPacketFilterData() { + return validateAndCall("readApfPacketFilterData", null, + () -> mWifiStaIface.readApfPacketFilterData()); + } + + /** + * See comments for {@link IWifiStaIface#setMacAddress(MacAddress)} + */ + public boolean setMacAddress(MacAddress mac) { + return validateAndCall("setMacAddress", false, + () -> mWifiStaIface.setMacAddress(mac)); + } + + /** + * See comments for {@link IWifiStaIface#setRoamingState(int)} + */ + public @WifiNative.RoamingEnableStatus int setRoamingState( + @WifiNative.RoamingEnableState int state) { + return validateAndCall("setRoamingState", SET_ROAMING_STATE_FAILURE_CODE, + () -> mWifiStaIface.setRoamingState(state)); + } + + /** + * See comments for {@link IWifiStaIface#setScanMode(boolean)} + */ + public boolean setScanMode(boolean enable) { + return validateAndCall("setScanMode", false, + () -> mWifiStaIface.setScanMode(enable)); + } + + /** + * See comments for {@link IWifiStaIface#startBackgroundScan(int, StaBackgroundScanParameters)} + */ + public boolean startBackgroundScan(int cmdId, StaBackgroundScanParameters params) { + return validateAndCall("startBackgroundScan", false, + () -> mWifiStaIface.startBackgroundScan(cmdId, params)); + } + + /** + * See comments for {@link IWifiStaIface#startDebugPacketFateMonitoring()} + */ + public boolean startDebugPacketFateMonitoring() { + return validateAndCall("startDebugPacketFateMonitoring", false, + () -> mWifiStaIface.startDebugPacketFateMonitoring()); + } + + /** + * See comments for {@link IWifiStaIface#startRssiMonitoring(int, int, int)} + */ + public boolean startRssiMonitoring(int cmdId, int maxRssi, int minRssi) { + return validateAndCall("startRssiMonitoring", false, + () -> mWifiStaIface.startRssiMonitoring(cmdId, maxRssi, minRssi)); + } + + /** + * See comments for {@link IWifiStaIface#startSendingKeepAlivePackets(int, byte[], int, + * MacAddress, MacAddress, int)} + */ + public boolean startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, + MacAddress srcAddress, MacAddress dstAddress, int periodInMs) { + return validateAndCall("startSendingKeepAlivePackets", false, + () -> mWifiStaIface.startSendingKeepAlivePackets(cmdId, ipPacketData, etherType, + srcAddress, dstAddress, periodInMs)); + } + + /** + * See comments for {@link IWifiStaIface#stopBackgroundScan(int)} + */ + public boolean stopBackgroundScan(int cmdId) { + return validateAndCall("stopBackgroundScan", false, + () -> mWifiStaIface.stopBackgroundScan(cmdId)); + } + + /** + * See comments for {@link IWifiStaIface#stopRssiMonitoring(int)} + */ + public boolean stopRssiMonitoring(int cmdId) { + return validateAndCall("stopRssiMonitoring", false, + () -> mWifiStaIface.stopRssiMonitoring(cmdId)); + } + + /** + * See comments for {@link IWifiStaIface#stopSendingKeepAlivePackets(int)} + */ + public boolean stopSendingKeepAlivePackets(int cmdId) { + return validateAndCall("stopSendingKeepAlivePackets", false, + () -> mWifiStaIface.stopSendingKeepAlivePackets(cmdId)); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java new file mode 100644 index 0000000000..90e9f797f2 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java @@ -0,0 +1,1203 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.wifi.IWifiStaIfaceEventCallback; +import android.hardware.wifi.Ssid; +import android.hardware.wifi.StaApfPacketFilterCapabilities; +import android.hardware.wifi.StaBackgroundScanBucketEventReportSchemeMask; +import android.hardware.wifi.StaBackgroundScanBucketParameters; +import android.hardware.wifi.StaBackgroundScanCapabilities; +import android.hardware.wifi.StaBackgroundScanParameters; +import android.hardware.wifi.StaLinkLayerIfaceStats; +import android.hardware.wifi.StaLinkLayerRadioStats; +import android.hardware.wifi.StaLinkLayerStats; +import android.hardware.wifi.StaPeerInfo; +import android.hardware.wifi.StaRateStat; +import android.hardware.wifi.StaRoamingCapabilities; +import android.hardware.wifi.StaRoamingConfig; +import android.hardware.wifi.StaRoamingState; +import android.hardware.wifi.StaScanData; +import android.hardware.wifi.StaScanDataFlagMask; +import android.hardware.wifi.StaScanResult; +import android.hardware.wifi.WifiBand; +import android.hardware.wifi.WifiChannelStats; +import android.hardware.wifi.WifiDebugPacketFateFrameType; +import android.hardware.wifi.WifiDebugRxPacketFate; +import android.hardware.wifi.WifiDebugRxPacketFateReport; +import android.hardware.wifi.WifiDebugTxPacketFate; +import android.hardware.wifi.WifiDebugTxPacketFateReport; +import android.hardware.wifi.WifiStatusCode; +import android.net.MacAddress; +import android.net.apf.ApfCapabilities; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiScanner; +import android.net.wifi.WifiSsid; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wifi.SsidTranslator; +import com.android.server.wifi.WifiLinkLayerStats; +import com.android.server.wifi.WifiLoggerHal; +import com.android.server.wifi.WifiNative; +import com.android.server.wifi.util.BitMask; +import com.android.server.wifi.util.NativeUtil; +import com.android.wifi.resources.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * AIDL implementation of the IWifiStaIface interface. + */ +public class WifiStaIfaceAidlImpl implements IWifiStaIface { + private static final String TAG = "WifiStaIfaceAidlImpl"; + private android.hardware.wifi.IWifiStaIface mWifiStaIface; + private IWifiStaIfaceEventCallback mHalCallback; + private WifiStaIface.Callback mFrameworkCallback; + private final Object mLock = new Object(); + private String mIfaceName; + private Context mContext; + private SsidTranslator mSsidTranslator; + + public WifiStaIfaceAidlImpl(@NonNull android.hardware.wifi.IWifiStaIface staIface, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiStaIface = staIface; + mContext = context; + mSsidTranslator = ssidTranslator; + mHalCallback = new StaIfaceEventCallback(); + } + + /** + * See comments for {@link IWifiStaIface#registerFrameworkCallback(WifiStaIface.Callback)} + */ + @Override + public boolean registerFrameworkCallback(WifiStaIface.Callback callback) { + final String methodStr = "registerFrameworkCallback"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return false; + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (callback == null) { + Log.e(TAG, "Cannot register a null callback"); + return false; + } + + try { + mWifiStaIface.registerEventCallback(mHalCallback); + mFrameworkCallback = callback; + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#getName()} + */ + @Override + @Nullable + public String getName() { + final String methodStr = "getName"; + synchronized (mLock) { + if (!checkIfaceAndLogFailure(methodStr)) return null; + if (mIfaceName != null) return mIfaceName; + try { + String ifaceName = mWifiStaIface.getName(); + mIfaceName = ifaceName; + return mIfaceName; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiStaIface#configureRoaming(List, List)} + */ + @Override + public boolean configureRoaming(List<MacAddress> bssidBlocklist, + List<byte[]> ssidAllowlist) { + final String methodStr = "configureRoaming"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + StaRoamingConfig config = + frameworkToHalStaRoamingConfig(bssidBlocklist, ssidAllowlist); + mWifiStaIface.configureRoaming(config); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#enableLinkLayerStatsCollection(boolean)} + */ + @Override + public boolean enableLinkLayerStatsCollection(boolean debug) { + final String methodStr = "enableLinkLayerStatsCollection"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.enableLinkLayerStatsCollection(debug); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#enableNdOffload(boolean)} + */ + @Override + public boolean enableNdOffload(boolean enable) { + final String methodStr = "enableNdOffload"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.enableNdOffload(enable); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#getApfPacketFilterCapabilities()} + */ + @Override + public ApfCapabilities getApfPacketFilterCapabilities() { + final String methodStr = "getApfPacketFilterCapabilities"; + final ApfCapabilities defaultVal = new ApfCapabilities(0, 0, 0); + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return defaultVal; + StaApfPacketFilterCapabilities halCaps = + mWifiStaIface.getApfPacketFilterCapabilities(); + return new ApfCapabilities( + halCaps.version, // apfVersionSupported + halCaps.maxLength, // maximumApfProgramSize + android.system.OsConstants.ARPHRD_ETHER); // apfPacketFormat + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return defaultVal; + } + } + + /** + * See comments for {@link IWifiStaIface#getBackgroundScanCapabilities()} + */ + @Override + @Nullable + public WifiNative.ScanCapabilities getBackgroundScanCapabilities() { + final String methodStr = "getBackgroundScanCapabilities"; + synchronized (mLock) { + try { + StaBackgroundScanCapabilities halCaps = + mWifiStaIface.getBackgroundScanCapabilities(); + WifiNative.ScanCapabilities frameworkCaps = new WifiNative.ScanCapabilities(); + frameworkCaps.max_scan_cache_size = halCaps.maxCacheSize; + frameworkCaps.max_ap_cache_per_scan = halCaps.maxApCachePerScan; + frameworkCaps.max_scan_buckets = halCaps.maxBuckets; + frameworkCaps.max_rssi_sample_size = 0; + frameworkCaps.max_scan_reporting_threshold = halCaps.maxReportingThreshold; + return frameworkCaps; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiStaIface#getCapabilities()} + */ + @Override + public long getCapabilities() { + final String methodStr = "getCapabilities"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return 0L; + long halCaps = mWifiStaIface.getCapabilities(); + return halToFrameworkStaIfaceCapability(halCaps); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return 0L; + } + } + + /** + * See comments for {@link IWifiStaIface#getDebugRxPacketFates()} + */ + @Override + public List<WifiNative.RxFateReport> getDebugRxPacketFates() { + final String methodStr = "getDebugRxPacketFates"; + List<WifiNative.RxFateReport> fateReports = new ArrayList<>(); + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return fateReports; + WifiDebugRxPacketFateReport[] halReports = mWifiStaIface.getDebugRxPacketFates(); + for (WifiDebugRxPacketFateReport report : halReports) { + if (fateReports.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; + byte code = halToFrameworkRxPktFate(report.fate); + long us = report.frameInfo.driverTimestampUsec; + byte type = halToFrameworkPktFateFrameType(report.frameInfo.frameType); + byte[] frame = report.frameInfo.frameContent; + fateReports.add(new WifiNative.RxFateReport(code, us, type, frame)); + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, methodStr); + return new ArrayList<>(); + } + return fateReports; + } + } + + /** + * See comments for {@link IWifiStaIface#getDebugTxPacketFates()} + */ + @Override + public List<WifiNative.TxFateReport> getDebugTxPacketFates() { + final String methodStr = "getDebugTxPacketFates"; + List<WifiNative.TxFateReport> fateReports = new ArrayList<>(); + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return fateReports; + WifiDebugTxPacketFateReport[] halReports = mWifiStaIface.getDebugTxPacketFates(); + for (WifiDebugTxPacketFateReport report : halReports) { + if (fateReports.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; + byte code = halToFrameworkTxPktFate(report.fate); + long us = report.frameInfo.driverTimestampUsec; + byte type = halToFrameworkPktFateFrameType(report.frameInfo.frameType); + byte[] frame = report.frameInfo.frameContent; + fateReports.add(new WifiNative.TxFateReport(code, us, type, frame)); + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, methodStr); + return new ArrayList<>(); + } + return fateReports; + } + } + + /** + * See comments for {@link IWifiStaIface#getFactoryMacAddress()} + */ + @Override + @Nullable + public MacAddress getFactoryMacAddress() { + final String methodStr = "getFactoryMacAddress"; + byte[] macBytes; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + macBytes = mWifiStaIface.getFactoryMacAddress(); + return MacAddress.fromBytes(macBytes); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid MAC address received: " + e); + } + return null; + } + } + + /** + * See comments for {@link IWifiStaIface#getLinkLayerStats()} + */ + @Override + @Nullable + public WifiLinkLayerStats getLinkLayerStats() { + final String methodStr = "getLinkLayerStats"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + StaLinkLayerStats halStats = mWifiStaIface.getLinkLayerStats(); + return halToFrameworkLinkLayerStats(halStats); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiStaIface#getRoamingCapabilities()} + */ + @Override + @Nullable + public WifiNative.RoamingCapabilities getRoamingCapabilities() { + final String methodStr = "getRoamingCapabilities"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + StaRoamingCapabilities halCaps = mWifiStaIface.getRoamingCapabilities(); + WifiNative.RoamingCapabilities out = new WifiNative.RoamingCapabilities(); + out.maxBlocklistSize = halCaps.maxBlocklistSize; + out.maxAllowlistSize = halCaps.maxAllowlistSize; + return out; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiStaIface#installApfPacketFilter(byte[])} + */ + @Override + public boolean installApfPacketFilter(byte[] program) { + final String methodStr = "installApfPacketFilter"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.installApfPacketFilter(program); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#readApfPacketFilterData()} + */ + @Override + @Nullable + public byte[] readApfPacketFilterData() { + final String methodStr = "readApfPacketFilterData"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return null; + return mWifiStaIface.readApfPacketFilterData(); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return null; + } + } + + /** + * See comments for {@link IWifiStaIface#setMacAddress(MacAddress)} + */ + @Override + public boolean setMacAddress(MacAddress mac) { + final String methodStr = "setMacAddress"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.setMacAddress(mac.toByteArray()); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#setRoamingState(int)} + */ + @Override public @WifiNative.RoamingEnableStatus int setRoamingState( + @WifiNative.RoamingEnableState int state) { + final String methodStr = "setRoamingState"; + final int errorCode = WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE; + final byte halState = frameworkToHalStaRoamingState(state); + if (halState == -1) return errorCode; + + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return errorCode; + mWifiStaIface.setRoamingState(halState); + return WifiNative.SET_FIRMWARE_ROAMING_SUCCESS; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + if (e.errorCode == WifiStatusCode.ERROR_BUSY) { + return WifiNative.SET_FIRMWARE_ROAMING_BUSY; + } + handleServiceSpecificException(e, methodStr); + } + return errorCode; + } + } + + /** + * See comments for {@link IWifiStaIface#setScanMode(boolean)} + */ + @Override + public boolean setScanMode(boolean enable) { + final String methodStr = "setScanMode"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.setScanMode(enable); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for + * {@link IWifiStaIface#startBackgroundScan(int, WifiStaIface.StaBackgroundScanParameters)} + */ + @Override + public boolean startBackgroundScan(int cmdId, WifiStaIface.StaBackgroundScanParameters params) { + final String methodStr = "startBackgroundScan"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + StaBackgroundScanParameters halParams = frameworkToHalBackgroundScanParams(params); + mWifiStaIface.startBackgroundScan(cmdId, halParams); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } catch (IllegalArgumentException e) { + handleIllegalArgumentException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#startDebugPacketFateMonitoring()} + */ + @Override + public boolean startDebugPacketFateMonitoring() { + final String methodStr = "startDebugPacketFateMonitoring"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.startDebugPacketFateMonitoring(); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for + * {@link IWifiStaIface#startRssiMonitoring(int, int, int)} + */ + @Override + public boolean startRssiMonitoring(int cmdId, int maxRssi, int minRssi) { + final String methodStr = "startRssiMonitoring"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.startRssiMonitoring(cmdId, maxRssi, minRssi); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#startSendingKeepAlivePackets(int, byte[], int, + * MacAddress, MacAddress, int)} + */ + @Override + public boolean startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, + MacAddress srcAddress, MacAddress dstAddress, int periodInMs) { + final String methodStr = "startSendingKeepAlivePackets"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.startSendingKeepAlivePackets(cmdId, ipPacketData, (char) etherType, + srcAddress.toByteArray(), dstAddress.toByteArray(), periodInMs); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#stopBackgroundScan(int)} + */ + @Override + public boolean stopBackgroundScan(int cmdId) { + final String methodStr = "stopBackgroundScan"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.stopBackgroundScan(cmdId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#stopRssiMonitoring(int)} + */ + @Override + public boolean stopRssiMonitoring(int cmdId) { + final String methodStr = "stopRssiMonitoring"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.stopRssiMonitoring(cmdId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + /** + * See comments for {@link IWifiStaIface#stopSendingKeepAlivePackets(int)} + */ + @Override + public boolean stopSendingKeepAlivePackets(int cmdId) { + final String methodStr = "stopSendingKeepAlivePackets"; + synchronized (mLock) { + try { + if (!checkIfaceAndLogFailure(methodStr)) return false; + mWifiStaIface.stopSendingKeepAlivePackets(cmdId); + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } catch (ServiceSpecificException e) { + handleServiceSpecificException(e, methodStr); + } + return false; + } + } + + private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { + @Override + public void onBackgroundScanFailure(int cmdId) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onBackgroundScanFailure(cmdId); + } + + @Override + public void onBackgroundFullScanResult(int cmdId, int bucketsScanned, + StaScanResult result) { + if (mFrameworkCallback == null) return; + ScanResult frameworkScanResult = halToFrameworkScanResult(result); + if (frameworkScanResult == null) { + Log.e(TAG, "Unable to convert scan result from HAL to framework"); + return; + } + mFrameworkCallback.onBackgroundFullScanResult(cmdId, bucketsScanned, + frameworkScanResult); + } + + @Override + public void onBackgroundScanResults(int cmdId, StaScanData[] scanDatas) { + if (mFrameworkCallback == null) return; + WifiScanner.ScanData[] frameworkScanDatas = halToFrameworkScanDatas(cmdId, scanDatas); + mFrameworkCallback.onBackgroundScanResults(cmdId, frameworkScanDatas); + } + + @Override + public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onRssiThresholdBreached(cmdId, currBssid, currRssi); + } + + @Override + public String getInterfaceHash() { + return IWifiStaIfaceEventCallback.HASH; + } + + @Override + public int getInterfaceVersion() { + return IWifiStaIfaceEventCallback.VERSION; + } + } + + + // Utilities + + // Only sets the fields of ScanResult used by Gscan clients. + private ScanResult halToFrameworkScanResult(StaScanResult scanResult) { + if (scanResult == null) return null; + WifiSsid originalSsid = WifiSsid.fromBytes(scanResult.ssid); + MacAddress bssid; + try { + bssid = MacAddress.fromString(NativeUtil.macAddressFromByteArray(scanResult.bssid)); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Failed to get BSSID of scan result: " + e); + return null; + } + ScanResult frameworkScanResult = new ScanResult(); + frameworkScanResult.setWifiSsid(mSsidTranslator.getTranslatedSsidAndRecordBssidCharset( + originalSsid, bssid)); + frameworkScanResult.BSSID = bssid.toString(); + frameworkScanResult.level = scanResult.rssi; + frameworkScanResult.frequency = scanResult.frequency; + frameworkScanResult.timestamp = scanResult.timeStampInUs; + return frameworkScanResult; + } + + private ScanResult[] aidlToFrameworkScanResults(StaScanResult[] scanResults) { + if (scanResults == null || scanResults.length == 0) return new ScanResult[0]; + ScanResult[] frameworkScanResults = new ScanResult[scanResults.length]; + int i = 0; + for (StaScanResult scanResult : scanResults) { + ScanResult frameworkScanResult = halToFrameworkScanResult(scanResult); + if (frameworkScanResult == null) { + Log.e(TAG, "halToFrameworkScanResults: unable to convert hidl to framework " + + "scan result!"); + continue; + } + frameworkScanResults[i++] = frameworkScanResult; + } + return frameworkScanResults; + } + + private static int halToFrameworkScanDataFlags(int flag) { + if (flag == StaScanDataFlagMask.INTERRUPTED) { + return 1; + } else { + return 0; + } + } + + private WifiScanner.ScanData[] halToFrameworkScanDatas(int cmdId, StaScanData[] scanDatas) { + if (scanDatas == null || scanDatas.length == 0) return new WifiScanner.ScanData[0]; + WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.length]; + int i = 0; + for (StaScanData scanData : scanDatas) { + int flags = halToFrameworkScanDataFlags(scanData.flags); + ScanResult[] frameworkScanResults = aidlToFrameworkScanResults(scanData.results); + frameworkScanDatas[i++] = + new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned, + WifiScanner.WIFI_BAND_UNSPECIFIED, frameworkScanResults); + } + return frameworkScanDatas; + } + + private static StaRoamingConfig frameworkToHalStaRoamingConfig(List<MacAddress> bssidBlocklist, + List<byte[]> ssidAllowlist) { + StaRoamingConfig config = new StaRoamingConfig(); + config.bssidBlocklist = new android.hardware.wifi.MacAddress[bssidBlocklist.size()]; + config.ssidAllowlist = new Ssid[ssidAllowlist.size()]; + for (int i = 0; i < bssidBlocklist.size(); i++) { + android.hardware.wifi.MacAddress mac = new android.hardware.wifi.MacAddress(); + mac.data = bssidBlocklist.get(i).toByteArray(); + config.bssidBlocklist[i] = mac; + } + for (int i = 0; i < ssidAllowlist.size(); i++) { + Ssid ssid = new Ssid(); + ssid.data = ssidAllowlist.get(i); + config.ssidAllowlist[i] = ssid; + } + return config; + } + + private static byte halToFrameworkPktFateFrameType(int type) throws IllegalArgumentException { + switch (type) { + case WifiDebugPacketFateFrameType.UNKNOWN: + return WifiLoggerHal.FRAME_TYPE_UNKNOWN; + case WifiDebugPacketFateFrameType.ETHERNET_II: + return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; + case WifiDebugPacketFateFrameType.MGMT_80211: + return WifiLoggerHal.FRAME_TYPE_80211_MGMT; + default: + throw new IllegalArgumentException("bad " + type); + } + } + + private static byte halToFrameworkRxPktFate(int type) throws IllegalArgumentException { + switch (type) { + case WifiDebugRxPacketFate.SUCCESS: + return WifiLoggerHal.RX_PKT_FATE_SUCCESS; + case WifiDebugRxPacketFate.FW_QUEUED: + return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; + case WifiDebugRxPacketFate.FW_DROP_FILTER: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; + case WifiDebugRxPacketFate.FW_DROP_INVALID: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; + case WifiDebugRxPacketFate.FW_DROP_NOBUFS: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; + case WifiDebugRxPacketFate.FW_DROP_OTHER: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; + case WifiDebugRxPacketFate.DRV_QUEUED: + return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; + case WifiDebugRxPacketFate.DRV_DROP_FILTER: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; + case WifiDebugRxPacketFate.DRV_DROP_INVALID: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; + case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; + case WifiDebugRxPacketFate.DRV_DROP_OTHER: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; + default: + throw new IllegalArgumentException("bad " + type); + } + } + + private static byte halToFrameworkTxPktFate(int type) throws IllegalArgumentException { + switch (type) { + case WifiDebugTxPacketFate.ACKED: + return WifiLoggerHal.TX_PKT_FATE_ACKED; + case WifiDebugTxPacketFate.SENT: + return WifiLoggerHal.TX_PKT_FATE_SENT; + case WifiDebugTxPacketFate.FW_QUEUED: + return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; + case WifiDebugTxPacketFate.FW_DROP_INVALID: + return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; + case WifiDebugTxPacketFate.FW_DROP_NOBUFS: + return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; + case WifiDebugTxPacketFate.FW_DROP_OTHER: + return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; + case WifiDebugTxPacketFate.DRV_QUEUED: + return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; + case WifiDebugTxPacketFate.DRV_DROP_INVALID: + return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; + case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: + return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; + case WifiDebugTxPacketFate.DRV_DROP_OTHER: + return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; + default: + throw new IllegalArgumentException("bad " + type); + } + } + + private static boolean hasCapability(long capabilities, long desiredCapability) { + return (capabilities & desiredCapability) != 0; + } + + @VisibleForTesting + protected static long halToFrameworkStaIfaceCapability(long caps) { + long features = 0; + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT)) { + features |= WifiManager.WIFI_FEATURE_PASSPOINT; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN)) { + features |= WifiManager.WIFI_FEATURE_SCANNER; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.PNO)) { + features |= WifiManager.WIFI_FEATURE_PNO; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.TDLS)) { + features |= WifiManager.WIFI_FEATURE_TDLS; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL)) { + features |= WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS)) { + features |= WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR)) { + features |= WifiManager.WIFI_FEATURE_RSSI_MONITOR; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE)) { + features |= WifiManager.WIFI_FEATURE_MKEEP_ALIVE; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD)) { + features |= WifiManager.WIFI_FEATURE_CONFIG_NDO; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING)) { + features |= WifiManager.WIFI_FEATURE_CONTROL_ROAMING; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.PROBE_IE_ALLOWLIST)) { + features |= WifiManager.WIFI_FEATURE_IE_WHITELIST; + } + if (hasCapability(caps, + android.hardware.wifi.IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND)) { + features |= WifiManager.WIFI_FEATURE_SCAN_RAND; + } + return features; + } + + @VisibleForTesting + WifiLinkLayerStats halToFrameworkLinkLayerStats(StaLinkLayerStats stats) { + if (stats == null) return null; + WifiLinkLayerStats out = new WifiLinkLayerStats(); + setIfaceStats(out, stats.iface); + setRadioStats(out, stats.radios); + out.timeStampInMs = stats.timeStampInMs; + out.version = WifiLinkLayerStats.V1_5; // only used in unit tests, keep latest HIDL + return out; + } + + private static void setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface) { + if (iface == null) return; + stats.beacon_rx = iface.beaconRx; + stats.rssi_mgmt = iface.avgRssiMgmt; + // Statistics are broken out by Wireless Multimedia Extensions categories + // WME Best Effort Access Category + stats.rxmpdu_be = iface.wmeBePktStats.rxMpdu; + stats.txmpdu_be = iface.wmeBePktStats.txMpdu; + stats.lostmpdu_be = iface.wmeBePktStats.lostMpdu; + stats.retries_be = iface.wmeBePktStats.retries; + // WME Background Access Category + stats.rxmpdu_bk = iface.wmeBkPktStats.rxMpdu; + stats.txmpdu_bk = iface.wmeBkPktStats.txMpdu; + stats.lostmpdu_bk = iface.wmeBkPktStats.lostMpdu; + stats.retries_bk = iface.wmeBkPktStats.retries; + // WME Video Access Category + stats.rxmpdu_vi = iface.wmeViPktStats.rxMpdu; + stats.txmpdu_vi = iface.wmeViPktStats.txMpdu; + stats.lostmpdu_vi = iface.wmeViPktStats.lostMpdu; + stats.retries_vi = iface.wmeViPktStats.retries; + // WME Voice Access Category + stats.rxmpdu_vo = iface.wmeVoPktStats.rxMpdu; + stats.txmpdu_vo = iface.wmeVoPktStats.txMpdu; + stats.lostmpdu_vo = iface.wmeVoPktStats.lostMpdu; + stats.retries_vo = iface.wmeVoPktStats.retries; + stats.timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent; + // WME Best Effort Access Category + stats.contentionTimeMinBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesBe = iface.wmeBeContentionTimeStats.contentionNumSamples; + // WME Background Access Category + stats.contentionTimeMinBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesBk = iface.wmeBkContentionTimeStats.contentionNumSamples; + // WME Video Access Category + stats.contentionTimeMinViInUsec = iface.wmeViContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxViInUsec = iface.wmeViContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgViInUsec = iface.wmeViContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesVi = iface.wmeViContentionTimeStats.contentionNumSamples; + // WME Voice Access Category + stats.contentionTimeMinVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesVo = iface.wmeVoContentionTimeStats.contentionNumSamples; + // Peer information statistics + stats.peerInfo = new WifiLinkLayerStats.PeerInfo[iface.peers.length]; + for (int i = 0; i < stats.peerInfo.length; i++) { + WifiLinkLayerStats.PeerInfo peer = new WifiLinkLayerStats.PeerInfo(); + StaPeerInfo staPeerInfo = iface.peers[i]; + peer.staCount = (short) staPeerInfo.staCount; + peer.chanUtil = (short) staPeerInfo.chanUtil; + WifiLinkLayerStats.RateStat[] rateStats = + new WifiLinkLayerStats.RateStat[staPeerInfo.rateStats.length]; + for (int j = 0; j < staPeerInfo.rateStats.length; j++) { + rateStats[j] = new WifiLinkLayerStats.RateStat(); + StaRateStat staRateStat = staPeerInfo.rateStats[j]; + rateStats[j].preamble = staRateStat.rateInfo.preamble; + rateStats[j].nss = staRateStat.rateInfo.nss; + rateStats[j].bw = staRateStat.rateInfo.bw; + rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx; + rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps; + rateStats[j].txMpdu = staRateStat.txMpdu; + rateStats[j].rxMpdu = staRateStat.rxMpdu; + rateStats[j].mpduLost = staRateStat.mpduLost; + rateStats[j].retries = staRateStat.retries; + } + peer.rateStats = rateStats; + stats.peerInfo[i] = peer; + } + } + + private void setRadioStats(WifiLinkLayerStats stats, StaLinkLayerRadioStats[] radios) { + if (radios == null) return; + int radioIndex = 0; + stats.radioStats = new WifiLinkLayerStats.RadioStat[radios.length]; + for (StaLinkLayerRadioStats radioStats : radios) { + WifiLinkLayerStats.RadioStat radio = new WifiLinkLayerStats.RadioStat(); + setFrameworkPerRadioStatsFromAidl(radio, radioStats); + stats.radioStats[radioIndex] = radio; + aggregateFrameworkRadioStatsFromAidl(radioIndex, stats, radioStats); + radioIndex++; + } + } + + private static void setFrameworkPerRadioStatsFromAidl(WifiLinkLayerStats.RadioStat radio, + StaLinkLayerRadioStats aidlRadioStats) { + radio.radio_id = aidlRadioStats.radioId; + radio.on_time = aidlRadioStats.onTimeInMs; + radio.tx_time = aidlRadioStats.txTimeInMs; + radio.rx_time = aidlRadioStats.rxTimeInMs; + radio.on_time_scan = aidlRadioStats.onTimeInMsForScan; + radio.on_time_nan_scan = aidlRadioStats.onTimeInMsForNanScan; + radio.on_time_background_scan = aidlRadioStats.onTimeInMsForBgScan; + radio.on_time_roam_scan = aidlRadioStats.onTimeInMsForRoamScan; + radio.on_time_pno_scan = aidlRadioStats.onTimeInMsForPnoScan; + radio.on_time_hs20_scan = aidlRadioStats.onTimeInMsForHs20Scan; + /* Copy list of channel stats */ + for (WifiChannelStats channelStats : aidlRadioStats.channelStats) { + WifiLinkLayerStats.ChannelStats channelStatsEntry = + new WifiLinkLayerStats.ChannelStats(); + channelStatsEntry.frequency = channelStats.channel.centerFreq; + channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; + channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; + radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); + } + } + + private void aggregateFrameworkRadioStatsFromAidl(int radioIndex, + WifiLinkLayerStats stats, StaLinkLayerRadioStats aidlRadioStats) { + if (!mContext.getResources() + .getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled) + && radioIndex > 0) { + return; + } + // Aggregate the radio stats from all the radios + stats.on_time += aidlRadioStats.onTimeInMs; + stats.tx_time += aidlRadioStats.txTimeInMs; + // Aggregate tx_time_per_level based on the assumption that the length of + // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other + // radios at array indices greater than the length of first radio will be dropped. + if (stats.tx_time_per_level == null) { + stats.tx_time_per_level = new int[aidlRadioStats.txTimeInMsPerLevel.length]; + } + for (int i = 0; i < aidlRadioStats.txTimeInMsPerLevel.length + && i < stats.tx_time_per_level.length; i++) { + stats.tx_time_per_level[i] += aidlRadioStats.txTimeInMsPerLevel[i]; + } + stats.rx_time += aidlRadioStats.rxTimeInMs; + stats.on_time_scan += aidlRadioStats.onTimeInMsForScan; + stats.on_time_nan_scan += aidlRadioStats.onTimeInMsForNanScan; + stats.on_time_background_scan += aidlRadioStats.onTimeInMsForBgScan; + stats.on_time_roam_scan += aidlRadioStats.onTimeInMsForRoamScan; + stats.on_time_pno_scan += aidlRadioStats.onTimeInMsForPnoScan; + stats.on_time_hs20_scan += aidlRadioStats.onTimeInMsForHs20Scan; + /* Copy list of channel stats */ + for (WifiChannelStats channelStats : aidlRadioStats.channelStats) { + WifiLinkLayerStats.ChannelStats channelStatsEntry = + stats.channelStatsMap.get(channelStats.channel.centerFreq); + if (channelStatsEntry == null) { + channelStatsEntry = new WifiLinkLayerStats.ChannelStats(); + channelStatsEntry.frequency = channelStats.channel.centerFreq; + stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); + } + channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs; + channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs; + } + stats.numRadios++; + } + + private static byte frameworkToHalStaRoamingState(@WifiNative.RoamingEnableState int state) { + switch (state) { + case WifiNative.DISABLE_FIRMWARE_ROAMING: + return StaRoamingState.DISABLED; + case WifiNative.ENABLE_FIRMWARE_ROAMING: + return StaRoamingState.ENABLED; + default: + Log.e(TAG, "Invalid firmware roaming state enum: " + state); + return -1; + } + } + + private static StaBackgroundScanParameters frameworkToHalBackgroundScanParams( + WifiStaIface.StaBackgroundScanParameters frameworkParams) + throws IllegalArgumentException { + StaBackgroundScanParameters halParams = new StaBackgroundScanParameters(); + halParams.basePeriodInMs = frameworkParams.basePeriodInMs; + halParams.maxApPerScan = frameworkParams.maxApPerScan; + halParams.reportThresholdPercent = frameworkParams.reportThresholdPercent; + halParams.reportThresholdNumScans = frameworkParams.reportThresholdNumScans; + int numBuckets = frameworkParams.buckets != null ? frameworkParams.buckets.size() : 0; + halParams.buckets = new android.hardware.wifi.StaBackgroundScanBucketParameters[numBuckets]; + if (frameworkParams.buckets != null) { + for (int i = 0; i < numBuckets; i++) { + halParams.buckets[i] = frameworkToHalBucketParams(frameworkParams.buckets.get(i)); + } + } + return halParams; + } + + private static StaBackgroundScanBucketParameters frameworkToHalBucketParams( + WifiNative.BucketSettings frameworkBucket) throws IllegalArgumentException { + StaBackgroundScanBucketParameters halBucket = new StaBackgroundScanBucketParameters(); + halBucket.bucketIdx = frameworkBucket.bucket; + halBucket.band = frameworkToHalWifiBand(frameworkBucket.band); + int numChannels = frameworkBucket.channels != null ? frameworkBucket.channels.length : 0; + halBucket.frequencies = new int[numChannels]; + if (frameworkBucket.channels != null) { + for (int i = 0; i < frameworkBucket.channels.length; i++) { + halBucket.frequencies[i] = frameworkBucket.channels[i].frequency; + } + } + halBucket.periodInMs = frameworkBucket.period_ms; + halBucket.eventReportScheme = frameworkToHalReportSchemeMask(frameworkBucket.report_events); + halBucket.exponentialMaxPeriodInMs = frameworkBucket.max_period_ms; + // Although HAL API allows configurable base value for the truncated + // exponential back off scan. Native API and above support only + // truncated binary exponential back off scan. + // Hard code value of base to 2 here. + halBucket.exponentialBase = 2; + halBucket.exponentialStepCount = frameworkBucket.step_count; + return halBucket; + } + + private static int frameworkToHalWifiBand(int frameworkBand) throws IllegalArgumentException { + switch (frameworkBand) { + case WifiScanner.WIFI_BAND_UNSPECIFIED: + return WifiBand.BAND_UNSPECIFIED; + case WifiScanner.WIFI_BAND_24_GHZ: + return WifiBand.BAND_24GHZ; + case WifiScanner.WIFI_BAND_5_GHZ: + return WifiBand.BAND_5GHZ; + case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: + return WifiBand.BAND_5GHZ_DFS; + case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: + return WifiBand.BAND_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_BOTH: + return WifiBand.BAND_24GHZ_5GHZ; + case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_6_GHZ: + return WifiBand.BAND_6GHZ; + case WifiScanner.WIFI_BAND_24_5_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ; + case WifiScanner.WIFI_BAND_60_GHZ: + return WifiBand.BAND_60GHZ; + case WifiScanner.WIFI_BAND_24_5_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS: + default: + throw new IllegalArgumentException("bad band " + frameworkBand); + } + } + + private static int frameworkToHalReportSchemeMask(int reportUnderscoreEvents) + throws IllegalArgumentException { + int ans = 0; + BitMask in = new BitMask(reportUnderscoreEvents); + if (in.testAndClear(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)) { + ans |= StaBackgroundScanBucketEventReportSchemeMask.EACH_SCAN; + } + if (in.testAndClear(WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)) { + ans |= StaBackgroundScanBucketEventReportSchemeMask.FULL_RESULTS; + } + if (in.testAndClear(WifiScanner.REPORT_EVENT_NO_BATCH)) { + ans |= StaBackgroundScanBucketEventReportSchemeMask.NO_BATCH; + } + if (in.value != 0) throw new IllegalArgumentException("bad " + reportUnderscoreEvents); + return ans; + } + + private boolean checkIfaceAndLogFailure(String methodStr) { + if (mWifiStaIface == null) { + Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); + return false; + } + return true; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + mWifiStaIface = null; + mIfaceName = null; + Log.e(TAG, methodStr + " failed with remote exception: " + e); + } + + private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { + Log.e(TAG, methodStr + " failed with service-specific exception: " + e); + } + + private void handleIllegalArgumentException(IllegalArgumentException e, String methodStr) { + Log.e(TAG, methodStr + " failed with illegal argument exception: " + e); + } +} diff --git a/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java new file mode 100644 index 0000000000..dc7f34ef12 --- /dev/null +++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java @@ -0,0 +1,1543 @@ +/* + * Copyright (C) 2022 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.hal; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; +import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask; +import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters; +import android.hardware.wifi.V1_0.StaBackgroundScanParameters; +import android.hardware.wifi.V1_0.StaLinkLayerIfaceStats; +import android.hardware.wifi.V1_0.StaLinkLayerRadioStats; +import android.hardware.wifi.V1_0.StaLinkLayerStats; +import android.hardware.wifi.V1_0.StaRoamingConfig; +import android.hardware.wifi.V1_0.StaRoamingState; +import android.hardware.wifi.V1_0.StaScanData; +import android.hardware.wifi.V1_0.StaScanDataFlagMask; +import android.hardware.wifi.V1_0.StaScanResult; +import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; +import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; +import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; +import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; +import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; +import android.hardware.wifi.V1_0.WifiStatus; +import android.hardware.wifi.V1_0.WifiStatusCode; +import android.hardware.wifi.V1_5.WifiBand; +import android.net.MacAddress; +import android.net.apf.ApfCapabilities; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiScanner; +import android.net.wifi.WifiSsid; +import android.os.RemoteException; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.wifi.SsidTranslator; +import com.android.server.wifi.WifiLinkLayerStats; +import com.android.server.wifi.WifiLoggerHal; +import com.android.server.wifi.WifiNative; +import com.android.server.wifi.util.BitMask; +import com.android.server.wifi.util.GeneralUtil; +import com.android.server.wifi.util.NativeUtil; +import com.android.wifi.resources.R; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + + +/** + * HIDL implementation of the IWifiStaIface interface. + */ +public class WifiStaIfaceHidlImpl implements IWifiStaIface { + private static final String TAG = "WifiStaIfaceHidlImpl"; + private android.hardware.wifi.V1_0.IWifiStaIface mWifiStaIface; + private String mIfaceName; + private IWifiStaIfaceEventCallback mHalCallback; + private WifiStaIface.Callback mFrameworkCallback; + private Context mContext; + private SsidTranslator mSsidTranslator; + + public WifiStaIfaceHidlImpl(@NonNull android.hardware.wifi.V1_0.IWifiStaIface staIface, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + mWifiStaIface = staIface; + mContext = context; + mSsidTranslator = ssidTranslator; + mHalCallback = new StaIfaceEventCallback(); + } + + /** + * See comments for {@link IWifiStaIface#registerFrameworkCallback(WifiStaIface.Callback)} + */ + public boolean registerFrameworkCallback(WifiStaIface.Callback callback) { + final String methodStr = "registerFrameworkCallback"; + return validateAndCall(methodStr, false, + () -> registerFrameworkCallbackInternal(methodStr, callback)); + } + + /** + * See comments for {@link IWifiStaIface#getName()} + */ + @Nullable + public String getName() { + final String methodStr = "getName"; + return validateAndCall(methodStr, null, + () -> getNameInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#configureRoaming(List, List)} + */ + public boolean configureRoaming(List<MacAddress> bssidBlocklist, + List<byte[]> ssidAllowlist) { + final String methodStr = "configureRoaming"; + return validateAndCall(methodStr, false, + () -> configureRoamingInternal(methodStr, bssidBlocklist, ssidAllowlist)); + } + + /** + * See comments for {@link IWifiStaIface#enableLinkLayerStatsCollection(boolean)} + */ + public boolean enableLinkLayerStatsCollection(boolean debug) { + final String methodStr = "enableLinkLayerStatsCollection"; + return validateAndCall(methodStr, false, + () -> enableLinkLayerStatsCollectionInternal(methodStr, debug)); + } + + /** + * See comments for {@link IWifiStaIface#enableNdOffload(boolean)} + */ + public boolean enableNdOffload(boolean enable) { + final String methodStr = "enableNdOffload"; + return validateAndCall(methodStr, false, + () -> enableNdOffloadInternal(methodStr, enable)); + } + + /** + * See comments for {@link IWifiStaIface#getApfPacketFilterCapabilities()} + */ + public ApfCapabilities getApfPacketFilterCapabilities() { + final String methodStr = "getApfPacketFilterCapabilities"; + return validateAndCall(methodStr, new ApfCapabilities(0, 0, 0), + () -> getApfPacketFilterCapabilitiesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#getBackgroundScanCapabilities()} + */ + @Nullable + public WifiNative.ScanCapabilities getBackgroundScanCapabilities() { + final String methodStr = "getBackgroundScanCapabilities"; + return validateAndCall(methodStr, null, + () -> getBackgroundScanCapabilitiesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#getCapabilities()} + */ + public long getCapabilities() { + final String methodStr = "getCapabilities"; + return validateAndCall(methodStr, 0L, + () -> getCapabilitiesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#getDebugRxPacketFates()} + */ + public List<WifiNative.RxFateReport> getDebugRxPacketFates() { + final String methodStr = "getDebugRxPacketFates"; + return validateAndCall(methodStr, new ArrayList<>(), + () -> getDebugRxPacketFatesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#getDebugTxPacketFates()} + */ + public List<WifiNative.TxFateReport> getDebugTxPacketFates() { + final String methodStr = "getDebugTxPacketFates"; + return validateAndCall(methodStr, new ArrayList<>(), + () -> getDebugTxPacketFatesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#getFactoryMacAddress()} + */ + @Nullable + public MacAddress getFactoryMacAddress() { + final String methodStr = "getFactoryMacAddress"; + return validateAndCall(methodStr, null, + () -> getFactoryMacAddressInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#getLinkLayerStats()} + */ + @Nullable + public WifiLinkLayerStats getLinkLayerStats() { + final String methodStr = "getLinkLayerStats"; + return validateAndCall(methodStr, null, + () -> getLinkLayerStatsInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#getRoamingCapabilities()} + */ + @Nullable + public WifiNative.RoamingCapabilities getRoamingCapabilities() { + final String methodStr = "getRoamingCapabilities"; + return validateAndCall(methodStr, null, + () -> getRoamingCapabilitiesInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#installApfPacketFilter(byte[])} + */ + public boolean installApfPacketFilter(byte[] program) { + final String methodStr = "installApfPacketFilter"; + return validateAndCall(methodStr, false, + () -> installApfPacketFilterInternal(methodStr, program)); + } + + /** + * See comments for {@link IWifiStaIface#readApfPacketFilterData()} + */ + @Nullable + public byte[] readApfPacketFilterData() { + final String methodStr = "readApfPacketFilterData"; + return validateAndCall(methodStr, null, + () -> readApfPacketFilterDataInternal(methodStr)); + } + + /** + * See comments for {@link IWifiStaIface#setMacAddress(MacAddress)} + */ + public boolean setMacAddress(MacAddress mac) { + final String methodStr = "setMacAddress"; + return validateAndCall(methodStr, false, + () -> setMacAddressInternal(methodStr, mac)); + } + + /** + * See comments for {@link IWifiStaIface#setRoamingState(int)} + */ + public @WifiNative.RoamingEnableStatus int setRoamingState( + @WifiNative.RoamingEnableState int state) { + final String methodStr = "setRoamingState"; + return validateAndCall(methodStr, WifiNative.SET_FIRMWARE_ROAMING_FAILURE, + () -> setRoamingStateInternal(methodStr, state)); + } + + /** + * See comments for {@link IWifiStaIface#setScanMode(boolean)} + */ + public boolean setScanMode(boolean enable) { + final String methodStr = "setScanMode"; + return validateAndCall(methodStr, false, + () -> setScanModeInternal(methodStr, enable)); + } + + /** + * See comments for + * {@link IWifiStaIface#startBackgroundScan(int, WifiStaIface.StaBackgroundScanParameters)} + */ + public boolean startBackgroundScan(int cmdId, WifiStaIface.StaBackgroundScanParameters params) { + final String methodStr = "startBackgroundScan"; + return validateAndCall(methodStr, false, + () -> startBackgroundScanInternal(methodStr, cmdId, params)); + } + + /** + * See comments for {@link IWifiStaIface#startDebugPacketFateMonitoring()} + */ + public boolean startDebugPacketFateMonitoring() { + final String methodStr = "startDebugPacketFateMonitoring"; + return validateAndCall(methodStr, false, + () -> startDebugPacketFateMonitoringInternal(methodStr)); + } + + /** + * See comments for + * {@link IWifiStaIface#startRssiMonitoring(int, int, int)} + */ + public boolean startRssiMonitoring(int cmdId, int maxRssi, int minRssi) { + final String methodStr = "startRssiMonitoring"; + return validateAndCall(methodStr, false, + () -> startRssiMonitoringInternal(methodStr, cmdId, maxRssi, minRssi)); + } + + /** + * See comments for {@link IWifiStaIface#startSendingKeepAlivePackets(int, byte[], int, + * MacAddress, MacAddress, int)} + */ + public boolean startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, + MacAddress srcAddress, MacAddress dstAddress, int periodInMs) { + final String methodStr = "startSendingKeepAlivePackets"; + return validateAndCall(methodStr, false, + () -> startSendingKeepAlivePacketsInternal(methodStr, cmdId, ipPacketData, + etherType, srcAddress, dstAddress, periodInMs)); + } + + /** + * See comments for {@link IWifiStaIface#stopBackgroundScan(int)} + */ + public boolean stopBackgroundScan(int cmdId) { + final String methodStr = "stopBackgroundScan"; + return validateAndCall(methodStr, false, + () -> stopBackgroundScanInternal(methodStr, cmdId)); + } + + /** + * See comments for {@link IWifiStaIface#stopRssiMonitoring(int)} + */ + public boolean stopRssiMonitoring(int cmdId) { + final String methodStr = "stopRssiMonitoring"; + return validateAndCall(methodStr, false, + () -> stopRssiMonitoringInternal(methodStr, cmdId)); + } + + /** + * See comments for {@link IWifiStaIface#stopSendingKeepAlivePackets(int)} + */ + public boolean stopSendingKeepAlivePackets(int cmdId) { + final String methodStr = "stopSendingKeepAlivePackets"; + return validateAndCall(methodStr, false, + () -> stopSendingKeepAlivePacketsInternal(methodStr, cmdId)); + } + + + // Internal Implementations + + private boolean registerFrameworkCallbackInternal(String methodStr, + WifiStaIface.Callback callback) { + if (mFrameworkCallback != null) { + Log.e(TAG, "Framework callback is already registered"); + return false; + } else if (callback == null) { + Log.e(TAG, "Cannot register a null callback"); + return false; + } + + try { + WifiStatus status = mWifiStaIface.registerEventCallback(mHalCallback); + if (!isOk(status, methodStr)) return false; + mFrameworkCallback = callback; + return true; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private String getNameInternal(String methodStr) { + if (mIfaceName != null) return mIfaceName; + GeneralUtil.Mutable<String> nameResp = new GeneralUtil.Mutable<>(); + try { + mWifiStaIface.getName((WifiStatus status, String name) -> { + if (isOk(status, methodStr)) { + nameResp.value = name; + mIfaceName = name; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return nameResp.value; + } + + private boolean configureRoamingInternal(String methodStr, List<MacAddress> bssidBlocklist, + List<byte[]> ssidAllowlist) { + StaRoamingConfig config = new StaRoamingConfig(); + config.ssidWhitelist = new ArrayList<>(ssidAllowlist); + config.bssidBlacklist = new ArrayList<>(); + for (MacAddress bssid : bssidBlocklist) { + config.bssidBlacklist.add(bssid.toByteArray()); + } + try { + WifiStatus status = mWifiStaIface.configureRoaming(config); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean enableLinkLayerStatsCollectionInternal(String methodStr, boolean debug) { + try { + WifiStatus status = mWifiStaIface.enableLinkLayerStatsCollection(debug); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean enableNdOffloadInternal(String methodStr, boolean enable) { + try { + WifiStatus status = mWifiStaIface.enableNdOffload(enable); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private ApfCapabilities getApfPacketFilterCapabilitiesInternal(String methodStr) { + GeneralUtil.Mutable<ApfCapabilities> apfResp = + new GeneralUtil.Mutable<>(new ApfCapabilities(0, 0, 0)); + try { + mWifiStaIface.getApfPacketFilterCapabilities((status, caps) -> { + if (isOk(status, methodStr)) { + apfResp.value = new ApfCapabilities( + /* apfVersionSupported */ caps.version, + /* maximumApfProgramSize */ caps.maxLength, + /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return apfResp.value; + } + + private WifiNative.ScanCapabilities getBackgroundScanCapabilitiesInternal(String methodStr) { + GeneralUtil.Mutable<WifiNative.ScanCapabilities> scanResp = new GeneralUtil.Mutable<>(); + try { + mWifiStaIface.getBackgroundScanCapabilities((status, caps) -> { + if (isOk(status, methodStr)) { + WifiNative.ScanCapabilities out = new WifiNative.ScanCapabilities(); + out.max_scan_cache_size = caps.maxCacheSize; + out.max_ap_cache_per_scan = caps.maxApCachePerScan; + out.max_scan_buckets = caps.maxBuckets; + out.max_rssi_sample_size = 0; + out.max_scan_reporting_threshold = caps.maxReportingThreshold; + scanResp.value = out; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return scanResp.value; + } + + private long getCapabilitiesInternal(String methodStr) { + GeneralUtil.Mutable<Long> capsResp = new GeneralUtil.Mutable<>(0L); + try { + mWifiStaIface.getCapabilities((status, caps) -> { + if (isOk(status, methodStr)) { + capsResp.value = halToFrameworkStaIfaceCapability(caps); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return capsResp.value; + } + + private List<WifiNative.RxFateReport> getDebugRxPacketFatesInternal(String methodStr) { + try { + List<WifiNative.RxFateReport> reportBufs = new ArrayList<>(); + mWifiStaIface.getDebugRxPacketFates((status, fates) -> { + if (!isOk(status, methodStr)) return; + for (WifiDebugRxPacketFateReport fate : fates) { + if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; + byte code = halToFrameworkRxPktFate(fate.fate); + long us = fate.frameInfo.driverTimestampUsec; + byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType); + byte[] frame = NativeUtil.byteArrayFromArrayList( + fate.frameInfo.frameContent); + reportBufs.add(new WifiNative.RxFateReport(code, us, type, frame)); + } + }); + return reportBufs; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return new ArrayList<>(); + } + } + + private List<WifiNative.TxFateReport> getDebugTxPacketFatesInternal(String methodStr) { + try { + List<WifiNative.TxFateReport> reportBufs = new ArrayList<>(); + mWifiStaIface.getDebugTxPacketFates((status, fates) -> { + if (!isOk(status, methodStr)) return; + for (WifiDebugTxPacketFateReport fate : fates) { + if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; + byte code = halToFrameworkTxPktFate(fate.fate); + long us = fate.frameInfo.driverTimestampUsec; + byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType); + byte[] frame = NativeUtil.byteArrayFromArrayList( + fate.frameInfo.frameContent); + reportBufs.add(new WifiNative.TxFateReport(code, us, type, frame)); + } + }); + return reportBufs; + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return new ArrayList<>(); + } + } + + private MacAddress getFactoryMacAddressInternal(String methodStr) { + GeneralUtil.Mutable<MacAddress> macResp = new GeneralUtil.Mutable<>(); + try { + android.hardware.wifi.V1_3.IWifiStaIface sta13 = getWifiStaIfaceV1_3Mockable(); + if (sta13 == null) return null; + sta13.getFactoryMacAddress((status, macBytes) -> { + if (isOk(status, methodStr)) { + macResp.value = MacAddress.fromBytes(macBytes); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return macResp.value; + } + + private WifiLinkLayerStats getLinkLayerStatsInternal(String methodStr) { + if (getWifiStaIfaceV1_6Mockable() != null) { + return getLinkLayerStatsV1_6Internal(methodStr); + } else if (getWifiStaIfaceV1_5Mockable() != null) { + return getLinkLayerStatsV1_5Internal(methodStr); + } else if (getWifiStaIfaceV1_3Mockable() != null) { + return getLinkLayerStatsV1_3Internal(methodStr); + } else { + return getLinkLayerStatsV1_0Internal(methodStr); + } + } + + private WifiLinkLayerStats getLinkLayerStatsV1_0Internal(String methodStr) { + final String methodStrV1_0 = methodStr + "V1_0"; + GeneralUtil.Mutable<StaLinkLayerStats> statsResp = new GeneralUtil.Mutable<>(); + try { + mWifiStaIface.getLinkLayerStats((status, stats) -> { + if (isOk(status, methodStrV1_0)) { + statsResp.value = stats; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStrV1_0); + return null; + } + return frameworkFromHalLinkLayerStats(statsResp.value); + } + + private WifiLinkLayerStats getLinkLayerStatsV1_3Internal(String methodStr) { + final String methodStrV1_3 = methodStr + "V1_3"; + GeneralUtil.Mutable<android.hardware.wifi.V1_3.StaLinkLayerStats> statsResp = + new GeneralUtil.Mutable<>(); + try { + android.hardware.wifi.V1_3.IWifiStaIface iface13 = getWifiStaIfaceV1_3Mockable(); + if (iface13 == null) return null; + iface13.getLinkLayerStats_1_3((status, stats) -> { + if (isOk(status, methodStrV1_3)) { + statsResp.value = stats; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStrV1_3); + return null; + } + return frameworkFromHalLinkLayerStats_1_3(statsResp.value); + } + + private WifiLinkLayerStats getLinkLayerStatsV1_5Internal(String methodStr) { + final String methodStrV1_5 = methodStr + "V1_5"; + GeneralUtil.Mutable<android.hardware.wifi.V1_5.StaLinkLayerStats> statsResp = + new GeneralUtil.Mutable<>(); + try { + android.hardware.wifi.V1_5.IWifiStaIface iface15 = getWifiStaIfaceV1_5Mockable(); + if (iface15 == null) return null; + iface15.getLinkLayerStats_1_5((status, stats) -> { + if (isOk(status, methodStrV1_5)) { + statsResp.value = stats; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStrV1_5); + return null; + } + return frameworkFromHalLinkLayerStats_1_5(statsResp.value); + } + + private WifiLinkLayerStats getLinkLayerStatsV1_6Internal(String methodStr) { + final String methodStrV1_6 = methodStr + "V1_6"; + GeneralUtil.Mutable<android.hardware.wifi.V1_6.StaLinkLayerStats> statsResp = + new GeneralUtil.Mutable<>(); + try { + android.hardware.wifi.V1_6.IWifiStaIface iface16 = getWifiStaIfaceV1_6Mockable(); + if (iface16 == null) return null; + iface16.getLinkLayerStats_1_6((status, stats) -> { + if (isOk(status, methodStrV1_6)) { + statsResp.value = stats; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStrV1_6); + return null; + } + return frameworkFromHalLinkLayerStats_1_6(statsResp.value); + } + + private WifiNative.RoamingCapabilities getRoamingCapabilitiesInternal(String methodStr) { + GeneralUtil.Mutable<WifiNative.RoamingCapabilities> capsResp = new GeneralUtil.Mutable<>(); + try { + mWifiStaIface.getRoamingCapabilities((status, caps) -> { + if (isOk(status, methodStr)) { + WifiNative.RoamingCapabilities out = new WifiNative.RoamingCapabilities(); + out.maxBlocklistSize = caps.maxBlacklistSize; + out.maxAllowlistSize = caps.maxWhitelistSize; + capsResp.value = out; + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return capsResp.value; + } + + private boolean installApfPacketFilterInternal(String methodStr, byte[] program) { + try { + int cmdId = 0; // We only aspire to support one program at a time. + ArrayList<Byte> filter = NativeUtil.byteArrayToArrayList(program); + WifiStatus status = mWifiStaIface.installApfPacketFilter(cmdId, filter); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private byte[] readApfPacketFilterDataInternal(String methodStr) { + GeneralUtil.Mutable<byte[]> dataResp = new GeneralUtil.Mutable<>(); + try { + android.hardware.wifi.V1_2.IWifiStaIface iface12 = getWifiStaIfaceV1_2Mockable(); + if (iface12 == null) return null; + iface12.readApfPacketFilterData((status, data) -> { + if (isOk(status, methodStr)) { + dataResp.value = NativeUtil.byteArrayFromArrayList(data); + } + }); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + } + return dataResp.value; + } + + private boolean setMacAddressInternal(String methodStr, MacAddress mac) { + try { + android.hardware.wifi.V1_2.IWifiStaIface iface12 = getWifiStaIfaceV1_2Mockable(); + if (iface12 == null) return false; + byte[] macBytes = mac.toByteArray(); + WifiStatus status = iface12.setMacAddress(macBytes); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private @WifiNative.RoamingEnableStatus int setRoamingStateInternal(String methodStr, + @WifiNative.RoamingEnableState int state) { + byte halState = frameworkToHalStaRoamingState(state); + if (halState == -1) { + return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE; + } + + try { + WifiStatus status = mWifiStaIface.setRoamingState(halState); + if (isOk(status, methodStr)) { + return WifiNative.SET_FIRMWARE_ROAMING_SUCCESS; + } else if (status.code == WifiStatusCode.ERROR_BUSY) { + return WifiNative.SET_FIRMWARE_ROAMING_BUSY; + } else { + return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE; + } + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE; + } + } + + private boolean setScanModeInternal(String methodStr, boolean enable) { + try { + android.hardware.wifi.V1_5.IWifiStaIface iface15 = getWifiStaIfaceV1_5Mockable(); + if (iface15 == null) return false; + WifiStatus status = iface15.setScanMode(enable); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean startBackgroundScanInternal(String methodStr, int cmdId, + WifiStaIface.StaBackgroundScanParameters params) { + try { + StaBackgroundScanParameters halParams = frameworkToHalBackgroundScanParams(params); + WifiStatus status = mWifiStaIface.startBackgroundScan(cmdId, halParams); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean startDebugPacketFateMonitoringInternal(String methodStr) { + try { + WifiStatus status = mWifiStaIface.startDebugPacketFateMonitoring(); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean startRssiMonitoringInternal(String methodStr, int cmdId, int maxRssi, + int minRssi) { + try { + WifiStatus status = mWifiStaIface.startRssiMonitoring(cmdId, maxRssi, minRssi); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean startSendingKeepAlivePacketsInternal(String methodStr, int cmdId, + byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress, + int periodInMs) { + try { + ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(ipPacketData); + byte[] srcMac = srcAddress.toByteArray(); + byte[] dstMac = dstAddress.toByteArray(); + WifiStatus status = mWifiStaIface.startSendingKeepAlivePackets( + cmdId, data, (short) etherType, srcMac, dstMac, periodInMs); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean stopBackgroundScanInternal(String methodStr, int cmdId) { + try { + WifiStatus status = mWifiStaIface.stopBackgroundScan(cmdId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean stopRssiMonitoringInternal(String methodStr, int cmdId) { + try { + WifiStatus status = mWifiStaIface.stopRssiMonitoring(cmdId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + private boolean stopSendingKeepAlivePacketsInternal(String methodStr, int cmdId) { + try { + WifiStatus status = mWifiStaIface.stopSendingKeepAlivePackets(cmdId); + return isOk(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + + + // Helper Functions + + private static byte frameworkToHalStaRoamingState(@WifiNative.RoamingEnableState int state) { + switch (state) { + case WifiNative.DISABLE_FIRMWARE_ROAMING: + return StaRoamingState.DISABLED; + case WifiNative.ENABLE_FIRMWARE_ROAMING: + return StaRoamingState.ENABLED; + default: + Log.e(TAG, "Invalid firmware roaming state enum: " + state); + return -1; + } + } + + private static byte halToFrameworkPktFateFrameType(int type) { + switch (type) { + case WifiDebugPacketFateFrameType.UNKNOWN: + return WifiLoggerHal.FRAME_TYPE_UNKNOWN; + case WifiDebugPacketFateFrameType.ETHERNET_II: + return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; + case WifiDebugPacketFateFrameType.MGMT_80211: + return WifiLoggerHal.FRAME_TYPE_80211_MGMT; + default: + throw new IllegalArgumentException("bad " + type); + } + } + + private static byte halToFrameworkRxPktFate(int type) { + switch (type) { + case WifiDebugRxPacketFate.SUCCESS: + return WifiLoggerHal.RX_PKT_FATE_SUCCESS; + case WifiDebugRxPacketFate.FW_QUEUED: + return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; + case WifiDebugRxPacketFate.FW_DROP_FILTER: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; + case WifiDebugRxPacketFate.FW_DROP_INVALID: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; + case WifiDebugRxPacketFate.FW_DROP_NOBUFS: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; + case WifiDebugRxPacketFate.FW_DROP_OTHER: + return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; + case WifiDebugRxPacketFate.DRV_QUEUED: + return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; + case WifiDebugRxPacketFate.DRV_DROP_FILTER: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; + case WifiDebugRxPacketFate.DRV_DROP_INVALID: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; + case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; + case WifiDebugRxPacketFate.DRV_DROP_OTHER: + return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; + default: + throw new IllegalArgumentException("bad " + type); + } + } + + private static byte halToFrameworkTxPktFate(int type) { + switch (type) { + case WifiDebugTxPacketFate.ACKED: + return WifiLoggerHal.TX_PKT_FATE_ACKED; + case WifiDebugTxPacketFate.SENT: + return WifiLoggerHal.TX_PKT_FATE_SENT; + case WifiDebugTxPacketFate.FW_QUEUED: + return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; + case WifiDebugTxPacketFate.FW_DROP_INVALID: + return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; + case WifiDebugTxPacketFate.FW_DROP_NOBUFS: + return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; + case WifiDebugTxPacketFate.FW_DROP_OTHER: + return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; + case WifiDebugTxPacketFate.DRV_QUEUED: + return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; + case WifiDebugTxPacketFate.DRV_DROP_INVALID: + return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; + case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: + return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; + case WifiDebugTxPacketFate.DRV_DROP_OTHER: + return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; + default: + throw new IllegalArgumentException("bad " + type); + } + } + + private static boolean hasCapability(long capabilities, long desiredCapability) { + return (capabilities & desiredCapability) != 0; + } + + @VisibleForTesting + long halToFrameworkStaIfaceCapability(int caps) { + long features = 0; + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT)) { + features |= WifiManager.WIFI_FEATURE_PASSPOINT; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN)) { + features |= WifiManager.WIFI_FEATURE_SCANNER; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.PNO)) { + features |= WifiManager.WIFI_FEATURE_PNO; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS)) { + features |= WifiManager.WIFI_FEATURE_TDLS; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL)) { + features |= 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; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR)) { + features |= WifiManager.WIFI_FEATURE_RSSI_MONITOR; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE)) { + features |= WifiManager.WIFI_FEATURE_MKEEP_ALIVE; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD)) { + features |= WifiManager.WIFI_FEATURE_CONFIG_NDO; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING)) { + features |= WifiManager.WIFI_FEATURE_CONTROL_ROAMING; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask + .PROBE_IE_WHITELIST)) { + features |= WifiManager.WIFI_FEATURE_IE_WHITELIST; + } + if (hasCapability(caps, + android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND)) { + features |= WifiManager.WIFI_FEATURE_SCAN_RAND; + } + return features; + } + + @VisibleForTesting + WifiLinkLayerStats frameworkFromHalLinkLayerStats(StaLinkLayerStats stats) { + if (stats == null) return null; + WifiLinkLayerStats out = new WifiLinkLayerStats(); + setIfaceStats(out, stats.iface); + setRadioStats(out, stats.radios); + out.timeStampInMs = stats.timeStampInMs; + out.version = WifiLinkLayerStats.V1_0; + return out; + } + + /** + * Makes the framework version of link layer stats from the hal version. + */ + @VisibleForTesting + WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_3( + android.hardware.wifi.V1_3.StaLinkLayerStats stats) { + if (stats == null) return null; + WifiLinkLayerStats out = new WifiLinkLayerStats(); + setIfaceStats(out, stats.iface); + setRadioStats_1_3(out, stats.radios); + out.timeStampInMs = stats.timeStampInMs; + out.version = WifiLinkLayerStats.V1_3; + return out; + } + + /** + * Makes the framework version of link layer stats from the hal version. + */ + @VisibleForTesting + WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_5( + android.hardware.wifi.V1_5.StaLinkLayerStats stats) { + if (stats == null) return null; + WifiLinkLayerStats out = new WifiLinkLayerStats(); + setIfaceStats_1_5(out, stats.iface); + setRadioStats_1_5(out, stats.radios); + out.timeStampInMs = stats.timeStampInMs; + out.version = WifiLinkLayerStats.V1_5; + return out; + } + + /** + * Makes the framework version of link layer stats from the hal version. + */ + @VisibleForTesting + WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_6( + android.hardware.wifi.V1_6.StaLinkLayerStats stats) { + if (stats == null) return null; + WifiLinkLayerStats out = new WifiLinkLayerStats(); + setIfaceStats_1_6(out, stats.iface); + setRadioStats_1_6(out, stats.radios); + out.timeStampInMs = stats.timeStampInMs; + out.version = WifiLinkLayerStats.V1_5; + return out; + } + + private static void setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface) { + if (iface == null) return; + stats.beacon_rx = iface.beaconRx; + stats.rssi_mgmt = iface.avgRssiMgmt; + // Statistics are broken out by Wireless Multimedia Extensions categories + // WME Best Effort Access Category + stats.rxmpdu_be = iface.wmeBePktStats.rxMpdu; + stats.txmpdu_be = iface.wmeBePktStats.txMpdu; + stats.lostmpdu_be = iface.wmeBePktStats.lostMpdu; + stats.retries_be = iface.wmeBePktStats.retries; + // WME Background Access Category + stats.rxmpdu_bk = iface.wmeBkPktStats.rxMpdu; + stats.txmpdu_bk = iface.wmeBkPktStats.txMpdu; + stats.lostmpdu_bk = iface.wmeBkPktStats.lostMpdu; + stats.retries_bk = iface.wmeBkPktStats.retries; + // WME Video Access Category + stats.rxmpdu_vi = iface.wmeViPktStats.rxMpdu; + stats.txmpdu_vi = iface.wmeViPktStats.txMpdu; + stats.lostmpdu_vi = iface.wmeViPktStats.lostMpdu; + stats.retries_vi = iface.wmeViPktStats.retries; + // WME Voice Access Category + stats.rxmpdu_vo = iface.wmeVoPktStats.rxMpdu; + stats.txmpdu_vo = iface.wmeVoPktStats.txMpdu; + stats.lostmpdu_vo = iface.wmeVoPktStats.lostMpdu; + stats.retries_vo = iface.wmeVoPktStats.retries; + } + + private static void setIfaceStats_1_5(WifiLinkLayerStats stats, + android.hardware.wifi.V1_5.StaLinkLayerIfaceStats iface) { + if (iface == null) return; + setIfaceStats(stats, iface.V1_0); + stats.timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent; + // WME Best Effort Access Category + stats.contentionTimeMinBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesBe = iface.wmeBeContentionTimeStats.contentionNumSamples; + // WME Background Access Category + stats.contentionTimeMinBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesBk = iface.wmeBkContentionTimeStats.contentionNumSamples; + // WME Video Access Category + stats.contentionTimeMinViInUsec = iface.wmeViContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxViInUsec = iface.wmeViContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgViInUsec = iface.wmeViContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesVi = iface.wmeViContentionTimeStats.contentionNumSamples; + // WME Voice Access Category + stats.contentionTimeMinVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesVo = iface.wmeVoContentionTimeStats.contentionNumSamples; + // Peer information statistics + stats.peerInfo = new WifiLinkLayerStats.PeerInfo[iface.peers.size()]; + for (int i = 0; i < stats.peerInfo.length; i++) { + WifiLinkLayerStats.PeerInfo peer = new WifiLinkLayerStats.PeerInfo(); + android.hardware.wifi.V1_5.StaPeerInfo staPeerInfo = iface.peers.get(i); + peer.staCount = staPeerInfo.staCount; + peer.chanUtil = staPeerInfo.chanUtil; + WifiLinkLayerStats.RateStat[] rateStats = + new WifiLinkLayerStats.RateStat[staPeerInfo.rateStats.size()]; + for (int j = 0; j < staPeerInfo.rateStats.size(); j++) { + rateStats[j] = new WifiLinkLayerStats.RateStat(); + android.hardware.wifi.V1_5.StaRateStat staRateStat = staPeerInfo.rateStats.get(j); + rateStats[j].preamble = staRateStat.rateInfo.preamble; + rateStats[j].nss = staRateStat.rateInfo.nss; + rateStats[j].bw = staRateStat.rateInfo.bw; + rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx; + rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps; + rateStats[j].txMpdu = staRateStat.txMpdu; + rateStats[j].rxMpdu = staRateStat.rxMpdu; + rateStats[j].mpduLost = staRateStat.mpduLost; + rateStats[j].retries = staRateStat.retries; + } + peer.rateStats = rateStats; + stats.peerInfo[i] = peer; + } + } + + private static void setIfaceStats_1_6(WifiLinkLayerStats stats, + android.hardware.wifi.V1_6.StaLinkLayerIfaceStats iface) { + if (iface == null) return; + setIfaceStats(stats, iface.V1_0); + stats.timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent; + // WME Best Effort Access Category + stats.contentionTimeMinBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgBeInUsec = iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesBe = iface.wmeBeContentionTimeStats.contentionNumSamples; + // WME Background Access Category + stats.contentionTimeMinBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgBkInUsec = iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesBk = iface.wmeBkContentionTimeStats.contentionNumSamples; + // WME Video Access Category + stats.contentionTimeMinViInUsec = iface.wmeViContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxViInUsec = iface.wmeViContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgViInUsec = iface.wmeViContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesVi = iface.wmeViContentionTimeStats.contentionNumSamples; + // WME Voice Access Category + stats.contentionTimeMinVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMinInUsec; + stats.contentionTimeMaxVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec; + stats.contentionTimeAvgVoInUsec = iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec; + stats.contentionNumSamplesVo = iface.wmeVoContentionTimeStats.contentionNumSamples; + // Peer information statistics + stats.peerInfo = new WifiLinkLayerStats.PeerInfo[iface.peers.size()]; + for (int i = 0; i < stats.peerInfo.length; i++) { + WifiLinkLayerStats.PeerInfo peer = new WifiLinkLayerStats.PeerInfo(); + android.hardware.wifi.V1_6.StaPeerInfo staPeerInfo = iface.peers.get(i); + peer.staCount = staPeerInfo.staCount; + peer.chanUtil = staPeerInfo.chanUtil; + WifiLinkLayerStats.RateStat[] rateStats = + new WifiLinkLayerStats.RateStat[staPeerInfo.rateStats.size()]; + for (int j = 0; j < staPeerInfo.rateStats.size(); j++) { + rateStats[j] = new WifiLinkLayerStats.RateStat(); + android.hardware.wifi.V1_6.StaRateStat staRateStat = staPeerInfo.rateStats.get(j); + rateStats[j].preamble = staRateStat.rateInfo.preamble; + rateStats[j].nss = staRateStat.rateInfo.nss; + rateStats[j].bw = staRateStat.rateInfo.bw; + rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx; + rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps; + rateStats[j].txMpdu = staRateStat.txMpdu; + rateStats[j].rxMpdu = staRateStat.rxMpdu; + rateStats[j].mpduLost = staRateStat.mpduLost; + rateStats[j].retries = staRateStat.retries; + } + peer.rateStats = rateStats; + stats.peerInfo[i] = peer; + } + } + + private static void setRadioStats(WifiLinkLayerStats stats, + List<StaLinkLayerRadioStats> radios) { + if (radios == null) return; + // Do not coalesce this info for multi radio devices with older HALs. + if (radios.size() > 0) { + StaLinkLayerRadioStats radioStats = radios.get(0); + stats.on_time = radioStats.onTimeInMs; + stats.tx_time = radioStats.txTimeInMs; + stats.tx_time_per_level = new int[radioStats.txTimeInMsPerLevel.size()]; + for (int i = 0; i < stats.tx_time_per_level.length; i++) { + stats.tx_time_per_level[i] = radioStats.txTimeInMsPerLevel.get(i); + } + stats.rx_time = radioStats.rxTimeInMs; + stats.on_time_scan = radioStats.onTimeInMsForScan; + stats.numRadios = 1; + } + } + + private void setRadioStats_1_3(WifiLinkLayerStats stats, + List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios) { + if (radios == null) return; + int radioIndex = 0; + for (android.hardware.wifi.V1_3.StaLinkLayerRadioStats radioStats : radios) { + aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats); + radioIndex++; + } + } + + private void setRadioStats_1_5(WifiLinkLayerStats stats, + List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios) { + if (radios == null) return; + int radioIndex = 0; + stats.radioStats = new WifiLinkLayerStats.RadioStat[radios.size()]; + for (android.hardware.wifi.V1_5.StaLinkLayerRadioStats radioStats : radios) { + WifiLinkLayerStats.RadioStat radio = new WifiLinkLayerStats.RadioStat(); + setFrameworkPerRadioStatsFromHidl_1_3(radioStats.radioId, radio, radioStats.V1_3); + stats.radioStats[radioIndex] = radio; + aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats.V1_3); + radioIndex++; + } + } + + private void setRadioStats_1_6(WifiLinkLayerStats stats, + List<android.hardware.wifi.V1_6.StaLinkLayerRadioStats> radios) { + if (radios == null) return; + int radioIndex = 0; + stats.radioStats = new WifiLinkLayerStats.RadioStat[radios.size()]; + for (android.hardware.wifi.V1_6.StaLinkLayerRadioStats radioStats : radios) { + WifiLinkLayerStats.RadioStat radio = new WifiLinkLayerStats.RadioStat(); + setFrameworkPerRadioStatsFromHidl_1_6(radio, radioStats); + stats.radioStats[radioIndex] = radio; + aggregateFrameworkRadioStatsFromHidl_1_6(radioIndex, stats, radioStats); + radioIndex++; + } + } + + /** + * Set individual radio stats from the hal radio stats for V1_3 + */ + private void setFrameworkPerRadioStatsFromHidl_1_3(int radioId, + WifiLinkLayerStats.RadioStat radio, + android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) { + radio.radio_id = radioId; + radio.on_time = hidlRadioStats.V1_0.onTimeInMs; + radio.tx_time = hidlRadioStats.V1_0.txTimeInMs; + radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs; + radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan; + radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan; + radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan; + radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan; + radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan; + radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan; + /* Copy list of channel stats */ + for (android.hardware.wifi.V1_3.WifiChannelStats channelStats + : hidlRadioStats.channelStats) { + WifiLinkLayerStats.ChannelStats channelStatsEntry = + new WifiLinkLayerStats.ChannelStats(); + channelStatsEntry.frequency = channelStats.channel.centerFreq; + channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; + channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; + radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); + } + } + + /** + * Set individual radio stats from the hal radio stats for V1_6 + */ + private void setFrameworkPerRadioStatsFromHidl_1_6(WifiLinkLayerStats.RadioStat radio, + android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) { + radio.radio_id = hidlRadioStats.radioId; + radio.on_time = hidlRadioStats.V1_0.onTimeInMs; + radio.tx_time = hidlRadioStats.V1_0.txTimeInMs; + radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs; + radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan; + radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan; + radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan; + radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan; + radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan; + radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan; + /* Copy list of channel stats */ + for (android.hardware.wifi.V1_6.WifiChannelStats channelStats + : hidlRadioStats.channelStats) { + WifiLinkLayerStats.ChannelStats channelStatsEntry = + new WifiLinkLayerStats.ChannelStats(); + channelStatsEntry.frequency = channelStats.channel.centerFreq; + channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; + channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; + radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); + } + } + + /** + * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate + * the radio stats from all the radios else process the stats from Radio 0 only. + * This method is for V1_3 + */ + private void aggregateFrameworkRadioStatsFromHidl_1_3(int radioIndex, + WifiLinkLayerStats stats, + android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) { + if (!mContext.getResources() + .getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled) + && radioIndex > 0) { + return; + } + // Aggregate the radio stats from all the radios + stats.on_time += hidlRadioStats.V1_0.onTimeInMs; + stats.tx_time += hidlRadioStats.V1_0.txTimeInMs; + // Aggregate tx_time_per_level based on the assumption that the length of + // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other + // radios at array indices greater than the length of first radio will be dropped. + if (stats.tx_time_per_level == null) { + stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()]; + } + for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size() + && i < stats.tx_time_per_level.length; i++) { + stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i); + } + stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs; + stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan; + stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan; + stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan; + stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan; + stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan; + stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan; + /* Copy list of channel stats */ + for (android.hardware.wifi.V1_3.WifiChannelStats channelStats + : hidlRadioStats.channelStats) { + WifiLinkLayerStats.ChannelStats channelStatsEntry = + stats.channelStatsMap.get(channelStats.channel.centerFreq); + if (channelStatsEntry == null) { + channelStatsEntry = new WifiLinkLayerStats.ChannelStats(); + channelStatsEntry.frequency = channelStats.channel.centerFreq; + stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); + } + channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs; + channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs; + } + stats.numRadios++; + } + + /** + * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate + * the radio stats from all the radios else process the stats from Radio 0 only. + * This method is for V1_6 + */ + private void aggregateFrameworkRadioStatsFromHidl_1_6(int radioIndex, + WifiLinkLayerStats stats, + android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) { + if (!mContext.getResources() + .getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled) + && radioIndex > 0) { + return; + } + // Aggregate the radio stats from all the radios + stats.on_time += hidlRadioStats.V1_0.onTimeInMs; + stats.tx_time += hidlRadioStats.V1_0.txTimeInMs; + // Aggregate tx_time_per_level based on the assumption that the length of + // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other + // radios at array indices greater than the length of first radio will be dropped. + if (stats.tx_time_per_level == null) { + stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()]; + } + for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size() + && i < stats.tx_time_per_level.length; i++) { + stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i); + } + stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs; + stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan; + stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan; + stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan; + stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan; + stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan; + stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan; + /* Copy list of channel stats */ + for (android.hardware.wifi.V1_6.WifiChannelStats channelStats + : hidlRadioStats.channelStats) { + WifiLinkLayerStats.ChannelStats channelStatsEntry = + stats.channelStatsMap.get(channelStats.channel.centerFreq); + if (channelStatsEntry == null) { + channelStatsEntry = new WifiLinkLayerStats.ChannelStats(); + channelStatsEntry.frequency = channelStats.channel.centerFreq; + stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); + } + channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs; + channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs; + } + stats.numRadios++; + } + + private static StaBackgroundScanParameters frameworkToHalBackgroundScanParams( + WifiStaIface.StaBackgroundScanParameters frameworkParams) { + StaBackgroundScanParameters halParams = new StaBackgroundScanParameters(); + halParams.basePeriodInMs = frameworkParams.basePeriodInMs; + halParams.maxApPerScan = frameworkParams.maxApPerScan; + halParams.reportThresholdPercent = frameworkParams.reportThresholdPercent; + halParams.reportThresholdNumScans = frameworkParams.reportThresholdNumScans; + if (frameworkParams.buckets != null) { + for (WifiNative.BucketSettings bucket : frameworkParams.buckets) { + halParams.buckets.add(frameworkToHalBucketParams(bucket)); + } + } + return halParams; + } + + private static StaBackgroundScanBucketParameters frameworkToHalBucketParams( + WifiNative.BucketSettings frameworkBucket) { + StaBackgroundScanBucketParameters halBucket = new StaBackgroundScanBucketParameters(); + halBucket.bucketIdx = frameworkBucket.bucket; + halBucket.band = frameworkToHalWifiBand(frameworkBucket.band); + if (frameworkBucket.channels != null) { + for (WifiNative.ChannelSettings cs : frameworkBucket.channels) { + halBucket.frequencies.add(cs.frequency); + } + } + halBucket.periodInMs = frameworkBucket.period_ms; + halBucket.eventReportScheme = frameworkToHalReportSchemeMask(frameworkBucket.report_events); + halBucket.exponentialMaxPeriodInMs = frameworkBucket.max_period_ms; + // Although HAL API allows configurable base value for the truncated + // exponential back off scan. Native API and above support only + // truncated binary exponential back off scan. + // Hard code value of base to 2 here. + halBucket.exponentialBase = 2; + halBucket.exponentialStepCount = frameworkBucket.step_count; + return halBucket; + } + + /** + * Convert WifiBand from framework to HAL. + * + * Note: This method is only used by background scan which does not + * support 6GHz, hence band combinations including 6GHz are considered invalid + * + * @param frameworkBand one of WifiScanner.WIFI_BAND_* + * @return A WifiBand value + * @throws IllegalArgumentException if frameworkBand is not recognized + */ + private static int frameworkToHalWifiBand(int frameworkBand) { + switch (frameworkBand) { + case WifiScanner.WIFI_BAND_UNSPECIFIED: + return WifiBand.BAND_UNSPECIFIED; + case WifiScanner.WIFI_BAND_24_GHZ: + return WifiBand.BAND_24GHZ; + case WifiScanner.WIFI_BAND_5_GHZ: + return WifiBand.BAND_5GHZ; + case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: + return WifiBand.BAND_5GHZ_DFS; + case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: + return WifiBand.BAND_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_BOTH: + return WifiBand.BAND_24GHZ_5GHZ; + case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; + case WifiScanner.WIFI_BAND_6_GHZ: + return WifiBand.BAND_6GHZ; + case WifiScanner.WIFI_BAND_24_5_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ; + case WifiScanner.WIFI_BAND_60_GHZ: + return WifiBand.BAND_60GHZ; + case WifiScanner.WIFI_BAND_24_5_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: + return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ; + case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS: + default: + throw new IllegalArgumentException("bad band " + frameworkBand); + } + } + + /** + * Convert the report scheme mask from framework to hal. + * + * @param reportUnderscoreEvents is logical OR of WifiScanner.REPORT_EVENT_* values + * @return Corresponding StaBackgroundScanBucketEventReportSchemeMask value + * @throws IllegalArgumentException if a mask bit is not recognized + */ + private static int frameworkToHalReportSchemeMask(int reportUnderscoreEvents) { + int ans = 0; + BitMask in = new BitMask(reportUnderscoreEvents); + if (in.testAndClear(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)) { + ans |= StaBackgroundScanBucketEventReportSchemeMask.EACH_SCAN; + } + if (in.testAndClear(WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)) { + ans |= StaBackgroundScanBucketEventReportSchemeMask.FULL_RESULTS; + } + if (in.testAndClear(WifiScanner.REPORT_EVENT_NO_BATCH)) { + ans |= StaBackgroundScanBucketEventReportSchemeMask.NO_BATCH; + } + if (in.value != 0) throw new IllegalArgumentException("bad " + reportUnderscoreEvents); + return ans; + } + + // Only sets the fields of ScanResult used by Gscan clients. + private ScanResult hidlToFrameworkScanResult(StaScanResult scanResult) { + if (scanResult == null) return null; + WifiSsid originalSsid = WifiSsid.fromBytes( + NativeUtil.byteArrayFromArrayList(scanResult.ssid)); + MacAddress bssid; + try { + bssid = MacAddress.fromString(NativeUtil.macAddressFromByteArray(scanResult.bssid)); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Failed to get BSSID of scan result: " + e); + return null; + } + ScanResult frameworkScanResult = new ScanResult(); + frameworkScanResult.setWifiSsid(mSsidTranslator.getTranslatedSsidAndRecordBssidCharset( + originalSsid, bssid)); + frameworkScanResult.BSSID = bssid.toString(); + frameworkScanResult.level = scanResult.rssi; + frameworkScanResult.frequency = scanResult.frequency; + frameworkScanResult.timestamp = scanResult.timeStampInUs; + return frameworkScanResult; + } + + private ScanResult[] hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults) { + if (scanResults == null || scanResults.isEmpty()) return new ScanResult[0]; + ScanResult[] frameworkScanResults = new ScanResult[scanResults.size()]; + int i = 0; + for (StaScanResult scanResult : scanResults) { + ScanResult frameworkScanResult = hidlToFrameworkScanResult(scanResult); + if (frameworkScanResult == null) { + Log.e(TAG, "hidlToFrameworkScanResults: unable to convert hidl to framework " + + "scan result!"); + continue; + } + frameworkScanResults[i++] = frameworkScanResult; + } + return frameworkScanResults; + } + + private static int hidlToFrameworkScanDataFlags(int flag) { + if (flag == StaScanDataFlagMask.INTERRUPTED) { + return 1; + } else { + return 0; + } + } + + private WifiScanner.ScanData[] hidlToFrameworkScanDatas( + int cmdId, ArrayList<StaScanData> scanDatas) { + if (scanDatas == null || scanDatas.isEmpty()) return new WifiScanner.ScanData[0]; + WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.size()]; + int i = 0; + for (StaScanData scanData : scanDatas) { + int flags = hidlToFrameworkScanDataFlags(scanData.flags); + ScanResult[] frameworkScanResults = hidlToFrameworkScanResults(scanData.results); + frameworkScanDatas[i++] = + new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned, + WifiScanner.WIFI_BAND_UNSPECIFIED, frameworkScanResults); + } + return frameworkScanDatas; + } + + protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceV1_2Mockable() { + return android.hardware.wifi.V1_2.IWifiStaIface.castFrom(mWifiStaIface); + } + + protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceV1_3Mockable() { + return android.hardware.wifi.V1_3.IWifiStaIface.castFrom(mWifiStaIface); + } + + protected android.hardware.wifi.V1_5.IWifiStaIface getWifiStaIfaceV1_5Mockable() { + return android.hardware.wifi.V1_5.IWifiStaIface.castFrom(mWifiStaIface); + } + + protected android.hardware.wifi.V1_6.IWifiStaIface getWifiStaIfaceV1_6Mockable() { + return android.hardware.wifi.V1_6.IWifiStaIface.castFrom(mWifiStaIface); + } + + private boolean isOk(WifiStatus status, String methodStr) { + if (status.code == WifiStatusCode.SUCCESS) return true; + Log.e(TAG, methodStr + " failed with status: " + status); + return false; + } + + private void handleRemoteException(RemoteException e, String methodStr) { + Log.e(TAG, methodStr + " failed with remote exception: " + e); + mWifiStaIface = null; + } + + private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { + if (mWifiStaIface == null) { + Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiStaIface is null"); + return defaultVal; + } + return supplier.get(); + } + + + // HAL Callback + private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { + @Override + public void onBackgroundScanFailure(int cmdId) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onBackgroundScanFailure(cmdId); + } + + @Override + public void onBackgroundFullScanResult(int cmdId, int bucketsScanned, + StaScanResult result) { + if (mFrameworkCallback == null) return; + ScanResult frameworkScanResult = hidlToFrameworkScanResult(result); + if (frameworkScanResult == null) { + Log.e(TAG, "Unable to convert scan result from HAL to framework"); + return; + } + mFrameworkCallback.onBackgroundFullScanResult(cmdId, bucketsScanned, + frameworkScanResult); + } + + @Override + public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) { + if (mFrameworkCallback == null) return; + WifiScanner.ScanData[] frameworkScanDatas = hidlToFrameworkScanDatas(cmdId, scanDatas); + mFrameworkCallback.onBackgroundScanResults(cmdId, frameworkScanDatas); + } + + @Override + public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) { + if (mFrameworkCallback == null) return; + mFrameworkCallback.onRssiThresholdBreached(cmdId, currBssid, currRssi); + } + } +} diff --git a/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfig.java b/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfig.java index 5f455f5174..8022ffb415 100644 --- a/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfig.java +++ b/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfig.java @@ -56,6 +56,7 @@ public class LegacyPasspointConfig { @Override public int hashCode() { - return Objects.hash(mFqdn, mFriendlyName, mRoamingConsortiumOis, mRealm, mImsi); + return Objects.hash(mFqdn, mFriendlyName, Arrays.hashCode(mRoamingConsortiumOis), mRealm, + mImsi); } } diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java index 2853390ee3..b75fb06a7b 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java @@ -35,7 +35,6 @@ import android.net.wifi.WifiSsid; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; -import android.os.Handler; import android.os.Looper; import android.os.Process; import android.text.TextUtils; @@ -47,6 +46,7 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.Clock; import com.android.server.wifi.MacAddressUtil; import com.android.server.wifi.NetworkUpdateResult; +import com.android.server.wifi.RunnerHandler; import com.android.server.wifi.WifiCarrierInfoManager; import com.android.server.wifi.WifiConfigManager; import com.android.server.wifi.WifiConfigStore; @@ -119,7 +119,7 @@ public class PasspointManager { private final PasspointEventHandler mPasspointEventHandler; private final WifiInjector mWifiInjector; - private final Handler mHandler; + private final RunnerHandler mHandler; private final WifiKeyStore mKeyStore; private final PasspointObjectFactory mObjectFactory; @@ -356,7 +356,7 @@ public class PasspointManager { mAppOps.stopWatchingMode(appOpsChangedListener); } - public PasspointManager(Context context, WifiInjector wifiInjector, Handler handler, + public PasspointManager(Context context, WifiInjector wifiInjector, RunnerHandler handler, WifiNative wifiNative, WifiKeyStore keyStore, Clock clock, PasspointObjectFactory objectFactory, WifiConfigManager wifiConfigManager, WifiConfigStore wifiConfigStore, @@ -388,7 +388,7 @@ public class PasspointManager { sPasspointManager = this; mMacAddressUtil = macAddressUtil; mClock = clock; - mHandler.postAtFrontOfQueue(() -> + mHandler.postToFront(() -> mWifiConfigManager.addOnNetworkUpdateListener( new PasspointManager.OnNetworkUpdateListener())); mWifiPermissionsUtil = wifiPermissionsUtil; diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java index 28ab21da65..51832ea35c 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java @@ -576,6 +576,7 @@ public class PasspointProvider { WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); enterpriseConfig.setRealm(mConfig.getCredential().getRealm()); enterpriseConfig.setDomainSuffixMatch(mConfig.getHomeSp().getFqdn()); + enterpriseConfig.setMinimumTlsVersion(mConfig.getCredential().getMinimumTlsVersion()); if (mConfig.getCredential().getUserCredential() != null) { buildEnterpriseConfigForUserCredential(enterpriseConfig, mConfig.getCredential().getUserCredential()); diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointXmlUtils.java b/service/java/com/android/server/wifi/hotspot2/PasspointXmlUtils.java index df3107fdba..df6d8c2231 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointXmlUtils.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointXmlUtils.java @@ -125,6 +125,7 @@ public class PasspointXmlUtils { private static final String XML_TAG_IS_OEM_PRIVATE = "IsOemPrivate"; private static final String XML_TAG_DECORATED_IDENTITY_PREFIX = "DecoratedIdentityPrefix"; private static final String XML_TAG_SUBSCRIPTION_GROUP = "SubscriptionGroup"; + private static final String XML_TAG_MINIMUM_TLS_VERSION = "MinimumTlsVersion"; /** * Serialize a {@link PasspointConfiguration} to the output stream as a XML block. @@ -343,6 +344,8 @@ public class PasspointXmlUtils { XmlUtil.writeNextValue(out, XML_TAG_REALM, credential.getRealm()); XmlUtil.writeNextValue(out, XML_TAG_CHECK_AAA_SERVER_CERT_STATUS, credential.getCheckAaaServerCertStatus()); + XmlUtil.writeNextValue(out, XML_TAG_MINIMUM_TLS_VERSION, + credential.getMinimumTlsVersion()); serializeUserCredential(out, credential.getUserCredential()); serializeCertCredential(out, credential.getCertCredential()); serializeSimCredential(out, credential.getSimCredential()); @@ -629,6 +632,9 @@ public class PasspointXmlUtils { case XML_TAG_CHECK_AAA_SERVER_CERT_STATUS: credential.setCheckAaaServerCertStatus((boolean) value); break; + case XML_TAG_MINIMUM_TLS_VERSION: + credential.setMinimumTlsVersion((int) value); + break; default: Log.w(TAG, "Unknown value under Credential: " + name[0]); diff --git a/service/java/com/android/server/wifi/mockwifi/MockWifiNl80211Manager.java b/service/java/com/android/server/wifi/mockwifi/MockWifiNl80211Manager.java new file mode 100644 index 0000000000..4e135fc7a0 --- /dev/null +++ b/service/java/com/android/server/wifi/mockwifi/MockWifiNl80211Manager.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 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.mockwifi; + +import android.content.Context; +import android.net.wifi.nl80211.WifiNl80211Manager; +import android.os.IBinder; + +/** + * Mocked WifiNl80211Manager + */ +public class MockWifiNl80211Manager { + private static final String TAG = "MockWifiNl80211Manager"; + + private Context mContext; + private WifiNl80211Manager mMockWifiNl80211Manager; + + public MockWifiNl80211Manager(IBinder wificondBinder, Context context) { + mContext = context; + mMockWifiNl80211Manager = new WifiNl80211Manager(mContext, wificondBinder); + } + + public WifiNl80211Manager getWifiNl80211Manager() { + return mMockWifiNl80211Manager; + } +} diff --git a/service/java/com/android/server/wifi/mockwifi/MockWifiServiceUtil.java b/service/java/com/android/server/wifi/mockwifi/MockWifiServiceUtil.java new file mode 100644 index 0000000000..dbce1ef611 --- /dev/null +++ b/service/java/com/android/server/wifi/mockwifi/MockWifiServiceUtil.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2022 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.mockwifi; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +/** This class provides wrapper APIs for binding interfaces to mock service. */ +public class MockWifiServiceUtil { + private static final String TAG = "MockWifiModemUtil"; + private static final String BIND_NL80211 = "android.wifi.mockwifimodem.nl80211"; + private static final int MOCK_NL80211_SERVICE = 0; + + public static final int MIN_SERVICE_IDX = MOCK_NL80211_SERVICE; + public static final int NUM_SERVICES = 1; + public static final int BINDER_RETRY_MILLIS = 3 * 100; + public static final int BINDER_MAX_RETRY = 3; + + private Context mContext; + private String mServiceName; + private String mPackageName; + private MockWifiNl80211Manager mMockWifiNl80211Manager; + private IBinder mMockNl80211Binder; + private ServiceConnection mMockNl80211ServiceConnection; + + public MockWifiServiceUtil(Context context, String serviceName) { + mContext = context; + String[] componentInfo = serviceName.split("/", 2); + mPackageName = componentInfo[0]; + mServiceName = componentInfo[1]; + } + + private class MockModemConnection implements ServiceConnection { + private int mService; + + MockModemConnection(int module) { + mService = module; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder binder) { + Log.d(TAG, "Wifi mock Service " + getModuleName(mService) + " - onServiceConnected"); + if (mService == MOCK_NL80211_SERVICE) { + mMockNl80211Binder = binder; + mMockWifiNl80211Manager = new MockWifiNl80211Manager(mMockNl80211Binder, mContext); + } + + } + + @Override + public void onServiceDisconnected(ComponentName name) { + Log.d(TAG, "Wifi mock Service " + getModuleName(mService) + + " - onServiceDisconnected"); + if (mService == MOCK_NL80211_SERVICE) { + mMockNl80211Binder = null; + mMockWifiNl80211Manager = null; + } + } + } + + private boolean bindModuleToMockModemService( + String actionName, ServiceConnection serviceConnection) { + boolean status = false; + + Intent intent = new Intent(); + intent.setComponent(new ComponentName(mPackageName, mServiceName)); + intent.setAction(actionName); + + status = mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + return status; + } + + /** waitForBinder */ + public IBinder getServiceBinder(int service) { + switch (service) { + case MOCK_NL80211_SERVICE: + return mMockNl80211Binder; + default: + return null; + } + } + + /** Binding interfaces with mock modem service */ + public void bindAllMockModemService() { + for (int service = MIN_SERVICE_IDX; service < NUM_SERVICES; service++) { + bindToMockModemService(service); + } + } + + /** bindToMockModemService */ + public void bindToMockModemService(int service) { + // Based on {@code service} to get each mocked HAL binder + if (service == MOCK_NL80211_SERVICE) { + mMockNl80211ServiceConnection = new MockModemConnection(MOCK_NL80211_SERVICE); + + boolean status = + bindModuleToMockModemService(BIND_NL80211, mMockNl80211ServiceConnection); + if (!status) { + Log.d(TAG, getModuleName(service) + " bind fail"); + mMockNl80211ServiceConnection = null; + } + } + } + + public String getServiceName() { + return mServiceName; + } + + private ServiceConnection getServiceConnection(int service) { + switch (service) { + case MOCK_NL80211_SERVICE: + return mMockNl80211ServiceConnection; + default: + return null; + } + } + + /** + * Returns name of the provided service. + */ + public String getModuleName(int service) { + switch (service) { + case MOCK_NL80211_SERVICE: + return "nl80211"; + default: + return "none"; + } + } +} diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java index 8aa77baa85..2a62b6c12b 100644 --- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java +++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java @@ -18,6 +18,7 @@ package com.android.server.wifi.p2p; import android.annotation.NonNull; import android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback; +import android.hardware.wifi.supplicant.P2pGroupStartedEventParams; import android.hardware.wifi.supplicant.P2pProvDiscStatusCode; import android.hardware.wifi.supplicant.P2pStatusCode; import android.hardware.wifi.supplicant.WpsConfigMethods; @@ -253,6 +254,27 @@ public class SupplicantP2pIfaceCallbackAidlImpl extends ISupplicantP2pIfaceCallb public void onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, boolean isPersistent) { + onGroupStarted(groupIfName, isGroupOwner, ssid, frequency, psk, passphrase, goDeviceAddress, + isPersistent, /* goInterfaceAddress */ null); + } + + /** + * Used to indicate the start of a P2P group, with some parameters describing the group. + * + * @param groupStartedEventParams Parameters describing the P2P group. + */ + @Override + public void onGroupStartedWithParams(P2pGroupStartedEventParams groupStartedEventParams) { + onGroupStarted(groupStartedEventParams.groupInterfaceName, + groupStartedEventParams.isGroupOwner, groupStartedEventParams.ssid, + groupStartedEventParams.frequencyMHz, groupStartedEventParams.psk, + groupStartedEventParams.passphrase, groupStartedEventParams.goDeviceAddress, + groupStartedEventParams.isPersistent, groupStartedEventParams.goInterfaceAddress); + } + + private void onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, + int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, + boolean isPersistent, byte[] goInterfaceAddress) { if (groupIfName == null) { Log.e(TAG, "Missing group interface name."); return; @@ -291,6 +313,8 @@ public class SupplicantP2pIfaceCallbackAidlImpl extends ISupplicantP2pIfaceCallb return; } + group.interfaceAddress = goInterfaceAddress; + group.setOwner(owner); mMonitor.broadcastP2pGroupStarted(mInterface, group); } diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlV1_4Impl.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlV1_4Impl.java index e29205e0f9..bacb5c7cba 100644 --- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlV1_4Impl.java +++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlV1_4Impl.java @@ -24,6 +24,7 @@ import android.util.Log; import com.android.server.wifi.util.NativeUtil; import java.util.ArrayList; +import java.util.Arrays; /** * Class used for processing all P2P callbacks. @@ -320,7 +321,7 @@ public class SupplicantP2pIfaceCallbackHidlV1_4Impl } logd("R2 Device discovered on " + mInterface + ": " - + device + " R2 Info:" + wfdR2DeviceInfo); + + device + " R2 Info:" + Arrays.toString(wfdR2DeviceInfo)); mMonitor.broadcastP2pDeviceFound(mInterface, device); } diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java index 970c31e44c..44462d26f0 100644 --- a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java +++ b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java @@ -18,7 +18,6 @@ package com.android.server.wifi.p2p; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.wifi.V1_0.IWifiP2pIface; import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.ScanResult; import android.net.wifi.nl80211.WifiNl80211Manager; @@ -57,7 +56,7 @@ public class WifiP2pNative { private final HalDeviceManager mHalDeviceManager; private final PropertyService mPropertyService; private final WifiVendorHal mWifiVendorHal; - private IWifiP2pIface mIWifiP2pIface; + private String mP2pIfaceName; private InterfaceDestroyedListenerInternal mInterfaceDestroyedListener; // Cache the features and return it when P2P interface is not up. private long mSupportedFeatures = -1L; @@ -79,7 +78,7 @@ public class WifiP2pNative { if (!TextUtils.isEmpty(ifaceName)) { mSupplicantP2pIfaceHal.teardownIface(ifaceName); } - mIWifiP2pIface = null; + mP2pIfaceName = null; mValid = false; } @@ -163,6 +162,7 @@ public class WifiP2pNative { private static final String P2P_IFACE_NAME = "p2p0"; private static final String P2P_INTERFACE_PROPERTY = "wifi.direct.interface"; + /** * Helper function to handle creation of P2P iface. * For devices which do not the support the HAL, this will bypass HalDeviceManager & @@ -170,19 +170,13 @@ public class WifiP2pNative { */ private String createP2pIface(Handler handler, WorkSource requestorWs) { if (mHalDeviceManager.isSupported()) { - mIWifiP2pIface = mHalDeviceManager - .createP2pIface(mInterfaceDestroyedListener, handler, requestorWs); - if (mIWifiP2pIface == null) { + mP2pIfaceName = mHalDeviceManager.createP2pIface( + mInterfaceDestroyedListener, handler, requestorWs); + if (mP2pIfaceName == null) { Log.e(TAG, "Failed to create P2p iface in HalDeviceManager"); return null; } - String ifaceName = HalDeviceManager.getName(mIWifiP2pIface); - if (TextUtils.isEmpty(ifaceName)) { - Log.e(TAG, "Failed to get p2p iface name"); - teardownInterface(); - return null; - } - return ifaceName; + return mP2pIfaceName; } else { Log.i(TAG, "Vendor Hal is not supported, ignoring createP2pIface."); return mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); @@ -200,7 +194,7 @@ public class WifiP2pNative { @Nullable HalDeviceManager.InterfaceDestroyedListener destroyedListener, @NonNull Handler handler, @NonNull WorkSource requestorWs) { Log.d(TAG, "Setup P2P interface"); - if (mIWifiP2pIface == null) { + if (mP2pIfaceName == null) { mInterfaceDestroyedListener = (null == destroyedListener) ? null : new InterfaceDestroyedListenerInternal(destroyedListener); @@ -226,9 +220,9 @@ public class WifiP2pNative { Log.i(TAG, "P2P interface setup completed"); return ifaceName; } else { - Log.i(TAG, "P2P interface is already existed"); + Log.i(TAG, "P2P interface already exists"); return mHalDeviceManager.isSupported() - ? HalDeviceManager.getName(mIWifiP2pIface) + ? mP2pIfaceName : mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); } } @@ -239,11 +233,10 @@ public class WifiP2pNative { public void teardownInterface() { Log.d(TAG, "Teardown P2P interface"); if (mHalDeviceManager.isSupported()) { - if (mIWifiP2pIface != null) { - String ifaceName = HalDeviceManager.getName(mIWifiP2pIface); - mHalDeviceManager.removeIface(mIWifiP2pIface); + if (mP2pIfaceName != null) { + mHalDeviceManager.removeP2pIface(mP2pIfaceName); if (null != mInterfaceDestroyedListener) { - mInterfaceDestroyedListener.teardownAndInvalidate(ifaceName); + mInterfaceDestroyedListener.teardownAndInvalidate(mP2pIfaceName); } Log.i(TAG, "P2P interface teardown completed"); } @@ -261,8 +254,8 @@ public class WifiP2pNative { */ public boolean replaceRequestorWs(WorkSource requestorWs) { if (mHalDeviceManager.isSupported()) { - if (mIWifiP2pIface == null) return false; - return mHalDeviceManager.replaceRequestorWs(mIWifiP2pIface, requestorWs); + if (mP2pIfaceName == null) return false; + return mHalDeviceManager.replaceRequestorWsForP2pIface(mP2pIfaceName, requestorWs); } else { Log.i(TAG, "HAL is not supported. Ignore replace requestorWs"); return true; @@ -289,7 +282,7 @@ public class WifiP2pNative { return 0L; } teardownInterface(); - mIWifiP2pIface = null; + mP2pIfaceName = null; return mSupportedFeatures; } @@ -929,7 +922,7 @@ public class WifiP2pNative { * Set vendor-specific information elements to the native service. * * @param vendorElements the vendor opaque data. - * @return true, if opeartion was successful. + * @return true, if operation was successful. */ public boolean setVendorElements(Set<ScanResult.InformationElement> vendorElements) { return mSupplicantP2pIfaceHal.setVendorElements(vendorElements); @@ -945,8 +938,8 @@ public class WifiP2pNative { /** Indicate whether or not 5GHz/6GHz DBS is supported. */ public boolean is5g6gDbsSupported() { - if (null == mIWifiP2pIface) return false; + if (mP2pIfaceName == null) return false; if (!mHalDeviceManager.isSupported()) return false; - return mHalDeviceManager.is5g6gDbsSupported(mIWifiP2pIface); + return mHalDeviceManager.is5g6gDbsSupportedOnP2pIface(mP2pIfaceName); } } diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java index 6109660bbe..6f3edc0c35 100644 --- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java +++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java @@ -16,6 +16,9 @@ package com.android.server.wifi.p2p; +import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP; +import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL; + 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; @@ -120,6 +123,7 @@ import com.android.server.wifi.p2p.ExternalApproverManager.ApproverEntry; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.proto.nano.WifiMetricsProto.GroupEvent; import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; +import com.android.server.wifi.util.LastCallerInfoManager; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.StringUtil; import com.android.server.wifi.util.WaitingState; @@ -130,9 +134,11 @@ import com.android.wifi.resources.R; import java.io.FileDescriptor; import java.io.PrintWriter; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; @@ -168,7 +174,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { + " Idle Shutdown Message Timeout"; private boolean mVerboseLoggingEnabled = false; private boolean mVerboseHalLoggingEnabled = false; - private static final String NETWORKTYPE = "WIFI_P2P"; + private static final String NETWORK_TYPE = "WIFI_P2P"; @VisibleForTesting static final String DEFAULT_DEVICE_NAME_PREFIX = "Android_"; // The maxinum length of the device name is 32 bytes, see @@ -194,29 +200,29 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // Otherwise it will cause interface down before function timeout. static final long P2P_INTERFACE_IDLE_SHUTDOWN_TIMEOUT_MS = 150_000; - private Context mContext; + private final Context mContext; NetdWrapper mNetdWrapper; private IIpClient mIpClient; private int mIpClientStartIndex = 0; private DhcpResultsParcelable mDhcpResultsParcelable; - private P2pStateMachine mP2pStateMachine; - private AsyncChannel mReplyChannel = new AsyncChannel(); + private final P2pStateMachine mP2pStateMachine; + private final AsyncChannel mReplyChannel = new AsyncChannel(); private AsyncChannel mWifiChannel; - private LocationManager mLocationManager; - private WifiInjector mWifiInjector; - private WifiPermissionsUtil mWifiPermissionsUtil; - private FrameworkFacade mFrameworkFacade; - private WifiSettingsConfigStore mSettingsConfigStore; - private WifiP2pMetrics mWifiP2pMetrics; + private final WifiInjector mWifiInjector; + private final WifiPermissionsUtil mWifiPermissionsUtil; + private final FrameworkFacade mFrameworkFacade; + private final WifiSettingsConfigStore mSettingsConfigStore; + private final WifiP2pMetrics mWifiP2pMetrics; private final BuildProperties mBuildProperties; // This will only be null if SdkLevel is not at least S - @Nullable private CoexManager mCoexManager; - private WifiGlobals mWifiGlobals; - private UserManager mUserManager; - private InterfaceConflictManager mInterfaceConflictManager; - private WifiP2pNative mWifiNative; + @Nullable private final CoexManager mCoexManager; + private final WifiGlobals mWifiGlobals; + private final UserManager mUserManager; + private final InterfaceConflictManager mInterfaceConflictManager; + private final WifiP2pNative mWifiNative; + private final LastCallerInfoManager mLastCallerInfoManager; private static final Boolean JOIN_GROUP = true; private static final Boolean FORM_GROUP = false; @@ -319,7 +325,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private static final int P2P_CONNECT_TRIGGER_INVITATION_REQ = 2; private static final int P2P_CONNECT_TRIGGER_OTHER = 3; - private final boolean mP2pSupported; private final WifiP2pDevice mThisDevice = new WifiP2pDevice(); @@ -366,23 +371,23 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private String mServiceDiscReqId; // clients(application) information list - private HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<Messenger, ClientInfo>(); + private final HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<>(); // clients(application) channel list - private Map<IBinder, Messenger> mClientChannelList = new HashMap<IBinder, Messenger>(); + private final Map<IBinder, Messenger> mClientChannelList = new HashMap<>(); // clients(application) approver manager - private ExternalApproverManager mExternalApproverManager = new ExternalApproverManager(); + private final ExternalApproverManager mExternalApproverManager = new ExternalApproverManager(); // client(application) attribution source list private Map<IBinder, AttributionSource> mClientAttributionSource = new HashMap<>(); // client(application) vendor-specific information element list - private Map<String, HashSet<ScanResult.InformationElement>> mVendorElements = + private final Map<String, HashSet<ScanResult.InformationElement>> mVendorElements = new HashMap<>(); // peer authorizing timestamp which is indexed by the peer MAC address. - private Map<String, Long> mPeerAuthorizingTimestamp = new HashMap<>(); + private final Map<String, Long> mPeerAuthorizingTimestamp = new HashMap<>(); // The empty device address set by wpa_supplicant. private static final String EMPTY_DEVICE_ADDRESS = "00:00:00:00:00:00"; @@ -520,7 +525,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { */ private class ClientHandler extends Handler { - ClientHandler(String tag, android.os.Looper looper) { + ClientHandler(String tag, Looper looper) { super(looper); } @@ -573,18 +578,18 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } } } - private ClientHandler mClientHandler; + private final ClientHandler mClientHandler; private NetworkInfo makeNetworkInfo() { final NetworkInfo info = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, - 0, NETWORKTYPE, ""); + 0, NETWORK_TYPE, ""); if (mDetailedState != NetworkInfo.DetailedState.IDLE) { info.setDetailedState(mDetailedState, null, null); } return info; } - private class DeathHandlerData { + private static class DeathHandlerData { DeathHandlerData(int uid, DeathRecipient dr, Messenger m, WorkSource ws, int displayId) { mUid = uid; mDeathRecipient = dr; @@ -605,11 +610,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { final WorkSource mWorkSource; final int mDisplayId; } - private Object mLock = new Object(); + private final Object mLock = new Object(); private final Map<IBinder, DeathHandlerData> mDeathDataByBinder = new ConcurrentHashMap<>(); private final Map<Integer, WorkSource> mActiveClients = new ConcurrentHashMap<>(); - private Clock mClock; + private final Clock mClock; public WifiP2pServiceImpl(Context context, WifiInjector wifiInjector) { mContext = context; @@ -633,6 +638,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { HandlerThread wifiP2pThread = mWifiInjector.getWifiP2pServiceHandlerThread(); mClientHandler = new ClientHandler(TAG, wifiP2pThread.getLooper()); mWifiNative = mWifiInjector.getWifiP2pNative(); + mLastCallerInfoManager = mWifiInjector.getLastCallerInfoManager(); mP2pStateMachine = new P2pStateMachine(TAG, wifiP2pThread.getLooper(), mP2pSupported); mP2pStateMachine.setDbg(false); // can enable for very verbose logs mP2pStateMachine.start(); @@ -706,20 +712,24 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mDhcpResultsParcelable = null; } - private void startIpClient(String ifname, Handler smHandler) { + private void startIpClient(String ifname, Handler smHandler, + int groupClientIpProvisioningMode) { stopIpClient(); mIpClientStartIndex++; IpClientUtil.makeIpClient(mContext, ifname, new IpClientCallbacksImpl( - mIpClientStartIndex, smHandler)); + mIpClientStartIndex, smHandler, groupClientIpProvisioningMode)); } private class IpClientCallbacksImpl extends IpClientCallbacks { private final int mStartIndex; private final Handler mHandler; + private final int mGroupClientIpProvisioningMode; - private IpClientCallbacksImpl(int startIndex, Handler handler) { + private IpClientCallbacksImpl(int startIndex, Handler handler, + int groupClientIpProvisioningMode) { mStartIndex = startIndex; mHandler = handler; + mGroupClientIpProvisioningMode = groupClientIpProvisioningMode; } @Override @@ -731,12 +741,25 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } mIpClient = ipClient; - final ProvisioningConfiguration config = - new ProvisioningConfiguration.Builder() + ProvisioningConfiguration config; + switch (mGroupClientIpProvisioningMode) { + case GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL: + config = new ProvisioningConfiguration.Builder() + .withoutIPv4() + .withIpv6LinkLocalOnly() + .withRandomMacAddress() + .build(); + break; + case GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP: + default: + // DHCP IPV4 by default. + config = new ProvisioningConfiguration.Builder() .withoutIpReachabilityMonitor() .withPreDhcpAction(30 * 1000) .withProvisioningTimeoutMs(36 * 1000) .build(); + } + try { mIpClient.startProvisioning(config.toStableParcelable()); } catch (RemoteException e) { @@ -759,7 +782,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } @Override public void onProvisioningSuccess(LinkProperties newLp) { - mP2pStateMachine.sendMessage(IPC_PROVISIONING_SUCCESS); + mP2pStateMachine.sendMessage(IPC_PROVISIONING_SUCCESS, newLp); } @Override public void onProvisioningFailure(LinkProperties newLp) { @@ -998,34 +1021,38 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { */ private class P2pStateMachine extends StateMachine { - private DefaultState mDefaultState = new DefaultState(); - private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState(); - private P2pDisablingState mP2pDisablingState = new P2pDisablingState(); - private P2pDisabledContainerState mP2pDisabledContainerState = + private final DefaultState mDefaultState = new DefaultState(); + private final P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState(); + private final P2pDisablingState mP2pDisablingState = new P2pDisablingState(); + private final P2pDisabledContainerState mP2pDisabledContainerState = new P2pDisabledContainerState(); - private P2pDisabledState mP2pDisabledState = new P2pDisabledState(); - private WaitingState mWaitingState = new WaitingState(this); - private P2pEnabledState mP2pEnabledState = new P2pEnabledState(); + private final P2pDisabledState mP2pDisabledState = new P2pDisabledState(); + private final WaitingState mWaitingState = new WaitingState(this); + private final P2pEnabledState mP2pEnabledState = new P2pEnabledState(); // Inactive is when p2p is enabled with no connectivity - private InactiveState mInactiveState = new InactiveState(); - private GroupCreatingState mGroupCreatingState = new GroupCreatingState(); - private UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState = + private final InactiveState mInactiveState = new InactiveState(); + private final GroupCreatingState mGroupCreatingState = new GroupCreatingState(); + private final UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState = new UserAuthorizingInviteRequestState(); - private UserAuthorizingNegotiationRequestState mUserAuthorizingNegotiationRequestState = + private final UserAuthorizingNegotiationRequestState + mUserAuthorizingNegotiationRequestState = new UserAuthorizingNegotiationRequestState(); - private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState(); - private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState(); - private FrequencyConflictState mFrequencyConflictState = new FrequencyConflictState(); - - private GroupCreatedState mGroupCreatedState = new GroupCreatedState(); - private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState(); - private OngoingGroupRemovalState mOngoingGroupRemovalState = new OngoingGroupRemovalState(); - - private WifiP2pMonitor mWifiMonitor = mWifiInjector.getWifiP2pMonitor(); + private final ProvisionDiscoveryState mProvisionDiscoveryState = + new ProvisionDiscoveryState(); + private final GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState(); + private final FrequencyConflictState mFrequencyConflictState = new FrequencyConflictState(); + + private final GroupCreatedState mGroupCreatedState = new GroupCreatedState(); + private final UserAuthorizingJoinState mUserAuthorizingJoinState = + new UserAuthorizingJoinState(); + private final OngoingGroupRemovalState mOngoingGroupRemovalState = + new OngoingGroupRemovalState(); + + private final WifiP2pMonitor mWifiMonitor = mWifiInjector.getWifiP2pMonitor(); private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); private String mInterfaceName; - private List<CoexUnsafeChannel> mCoexUnsafeChannels = new ArrayList<>(); + private final List<CoexUnsafeChannel> mCoexUnsafeChannels = new ArrayList<>(); private int mUserListenChannel = 0; private int mUserOperatingChannel = 0; @@ -1147,12 +1174,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { (key, newValue) -> enableVerboseLogging(newValue), getHandler()); if (SdkLevel.isAtLeastS()) { - mCoexManager.registerCoexListener(new CoexManager.CoexListener() { - @Override - public void onCoexUnsafeChannelsChanged() { - checkCoexUnsafeChannels(); - } - }); + mCoexManager.registerCoexListener(this::checkCoexUnsafeChannels); } if (SdkLevel.isAtLeastT()) { mContext.registerReceiver( @@ -1610,7 +1632,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { ac.connect(mContext, getHandler(), message.replyTo); break; case BLOCK_DISCOVERY: - mDiscoveryBlocked = (message.arg1 == ENABLED ? true : false); + mDiscoveryBlocked = (message.arg1 == ENABLED); // always reset this - we went to a state that doesn't support discovery so // it would have stopped regardless mDiscoveryPostponed = false; @@ -2463,7 +2485,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { break; } case BLOCK_DISCOVERY: - boolean blocked = (message.arg1 == ENABLED ? true : false); + boolean blocked = (message.arg1 == ENABLED); if (mDiscoveryBlocked == blocked) break; mDiscoveryBlocked = blocked; if (blocked && mDiscoveryStarted) { @@ -2520,6 +2542,14 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { WifiP2pManager.BUSY); break; } + int apiType = WifiManager.API_P2P_DISCOVER_PEERS; + if (scanType == WifiP2pManager.WIFI_P2P_SCAN_SOCIAL) { + apiType = WifiManager.API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS; + } else if (scanType == WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ) { + apiType = WifiManager.API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY; + } + mLastCallerInfoManager.put(apiType, Process.myTid(), uid, 0, packageName, + true); // do not send service discovery request while normal find operation. clearSupplicantServiceRequest(); Log.e(TAG, "-------discover_peers before p2pFind"); @@ -2538,6 +2568,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { sendP2pDiscoveryChangedBroadcast(false); 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()) { replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); } else { @@ -2621,7 +2654,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } int uid = message.sendingUid; Bundle extras = (Bundle) message.obj; - boolean hasPermission = false; + boolean hasPermission; if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( packageName, @@ -2637,7 +2670,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { break; } if (mVerboseLoggingEnabled) logd(getName() + " add service"); - WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo) + WifiP2pServiceInfo servInfo = extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_SERVICE_INFO); if (addLocalService(message.replyTo, servInfo)) { replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED); @@ -2719,7 +2752,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } int uid = message.sendingUid; Bundle extras = (Bundle) message.obj; - boolean hasPermission = false; + boolean hasPermission; if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( packageName, @@ -2733,6 +2766,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { 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, @@ -2746,6 +2781,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } 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)) { replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); @@ -2768,6 +2806,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { 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); @@ -2861,6 +2902,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // 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); @@ -2911,6 +2954,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { 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 @@ -3027,7 +3073,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } int uid = message.sendingUid; Bundle extras = (Bundle) message.obj; - boolean hasPermission = false; + boolean hasPermission; if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( packageName, @@ -3045,8 +3091,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } mAutonomousGroup = true; int netId = message.arg1; - config = (WifiP2pConfig) - extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG); + 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)) { @@ -3054,8 +3103,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { P2pConnectionEvent.CONNECTION_FAST, config, GroupEvent.GROUP_OWNER, uid); ret = mWifiNative.p2pGroupAdd(config, false); - } else { - ret = false; } } else if (netId == WifiP2pGroup.NETWORK_ID_PERSISTENT) { // check if the go persistent group is present. @@ -3118,7 +3165,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } int uid = message.sendingUid; Bundle extras = (Bundle) message.obj; - boolean hasPermission = false; + boolean hasPermission; if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( packageName, @@ -3132,6 +3179,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { 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, @@ -3145,6 +3194,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } 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)) { replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); @@ -3167,6 +3219,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { 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); @@ -3282,6 +3337,9 @@ 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 + mLastCallerInfoManager.put(WifiManager.API_P2P_CANCEL_CONNECT, + Process.myTid(), message.sendingUid, 0, + getCallingPkgName(message.sendingUid, message.replyTo), true); mWifiNative.p2pCancelConnect(); mWifiP2pMetrics.endConnectionEvent( P2pConnectionEvent.CLF_CANCEL); @@ -3321,7 +3379,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { @Override public boolean processMessage(Message message) { if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - boolean ret = HANDLED; switch (message.what) { case PEER_CONNECTION_USER_ACCEPT: mWifiNative.p2pStopFind(); @@ -3385,7 +3442,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { default: return NOT_HANDLED; } - return ret; + return HANDLED; } @Override @@ -3412,7 +3469,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { @Override public boolean processMessage(Message message) { if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - boolean ret = HANDLED; switch (message.what) { case PEER_CONNECTION_USER_ACCEPT: mWifiNative.p2pStopFind(); @@ -3451,7 +3507,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { default: return NOT_HANDLED; } - return ret; + return HANDLED; } @Override @@ -3635,7 +3691,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S); - startIpClient(mGroup.getInterface(), getHandler()); + startIpClient(mGroup.getInterface(), getHandler(), + mSavedPeerConfig.getGroupClientIpProvisioningMode()); WifiP2pDevice groupOwner = mGroup.getOwner(); WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress); if (peer != null) { @@ -3936,8 +3993,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { @Override public boolean processMessage(Message message) { if (mVerboseLoggingEnabled) logd(getName() + message.toString()); - WifiP2pDevice device = null; - String deviceAddress = null; + WifiP2pDevice device; + String deviceAddress; switch (message.what) { case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: if (message.obj == null) { @@ -4038,12 +4095,46 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { sendP2pConnectionChangedBroadcast(); break; case IPC_PROVISIONING_SUCCESS: + if (mSavedPeerConfig.getGroupClientIpProvisioningMode() + != GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL) { + break; + } + + LinkProperties linkProperties = (LinkProperties) message.obj; + if (mVerboseLoggingEnabled) { + logd("IP provisioning result " + linkProperties); + } + try { + mNetdWrapper.addInterfaceToLocalNetwork( + mGroup.getInterface(), + linkProperties.getRoutes()); + } catch (Exception e) { + loge("Failed to add iface to local network " + e); + mWifiNative.p2pGroupRemove(mGroup.getInterface()); + } + + byte[] goInterfaceMacAddress = mGroup.interfaceAddress; + byte[] goIpv6Address = MacAddress.fromBytes(goInterfaceMacAddress) + .getLinkLocalIpv6FromEui48Mac().getAddress(); + try { + InetAddress goIp = Inet6Address.getByAddress(null, goIpv6Address, + NetworkInterface.getByName(mGroup.getInterface())); + setWifiP2pInfoOnGroupFormationWithInetAddress(goIp); + sendP2pConnectionChangedBroadcast(); + } catch (UnknownHostException | SocketException e) { + loge("Unable to retrieve link-local IPv6 address of group owner " + + e); + mWifiNative.p2pGroupRemove(mGroup.getInterface()); + } break; case IPC_PROVISIONING_FAILURE: loge("IP provisioning failed"); mWifiNative.p2pGroupRemove(mGroup.getInterface()); break; case WifiP2pManager.REMOVE_GROUP: + mLastCallerInfoManager.put(WifiManager.API_P2P_REMOVE_GROUP, + Process.myTid(), message.sendingUid, 0, + getCallingPkgName(message.sendingUid, message.replyTo), true); if (mVerboseLoggingEnabled) logd(getName() + " remove group"); if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) { transitionTo(mOngoingGroupRemovalState); @@ -4141,6 +4232,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // remain at this state. break; } + mLastCallerInfoManager.put(WifiManager.API_P2P_CONNECT, + Process.myTid(), uid, 0, packageName, true); WifiP2pConfig config = (WifiP2pConfig) extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG); if (isConfigInvalid(config)) { @@ -4226,6 +4319,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { loge("Duplicate group creation event notice, ignore"); break; case WifiP2pManager.CANCEL_CONNECT: + mLastCallerInfoManager.put(WifiManager.API_P2P_CANCEL_CONNECT, + Process.myTid(), message.sendingUid, 0, + getCallingPkgName(message.sendingUid, message.replyTo), true); mWifiNative.p2pCancelConnect(); mWifiP2pMetrics.endConnectionEvent( P2pConnectionEvent.CLF_CANCEL); @@ -4964,8 +5060,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private boolean isConfigInvalid(WifiP2pConfig config) { if (config == null) return true; if (TextUtils.isEmpty(config.deviceAddress)) return true; - if (mPeers.get(config.deviceAddress) == null) return true; - return false; + return mPeers.get(config.deviceAddress) == null; } /** @@ -4980,9 +5075,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { byte[] ssidBytes = networkName.getBytes(StandardCharsets.UTF_8); if (ssidBytes.length < MIN_NETWORK_NAME_BYTES) return false; - if (ssidBytes.length > MAX_NETWORK_NAME_BYTES) return false; - - return true; + return ssidBytes.length <= MAX_NETWORK_NAME_BYTES; } /** @@ -4995,12 +5088,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private boolean isConfigValidAsGroup(WifiP2pConfig config) { if (config == null) return false; if (TextUtils.isEmpty(config.deviceAddress)) return false; - if (isValidNetworkName(config.networkName) - && !TextUtils.isEmpty(config.passphrase)) { - return true; - } - - return false; + return isValidNetworkName(config.networkName) + && !TextUtils.isEmpty(config.passphrase); } private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) { @@ -5205,10 +5294,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } if (netId >= 0) { // Skip WPS and start 4way handshake immediately. - if (!mWifiNative.p2pGroupAdd(netId)) { - return false; - } - return true; + return mWifiNative.p2pGroupAdd(netId); } } @@ -5361,9 +5447,13 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { InetAddress serverInetAddress = serverAddress == null ? null : InetAddresses.parseNumericAddress(serverAddress); + setWifiP2pInfoOnGroupFormationWithInetAddress(serverInetAddress); + } + + private void setWifiP2pInfoOnGroupFormationWithInetAddress(InetAddress serverAddress) { mWifiP2pInfo.groupFormed = true; mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner(); - mWifiP2pInfo.groupOwnerAddress = serverInetAddress; + mWifiP2pInfo.groupOwnerAddress = serverAddress; } private void resetWifiP2pInfo() { @@ -5377,7 +5467,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (d != null) { return d.deviceName; } - //Treat the address as name if there is no match + // Treat the address as name if there is no match return deviceAddress; } @@ -5449,7 +5539,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { decoder.flush(cb); sb.append(new String(cb.array(), 0, cb.position())); } - Log.i(TAG, "P2P SSID postfix: " + sb.toString() + Log.i(TAG, "P2P SSID postfix: " + sb + " len=" + sb.toString().length() + " bytes=" + sb.toString().getBytes(charset).length); return sb.toString(); @@ -5486,7 +5576,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private boolean setWfdInfo(WifiP2pWfdInfo wfdInfo) { final boolean enabled = wfdInfo.isEnabled(); - boolean success; if (!mWifiNative.setWfdEnable(enabled)) { loge("Failed to set wfd enable: " + enabled); return false; @@ -5718,7 +5807,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { clearSupplicantServiceRequest(); StringBuffer sb = new StringBuffer(); for (ClientInfo c: mClientInfoList.values()) { - int key; WifiP2pServiceRequest req; for (int i = 0; i < c.mReqList.size(); i++) { req = c.mReqList.valueAt(i); @@ -5732,10 +5820,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } mServiceDiscReqId = mWifiNative.p2pServDiscReq("00:00:00:00:00:00", sb.toString()); - if (mServiceDiscReqId == null) { - return false; - } - return true; + return mServiceDiscReqId != null; } /** @@ -6064,8 +6149,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { return false; } - mVendorElements.put(packageName, - new HashSet<ScanResult.InformationElement>(vendorElements)); + mVendorElements.put(packageName, new HashSet<>(vendorElements)); Set<ScanResult.InformationElement> aggregatedVendorElements = new HashSet<>(); mVendorElements.forEach((k, v) -> aggregatedVendorElements.addAll(v)); @@ -6414,27 +6498,24 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { * Information about a particular client and we track the service discovery requests * and the local services registered by the client. */ - private class ClientInfo { + private static class ClientInfo { // A reference to WifiP2pManager.Channel handler. // The response of this request is notified to WifiP2pManager.Channel handler - private Messenger mMessenger; + private final Messenger mMessenger; private String mPackageName; - private @Nullable String mFeatureId; - + @Nullable private String mFeatureId; // A service discovery request list. - private SparseArray<WifiP2pServiceRequest> mReqList; + private final SparseArray<WifiP2pServiceRequest> mReqList = new SparseArray<>(); // A local service information list. - private List<WifiP2pServiceInfo> mServList; + private final List<WifiP2pServiceInfo> mServList = new ArrayList<>(); private ClientInfo(Messenger m) { mMessenger = m; mPackageName = null; mFeatureId = null; - mReqList = new SparseArray(); - mServList = new ArrayList<WifiP2pServiceInfo>(); } } diff --git a/service/java/com/android/server/wifi/rtt/RttMetrics.java b/service/java/com/android/server/wifi/rtt/RttMetrics.java index 0d68e898d9..1c00bdeaf0 100644 --- a/service/java/com/android/server/wifi/rtt/RttMetrics.java +++ b/service/java/com/android/server/wifi/rtt/RttMetrics.java @@ -31,6 +31,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import com.android.server.wifi.Clock; +import com.android.server.wifi.hal.WifiRttController; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.util.MetricsUtils; @@ -419,37 +420,37 @@ public class RttMetrics { */ public static int convertRttStatusTypeToProtoEnum(int rttStatusType) { switch (rttStatusType) { - case RttNative.FRAMEWORK_RTT_STATUS_SUCCESS: + case WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS: return WifiMetricsProto.WifiRttLog.SUCCESS; - case RttNative.FRAMEWORK_RTT_STATUS_FAILURE: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE: return WifiMetricsProto.WifiRttLog.FAILURE; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP: return WifiMetricsProto.WifiRttLog.FAIL_NO_RSP; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_REJECTED: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED: return WifiMetricsProto.WifiRttLog.FAIL_REJECTED; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET: return WifiMetricsProto.WifiRttLog.FAIL_NOT_SCHEDULED_YET; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT: return WifiMetricsProto.WifiRttLog.FAIL_TM_TIMEOUT; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL: return WifiMetricsProto.WifiRttLog.FAIL_AP_ON_DIFF_CHANNEL; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY: return WifiMetricsProto.WifiRttLog.FAIL_NO_CAPABILITY; - case RttNative.FRAMEWORK_RTT_STATUS_ABORTED: + case WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED: return WifiMetricsProto.WifiRttLog.ABORTED; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS: return WifiMetricsProto.WifiRttLog.FAIL_INVALID_TS; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL: return WifiMetricsProto.WifiRttLog.FAIL_PROTOCOL; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE: return WifiMetricsProto.WifiRttLog.FAIL_SCHEDULE; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER: return WifiMetricsProto.WifiRttLog.FAIL_BUSY_TRY_LATER; - case RttNative.FRAMEWORK_RTT_STATUS_INVALID_REQ: + case WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ: return WifiMetricsProto.WifiRttLog.INVALID_REQ; - case RttNative.FRAMEWORK_RTT_STATUS_NO_WIFI: + case WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI: return WifiMetricsProto.WifiRttLog.NO_WIFI; - case RttNative.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE: + case WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE: return WifiMetricsProto.WifiRttLog.FAIL_FTM_PARAM_OVERRIDE; default: Log.e(TAG, "Unrecognized RttStatus: " + rttStatusType); diff --git a/service/java/com/android/server/wifi/rtt/RttService.java b/service/java/com/android/server/wifi/rtt/RttService.java index 29b99a9195..fdfc55f901 100644 --- a/service/java/com/android/server/wifi/rtt/RttService.java +++ b/service/java/com/android/server/wifi/rtt/RttService.java @@ -23,7 +23,6 @@ import android.os.HandlerThread; import android.util.Log; import com.android.server.SystemService; -import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.WifiInjector; import com.android.server.wifi.util.WifiPermissionsUtil; @@ -56,17 +55,14 @@ public class RttService extends SystemService { return; } - HalDeviceManager halDeviceManager = wifiInjector.getHalDeviceManager(); HandlerThread handlerThread = wifiInjector.getRttHandlerThread(); WifiPermissionsUtil wifiPermissionsUtil = wifiInjector.getWifiPermissionsUtil(); RttMetrics rttMetrics = wifiInjector.getWifiMetrics().getRttMetrics(); - WifiAwareManager awareManager = getContext().getSystemService(WifiAwareManager.class); - RttNative rttNative = new RttNative(mImpl, halDeviceManager); - mImpl.start(handlerThread.getLooper(), wifiInjector.getClock(), awareManager, rttNative, - rttMetrics, wifiPermissionsUtil, wifiInjector.getSettingsConfigStore()); - + mImpl.start(handlerThread.getLooper(), wifiInjector.getClock(), awareManager, + rttMetrics, wifiPermissionsUtil, wifiInjector.getSettingsConfigStore(), + wifiInjector.getHalDeviceManager()); } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { mImpl.handleBootCompleted(); } diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java index d884f79701..9d7e979d34 100644 --- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java +++ b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java @@ -17,6 +17,9 @@ package com.android.server.wifi.rtt; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; +import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_LCI; +import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_LCR; +import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; @@ -63,8 +66,10 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.BuildProperties; import com.android.server.wifi.Clock; import com.android.server.wifi.FrameworkFacade; +import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.SystemBuildProperties; import com.android.server.wifi.WifiSettingsConfigStore; +import com.android.server.wifi.hal.WifiRttController; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.wifi.resources.R; @@ -95,7 +100,8 @@ public class RttServiceImpl extends IWifiRttManager.Stub { private final RttShellCommand mShellCommand; private Clock mClock; private WifiAwareManager mAwareManager; - private RttNative mRttNative; + private WifiRttController mWifiRttController; + private HalDeviceManager mHalDeviceManager; private RttMetrics mRttMetrics; private WifiPermissionsUtil mWifiPermissionsUtil; private ActivityManager mActivityManager; @@ -104,6 +110,7 @@ public class RttServiceImpl extends IWifiRttManager.Stub { private long mLastRequestTimestamp; private final BuildProperties mBuildProperties; private FrameworkFacade mFrameworkFacade; + private WifiRttController.Capabilities mCapabilities; private RttServiceSynchronized mRttServiceSynchronized; @@ -116,6 +123,41 @@ public class RttServiceImpl extends IWifiRttManager.Stub { // arbitrary, larger than anything reasonable /* package */ static final int MAX_QUEUED_PER_UID = 20; + + private final WifiRttController.RttControllerRangingResultsCallback mRangingResultsCallback = + new WifiRttController.RttControllerRangingResultsCallback() { + @Override + public void onRangingResults(int cmdId, List<RangingResult> rangingResults) { + if (mVerboseLoggingEnabled) Log.d(TAG, "onRangingResults: cmdId=" + cmdId); + mRttServiceSynchronized.mHandler.post(() -> { + mRttServiceSynchronized.onRangingResults(cmdId, rangingResults); + }); + } + }; + + private final HalDeviceManager.InterfaceRttControllerLifecycleCallback mRttLifecycleCb = + new HalDeviceManager.InterfaceRttControllerLifecycleCallback() { + @Override + public void onNewRttController(WifiRttController controller) { + if (mVerboseLoggingEnabled) { + Log.d(TAG, "onNewRttController: controller=" + controller); + } + boolean changed = mWifiRttController == null; + mWifiRttController = controller; + mWifiRttController.registerRangingResultsCallback(mRangingResultsCallback); + if (changed) { + enableIfPossible(); + } + } + + @Override + public void onRttControllerDestroyed() { + if (mVerboseLoggingEnabled) Log.d(TAG, "onRttControllerDestroyed"); + mWifiRttController = null; + disable(); + } + }; + public RttServiceImpl(Context context) { mContext = context; mBuildProperties = new SystemBuildProperties(); @@ -182,17 +224,18 @@ public class RttServiceImpl extends IWifiRttManager.Stub { return -1; } } else if ("get_capabilities".equals(cmd)) { - RttNative.Capabilities cap = - mRttNative.getRttCapabilities(); + if (mCapabilities == null && mWifiRttController != null) { + mCapabilities = mWifiRttController.getRttCapabilities(); + } JSONObject j = new JSONObject(); - if (cap != null) { + if (mCapabilities != null) { try { - j.put("rttOneSidedSupported", cap.oneSidedRttSupported); - j.put("rttFtmSupported", cap.rttFtmSupported); - j.put("lciSupported", cap.lciSupported); - j.put("lcrSupported", cap.lcrSupported); - j.put("responderSupported", cap.responderSupported); - j.put("mcVersion", cap.mcVersion); + j.put("rttOneSidedSupported", mCapabilities.oneSidedRttSupported); + j.put("rttFtmSupported", mCapabilities.rttFtmSupported); + j.put("lciSupported", mCapabilities.lciSupported); + j.put("lcrSupported", mCapabilities.lcrSupported); + j.put("responderSupported", mCapabilities.responderSupported); + j.put("mcVersion", mCapabilities.mcVersion); } catch (JSONException e) { Log.e(TAG, "onCommand: get_capabilities e=" + e); } @@ -254,20 +297,20 @@ public class RttServiceImpl extends IWifiRttManager.Stub { * @param looper The looper on which to synchronize operations. * @param clock A mockable clock. * @param awareManager The Wi-Fi Aware service (binder) if supported on the system. - * @param rttNative The Native interface to the HAL. * @param rttMetrics The Wi-Fi RTT metrics object. * @param wifiPermissionsUtil Utility for permission checks. * @param settingsConfigStore Used for retrieving verbose logging level. + * @param halDeviceManager The HAL device manager object. */ public void start(Looper looper, Clock clock, WifiAwareManager awareManager, - RttNative rttNative, RttMetrics rttMetrics, WifiPermissionsUtil wifiPermissionsUtil, - WifiSettingsConfigStore settingsConfigStore) { + RttMetrics rttMetrics, WifiPermissionsUtil wifiPermissionsUtil, + WifiSettingsConfigStore settingsConfigStore, HalDeviceManager halDeviceManager) { mClock = clock; mAwareManager = awareManager; - mRttNative = rttNative; + mHalDeviceManager = halDeviceManager; mRttMetrics = rttMetrics; mWifiPermissionsUtil = wifiPermissionsUtil; - mRttServiceSynchronized = new RttServiceSynchronized(looper, rttNative); + mRttServiceSynchronized = new RttServiceSynchronized(looper); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); mPowerManager = mContext.getSystemService(PowerManager.class); @@ -316,7 +359,18 @@ public class RttServiceImpl extends IWifiRttManager.Stub { } }, intentFilter); - rttNative.start(mRttServiceSynchronized.mHandler); + mHalDeviceManager.initialize(); + mHalDeviceManager.registerStatusListener(() -> { + if (VDBG) Log.d(TAG, "hdm.onStatusChanged"); + if (mHalDeviceManager.isStarted()) { + mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, + mRttServiceSynchronized.mHandler); + } + }, mRttServiceSynchronized.mHandler); + if (mHalDeviceManager.isStarted()) { + mHalDeviceManager.registerRttControllerLifecycleCallback( + mRttLifecycleCb, mRttServiceSynchronized.mHandler); + } }); } @@ -324,8 +378,8 @@ public class RttServiceImpl extends IWifiRttManager.Stub { mVerboseHalLoggingEnabled = verboseEnabled || VDBG; updateVerboseLoggingEnabled(); mRttMetrics.enableVerboseLogging(mVerboseLoggingEnabled); - if (mRttNative != null) { - mRttNative.enableVerboseLogging(mVerboseLoggingEnabled); + if (mWifiRttController != null) { + mWifiRttController.enableVerboseLogging(mVerboseLoggingEnabled); } } @@ -399,13 +453,34 @@ public class RttServiceImpl extends IWifiRttManager.Stub { public boolean isAvailable() { long ident = Binder.clearCallingIdentity(); try { - return mRttNative != null && mRttNative.isReady() && !mPowerManager.isDeviceIdleMode() + return mWifiRttController != null && !mPowerManager.isDeviceIdleMode() && mWifiPermissionsUtil.isLocationModeEnabled(); } finally { Binder.restoreCallingIdentity(ident); } } + @Override + public Bundle getRttCharacteristics() { + enforceAccessPermission(); + if (mCapabilities == null && mWifiRttController != null) { + mCapabilities = mWifiRttController.getRttCapabilities(); + } + return covertCapabilitiesToBundle(mCapabilities); + } + + private Bundle covertCapabilitiesToBundle(WifiRttController.Capabilities capabilities) { + Bundle characteristics = new Bundle(); + if (capabilities == null) { + return characteristics; + } + characteristics.putBoolean(CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT, + capabilities.oneSidedRttSupported); + characteristics.putBoolean(CHARACTERISTICS_KEY_BOOLEAN_LCI, capabilities.lciSupported); + characteristics.putBoolean(CHARACTERISTICS_KEY_BOOLEAN_LCR, capabilities.lcrSupported); + return characteristics; + } + /** * Binder interface API to start a ranging operation. Called on binder thread, operations needs * to be posted to handler thread. @@ -534,17 +609,6 @@ public class RttServiceImpl extends IWifiRttManager.Stub { }); } - /** - * Called by HAL to report ranging results. Called on HAL thread - needs to post to local - * thread. - */ - public void onRangingResults(int cmdId, List<RangingResult> results) { - if (VDBG) Log.v(TAG, "onRangingResults: cmdId=" + cmdId); - mRttServiceSynchronized.mHandler.post(() -> { - mRttServiceSynchronized.onRangingResults(cmdId, results); - }); - } - private void enforceAccessPermission() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, TAG); } @@ -580,6 +644,10 @@ public class RttServiceImpl extends IWifiRttManager.Stub { } pw.println("Wi-Fi RTT Service"); mRttServiceSynchronized.dump(fd, pw, args); + pw.println(" mWifiRttController: " + mWifiRttController); + if (mWifiRttController != null) { + mWifiRttController.dump(pw); + } } /* @@ -593,15 +661,12 @@ public class RttServiceImpl extends IWifiRttManager.Stub { private class RttServiceSynchronized { public Handler mHandler; - private RttNative mRttNative; private int mNextCommandId = 1000; private Map<Integer, RttRequesterInfo> mRttRequesterInfo = new HashMap<>(); private List<RttRequestInfo> mRttRequestQueue = new LinkedList<>(); private WakeupMessage mRangingTimeoutMessage = null; - RttServiceSynchronized(Looper looper, RttNative rttNative) { - mRttNative = rttNative; - + RttServiceSynchronized(Looper looper) { mHandler = new Handler(looper); mRangingTimeoutMessage = new WakeupMessage(mContext, mHandler, HAL_RANGING_TIMEOUT_TAG, () -> { @@ -610,12 +675,16 @@ public class RttServiceImpl extends IWifiRttManager.Stub { } private void cancelRanging(RttRequestInfo rri) { - ArrayList<byte[]> macAddresses = new ArrayList<>(); + ArrayList<MacAddress> macAddresses = new ArrayList<>(); for (ResponderConfig peer : rri.request.mRttPeers) { - macAddresses.add(peer.macAddress.toByteArray()); + macAddresses.add(peer.macAddress); } - mRttNative.rangeCancel(rri.cmdId, macAddresses); + if (mWifiRttController != null) { + mWifiRttController.rangeCancel(rri.cmdId, macAddresses); + } else { + Log.e(TAG, "Could not call cancelRanging, rttControllerHal is null"); + } } private void cleanUpOnDisable() { @@ -875,8 +944,8 @@ public class RttServiceImpl extends IWifiRttManager.Stub { nextRequest.cmdId = mNextCommandId++; mLastRequestTimestamp = mClock.getWallClockMillis(); - if (mRttNative.rangeRequest(nextRequest.cmdId, nextRequest.request, - nextRequest.isCalledFromPrivilegedContext)) { + if (mWifiRttController != null + && mWifiRttController.rangeRequest(nextRequest.cmdId, nextRequest.request)) { long timeout = HAL_RANGING_TIMEOUT_MS; for (ResponderConfig responderConfig : nextRequest.request.mRttPeers) { if (responderConfig.responderType == ResponderConfig.RESPONDER_AWARE) { @@ -887,6 +956,9 @@ public class RttServiceImpl extends IWifiRttManager.Stub { mRangingTimeoutMessage.schedule(mClock.getElapsedSinceBootMillis() + timeout); } else { Log.w(TAG, "RttServiceSynchronized.startRanging: native rangeRequest call failed"); + if (mWifiRttController == null) { + Log.e(TAG, "mWifiRttController is null"); + } try { mRttMetrics.recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE); @@ -1188,8 +1260,8 @@ public class RttServiceImpl extends IWifiRttManager.Stub { for (ResponderConfig peer : request.mRttPeers) { RangingResult resultForRequest = resultEntries.get(peer.macAddress); - if (resultForRequest == null - || resultForRequest.getStatus() != RttNative.FRAMEWORK_RTT_STATUS_SUCCESS) { + if (resultForRequest == null || resultForRequest.getStatus() + != WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS) { if (mVerboseLoggingEnabled) { Log.v(TAG, "postProcessResults: missing=" + peer.macAddress); } @@ -1259,8 +1331,9 @@ public class RttServiceImpl extends IWifiRttManager.Stub { pw.println(" mRttRequesterInfo: " + mRttRequesterInfo); pw.println(" mRttRequestQueue: " + mRttRequestQueue); pw.println(" mRangingTimeoutMessage: " + mRangingTimeoutMessage); + pw.println(" mWifiRttController: " + mWifiRttController); + pw.println(" mHalDeviceManager: " + mHalDeviceManager); mRttMetrics.dump(fd, pw, args); - mRttNative.dump(fd, pw, args); } } diff --git a/service/java/com/android/server/wifi/scanner/WifiScannerInternal.java b/service/java/com/android/server/wifi/scanner/WifiScannerInternal.java new file mode 100644 index 0000000000..148f15ea6f --- /dev/null +++ b/service/java/com/android/server/wifi/scanner/WifiScannerInternal.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2022 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.scanner; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.wifi.IWifiScannerListener; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiScanner; +import android.os.Handler; +import android.os.Process; +import android.os.WorkSource; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.Collections; +import java.util.List; + +/** + * WifiScanner manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class WifiScannerInternal { + + /** + * Local scan listener + */ + public static class ScanListener extends IWifiScannerListener.Stub { + private static final String TAG = "WifiScannerInternal"; + private final WifiScanner.ScanListener mScanListener; + private final Handler mHandler; + + /** + * Local scan listener constructor + * @param scanListener WifiScanner listener + * @param handler handler for the listener + */ + public ScanListener(WifiScanner.ScanListener scanListener, Handler handler) { + mScanListener = scanListener; + mHandler = handler; + } + + /** + * Get the WifiScanner listener + * @hide + */ + @VisibleForTesting + public WifiScanner.ScanListener getWifiScannerListener() { + return mScanListener; + } + + @Override + public void onSuccess() { + mHandler.post(() -> { + mScanListener.onSuccess(); + }); + } + + @Override + public void onFailure(int reason, String description) { + mHandler.post(() -> { + mScanListener.onFailure(reason, description); + }); + } + + @Override + public void onResults(WifiScanner.ScanData[] scanDatas) { + mHandler.post(() -> { + mScanListener.onResults(scanDatas); + }); + } + + @Override + public void onFullResult(ScanResult fullScanResult) { + mHandler.post(() -> { + mScanListener.onFullResult(fullScanResult); + }); + } + + @Override + public void onSingleScanCompleted() { + // Internal scan listener doesn't need to handle this. + } + + @Override + public void onPnoNetworkFound(ScanResult[] scanResult) { + if (!(mScanListener instanceof WifiScanner.PnoScanListener)) { + Log.wtf(TAG, "Listener is not a PnoScanListener!"); + return; + } + WifiScanner.PnoScanListener pnoScanListener = + (WifiScanner.PnoScanListener) mScanListener; + mHandler.post(() -> { + pnoScanListener.onPnoNetworkFound(scanResult); + }); + } + } + + /** + * Enable/Disable wifi scanning. + * + * @param enable set true to enable scanning, false to disable all types of scanning. + */ + public void setScanningEnabled(boolean enable) { + } + + /** + * Register a listener that will receive results from all single scans. + * @param listener specifies the object to report events to. + */ + public void registerScanListener(@NonNull ScanListener listener) { + } + + /** + * Start a single scan. + * @param settings Wifi single scan setting + * @param listener listener to the scan + */ + public void startScan(WifiScanner.ScanSettings settings, ScanListener listener) { + startScan(settings, listener, new WorkSource(Process.WIFI_UID)); + } + + /** + * Start a single scan. + * @param settings Wifi single scan setting + * @param listener listener to the scan + * @param workSource WorkSource to blame for power usage + */ + public void startScan(WifiScanner.ScanSettings settings, ScanListener listener, + @Nullable WorkSource workSource) { + } + + /** + * Stop a single scan. + * @param listener listener to the scan + */ + public void stopScan(ScanListener listener) { + } + + /** + * Start a PNO scan. + * @param scanSettings Wifi single scan setting + * @param pnoSettings Wifi pno scan setting + * @param listener listener to the scan + */ + public void startPnoScan(WifiScanner.ScanSettings scanSettings, + WifiScanner.PnoSettings pnoSettings, + ScanListener listener) { + } + + /** + * Stop a pno scan. + * @param listener listener to the scan + */ + public void stopPnoScan(ScanListener listener) { + } + + /** + * Get single scan results. + * @return the list of scan results + */ + public List<ScanResult> getSingleScanResults() { + return Collections.emptyList(); + } + +} diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java index 2cab1fd067..7d0a679404 100644 --- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java +++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java @@ -38,10 +38,12 @@ import android.net.wifi.WifiScanner.WifiBand; import android.net.wifi.util.ScanResultUtil; import android.os.BatteryStatsManager; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.WorkSource; import android.util.ArrayMap; @@ -58,6 +60,7 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.ClientModeImpl; import com.android.server.wifi.Clock; import com.android.server.wifi.WifiInjector; +import com.android.server.wifi.WifiLocalServices; import com.android.server.wifi.WifiLog; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; @@ -114,17 +117,30 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } } + private boolean isPlatformOrTargetSdkLessThanU(String packageName, int uid) { + if (!SdkLevel.isAtLeastU()) { + return true; + } + return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, + Build.VERSION_CODES.UPSIDE_DOWN_CAKE, uid); + } + @Override public Bundle getAvailableChannels(@WifiBand int band, String packageName, - @Nullable String attributionTag) { + @Nullable String attributionTag, Bundle extras) { int uid = Binder.getCallingUid(); - long ident = Binder.clearCallingIdentity(); - try { - enforcePermission(uid, packageName, attributionTag, false, false, false); - } finally { - Binder.restoreCallingIdentity(ident); + if (isPlatformOrTargetSdkLessThanU(packageName, uid)) { + long ident = Binder.clearCallingIdentity(); + try { + enforcePermission(uid, packageName, attributionTag, false, false, false); + } finally { + Binder.restoreCallingIdentity(ident); + } + } else { + mWifiPermissionsUtil.enforceNearbyDevicesPermission( + extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), + true, TAG + " getAvailableChannels"); } - ChannelSpec[][] channelSpecs = mWifiThreadRunner.call(() -> { if (mChannelHelper == null) return new ChannelSpec[0][0]; mChannelHelper.updateChannels(); @@ -298,6 +314,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { localLog("stop background scan: " + client); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_STOP_BACKGROUND_SCAN; + msg.obj = new ScanParams(listener, null, null); msg.sendingUid = uid; mBackgroundScanStateMachine.sendMessage(msg); } @@ -359,6 +376,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { notifyFailure(listener, WifiScanner.REASON_NOT_AUTHORIZED, "Not authorized"); return; } + mLastCallerInfoManager.put(WifiManager.API_WIFI_SCANNER_START_SCAN, Process.myTid(), + uid, Binder.getCallingPid(), packageName, true); mWifiThreadRunner.post(() -> { ExternalClientInfo client = (ExternalClientInfo) mClients.get(listener); if (client == null) { @@ -396,6 +415,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { localLog("stop scan: " + client); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_STOP_SINGLE_SCAN; + msg.obj = new ScanParams(listener, null, null); msg.sendingUid = uid; mSingleScanStateMachine.sendMessage(msg); }); @@ -599,6 +619,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { public void startService() { mWifiThreadRunner.post(() -> { + WifiLocalServices.addService(WifiScannerInternal.class, new LocalService()); mBackgroundScanStateMachine = new WifiBackgroundScanStateMachine(mLooper); mSingleScanStateMachine = new WifiSingleScanStateMachine(mLooper); mPnoScanStateMachine = new WifiPnoScanStateMachine(mLooper); @@ -993,11 +1014,9 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { /** * Helper method to handle the scan start message. */ - private void handleScanStartMessage(ClientInfo ci, Message msg) { - ScanParams scanParams = (ScanParams) msg.obj; - if (scanParams == null) { - logCallback("singleScanInvalidRequest", ci, "null params"); - ci.replyFailed(WifiScanner.REASON_INVALID_REQUEST, "params null"); + private void handleScanStartMessage(ClientInfo ci, ScanParams scanParams) { + if (ci == null) { + logCallback("singleScanInvalidRequest", ci, "null params"); return; } ScanSettings scanSettings = scanParams.settings; @@ -1075,13 +1094,17 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { return HANDLED; case WifiScanner.CMD_START_SINGLE_SCAN: ScanParams scanParams = (ScanParams) msg.obj; - ClientInfo ci = mClients.get(scanParams.listener); - handleScanStartMessage(ci, msg); + if (scanParams != null) { + ClientInfo ci = mClients.get(scanParams.listener); + handleScanStartMessage(ci, scanParams); + } return HANDLED; case WifiScanner.CMD_STOP_SINGLE_SCAN: scanParams = (ScanParams) msg.obj; - ci = mClients.get(scanParams.listener); - removeSingleScanRequests(ci); + if (scanParams != null) { + ClientInfo ci = mClients.get(scanParams.listener); + removeSingleScanRequests(ci); + } return HANDLED; case CMD_SCAN_RESULTS_AVAILABLE: if (DBG) localLog("ignored scan results available event"); @@ -2515,10 +2538,11 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { private void addSingleScanRequest(ScanSettings settings) { if (DBG) localLog("Starting single scan"); if (mInternalClientInfo != null) { - mSingleScanStateMachine.sendMessage( - WifiScanner.CMD_START_SINGLE_SCAN, - new ScanParams(mInternalClientInfo.mListener, settings, - ClientModeImpl.WIFI_WORK_SOURCE)); + Message msg = Message.obtain(); + msg.what = WifiScanner.CMD_START_SINGLE_SCAN; + msg.obj = new ScanParams(mInternalClientInfo.mListener, settings, + ClientModeImpl.WIFI_WORK_SOURCE); + mSingleScanStateMachine.sendMessage(msg); } mWifiMetrics.getScanMetrics().setWorkSource(ClientModeImpl.WIFI_WORK_SOURCE); } @@ -2763,6 +2787,54 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } } + private class LocalService extends WifiScannerInternal { + @Override + public void setScanningEnabled(boolean enable) { + WifiScanningServiceImpl.this.setScanningEnabled(enable, Process.myTid(), + mContext.getOpPackageName()); + } + + @Override + public void registerScanListener(@NonNull WifiScannerInternal.ScanListener listener) { + WifiScanningServiceImpl.this.registerScanListener(listener, + mContext.getOpPackageName(), mContext.getAttributionTag()); + } + + @Override + public void startScan(WifiScanner.ScanSettings settings, + WifiScannerInternal.ScanListener listener, + @Nullable WorkSource workSource) { + WifiScanningServiceImpl.this.startScan(listener, settings, workSource, + workSource.getPackageName(0), mContext.getAttributionTag()); + } + + @Override + public void stopScan(WifiScannerInternal.ScanListener listener) { + WifiScanningServiceImpl.this.stopScan(listener, + mContext.getOpPackageName(), mContext.getAttributionTag()); + } + + @Override + public void startPnoScan(WifiScanner.ScanSettings scanSettings, + WifiScanner.PnoSettings pnoSettings, + WifiScannerInternal.ScanListener listener) { + WifiScanningServiceImpl.this.startPnoScan(listener, + scanSettings, pnoSettings, mContext.getOpPackageName(), + mContext.getAttributionTag()); + } + + @Override + public void stopPnoScan(WifiScannerInternal.ScanListener listener) { + WifiScanningServiceImpl.this.stopPnoScan(listener, mContext.getOpPackageName(), + mContext.getAttributionTag()); + } + + @Override + public List<ScanResult> getSingleScanResults() { + return mSingleScanStateMachine.filterCachedScanResultsByAge(); + } + } + private static String toString(int uid, ScanSettings settings) { StringBuilder sb = new StringBuilder(); sb.append("ScanSettings[uid=").append(uid); diff --git a/service/java/com/android/server/wifi/util/HalAidlUtil.java b/service/java/com/android/server/wifi/util/HalAidlUtil.java new file mode 100644 index 0000000000..6b822ca133 --- /dev/null +++ b/service/java/com/android/server/wifi/util/HalAidlUtil.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 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.util; + +import android.hardware.wifi.supplicant.KeyMgmtMask; +import android.net.wifi.WifiConfiguration; + +import java.util.BitSet; + +/** + * Provide utility functions for HAL AIDL implementation. + */ +public class HalAidlUtil { + private static int supplicantMaskValueToWifiConfigurationBitSet(int supplicantMask, + int supplicantValue, BitSet bitset, int bitSetPosition) { + bitset.set(bitSetPosition, (supplicantMask & supplicantValue) == supplicantValue); + int modifiedSupplicantMask = supplicantMask & ~supplicantValue; + return modifiedSupplicantMask; + } + + /** Convert supplicant key management mask to framework key management mask. */ + public static BitSet supplicantToWifiConfigurationKeyMgmtMask(int mask) { + BitSet bitset = new BitSet(); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.NONE, bitset, + WifiConfiguration.KeyMgmt.NONE); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.WPA_PSK, bitset, + WifiConfiguration.KeyMgmt.WPA_PSK); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.WPA_EAP, bitset, + WifiConfiguration.KeyMgmt.WPA_EAP); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.IEEE8021X, bitset, + WifiConfiguration.KeyMgmt.IEEE8021X); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.OSEN, bitset, + WifiConfiguration.KeyMgmt.OSEN); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.FT_PSK, bitset, + WifiConfiguration.KeyMgmt.FT_PSK); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.FT_EAP, bitset, + WifiConfiguration.KeyMgmt.FT_EAP); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.SAE, + bitset, WifiConfiguration.KeyMgmt.SAE); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.OWE, + bitset, WifiConfiguration.KeyMgmt.OWE); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.SUITE_B_192, + bitset, WifiConfiguration.KeyMgmt.SUITE_B_192); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.WPA_PSK_SHA256, + bitset, WifiConfiguration.KeyMgmt.WPA_PSK_SHA256); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.WPA_EAP_SHA256, + bitset, WifiConfiguration.KeyMgmt.WPA_EAP_SHA256); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.WAPI_PSK, + bitset, WifiConfiguration.KeyMgmt.WAPI_PSK); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.WAPI_CERT, + bitset, WifiConfiguration.KeyMgmt.WAPI_CERT); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.FILS_SHA256, + bitset, WifiConfiguration.KeyMgmt.FILS_SHA256); + mask = supplicantMaskValueToWifiConfigurationBitSet( + mask, KeyMgmtMask.FILS_SHA384, + bitset, WifiConfiguration.KeyMgmt.FILS_SHA384); + if (mask != 0) { + throw new IllegalArgumentException( + "invalid key mgmt mask from supplicant: " + mask); + } + return bitset; + } +} diff --git a/service/java/com/android/server/wifi/util/NativeUtil.java b/service/java/com/android/server/wifi/util/NativeUtil.java index bcc426c48a..0d422d0b9a 100644 --- a/service/java/com/android/server/wifi/util/NativeUtil.java +++ b/service/java/com/android/server/wifi/util/NativeUtil.java @@ -16,10 +16,14 @@ package com.android.server.wifi.util; +import android.annotation.Nullable; +import android.net.MacAddress; +import android.net.wifi.WifiConfiguration; import android.net.wifi.util.HexEncoding; import android.text.TextUtils; import com.android.server.wifi.ByteBufferReader; +import com.android.server.wifi.WifiGlobals; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; @@ -31,6 +35,7 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; /** * Provide utility functions for native interfacing modules. @@ -128,6 +133,23 @@ public class NativeUtil { } /** + * Converts a MAC address from the given string representation to android.net.MacAddress. A + * valid String representation for a MacAddress is a series of 6 values in the range [0,ff] + * printed in hexadecimal and joined by ':' characters. + * + * @param macAddress a String representation of a MAC address. + * @return the MacAddress corresponding to the given string representation or null. + */ + public static MacAddress getMacAddressOrNull(@Nullable String macAddress) { + if (macAddress == null) return null; + try { + return MacAddress.fromString(macAddress); + } catch (IllegalArgumentException e) { + return null; + } + } + + /** * Converts an array of 6 bytes to a HexEncoded String with format: "XX:XX:XX:XX:XX:XX", where X * is any hexadecimal digit. * @@ -356,4 +378,71 @@ public class NativeUtil { int z = ((a[6] & 0xFF) << 8) | (a[7] & 0xFF); return String.format("%d-%s-%d", x, y, z); } + + /** + * Update PMF requirement if auto-upgrade offload is supported. + * + * If SAE auto-upgrade offload is supported and this config enables + * both PSK and SAE, do not set PMF requirement to + * mandatory to allow the device to roam between PSK and SAE BSSes. + * wpa_supplicant will set PMF requirement to optional by default. + */ + public static boolean getOptimalPmfSettingForConfig(WifiConfiguration config, + boolean isPmfRequiredFromSelectedSecurityParams, WifiGlobals wifiGlobals) { + if (isPskSaeParamsMergeable(config, wifiGlobals)) { + return false; + } + return isPmfRequiredFromSelectedSecurityParams; + } + + /** + * Update group ciphers if auto-upgrade offload is supported. + * + * If auto-upgrade offload is supported and this config enables both PSK and + * SAE, merge allowed group ciphers to allow native service to roam + * between two types. + */ + public static BitSet getOptimalGroupCiphersForConfig(WifiConfiguration config, + BitSet ciphersFromSelectedParams, WifiGlobals wifiGlobals) { + BitSet ciphers = ciphersFromSelectedParams; + if (isPskSaeParamsMergeable(config, wifiGlobals)) { + ciphers = (BitSet) config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK) + .getAllowedGroupCiphers().clone(); + ciphers.or((BitSet) config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE) + .getAllowedGroupCiphers().clone()); + } + return ciphers; + } + + /** + * Update pairwise ciphers if auto-upgrade offload is supported. + * + * If auto-upgrade offload is supported and this config enables both PSK and + * SAE, merge allowed pairwise ciphers to allow native service to roam + * between two types. + */ + public static BitSet getOptimalPairwiseCiphersForConfig(WifiConfiguration config, + BitSet ciphersFromSelectedParams, WifiGlobals wifiGlobal) { + BitSet ciphers = ciphersFromSelectedParams; + if (isPskSaeParamsMergeable(config, wifiGlobal)) { + ciphers = (BitSet) config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK) + .getAllowedPairwiseCiphers().clone(); + ciphers.or((BitSet) config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE) + .getAllowedPairwiseCiphers().clone()); + } + return ciphers; + } + + private static boolean isPskSaeParamsMergeable( + WifiConfiguration config, WifiGlobals wifiGlobals) { + if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK) + && config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK).isEnabled() + && config.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE) + && config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE).isEnabled() + && wifiGlobals.isWpa3SaeUpgradeOffloadEnabled()) { + return true; + } + return false; + } + } diff --git a/service/java/com/android/server/wifi/util/WifiPermissionsWrapper.java b/service/java/com/android/server/wifi/util/WifiPermissionsWrapper.java index a8d3e49a09..584cf66ed8 100644 --- a/service/java/com/android/server/wifi/util/WifiPermissionsWrapper.java +++ b/service/java/com/android/server/wifi/util/WifiPermissionsWrapper.java @@ -37,23 +37,42 @@ public class WifiPermissionsWrapper { /** * Determine if a UID has a permission. + * * @param permissionType permission string * @param uid to get permission for + * @param pid to get permission for * @return Permissions setting */ + public int getUidPermission(String permissionType, int uid, int pid) { + return mContext.checkPermission(permissionType, pid, uid); + } + + /** + * Wrapper around {@link #getUidPermission(String, int, int)}. + * TODO (b/231480106): Remove this wrapper and always pass the pid + */ public int getUidPermission(String permissionType, int uid) { - // We don't care about pid, pass in -1 - return mContext.checkPermission(permissionType, -1, uid); + // We don't care about the pid, pass in -1 + return getUidPermission(permissionType, uid, -1); } /** * Determines if the caller has the override wifi config permission. * * @param uid to check the permission for + * @param pid to check the permission for * @return int representation of success or denied */ - public int getOverrideWifiConfigPermission(int uid) { - return getUidPermission(android.Manifest.permission.OVERRIDE_WIFI_CONFIG, uid); + public int getOverrideWifiConfigPermission(int uid, int pid) { + return getUidPermission(android.Manifest.permission.OVERRIDE_WIFI_CONFIG, uid, pid); } + /** + * Wrapper around {@link #getOverrideWifiConfigPermission(int, int)} + * TODO (b/231480106): Remove this wrapper and always pass the pid + */ + public int getOverrideWifiConfigPermission(int uid) { + // We don't care about the pid, pass in -1 + return getOverrideWifiConfigPermission(uid, -1); + } } diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java index 03632f6c7d..ee4f4bf830 100644 --- a/service/java/com/android/server/wifi/util/XmlUtil.java +++ b/service/java/com/android/server/wifi/util/XmlUtil.java @@ -1431,6 +1431,7 @@ public class XmlUtil { public static final String XML_TAG_DECORATED_IDENTITY_PREFIX = "DecoratedIdentityPrefix"; public static final String XML_TAG_TRUST_ON_FIRST_USE = "TrustOnFirstUse"; public static final String XML_TAG_USER_APPROVE_NO_CA_CERT = "UserApproveNoCaCert"; + public static final String XML_TAG_MINIMUM_TLS_VERSION = "MinimumTlsVersion"; /** * Write password key to the XML stream. @@ -1518,6 +1519,8 @@ public class XmlUtil { enterpriseConfig.isTrustOnFirstUseEnabled()); XmlUtil.writeNextValue(out, XML_TAG_USER_APPROVE_NO_CA_CERT, enterpriseConfig.isUserApproveNoCaCert()); + XmlUtil.writeNextValue(out, XML_TAG_MINIMUM_TLS_VERSION, + enterpriseConfig.getMinimumTlsVersion()); } /** @@ -1640,6 +1643,9 @@ public class XmlUtil { case XML_TAG_USER_APPROVE_NO_CA_CERT: enterpriseConfig.setUserApproveNoCaCert((boolean) value); break; + case XML_TAG_MINIMUM_TLS_VERSION: + enterpriseConfig.setMinimumTlsVersion((int) value); + break; default: Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); break; diff --git a/service/tests/OWNERS b/service/tests/OWNERS deleted file mode 100644 index 4c05cfe0c3..0000000000 --- a/service/tests/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# Add owners from connectivity for the time of the NetworkSelection -# This also inherits OWNERS from the parent -lorenzo@google.com -jchalard@google.com 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 2cc22f638f..7ba5c836d6 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java @@ -26,6 +26,7 @@ import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TR import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED; import static com.android.server.wifi.ActiveModeWarden.INTERNAL_REQUESTOR_WS; +import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -63,6 +64,8 @@ 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; import android.net.wifi.ISubsystemRestartCallback; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.SoftApCapability; @@ -72,6 +75,7 @@ import android.net.wifi.SoftApInfo; import android.net.wifi.WifiClient; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; +import android.net.wifi.WifiScanner; import android.os.BatteryStatsManager; import android.os.Build; import android.os.IBinder; @@ -81,6 +85,7 @@ import android.os.UserManager; import android.os.WorkSource; import android.os.test.TestLooper; import android.telephony.TelephonyManager; +import android.util.LocalLog; import android.util.Log; import androidx.test.filters.SmallTest; @@ -141,6 +146,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { private static final WorkSource TEST_WORKSOURCE = new WorkSource(TEST_UID, TEST_PACKAGE); private static final WorkSource SETTINGS_WORKSOURCE = new WorkSource(Process.SYSTEM_UID, "system-service"); + private static final int TEST_SUPPORTED_BANDS = 15; TestLooper mLooper; @Mock WifiInjector mWifiInjector; @@ -169,6 +175,9 @@ public class ActiveModeWardenTest extends WifiBaseTest { @Mock HalDeviceManager mHalDeviceManager; @Mock UserManager mUserManager; @Mock PackageManager mPackageManager; + @Mock Network mNetwork; + @Mock LocalLog mLocalLog; + @Mock WifiSettingsConfigStore mSettingsConfigStore; Listener<ConcreteClientModeManager> mClientListener; Listener<SoftApManager> mSoftApListener; @@ -200,6 +209,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mWifiInjector.getSarManager()).thenReturn(mSarManager); when(mWifiInjector.getHalDeviceManager()).thenReturn(mHalDeviceManager); when(mWifiInjector.getUserManager()).thenReturn(mUserManager); + when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog); when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); when(mContext.getResources()).thenReturn(mResources); @@ -221,6 +231,10 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mFacade.getSettingsWorkSource(mContext)).thenReturn(SETTINGS_WORKSOURCE); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn(true); + when(mWifiInjector.getSettingsConfigStore()).thenReturn(mSettingsConfigStore); + when(mSettingsConfigStore.get( + eq(WIFI_NATIVE_SUPPORTED_STA_BANDS))).thenReturn( + TEST_SUPPORTED_BANDS); doAnswer(new Answer<ClientModeManager>() { public ClientModeManager answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); @@ -336,6 +350,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); mLooper.dispatchAll(); when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); + when(mClientModeManager.getCurrentNetwork()).thenReturn(mNetwork); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(TEST_FEATURE_SET); // ClientModeManager starts in SCAN_ONLY role. mClientListener.onRoleChanged(mClientModeManager); @@ -380,6 +395,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { mLooper.dispatchAll(); when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); + when(mClientModeManager.getCurrentNetwork()).thenReturn(null); when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(TEST_FEATURE_SET); if (!isClientModeSwitch) { mClientListener.onStarted(mClientModeManager); @@ -4786,4 +4802,46 @@ public class ActiveModeWardenTest extends WifiBaseTest { testGetSupportedFeaturesCaseForRtt( featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, true)); } + + @Test + public void testGetCurrentNetworkScanOnly() throws Exception { + enterScanOnlyModeActiveState(); + assertNull(mActiveModeWarden.getCurrentNetwork()); + } + + @Test public void testGetCurrentNetworkClientMode() throws Exception { + mActiveModeWarden.setCurrentNetwork(mNetwork); + assertEquals(mNetwork, mActiveModeWarden.getCurrentNetwork()); + } + + /** + * Verifies that isClientModeManagerConnectedOrConnectingToBssid() checks for Affiliated link + * BSSID, if exists. + */ + @Test + public void testClientModeManagerConnectedOrConnectingToBssid() { + + WifiConfiguration config1 = new WifiConfiguration(); + config1.SSID = TEST_SSID_1; + MacAddress bssid2 = MacAddress.fromString(TEST_BSSID_2); + when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); + when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); + when(mClientModeManager.isAffiliatedLinkBssid(eq(bssid2))).thenReturn(true); + + assertTrue(mActiveModeWarden.isClientModeManagerConnectedOrConnectingToBssid( + mClientModeManager, TEST_SSID_1, TEST_BSSID_2)); + } + + @Test + public void syncGetSupportedBands() throws Exception { + enterClientModeActiveState(); + when(mWifiNative.getSupportedBandsForSta(anyString())).thenReturn(11); + mClientListener.onStarted(mClientModeManager); + mLooper.dispatchAll(); + verify(mSettingsConfigStore).put(WIFI_NATIVE_SUPPORTED_STA_BANDS, 11); + assertTrue(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ)); + assertTrue(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ)); + assertFalse(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY)); + assertTrue(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java b/service/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java index 5541a7360a..1e83b4c9c8 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/CandidateScorerTest.java @@ -220,7 +220,7 @@ public class CandidateScorerTest extends WifiBaseTest { * Prefer current network when current network has low throughput and no internet (but expected) */ @Test - public void testSwitchifCurrentNetworkHasNoInternetExceptedAndLowThroughput() throws Exception { + public void testSwitchifCurrentNetworkHasNoInternetExpectedAndLowThroughput() throws Exception { if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; assertThat(evaluate(mCandidate1.setScanRssi(-57) .setCurrentNetwork(true) @@ -232,6 +232,36 @@ public class CandidateScorerTest extends WifiBaseTest { } /** + * Prefer to switch when current network has higher throughput but no internet access + */ + @Test + public void testSwitchifCurrentNetworkNoInternetAndHighThroughput() throws Exception { + if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; + assertThat(evaluate(mCandidate1.setScanRssi(-57) + .setCurrentNetwork(true) + .setPredictedThroughputMbps(560) + .setNoInternetAccess(true) + .setNoInternetAccessExpected(false)), + lessThan(evaluate(mCandidate2.setScanRssi(-57) + .setPredictedThroughputMbps(433)))); + } + + /** + * Prefer to switch when current network has lower RSSI but no internet access + */ + @Test + public void testSwitchifCurrentNetworkNoInternetAndLowRssi() throws Exception { + if (mExpectedExpId != ThroughputScorer.THROUGHPUT_SCORER_DEFAULT_EXPID) return; + assertThat(evaluate(mCandidate1.setScanRssi(-57) + .setCurrentNetwork(true) + .setPredictedThroughputMbps(560) + .setNoInternetAccess(true) + .setNoInternetAccessExpected(false)), + lessThan(evaluate(mCandidate2.setScanRssi(-70) + .setPredictedThroughputMbps(560)))); + } + + /** * Prefer to switch with a larger rssi difference. */ @Test 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 efa7011aa3..f5b31023c3 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -32,12 +32,14 @@ import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED; 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.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; import static com.android.server.wifi.ClientModeImpl.ARP_TABLE_PATH; import static com.android.server.wifi.ClientModeImpl.CMD_PRE_DHCP_ACTION; import static com.android.server.wifi.ClientModeImpl.CMD_UNWANTED_NETWORK; import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE; +import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS; import static org.junit.Assert.assertArrayEquals; @@ -74,6 +76,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; @@ -138,16 +141,17 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; -import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.Process; +import android.os.UserHandle; import android.os.test.TestLooper; import android.provider.Settings; import android.telephony.TelephonyManager; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.util.ArraySet; +import android.util.LocalLog; import android.util.Log; import android.util.Pair; import android.util.Range; @@ -204,6 +208,7 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -268,7 +273,18 @@ public class ClientModeImplTest extends WifiBaseTest { private static final String TEST_AP_MLD_MAC_ADDRESS_STR = "02:03:04:05:06:07"; private static final MacAddress TEST_AP_MLD_MAC_ADDRESS = MacAddress.fromString(TEST_AP_MLD_MAC_ADDRESS_STR); + + private static final String TEST_MLO_LINK_ADDR_STR = "02:03:04:05:06:0A"; + private static final MacAddress TEST_MLO_LINK_ADDR = + MacAddress.fromString(TEST_MLO_LINK_ADDR_STR); + + + private static final String TEST_MLO_LINK_ADDR_1_STR = "02:03:04:05:06:0B"; + private static final MacAddress TEST_MLO_LINK_ADDR_1 = + MacAddress.fromString(TEST_MLO_LINK_ADDR_1_STR); + private static final int TEST_MLO_LINK_ID = 1; + private static final int TEST_MLO_LINK_ID_1 = 2; private long mBinderToken; private MockitoSession mSession; @@ -452,6 +468,7 @@ public class ClientModeImplTest extends WifiBaseTest { static final WifiSsid TEST_WIFI_SSID1 = WifiSsid.fromUtf8Text(SSID_NO_QUOTE1); static final String TEST_BSSID_STR = "01:02:03:04:05:06"; static final String TEST_BSSID_STR1 = "02:01:04:03:06:05"; + static final String TEST_BSSID_STR2 = "02:01:04:03:06:04"; static final int sFreq = 2437; static final int sFreq1 = 5240; static final String WIFI_IFACE_NAME = "mockWlan"; @@ -544,6 +561,7 @@ public class ClientModeImplTest extends WifiBaseTest { @Mock ScanResult mScanResult; @Mock HandlerThread mWifiHandlerThread; @Mock SsidTranslator mSsidTranslator; + @Mock LocalLog mLocalLog; @Captor ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> mConfigUpdateListenerCaptor; @Captor ArgumentCaptor<WifiNetworkAgent.Callback> mWifiNetworkAgentCallbackCaptor; @@ -552,6 +570,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiCarrierInfoManager.OnCarrierOffloadDisabledListener.class); @Captor ArgumentCaptor<BroadcastReceiver> mScreenStateBroadcastReceiverCaptor; @Captor ArgumentCaptor<ProvisioningConfigurationParcelable> mProvisioningConfigurationCaptor; + WifiInfo mPrimaryWifiInfo; private void setUpWifiNative() throws Exception { when(mWifiNative.getStaFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn( @@ -620,6 +639,7 @@ public class ClientModeImplTest extends WifiBaseTest { when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(true); when(mOemWifiNetworkFactory.hasConnectionRequests()).thenReturn(true); when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(true); + when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog); mFrameworkFacade = getFrameworkFacade(); mContext = getContext(); @@ -682,7 +702,13 @@ public class ClientModeImplTest extends WifiBaseTest { } }); when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); - + // Update the WifiInfo in WifiActiveModeWarden + doAnswer(inv -> { + if (mCmi != null) { + mPrimaryWifiInfo = mCmi.getConnectionInfo(); + } + return null; + }).when(mActiveModeWarden).updateCurrentConnectionInfo(); initializeCmi(); // Retrieve factory MAC address on first bootup. verify(mWifiNative).getStaFactoryMacAddress(WIFI_IFACE_NAME); @@ -718,41 +744,12 @@ public class ClientModeImplTest extends WifiBaseTest { }).when(mBroadcastQueue).queueOrSendBroadcast(any(), any()); } - private void registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger, - Handler wrappedHandler) { - final AsyncChannel channel = new AsyncChannel(); - Handler handler = new Handler(mLooper.getLooper()) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - consumer.accept(channel); - } else { - Log.d(TAG, "Failed to connect Command channel " + this); - } - break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - Log.d(TAG, "Command channel disconnected " + this); - break; - case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: - Log.d(TAG, "Command channel fully connected " + this); - break; - default: - if (wrappedHandler != null) { - wrappedHandler.handleMessage(msg); - } - break; - } - } - }; - - channel.connect(mContext, handler, messenger); - mLooper.dispatchAll(); - } - - private void registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger) { - registerAsyncChannel(consumer, messenger, null /* wrappedHandler */); + private void validateConnectionInfo() { + // The WifiInfo#equals returns false for pre-S, don't enforce the check. + if (!SdkLevel.isAtLeastS()) return; + if (mClientModeManager.getRole() == ROLE_CLIENT_PRIMARY) { + assertEquals(mCmi.getConnectionInfo(), mPrimaryWifiInfo); + } } private void initializeCmi() throws Exception { @@ -774,7 +771,6 @@ public class ClientModeImplTest extends WifiBaseTest { WIFI_IFACE_NAME, mClientModeManager, mCmiMonitor, mBroadcastQueue, mWifiNetworkSelector, mTelephonyManager, mWifiInjector, mSettingsConfigStore, false, mWifiNotificationManager); - mCmi.mInsecureEapNetworkHandler = mInsecureEapNetworkHandler; mWifiCoreThread = getCmiHandlerThread(mCmi); @@ -794,6 +790,7 @@ public class ClientModeImplTest extends WifiBaseTest { verify(mWifiLastResortWatchdog, atLeastOnce()).clearAllFailureCounts(); assertEquals("DisconnectedState", getCurrentState().getName()); + validateConnectionInfo(); verify(mContext, atLeastOnce()).registerReceiver( mScreenStateBroadcastReceiverCaptor.capture(), @@ -1112,6 +1109,7 @@ public class ClientModeImplTest extends WifiBaseTest { assertNull(mCmi.getConnectedWifiConfiguration()); triggerConnect(); + validateConnectionInfo(); assertNotNull(mCmi.getConnectingWifiConfiguration()); assertNull(mCmi.getConnectedWifiConfiguration()); @@ -1136,12 +1134,15 @@ public class ClientModeImplTest extends WifiBaseTest { new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, SupplicantState.ASSOCIATED)); mLooper.dispatchAll(); + validateConnectionInfo(); WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); + // WifiInfo should be updated if it is primary + validateConnectionInfo(); verify(mWifiMetrics).noteFirstL2ConnectionAfterBoot(true); @@ -1153,6 +1154,7 @@ public class ClientModeImplTest extends WifiBaseTest { new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, SupplicantState.COMPLETED)); mLooper.dispatchAll(); + validateConnectionInfo(); assertEquals("L3ProvisioningState", getCurrentState().getName()); verify(mContext).sendStickyBroadcastAsUser( @@ -1235,6 +1237,7 @@ public class ClientModeImplTest extends WifiBaseTest { verify(mWifiMetrics).setConnectionMaxSupportedLinkSpeedMbps(WIFI_IFACE_NAME, 90, 80); assertEquals(90, wifiInfo.getMaxSupportedTxLinkSpeedMbps()); verify(mWifiMetrics).noteFirstL3ConnectionAfterBoot(true); + validateConnectionInfo(); } private void setupEapSimConnection() throws Exception { @@ -1258,7 +1261,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); assertEquals("L3ProvisioningState", getCurrentState().getName()); } @@ -1285,7 +1288,7 @@ public class ClientModeImplTest extends WifiBaseTest { // send NETWORK_CONNECTION_EVENT for previous network ID mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, new NetworkConnectionEventInfo( - FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); // should ignore it, stay in L2ConnectingState @@ -1296,7 +1299,7 @@ public class ClientModeImplTest extends WifiBaseTest { NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(config.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, new NetworkConnectionEventInfo( - OTHER_NETWORK_ID, wifiSsid, TEST_BSSID_STR1, false)); + OTHER_NETWORK_ID, wifiSsid, TEST_BSSID_STR1, false, null)); mLooper.dispatchAll(); // then move to next state @@ -1444,7 +1447,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); verify(mWifiNative).getEapAnonymousIdentity(any()); @@ -1498,7 +1501,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); verify(mWifiNative).getEapAnonymousIdentity(any()); @@ -1560,7 +1563,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); verify(mWifiNative).getEapAnonymousIdentity(any()); @@ -1619,7 +1622,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); verify(mWifiNative).getEapAnonymousIdentity(any()); @@ -1683,7 +1686,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); verify(mWifiNative).getEapAnonymousIdentity(any()); @@ -2097,6 +2100,34 @@ public class ClientModeImplTest extends WifiBaseTest { } /** + * If the interface has been switched to scan, the network disconnection event should clear the + * current network. + * @throws Exception + */ + @Test + public void testNetworkDisconnectAfterInterfaceSwitchedToScan() throws Exception { + triggerConnect(); + IActionListener connectActionListener = mock(IActionListener.class); + mCmi.connectNetwork( + new NetworkUpdateResult(FRAMEWORK_NETWORK_ID), + new ActionListenerWrapper(connectActionListener), + Binder.getCallingUid(), OP_PACKAGE_NAME); + mLooper.dispatchAll(); + verify(connectActionListener).onSuccess(); + + when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); + // Disconnection from previous network. + DisconnectEventInfo disconnectEventInfo = + new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false); + mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo); + mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, + new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, + SupplicantState.DISCONNECTED)); + mLooper.dispatchAll(); + verify(mActiveModeWarden).setCurrentNetwork(null); + } + + /** * If caller tries to connect to a new network while still provisioning the current one, * the connection attempt should succeed. */ @@ -2109,7 +2140,7 @@ public class ClientModeImplTest extends WifiBaseTest { startConnectSuccess(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -2154,7 +2185,7 @@ public class ClientModeImplTest extends WifiBaseTest { startConnectSuccess(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -2234,7 +2265,7 @@ public class ClientModeImplTest extends WifiBaseTest { mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID); @@ -2794,18 +2825,26 @@ public class ClientModeImplTest extends WifiBaseTest { } @Test - public void testSyncGetCurrentNetwork() throws Exception { - // syncGetCurrentNetwork() returns null when disconnected - mLooper.startAutoDispatch(); - assertNull(mCmi.syncGetCurrentNetwork()); - mLooper.stopAutoDispatch(); - + public void testGetCurrentNetwork() throws Exception { + // getCurrentNetwork() returns null when disconnected + assertNull(mCmi.getCurrentNetwork()); connect(); - // syncGetCurrentNetwork() returns non-null Network when connected - mLooper.startAutoDispatch(); - assertEquals(mNetwork, mCmi.syncGetCurrentNetwork()); - mLooper.stopAutoDispatch(); + assertEquals("L3ConnectedState", getCurrentState().getName()); + // getCurrentNetwork() returns non-null Network when connected + assertEquals(mNetwork, mCmi.getCurrentNetwork()); + // Now trigger disconnect + mCmi.disconnect(); + DisconnectEventInfo disconnectEventInfo = + new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false); + mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo); + mLooper.dispatchAll(); + mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, + new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID), + TEST_BSSID_STR, SupplicantState.DISCONNECTED)); + mLooper.dispatchAll(); + assertEquals("DisconnectedState", getCurrentState().getName()); + assertNull(mCmi.getCurrentNetwork()); } /** @@ -2829,7 +2868,7 @@ public class ClientModeImplTest extends WifiBaseTest { getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult()); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -3021,9 +3060,6 @@ public class ClientModeImplTest extends WifiBaseTest { @Test public void testWifiInfoCleanedUpEnteringExitingConnectableState2() throws Exception { - String initialBSSID = "aa:bb:cc:dd:ee:ff"; - InOrder inOrderMetrics = inOrder(mWifiMetrics); - // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, @@ -3054,7 +3090,7 @@ public class ClientModeImplTest extends WifiBaseTest { /** * Test that connected SSID and BSSID are exposed to system server. - * Also tests that {@link ClientModeImpl#syncRequestConnectionInfo()} always + * Also tests that {@link ClientModeImpl#getConnectionInfo()} always * returns a copy of WifiInfo. */ @Test @@ -3065,10 +3101,7 @@ public class ClientModeImplTest extends WifiBaseTest { assertEquals(TEST_BSSID_STR, wifiInfo.getBSSID()); assertEquals(TEST_WIFI_SSID, wifiInfo.getWifiSsid()); - mLooper.startAutoDispatch(); - WifiInfo connectionInfo = mCmi.syncRequestConnectionInfo(); - mLooper.stopAutoDispatch(); - + WifiInfo connectionInfo = mCmi.getConnectionInfo(); assertEquals(wifiInfo.getSSID(), connectionInfo.getSSID()); assertEquals(wifiInfo.getBSSID(), connectionInfo.getBSSID()); assertEquals(wifiInfo.getMacAddress(), connectionInfo.getMacAddress()); @@ -3150,7 +3183,7 @@ public class ClientModeImplTest extends WifiBaseTest { mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, null, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, null, false, null)); mLooper.dispatchAll(); verify(mWifiConfigManager).clearRecentFailureReason(eq(0)); verify(mWifiConfigManager, never()).setRecentFailureAssociationStatus(anyInt(), anyInt()); @@ -3393,6 +3426,7 @@ public class ClientModeImplTest extends WifiBaseTest { mCmi.enableRssiPolling(true); connect(); mLooper.dispatchAll(); + assertRssiChangeBroadcastSent(); when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333); mLooper.dispatchAll(); WifiInfo wifiInfo = mWifiInfo; @@ -4554,7 +4588,7 @@ public class ClientModeImplTest extends WifiBaseTest { Pair.create("aaa", "bbb")); // Now send a network connection (indicating a roam) event mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false, null)); mLooper.dispatchAll(); inOrder.verify(mIpClient).updateLayer2Information(any()); @@ -4633,7 +4667,7 @@ public class ClientModeImplTest extends WifiBaseTest { when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) .thenReturn(TEST_GLOBAL_MAC_ADDRESS.toString()); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress()); } @@ -4654,7 +4688,7 @@ public class ClientModeImplTest extends WifiBaseTest { when(mWifiNative.getMacAddress(WIFI_IFACE_NAME)) .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString()); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress()); } @@ -5018,7 +5052,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -5100,7 +5134,7 @@ public class ClientModeImplTest extends WifiBaseTest { * when both Tx and Rx link speed are unavailable. */ @Test - public void verifyNetworkCapabilitiesForSpecificRequest() throws Exception { + public void verifyNetworkCapabilitiesForSpecificRequestWithInternet() throws Exception { mWifiInfo.setFrequency(2437); when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(30_000); when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(40_000); @@ -5147,6 +5181,58 @@ public class ClientModeImplTest extends WifiBaseTest { } /** + * Verify that we set the INTERNET capability in the network agent when connected + * as a result of the new network which indicate the internet capabilites should be set. + */ + @Test + public void verifyNetworkCapabilitiesForSpecificRequest() throws Exception { + mWifiInfo.setFrequency(2437); + when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(30_000); + when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(40_000); + when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any())) + .thenReturn(Set.of(TEST_UID)); + when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any())) + .thenReturn(Pair.create(TEST_UID, OP_PACKAGE_NAME)); + when(mWifiNetworkFactory.shouldHaveInternetCapabilities()).thenReturn(true); + // Simulate the first connection. + connectWithValidInitRssi(-42); + ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor = + ArgumentCaptor.forClass(NetworkCapabilities.class); + + verify(mWifiInjector).makeWifiNetworkAgent( + networkCapabilitiesCaptor.capture(), any(), any(), any(), any()); + + NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue(); + assertNotNull(networkCapabilities); + + // should not have internet capability. + assertTrue(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)); + + NetworkSpecifier networkSpecifier = networkCapabilities.getNetworkSpecifier(); + assertTrue(networkSpecifier instanceof WifiNetworkAgentSpecifier); + WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier = + (WifiNetworkAgentSpecifier) networkSpecifier; + + // createNetworkAgentSpecifier does not write the BSSID to the current wifi configuration. + WifiConfiguration expectedConfig = new WifiConfiguration( + mCmi.getConnectedWifiConfiguration()); + expectedConfig.BSSID = TEST_BSSID_STR; + WifiNetworkAgentSpecifier expectedWifiNetworkAgentSpecifier = + new WifiNetworkAgentSpecifier(expectedConfig, ScanResult.WIFI_BAND_24_GHZ, + true /* matchLocalOnlySpecifiers */); + assertEquals(expectedWifiNetworkAgentSpecifier, wifiNetworkAgentSpecifier); + if (SdkLevel.isAtLeastS()) { + assertEquals(Set.of(new Range<Integer>(TEST_UID, TEST_UID)), + networkCapabilities.getUids()); + } else { + assertEquals(TEST_UID, networkCapabilities.getRequestorUid()); + assertEquals(OP_PACKAGE_NAME, networkCapabilities.getRequestorPackageName()); + } + assertEquals(30_000, networkCapabilities.getLinkUpstreamBandwidthKbps()); + assertEquals(40_000, networkCapabilities.getLinkDownstreamBandwidthKbps()); + } + + /** * Verifies that no RSSI change broadcast should be sent */ private void failOnRssiChangeBroadcast() throws Exception { @@ -5166,6 +5252,26 @@ public class ClientModeImplTest extends WifiBaseTest { } return null; }).when(mContext).sendBroadcastAsUser(any(), any(), anyString()); + + doAnswer(invocation -> { + final Intent intent = invocation.getArgument(0); + if (WifiManager.RSSI_CHANGED_ACTION.equals(intent.getAction())) { + fail("Should not send RSSI_CHANGED broadcast!"); + } + return null; + }).when(mContext).sendBroadcastAsUser(any(), any(), anyString(), any()); + } + + /** + * Verifies that RSSI change broadcast is sent. + */ + private void assertRssiChangeBroadcastSent() throws Exception { + ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mContext).sendBroadcastAsUser(intentCaptor.capture(), + eq(UserHandle.ALL), eq(Manifest.permission.ACCESS_WIFI_STATE), any()); + Intent intent = intentCaptor.getValue(); + assertNotNull(intent); + assertEquals(WifiManager.RSSI_CHANGED_ACTION, intent.getAction()); } /** @@ -5405,6 +5511,18 @@ public class ClientModeImplTest extends WifiBaseTest { assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress()); verify(mSettingsConfigStore).get(WIFI_STA_FACTORY_MAC_ADDRESS); + // Verify secondary MAC is not stored + verify(mSettingsConfigStore, never()).put( + eq(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS), any()); + verify(mSettingsConfigStore, never()).get(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS); + + // Query again as secondary STA, and then verify the result is saved to secondary. + when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED); + mCmi.getFactoryMacAddress(); + verify(mWifiNative).getStaFactoryMacAddress(WIFI_IFACE_NAME); + verify(mSettingsConfigStore).put(eq(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS), any()); + verify(mSettingsConfigStore).get(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS); + verifyNoMoreInteractions(mWifiNative, mSettingsConfigStore); } @@ -5702,7 +5820,7 @@ public class ClientModeImplTest extends WifiBaseTest { startConnectSuccess(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -6151,7 +6269,7 @@ public class ClientModeImplTest extends WifiBaseTest { verify(mWifiMetrics, times(1)).incrementConnectRequestWithFilsAkmCount(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, true)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, true, null)); mLooper.dispatchAll(); verify(mWifiMetrics, times(1)).incrementL2ConnectionThroughFilsAuthCount(); @@ -6438,7 +6556,7 @@ public class ClientModeImplTest extends WifiBaseTest { startConnectSuccess(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -6637,6 +6755,41 @@ public class ClientModeImplTest extends WifiBaseTest { } @Test + public void testIpReachabilityFailureRoamL3ProvisioningState_recreateIpClient() + throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + connect(); + expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { }); + reset(mWifiNetworkAgent); + + // Save current IpClientCallbacks instance and verify the onProvisioningFailure + // from this instance won't trigger wifi disconnection after recreating a new + // IpClient and IpClientCallbacks in WaitBeforeL3ProvisioningState. + final IpClientCallbacks callback = mIpClientCallback; + + // Trigger ip reachability failure and ensure we do not trigger a disconnect. + ReachabilityLossInfoParcelable lossInfo = + new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ROAM); + callback.onReachabilityFailure(lossInfo); + mLooper.dispatchAll(); + verify(mWifiNetworkAgent).unregisterAfterReplacement(anyInt()); + verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME); + assertEquals("L3ProvisioningState", getCurrentState().getName()); + + // Verify that onProvisioningFailure from the legacy IpClientCallbacks instance + // doesn't trigger wifi disconnection. + callback.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME); + + // Verify that onProvisioningFailure from the current IpClientCallbacks instance + // triggers wifi disconnection. + mIpClientCallback.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + verify(mWifiNative).disconnect(WIFI_IFACE_NAME); + } + + @Test public void testIpReachabilityLostAndRoamEventsRace() throws Exception { connect(); expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { }); @@ -6650,7 +6803,7 @@ public class ClientModeImplTest extends WifiBaseTest { // Now send a network connection (indicating a roam) event before we get the disconnect // event. mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); // ensure that we ignored the transient roam while we're disconnecting. verifyNoMoreInteractions(mWifiNetworkAgent); @@ -6932,7 +7085,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSsid wifiSsid = WifiSsid.fromBytes( NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); assertEquals("L3ProvisioningState", getCurrentState().getName()); } @@ -6963,7 +7116,7 @@ public class ClientModeImplTest extends WifiBaseTest { // Now send a network connection (indicating a roam) event mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false, null)); mLooper.dispatchAll(); verify(mContext, times(2)).sendStickyBroadcastAsUser( @@ -7136,7 +7289,7 @@ public class ClientModeImplTest extends WifiBaseTest { startConnectSuccess(); mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -8389,7 +8542,7 @@ public class ClientModeImplTest extends WifiBaseTest { } mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false)); + new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null)); mLooper.dispatchAll(); mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, @@ -8607,7 +8760,11 @@ public class ClientModeImplTest extends WifiBaseTest { private void setScanResultWithMloInfo() { List<MloLink> mloLinks = new ArrayList<>(); MloLink link1 = new MloLink(); + link1.setApMacAddress(MacAddress.fromString(TEST_BSSID_STR)); + link1.setLinkId(TEST_MLO_LINK_ID); MloLink link2 = new MloLink(); + link2.setApMacAddress(MacAddress.fromString(TEST_BSSID_STR1)); + link2.setLinkId(TEST_MLO_LINK_ID_1); mloLinks.add(link1); mloLinks.add(link2); @@ -8620,6 +8777,8 @@ public class ClientModeImplTest extends WifiBaseTest { } private void setScanResultWithoutMloInfo() { + mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11AC; + when(mScanResult.getApMldMacAddress()).thenReturn(null); when(mScanResult.getApMloLinkId()).thenReturn(MloLink.INVALID_MLO_LINK_ID); when(mScanResult.getAffiliatedMloLinks()).thenReturn(Collections.emptyList()); @@ -8634,6 +8793,35 @@ public class ClientModeImplTest extends WifiBaseTest { validateSuccessfulConnectSequence(config); } + private void setConnectionMloLinksInfo() { + mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE; + WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo(); + info.links = new WifiNative.ConnectionMloLink[2]; + info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, + TEST_MLO_LINK_ADDR, Byte.MIN_VALUE, Byte.MAX_VALUE); + info.links[1] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID_1, TEST_MLO_LINK_ADDR_1, + Byte.MAX_VALUE, Byte.MIN_VALUE); + when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info); + } + + /** + * Verify Affiliated link BSSID matching + */ + @Test + public void testAffiliatedLinkBssidMatch() throws Exception { + setConnection(); + setScanResultWithMloInfo(); + // Associate + mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, + new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, + SupplicantState.ASSOCIATED)); + mLooper.dispatchAll(); + // Validate Affiliated BSSID match + assertTrue(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR))); + assertTrue(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR1))); + assertFalse(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR2))); + } + /** * Verify MLO parameters update from ScanResult at association */ @@ -8646,9 +8834,7 @@ public class ClientModeImplTest extends WifiBaseTest { SupplicantState.ASSOCIATED)); mLooper.dispatchAll(); - mLooper.startAutoDispatch(); - WifiInfo connectionInfo = mCmi.syncRequestConnectionInfo(); - mLooper.stopAutoDispatch(); + WifiInfo connectionInfo = mCmi.getConnectionInfo(); assertNotNull(connectionInfo.getApMldMacAddress()); assertEquals(TEST_AP_MLD_MAC_ADDRESS_STR, connectionInfo.getApMldMacAddress().toString()); assertEquals(TEST_MLO_LINK_ID, connectionInfo.getApMloLinkId()); @@ -8664,16 +8850,13 @@ public class ClientModeImplTest extends WifiBaseTest { connect(); setScanResultWithMloInfo(); - // Roam to a MLD AP + // Roam to an MLD AP mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, SupplicantState.ASSOCIATED)); mLooper.dispatchAll(); - mLooper.startAutoDispatch(); - WifiInfo connectionInfo = mCmi.syncRequestConnectionInfo(); - mLooper.stopAutoDispatch(); - + WifiInfo connectionInfo = mCmi.getConnectionInfo(); assertNotNull(connectionInfo.getApMldMacAddress()); assertEquals(TEST_AP_MLD_MAC_ADDRESS_STR, connectionInfo.getApMldMacAddress().toString()); assertEquals(TEST_MLO_LINK_ID, connectionInfo.getApMloLinkId()); @@ -8686,15 +8869,97 @@ public class ClientModeImplTest extends WifiBaseTest { SupplicantState.ASSOCIATED)); mLooper.dispatchAll(); - mLooper.startAutoDispatch(); - connectionInfo = mCmi.syncRequestConnectionInfo(); - mLooper.stopAutoDispatch(); + connectionInfo = mCmi.getConnectionInfo(); assertNull(connectionInfo.getApMldMacAddress()); assertEquals(MloLink.INVALID_MLO_LINK_ID, connectionInfo.getApMloLinkId()); assertTrue(connectionInfo.getAffiliatedMloLinks().isEmpty()); } /** + * Verify API calls on affiliated BSSIDs during association and disconnect. + */ + @Test + public void verifyAffiliatedBssidsAssocDisconnect() throws Exception { + List<String> affiliatedBssids = Arrays.asList(TEST_BSSID_STR1); + + connect(); + setScanResultWithMloInfo(); + setConnectionMloLinksInfo(); + mLooper.dispatchAll(); + + // Association + mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, + new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, + SupplicantState.ASSOCIATED)); + mLooper.dispatchAll(); + verify(mWifiBlocklistMonitor).setAffiliatedBssids(eq(TEST_BSSID_STR), eq(affiliatedBssids)); + + // Disconnect + DisconnectEventInfo disconnectEventInfo = + new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false); + mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo); + mLooper.dispatchAll(); + verify(mWifiBlocklistMonitor).removeAffiliatedBssids(eq(TEST_BSSID_STR)); + } + + private void configureMloLinksInfoWithIdleLinks() { + mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE; + WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo(); + info.links = new WifiNative.ConnectionMloLink[2]; + info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, + TEST_MLO_LINK_ADDR, (byte) 0xFF, (byte) 0xFF); + info.links[1] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID_1, TEST_MLO_LINK_ADDR_1, + (byte) 0, (byte) 0); + when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info); + } + + private void reconfigureMloLinksInfoWithOneLink() { + mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE; + WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo(); + info.links = new WifiNative.ConnectionMloLink[1]; + info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, + TEST_MLO_LINK_ADDR, (byte) 0xFF, (byte) 0xFF); + when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info); + } + + @Test + public void verifyMloLinkChangeTidToLinkMapping() throws Exception { + // Initialize + connect(); + setScanResultWithMloInfo(); + setConnectionMloLinksInfo(); + mLooper.dispatchAll(); + + // Association + mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, + new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, + SupplicantState.ASSOCIATED)); + mLooper.dispatchAll(); + // Make sure all links are active + for (MloLink link: mWifiInfo.getAffiliatedMloLinks()) { + assertEquals(link.getState(), MloLink.MLO_LINK_STATE_ACTIVE); + } + + // TID to link mapping. Make sure one link is IDLE. + configureMloLinksInfoWithIdleLinks(); + mCmi.sendMessage(WifiMonitor.MLO_LINKS_INFO_CHANGED, + WifiMonitor.MloLinkInfoChangeReason.TID_TO_LINK_MAP); + mLooper.dispatchAll(); + List<MloLink> links = mWifiInfo.getAffiliatedMloLinks(); + assertEquals(links.get(0).getState(), MloLink.MLO_LINK_STATE_ACTIVE); + assertEquals(links.get(1).getState(), MloLink.MLO_LINK_STATE_IDLE); + + // LInk Removal. Make sure removed link is UNASSOCIATED. + reconfigureMloLinksInfoWithOneLink(); + mCmi.sendMessage(WifiMonitor.MLO_LINKS_INFO_CHANGED, + WifiMonitor.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL); + mLooper.dispatchAll(); + links = mWifiInfo.getAffiliatedMloLinks(); + assertEquals(links.get(0).getState(), MloLink.MLO_LINK_STATE_ACTIVE); + assertEquals(links.get(1).getState(), MloLink.MLO_LINK_STATE_UNASSOCIATED); + } + + /** * Verify that an event that occurs on a managed network is handled by * logEventIfManagedNetwork. */ @@ -9101,4 +9366,42 @@ public class ClientModeImplTest extends WifiBaseTest { isWpa2Wpa3EnterpriseTransitionNetworkInRange, isWpa3EnterpriseOnlyNetworkInRange, shouldDropRequest); } + + @Test + public void testUpdateAkmByConnectionInfo() throws Exception { + mConnectedNetwork = spy(WifiConfigurationTestUtil.createPskSaeNetwork()); + + triggerConnect(); + + // WifiInfo is not updated yet. + assertEquals(WifiInfo.SECURITY_TYPE_UNKNOWN, mWifiInfo.getCurrentSecurityType()); + + WifiSsid wifiSsid = WifiSsid.fromBytes( + NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); + BitSet akm = new BitSet(); + akm.set(WifiConfiguration.KeyMgmt.SAE); + mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, akm)); + mLooper.dispatchAll(); + // WifiInfo is updated to the actual used type. + assertEquals(WifiInfo.SECURITY_TYPE_SAE, mWifiInfo.getCurrentSecurityType()); + + // Roam to a PSK BSS. + akm.clear(); + akm.set(WifiConfiguration.KeyMgmt.WPA_PSK); + mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, akm)); + mLooper.dispatchAll(); + // WifiInfo is updated to the actual used type. + assertEquals(WifiInfo.SECURITY_TYPE_PSK, mWifiInfo.getCurrentSecurityType()); + + // Roam back to a SAE BSS. + akm.clear(); + akm.set(WifiConfiguration.KeyMgmt.SAE); + mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, akm)); + mLooper.dispatchAll(); + // WifiInfo is updated to the actual used type. + assertEquals(WifiInfo.SECURITY_TYPE_SAE, mWifiInfo.getCurrentSecurityType()); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java b/service/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java index 490dc483c6..3884712f51 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ConcreteCandidate.java @@ -35,7 +35,6 @@ public final class ConcreteCandidate implements WifiCandidates.Candidate { private boolean mIsTrusted = true; private boolean mIsOemPaid; private boolean mIsOemPrivate; - private boolean mSecondaryInternet; private boolean mCarrierOrPrivileged; private boolean mIsMetered; private boolean mHasNoInternetAccess; @@ -65,7 +64,6 @@ public final class ConcreteCandidate implements WifiCandidates.Candidate { mIsTrusted = candidate.isTrusted(); mRestricted = candidate.isRestricted(); mIsOemPaid = candidate.isOemPaid(); - mSecondaryInternet = candidate.isSecondaryInternet(); mCarrierOrPrivileged = candidate.isCarrierOrPrivileged(); mIsMetered = candidate.isMetered(); mHasNoInternetAccess = candidate.hasNoInternetAccess(); @@ -166,11 +164,6 @@ public final class ConcreteCandidate implements WifiCandidates.Candidate { return mIsOemPrivate; } - @Override - public boolean isSecondaryInternet() { - return mSecondaryInternet; - } - public ConcreteCandidate setCarrierOrPrivileged(boolean carrierOrPrivileged) { mCarrierOrPrivileged = carrierOrPrivileged; return this; diff --git a/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java index 8ae6cb7131..f79c83c257 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java @@ -61,6 +61,7 @@ import android.telephony.SubscriptionManager; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.RegistrationManager; import android.test.suitebuilder.annotation.SmallTest; +import android.util.LocalLog; import android.util.Log; import com.android.server.wifi.ClientModeManagerBroadcastQueue.QueuedBroadcast; @@ -118,6 +119,7 @@ public class ConcreteClientModeManagerTest extends WifiBaseTest { @Mock DefaultClientModeManager mDefaultClientModeManager; @Mock ClientModeManagerBroadcastQueue mBroadcastQueue; @Mock ActiveModeWarden mActiveModeWarden; + @Mock LocalLog mLocalLog; private RegistrationManager.RegistrationCallback mImsMmTelManagerRegistrationCallback = null; private @RegistrationManager.ImsRegistrationState int mCurrentImsRegistrationState = @@ -247,6 +249,7 @@ public class ConcreteClientModeManagerTest extends WifiBaseTest { when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade); when(mWifiInjector.getWifiDiagnostics()).thenReturn(mWifiDiagnostics); when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); + when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog); mLooper = new TestLooper(); } @@ -278,6 +281,7 @@ public class ConcreteClientModeManagerTest extends WifiBaseTest { // DeferStopHandler(): ConnectivityManager.class verify(mContext).getSystemService(eq(ConnectivityManager.class)); + verify(mContext).getResources(); // Ensure that no public broadcasts were sent. verifyNoMoreInteractions(mContext); @@ -470,6 +474,7 @@ public class ConcreteClientModeManagerTest extends WifiBaseTest { verify(mContext).getSystemService(eq(SubscriptionManager.class)); verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any()); verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any()); + verify(mContext).getResources(); // Ensure that no public broadcasts were sent. verifyNoMoreInteractions(mContext); @@ -630,6 +635,10 @@ public class ConcreteClientModeManagerTest extends WifiBaseTest { when(mClientModeImpl.hasQuit()).thenReturn(true); mClientModeManager.onClientModeImplQuit(); verify(mListener).onStopped(mClientModeManager); + + mClientModeManager.stop(); + mLooper.dispatchAll(); + verify(mWifiNative, never()).teardownInterface(TEST_INTERFACE_NAME); } /** @@ -638,11 +647,11 @@ public class ConcreteClientModeManagerTest extends WifiBaseTest { @Test public void noCallbackOnInterfaceDestroyedWhenAlreadyStopped() throws Exception { startClientInConnectModeAndVerifyEnabled(); - reset(mListener); mClientModeManager.stop(); mLooper.dispatchAll(); + verify(mWifiNative).teardownInterface(TEST_INTERFACE_NAME); // now trigger interface destroyed and make sure callback doesn't get called mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_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 d9f62e53f0..1b8750e746 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java @@ -23,7 +23,6 @@ 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.HalDeviceManager.START_HAL_RETRY_TIMES; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -38,9 +37,9 @@ import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; @@ -54,31 +53,11 @@ import static org.mockito.Mockito.when; import android.app.test.MockAnswerUtil; import android.content.res.Resources; -import android.hardware.wifi.V1_0.IWifi; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.IWifiP2pIface; -import android.hardware.wifi.V1_0.IWifiRttController; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_5.WifiBand; -import android.hardware.wifi.V1_6.IfaceConcurrencyType; -import android.hardware.wifi.V1_6.WifiRadioCombination; -import android.hardware.wifi.V1_6.WifiRadioCombinationMatrix; -import android.hardware.wifi.V1_6.WifiRadioConfiguration; -import android.hidl.manager.V1_0.IServiceNotification; -import android.hidl.manager.V1_2.IServiceManager; import android.net.wifi.WifiContext; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiScanner; import android.os.Handler; import android.os.HandlerThread; -import android.os.IHwBinder; -import android.os.RemoteException; import android.os.WorkSource; import android.os.test.TestLooper; import android.util.Log; @@ -89,6 +68,14 @@ import androidx.test.filters.SmallTest; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; +import com.android.server.wifi.hal.WifiApIface; +import com.android.server.wifi.hal.WifiChip; +import com.android.server.wifi.hal.WifiHal; +import com.android.server.wifi.hal.WifiHal.WifiInterface; +import com.android.server.wifi.hal.WifiNanIface; +import com.android.server.wifi.hal.WifiP2pIface; +import com.android.server.wifi.hal.WifiRttController; +import com.android.server.wifi.hal.WifiStaIface; import com.android.server.wifi.util.WorkSourceHelper; import com.android.wifi.resources.R; @@ -127,10 +114,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { private static final WorkSource TEST_WORKSOURCE_2 = new WorkSource(452, "com.test.2"); private HalDeviceManager mDut; - @Mock IServiceManager mServiceManagerMock; - @Mock IWifi mWifiMock; - @Mock android.hardware.wifi.V1_5.IWifi mWifiMockV15; - @Mock IWifiRttController mRttControllerMock; + @Mock WifiHal mWifiMock; + @Mock WifiRttController mRttControllerMock; @Mock HalDeviceManager.ManagerStatusListener mManagerStatusListenerMock; @Mock private WifiContext mContext; @Mock private Resources mResources; @@ -138,26 +123,16 @@ public class HalDeviceManagerTest extends WifiBaseTest { @Mock private WifiInjector mWifiInjector; @Mock private SoftApManager mSoftApManager; @Mock private WifiSettingsConfigStore mWifiSettingsConfigStore; + @Mock private InterfaceConflictManager mInterfaceConflictManager; @Mock private WorkSourceHelper mWorkSourceHelper0; @Mock private WorkSourceHelper mWorkSourceHelper1; @Mock private WorkSourceHelper mWorkSourceHelper2; - private android.hardware.wifi.V1_5.IWifiChip mWifiChipV15 = null; - private android.hardware.wifi.V1_6.IWifiChip mWifiChipV16 = null; private TestLooper mTestLooper; private Handler mHandler; - private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor = - ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); - private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = - ArgumentCaptor.forClass(IServiceNotification.Stub.class); - private ArgumentCaptor<IWifiEventCallback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass( - IWifiEventCallback.class); - private ArgumentCaptor<android.hardware.wifi.V1_5.IWifiEventCallback> - mWifiEventCallbackCaptorV15 = ArgumentCaptor.forClass( - android.hardware.wifi.V1_5.IWifiEventCallback.class); + private ArgumentCaptor<WifiHal.Callback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass( + WifiHal.Callback.class); private InOrder mInOrder; @Rule public ErrorCollector collector = new ErrorCollector(); - private WifiStatus mStatusOk; - private WifiStatus mStatusFail; private boolean mIsBridgedSoftApSupported = false; private boolean mIsStaWithBridgedSoftApConcurrencySupported = false; private boolean mWifiUserApprovalRequiredForD2dInterfacePriority = false; @@ -169,52 +144,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { } @Override - protected IWifi getWifiServiceMockable() { + protected WifiHal getWifiHalMockable(WifiContext context, WifiInjector wifiInjector) { return mWifiMock; } @Override - protected android.hardware.wifi.V1_5.IWifi getWifiServiceForV1_5Mockable(IWifi iWifi) { - return (mWifiMockV15 != null) - ? mWifiMockV15 - : null; - } - - @Override - protected IServiceManager getServiceManagerMockable() { - return mServiceManagerMock; - } - - @Override - protected android.hardware.wifi.V1_5.IWifiChip getWifiChipForV1_5Mockable(IWifiChip chip) { - return mWifiChipV15; - } - - @Override - protected android.hardware.wifi.V1_6.IWifiChip getWifiChipForV1_6Mockable(IWifiChip chip) { - return mWifiChipV16; - } - - @Override - protected android.hardware.wifi.V1_5.IWifiApIface getIWifiApIfaceForV1_5Mockable( - IWifiApIface iface) { - if (iface instanceof android.hardware.wifi.V1_5.IWifiApIface) { - return (android.hardware.wifi.V1_5.IWifiApIface) iface; - } - return null; - } - - @Override - protected boolean isBridgedSoftApSupportedMockable() { - return mIsBridgedSoftApSupported; - } - - @Override - protected boolean isStaWithBridgedSoftApConcurrencySupportedMockable() { - return mIsStaWithBridgedSoftApConcurrencySupported; - } - - @Override protected boolean isWaitForDestroyedListenersMockable() { return mWaitForDestroyedListeners; } @@ -227,12 +161,9 @@ public class HalDeviceManagerTest extends WifiBaseTest { mTestLooper = new TestLooper(); mHandler = new Handler(mTestLooper.getLooper()); - // initialize placeholder status objects - mStatusOk = getStatus(WifiStatusCode.SUCCESS); - mStatusFail = getStatus(WifiStatusCode.ERROR_UNKNOWN); - - setupWifiV15(mWifiMock); - + when(mWifiInjector.getInterfaceConflictManager()).thenReturn(mInterfaceConflictManager); + when(mInterfaceConflictManager.needsUserApprovalToDelete(anyInt(), any(), anyInt(), any())) + .thenReturn(false); when(mWifiInjector.makeWsHelper(TEST_WORKSOURCE_0)).thenReturn(mWorkSourceHelper0); when(mWifiInjector.makeWsHelper(TEST_WORKSOURCE_1)).thenReturn(mWorkSourceHelper1); when(mWifiInjector.makeWsHelper(TEST_WORKSOURCE_2)).thenReturn(mWorkSourceHelper2); @@ -247,19 +178,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mWorkSourceHelper2.getWorkSource()).thenReturn(TEST_WORKSOURCE_2); when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore); - when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong())).thenReturn(true); - when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), - any(IServiceNotification.Stub.class))).thenReturn(true); - when(mServiceManagerMock.listManifestByInterface(eq(IWifi.kInterfaceName))) - .thenReturn(new ArrayList(Arrays.asList("default"))); - when(mWifiMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn( - true); - when(mWifiMock.registerEventCallback(any(IWifiEventCallback.class))).thenReturn(mStatusOk); - when(mWifiMock.start()).thenReturn(mStatusOk); - when(mWifiMock.stop()).thenReturn(mStatusOk); + when(mWifiMock.registerEventCallback(any(WifiHal.Callback.class))).thenReturn(true); + when(mWifiMock.start()).thenReturn(WifiHal.WIFI_STATUS_SUCCESS); + when(mWifiMock.stop()).thenReturn(true); when(mWifiMock.isStarted()).thenReturn(true); - when(mWifiMockV15.isStarted()).thenReturn(true); + when(mWifiMock.isInitializationComplete()).thenReturn(true); when(mContext.getResources()).thenReturn(mResources); when(mResources.getBoolean(R.bool.config_wifiBridgedSoftApSupported)) .thenReturn(mIsBridgedSoftApSupported); @@ -288,20 +211,14 @@ public class HalDeviceManagerTest extends WifiBaseTest { /** * Test basic startup flow: - * - IServiceManager registrations - * - IWifi registrations - * - IWifi startup delayed * - Start Wi-Fi -> onStart * - Stop Wi-Fi -> onStop */ @Test public void testStartStopFlow() throws Exception { - TestChipV5 chipMock = new TestChipV5(); - setupWifiChipV15(chipMock); + TestChipV5 chipMock = new HalDeviceManagerTest.TestChipV5(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // act: stop Wi-Fi @@ -316,34 +233,14 @@ public class HalDeviceManagerTest extends WifiBaseTest { } /** - * Test the service manager notification coming in after - * {@link HalDeviceManager#initIWifiIfNecessary()} is already invoked as a part of - * {@link HalDeviceManager#initialize()}. - */ - @Test - public void testServiceRegisterationAfterInitialize() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - - // This should now be ignored since IWifi is already non-null. - mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", true); - - verifyNoMoreInteractions(mManagerStatusListenerMock, mWifiMock, mServiceManagerMock); - } - - /** * Validate that multiple callback registrations are called and that duplicate ones are * only called once. */ @Test public void testMultipleCallbackRegistrations() throws Exception { - TestChipV5 chipMock = new TestChipV5(); - setupWifiChipV15(chipMock); + TestChipV5 chipMock = new HalDeviceManagerTest.TestChipV5(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, mManagerStatusListenerMock); // register another 2 callbacks - one of them twice HalDeviceManager.ManagerStatusListener callback1 = mock( @@ -370,44 +267,28 @@ public class HalDeviceManagerTest extends WifiBaseTest { @Test public void testWifiDeathAndRegistration() throws Exception { TestChipV5 chipMock = new TestChipV5(); - setupWifiChipV15(chipMock); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, mWifiMockV15, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // act: IWifi service death - mDeathRecipientCaptor.getValue().serviceDied(0); + ArgumentCaptor<WifiHal.DeathRecipient> deathRecipientCaptor = + ArgumentCaptor.forClass(WifiHal.DeathRecipient.class); + verify(mWifiMock, atLeastOnce()).initialize(deathRecipientCaptor.capture()); + deathRecipientCaptor.getValue().onDeath(); mTestLooper.dispatchAll(); // verify: getting onStop mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); - // act: service startup - mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", false); - - // verify: initialization of IWifi - mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); - if (null != mWifiMockV15) { - mInOrder.verify(mWifiMockV15).registerEventCallback_1_5( - mWifiEventCallbackCaptorV15.capture()); - } else { - mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); - } - // act: start collector.checkThat(mDut.start(), equalTo(true)); - if (null != mWifiMockV15) { - mWifiEventCallbackCaptorV15.getValue().onStart(); - } else { - mWifiEventCallbackCaptor.getValue().onStart(); - } + mWifiEventCallbackCaptor.getValue().onStart(); mTestLooper.dispatchAll(); // verify: service and callback calls mInOrder.verify(mWifiMock).start(); - mInOrder.verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); + mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); verifyNoMoreInteractions(mManagerStatusListenerMock); } @@ -417,20 +298,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { */ @Test public void testWifiFail() throws Exception { - TestChipV5 chipMock = new TestChipV5(); - setupWifiChipV15(chipMock); + HalDeviceManagerTest.TestChipV5 chipMock = new HalDeviceManagerTest.TestChipV5(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, mWifiMockV15, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // act: IWifi failure - if (null != mWifiMockV15) { - mWifiEventCallbackCaptorV15.getValue().onFailure(mStatusFail); - } else { - mWifiEventCallbackCaptor.getValue().onFailure(mStatusFail); - } + mWifiEventCallbackCaptor.getValue().onFailure(WifiHal.WIFI_STATUS_ERROR_UNKNOWN); mTestLooper.dispatchAll(); // verify: getting onStop @@ -438,16 +312,12 @@ public class HalDeviceManagerTest extends WifiBaseTest { // act: start again collector.checkThat(mDut.start(), equalTo(true)); - if (null != mWifiMockV15) { - mWifiEventCallbackCaptorV15.getValue().onStart(); - } else { - mWifiEventCallbackCaptor.getValue().onStart(); - } + mWifiEventCallbackCaptor.getValue().onStart(); mTestLooper.dispatchAll(); // verify: service and callback calls mInOrder.verify(mWifiMock).start(); - mInOrder.verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); + mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); verifyNoMoreInteractions(mManagerStatusListenerMock); } @@ -463,9 +333,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testCacheMismatchError() throws Exception { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener = mock( @@ -475,7 +343,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener.class); // Request STA - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -488,7 +356,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("STA can't be created", staIface, IsNull.notNullValue()); // Request NAN - IWifiIface nanIface = validateInterfaceSequence(chipMock, + WifiInterface nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV1.STA_CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate @@ -501,17 +369,17 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("NAN can't be created", nanIface, IsNull.notNullValue()); // fiddle with the "chip" by removing the STA - chipMock.interfaceNames.get(IfaceType.STA).remove("wlan0"); + chipMock.interfaceNames.get(WifiChip.IFACE_TYPE_STA).remove("wlan0"); - // now try to request another NAN - IWifiIface nanIface2 = + // Now try to request another NAN. + WifiNanIface nanIface2 = mDut.createNanIface(nanDestroyedListener, mHandler, TEST_WORKSOURCE_0); collector.checkThat("NAN can't be created", nanIface2, IsNull.nullValue()); mTestLooper.dispatchAll(); // verify that Wi-Fi is shut-down: should also get all onDestroyed messages that are // registered (even if they seem out-of-sync to chip) - verify(mWifiMock, times(2)).stop(); + verify(mWifiMock).stop(); verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); verify(staDestroyedListener).onDestroyed(getName(staIface)); verify(nanDestroyedListener).onDestroyed(getName(nanIface)); @@ -542,14 +410,12 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testStartHalRetryUponNotAvailableFailure() throws Exception { // Override the stubbing for mWifiMock in before(). when(mWifiMock.start()) - .thenReturn(getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE)) - .thenReturn(mStatusOk); + .thenReturn(WifiHal.WIFI_STATUS_ERROR_NOT_AVAILABLE) + .thenReturn(WifiHal.WIFI_STATUS_SUCCESS); TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(2, true); } @@ -562,13 +428,12 @@ public class HalDeviceManagerTest extends WifiBaseTest { @Test public void testStartHalRetryFailUponMultipleNotAvailableFailures() throws Exception { // Override the stubbing for mWifiMock in before(). - when(mWifiMock.start()).thenReturn(getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE)); + when(mWifiMock.start()).thenReturn(WifiHal.WIFI_STATUS_ERROR_NOT_AVAILABLE); TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(START_HAL_RETRY_TIMES + 1, false); + mInOrder = inOrder(mWifiMock, chipMock.chip); + executeAndValidateStartupSequence(mDut.START_HAL_RETRY_TIMES + 1, false); } /** @@ -580,40 +445,15 @@ public class HalDeviceManagerTest extends WifiBaseTest { @Test public void testStartHalRetryFailUponTrueFailure() throws Exception { // Override the stubbing for mWifiMock in before(). - when(mWifiMock.start()).thenReturn(getStatus(WifiStatusCode.ERROR_UNKNOWN)); + when(mWifiMock.start()).thenReturn(WifiHal.WIFI_STATUS_ERROR_UNKNOWN); TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip); executeAndValidateStartupSequence(1, false); } /** - * Validate that isSupported() returns true when IServiceManager finds the vendor HAL daemon in - * the VINTF. - */ - @Test - public void testIsSupportedTrue() throws Exception { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15); - executeAndValidateInitializationSequence(); - assertTrue(mDut.isSupported()); - } - - /** - * Validate that isSupported() returns false when IServiceManager does not find the vendor HAL - * daemon in the VINTF. - */ - @Test - public void testIsSupportedFalse() throws Exception { - when(mServiceManagerMock.listManifestByInterface(eq(IWifi.kInterfaceName))) - .thenReturn(new ArrayList()); - mInOrder = inOrder(mServiceManagerMock, mWifiMock); - executeAndValidateInitializationSequence(false); - assertFalse(mDut.isSupported()); - } - - /** * Validate RTT configuration when the callback is registered first and the chip is * configured later - i.e. RTT isn't available immediately. */ @@ -628,9 +468,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // concurrency in this test). ChipMockBase chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // register initial cb: don't expect RTT since chip isn't configured @@ -649,8 +487,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { null, // destroyedListener TEST_WORKSOURCE_0 // requestorWs ); - verify(chipMock.chip).createRttController(any(), any()); - io.verify(cb).onNewRttController(any()); + verify(chipMock.chip).createRttController(); + io.verify(cb).onNewRttController(any(WifiRttController.class)); verifyNoMoreInteractions(cb); } @@ -686,11 +524,9 @@ public class HalDeviceManagerTest extends WifiBaseTest { // STA (which will configure the chip). ChipMockBase chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, @@ -700,35 +536,36 @@ public class HalDeviceManagerTest extends WifiBaseTest { staDestroyedListener, // destroyedListener TEST_WORKSOURCE_0 // requestorWs ); - mInOrder.verify(chipMock.chip, times(0)).createRttController(any(), any()); + mInOrder.verify(chipMock.chip, times(0)).createRttController(); // register initial cb - expect the cb right away mDut.registerRttControllerLifecycleCallback(cb1, mHandler); mTestLooper.dispatchAll(); - verify(chipMock.chip).createRttController(any(), any()); - io1.verify(cb1).onNewRttController(mRttControllerMock); + verify(chipMock.chip).createRttController(); + io1.verify(cb1).onNewRttController(any(WifiRttController.class)); // register a second callback and the first one again mDut.registerRttControllerLifecycleCallback(cb2, mHandler); mDut.registerRttControllerLifecycleCallback(cb1, mHandler); mTestLooper.dispatchAll(); - io2.verify(cb2).onNewRttController(mRttControllerMock); + io2.verify(cb2).onNewRttController(any(WifiRttController.class)); + verify(chipMock.chip, times(1)).createRttController(); // change to AP mode (which for TestChipV1 doesn't allow RTT): trigger onDestroyed for all - doAnswer(new GetBoundIfaceAnswer(false)).when(mRttControllerMock).getBoundIface(any()); - IWifiIface apIface = validateInterfaceSequence(chipMock, + when(mRttControllerMock.validate()).thenReturn(false); + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV1.STA_CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP, "wlan0", TestChipV1.AP_CHIP_MODE_ID, - new IWifiIface[]{staIface}, // tearDownList + new WifiInterface[]{staIface}, // tearDownList apDestroyedListener, // destroyedListener TEST_WORKSOURCE_0, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(staIface), staDestroyedListener) ); mTestLooper.dispatchAll(); - verify(chipMock.chip, times(2)).createRttController(any(), any()); // but returns a null! + verify(chipMock.chip, times(2)).createRttController(); // but returns a null! io1.verify(cb1).onRttControllerDestroyed(); io2.verify(cb2).onRttControllerDestroyed(); @@ -739,15 +576,15 @@ public class HalDeviceManagerTest extends WifiBaseTest { HDM_CREATE_IFACE_STA, "wlan0", TestChipV1.STA_CHIP_MODE_ID, - new IWifiIface[]{apIface}, // tearDownList + new WifiInterface[]{apIface}, // tearDownList null, // destroyedListener TEST_WORKSOURCE_0, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(apIface), apDestroyedListener) ); mTestLooper.dispatchAll(); - verify(chipMock.chip, times(3)).createRttController(any(), any()); - io1.verify(cb1).onNewRttController(mRttControllerMock); - io2.verify(cb2).onNewRttController(mRttControllerMock); + verify(chipMock.chip, times(3)).createRttController(); + io1.verify(cb1).onNewRttController(any(WifiRttController.class)); + io2.verify(cb2).onNewRttController(any(WifiRttController.class)); verifyNoMoreInteractions(cb1, cb2); } @@ -767,11 +604,9 @@ public class HalDeviceManagerTest extends WifiBaseTest { // & create a STA (which will configure the chip). ChipMockBase chipMock = new TestChipV2(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); - IWifiIface sta = validateInterfaceSequence(chipMock, + WifiInterface sta = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, @@ -781,13 +616,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { null, // destroyedListener TEST_WORKSOURCE_0 // requestorWs ); - mInOrder.verify(chipMock.chip, times(0)).createRttController(any(), any()); + mInOrder.verify(chipMock.chip, times(0)).createRttController(); // register initial cb - expect the cb right away mDut.registerRttControllerLifecycleCallback(cb, mHandler); mTestLooper.dispatchAll(); - verify(chipMock.chip).createRttController(any(), any()); - io.verify(cb).onNewRttController(mRttControllerMock); + verify(chipMock.chip).createRttController(); + io.verify(cb).onNewRttController(any(WifiRttController.class)); // create an AP: no mode change for TestChipV2 -> expect no impact on RTT validateInterfaceSequence(chipMock, @@ -802,11 +637,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { ); mTestLooper.dispatchAll(); - doAnswer(new GetBoundIfaceAnswer(false)).when(mRttControllerMock).getBoundIface(any()); + when(mRttControllerMock.validate()).thenReturn(false); chipMock.chipModeIdValidForRtt = -1; mDut.removeIface(sta); mTestLooper.dispatchAll(); - verify(chipMock.chip, times(2)).createRttController(any(), any()); + verify(chipMock.chip, times(2)).createRttController(); io.verify(cb).onRttControllerDestroyed(); verifyNoMoreInteractions(cb); @@ -822,19 +657,17 @@ public class HalDeviceManagerTest extends WifiBaseTest { @Test public void testReplaceRequestorWs() throws Exception { assumeTrue(SdkLevel.isAtLeastS()); - // initialize a test chip & create a P2P (which will configure the chip). + // initialize a test chip & create a STA (which will configure the chip). ChipMockBase chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener p2pDestroyedListener = mock( InterfaceDestroyedListener.class); // create P2P interface from privileged app: should succeed. - IWifiIface p2pIface = validateInterfaceSequence(chipMock, + WifiInterface p2pIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_P2P, @@ -844,7 +677,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { p2pDestroyedListener, // destroyedListener TEST_WORKSOURCE_0 // requestorWs ); - collector.checkThat("P2P was not created", p2pIface, IsNull.notNullValue()); + collector.checkThat("P2P not created", p2pIface, IsNull.notNullValue()); // get NAN interface from a system app: should fail when(mWorkSourceHelper1.getRequestorWsPriority()) @@ -854,7 +687,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertNull("Should not create this NAN", nanDetails); nanDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_NAN, true, TEST_WORKSOURCE_1); assertNull("Should not create this NAN", nanDetails); - IWifiNanIface nanIface = (IWifiNanIface) mDut.createNanIface(null, null, TEST_WORKSOURCE_1); + WifiNanIface nanIface = mDut.createNanIface(null, null, TEST_WORKSOURCE_1); collector.checkThat("not allocated interface", nanIface, IsNull.nullValue()); // Now replace the requestorWs (fg app now) for the P2P iface. @@ -862,55 +695,47 @@ public class HalDeviceManagerTest extends WifiBaseTest { .thenReturn(WorkSourceHelper.PRIORITY_FG_APP); assertTrue(mDut.replaceRequestorWs(p2pIface, TEST_WORKSOURCE_2)); - // get AP interface again from a system app: should succeed now + // get NAN interface again from a system app: should succeed now when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - nanIface = (IWifiNanIface) validateInterfaceSequence(chipMock, + nanIface = (WifiNanIface) validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV1.STA_CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_NAN, "wlan0", TestChipV1.STA_CHIP_MODE_ID, - new IWifiIface[]{p2pIface}, // tearDownList + new WifiInterface[]{p2pIface}, // tearDownList null, // destroyedListener TEST_WORKSOURCE_1, // requestorWs - new InterfaceDestroyedListenerWithIfaceName(getName(p2pIface), p2pDestroyedListener) + new InterfaceDestroyedListenerWithIfaceName( + getName(p2pIface), p2pDestroyedListener) ); collector.checkThat("not allocated interface", nanIface, IsNull.notNullValue()); } /** - * Validate a flow sequence for test chip 2 if the - * |config_wifiUserApprovalRequiredForD2dInterfacePriority| overlay value is true. If enabled, - * interface requests for AP/P2P/NAN should be approved over other AP/P2P/NAN interfaces as - * long as the new requestor's worksource priority is > PRIORITY_BG and they aren't the same - * type. + * Validate a flow sequence for test chip 2 if a new interface is able to delete an existing + * interface with user approval. * * Flow sequence: * - create P2P (privileged app) - * - create NAN (foreground app) - * - tear down NAN - * - create P2P (privileged app) - * - create NAN (background app): should fail. + * - create NAN (foreground app) but cannot delete P2P with user approval: should fail + * - create NAN (foreground app) but can delete P2P with user approval: should succeed */ @Test - public void testInterfaceCreationFlowIfD2dInterfacePriorityOverlayEnabled() throws Exception { + public void testInterfaceCreationFlowIfCanDeleteWithUserApproval() throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)) - .thenReturn(true); mDut = new HalDeviceManagerSpy(); ChipMockBase chipMock = new TestChipV2(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener nanDestroyedListener = mock( InterfaceDestroyedListener.class); // Create P2P interface from privileged app: should succeed. - IWifiIface p2pIface = validateInterfaceSequence(chipMock, + WifiInterface p2pIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV2.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_P2P, @@ -922,153 +747,35 @@ public class HalDeviceManagerTest extends WifiBaseTest { ); collector.checkThat("P2P was not created", p2pIface, IsNull.notNullValue()); - // Check if we can create a new P2P interface from foreground app: should fail. + // Create NAN interface from foreground app: should fail. when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_FG_APP); - List<Pair<Integer, WorkSource>> p2pDetails = mDut.reportImpactToCreateIface( - HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_1); - assertNull("Should not create this P2P", p2pDetails); - - // Create NAN interface from foreground app: should succeed. List<Pair<Integer, WorkSource>> nanDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_NAN, true, TEST_WORKSOURCE_1); + assertNull("Should not create this NAN", nanDetails); + WifiInterface nanIface = mDut.createNanIface(null, null, TEST_WORKSOURCE_1); + collector.checkThat("NAN was created", nanIface, IsNull.nullValue()); + + // Can now delete P2P with user approval + when(mInterfaceConflictManager.needsUserApprovalToDelete(anyInt(), any(), anyInt(), any())) + .thenReturn(true); + + // Can create NAN now. + nanDetails = mDut.reportImpactToCreateIface( + HDM_CREATE_IFACE_NAN, true, TEST_WORKSOURCE_1); assertNotNull("Should create this NAN", nanDetails); - IWifiIface nanIface = validateInterfaceSequence(chipMock, + nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV2.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_NAN, "wlan1", TestChipV2.CHIP_MODE_ID, - new IWifiIface[]{p2pIface}, // tearDownList + new WifiInterface[]{p2pIface}, // tearDownList null, // destroyedListener TEST_WORKSOURCE_1, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(p2pIface), nanDestroyedListener) ); collector.checkThat("NAN was not created", nanIface, IsNull.notNullValue()); - - // Tear down the NAN interface. - mDut.removeIface(nanIface); - mTestLooper.dispatchAll(); - - // Create a new P2P interface from privileged app: should succeed. - p2pIface = validateInterfaceSequence(chipMock, - true, // chipModeValid - TestChipV2.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) - HDM_CREATE_IFACE_P2P, - "wlan0", - TestChipV2.CHIP_MODE_ID, - null, // tearDownList - nanDestroyedListener, // destroyedListener - TEST_WORKSOURCE_0 // requestorWs - ); - collector.checkThat("P2P was not created", p2pIface, IsNull.notNullValue()); - - // Check if we can create a new NAN interface from background app: should fail. - when(mWorkSourceHelper1.getRequestorWsPriority()) - .thenReturn(WorkSourceHelper.PRIORITY_BG); - nanDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_NAN, true, TEST_WORKSOURCE_1); - assertNull("Should not create this NAN", nanDetails); - } - - /** - * Tests that - * {@link HalDeviceManager#needsUserApprovalToDelete(int, WorkSource, int, WorkSource)} returns - * true on the following conditions: - * 1) Requested interface is AP, AP_BRIDGED, P2P, or NAN. - * 2) Existing interface is AP, AP_BRIDGED, P2P, or NAN (but not the same as the requested). - * 3) Requestor worksource has higher priority than PRIORITY_BG. - * 4) Existing worksource is not PRIORITY_INTERNAL. - */ - @Test - public void testShouldShowDialogToDelete() throws Exception { - WorkSourceHelper newWsHelper = mock(WorkSourceHelper.class); - WorkSourceHelper oldWsHelper = mock(WorkSourceHelper.class); - - when(mResources.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)) - .thenReturn(false); - mDut = new HalDeviceManagerSpy(); - - // No dialog if dialogs aren't enabled - when(newWsHelper.getRequestorWsPriority()).thenReturn(WorkSourceHelper.PRIORITY_FG_APP); - when(oldWsHelper.getRequestorWsPriority()).thenReturn(WorkSourceHelper.PRIORITY_FG_APP); - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_P2P, newWsHelper, - HDM_CREATE_IFACE_AP, oldWsHelper)); - - when(mResources.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)) - .thenReturn(true); - mDut = new HalDeviceManagerSpy(); - - // Should show dialog for appropriate types. - - // Requesting AP - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP, newWsHelper, - HDM_CREATE_IFACE_AP, oldWsHelper)); - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP, newWsHelper, - HDM_CREATE_IFACE_AP_BRIDGE, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP, newWsHelper, - HDM_CREATE_IFACE_NAN, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP, newWsHelper, - HDM_CREATE_IFACE_P2P, oldWsHelper)); - - // Requesting AP_BRIDGE - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP_BRIDGE, newWsHelper, - HDM_CREATE_IFACE_AP, oldWsHelper)); - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP_BRIDGE, newWsHelper, - HDM_CREATE_IFACE_AP_BRIDGE, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP_BRIDGE, newWsHelper, - HDM_CREATE_IFACE_NAN, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_AP_BRIDGE, newWsHelper, - HDM_CREATE_IFACE_P2P, oldWsHelper)); - - // Requesting P2P - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_P2P, newWsHelper, - HDM_CREATE_IFACE_AP, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_P2P, newWsHelper, - HDM_CREATE_IFACE_AP_BRIDGE, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_P2P, newWsHelper, - HDM_CREATE_IFACE_NAN, oldWsHelper)); - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_P2P, newWsHelper, - HDM_CREATE_IFACE_P2P, oldWsHelper)); - - // Requesting NAN - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_NAN, newWsHelper, - HDM_CREATE_IFACE_AP, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_NAN, newWsHelper, - HDM_CREATE_IFACE_AP_BRIDGE, oldWsHelper)); - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_NAN, newWsHelper, - HDM_CREATE_IFACE_NAN, oldWsHelper)); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_NAN, newWsHelper, - HDM_CREATE_IFACE_P2P, oldWsHelper)); - - // Foreground should show dialog over Privileged - when(newWsHelper.getRequestorWsPriority()).thenReturn(WorkSourceHelper.PRIORITY_FG_APP); - when(oldWsHelper.getRequestorWsPriority()).thenReturn(WorkSourceHelper.PRIORITY_PRIVILEGED); - assertTrue(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_NAN, newWsHelper, - HDM_CREATE_IFACE_P2P, oldWsHelper)); - - // Foreground should delete Internal without showing dialog - when(oldWsHelper.getRequestorWsPriority()).thenReturn(WorkSourceHelper.PRIORITY_INTERNAL); - assertFalse(mDut.needsUserApprovalToDelete( - HDM_CREATE_IFACE_NAN, newWsHelper, - HDM_CREATE_IFACE_P2P, oldWsHelper)); } ////////////////////////////////////////////////////////////////////////////////////// @@ -1223,15 +930,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( InterfaceDestroyedListener.class); - IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock, + WifiApIface iface = (WifiApIface) validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV1.STA_CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -1302,18 +1007,14 @@ public class HalDeviceManagerTest extends WifiBaseTest { // Setup Wi-Fi TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, staIdl, chipMock.chip); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, staIdl, chipMock.chip); // Start Wi-Fi assertTrue(mDut.start()); // Create STA Iface. - IWifiStaIface staIface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(staIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, staIface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); + WifiStaIface staIface = mock(WifiStaIface.class); + when(staIface.getName()).thenReturn("wlan0"); + doAnswer(new CreateStaIfaceAnswer(chipMock, true, staIface)) + .when(chipMock.chip).createStaIface(); assertEquals(staIface, mDut.createStaIface(staIdl, staIfaceOnDestroyedHandler, TEST_WORKSOURCE_0)); // Remove STA interface @@ -1355,21 +1056,16 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); // start Wi-Fi assertTrue(mDut.start()); // Create STA Iface. - IWifiStaIface staIface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(staIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, staIface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); + WifiStaIface staIface = mock(WifiStaIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName(); + doAnswer(new CreateStaIfaceAnswer(chipMock, true, staIface)) + .when(chipMock.chip).createStaIface(); assertEquals(staIface, mDut.createStaIface(staIdl, staIfaceOnDestroyedHandler, TEST_WORKSOURCE_0)); @@ -1399,9 +1095,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener apIdl = mock( InterfaceDestroyedListener.class); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock, staIdl, apIdl); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock, staIdl, apIdl); // Register listener & start Wi-Fi mDut.registerStatusListener(mManagerStatusListenerMock, null); @@ -1409,13 +1103,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); // Create STA Iface first. - IWifiStaIface staIface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(staIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, staIface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); + WifiStaIface staIface = mock(WifiStaIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName(); + doAnswer(new CreateStaIfaceAnswer(chipMock, true, staIface)) + .when(chipMock.chip).createStaIface(); List<Pair<Integer, WorkSource>> staDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_STA, false, TEST_WORKSOURCE_0); assertTrue("Expecting nothing to destroy on creating STA", staDetails.isEmpty()); @@ -1426,23 +1117,19 @@ public class HalDeviceManagerTest extends WifiBaseTest { mInOrder.verify(chipMock.chip).configureChip(TestChipV1.STA_CHIP_MODE_ID); // Now Create AP Iface. - IWifiApIface apIface = mock(IWifiApIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(apIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.AP)).when(apIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, apIface)).when( - chipMock.chip).createApIface( - any(IWifiChip.createApIfaceCallback.class)); + WifiApIface apIface = mock(WifiApIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(apIface).getName(); + doAnswer(new CreateApIfaceAnswer(chipMock, true, apIface)) + .when(chipMock.chip).createApIface(); List<Pair<Integer, WorkSource>> apDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_AP, false, TEST_WORKSOURCE_0); assertEquals("Should get STA destroy details", 1, apDetails.size()); - assertEquals("Need to destroy the STA", Pair.create(IfaceType.STA, TEST_WORKSOURCE_0), - apDetails.get(0)); + assertEquals("Need to destroy the STA", + Pair.create(WifiChip.IFACE_TYPE_STA, TEST_WORKSOURCE_0), apDetails.get(0)); apDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_0); assertEquals("Should get STA destroy details", 1, apDetails.size()); - assertEquals("Need to destroy the STA", Pair.create(IfaceType.STA, TEST_WORKSOURCE_0), - apDetails.get(0)); + assertEquals("Need to destroy the STA", + Pair.create(WifiChip.IFACE_TYPE_STA, TEST_WORKSOURCE_0), apDetails.get(0)); assertEquals(apIface, mDut.createApIface( CHIP_CAPABILITY_ANY, apIdl, mHandler, TEST_WORKSOURCE_0, false, mSoftApManager)); mInOrder.verify(chipMock.chip).removeStaIface(getName(staIface)); @@ -1479,9 +1166,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener apIdl = mock( InterfaceDestroyedListener.class); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock, staIdl, apIdl); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock, staIdl, apIdl); // Register listener & start Wi-Fi mDut.registerStatusListener(mManagerStatusListenerMock, null); @@ -1489,13 +1174,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); // Create STA Iface first. - IWifiStaIface staIface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(staIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, staIface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); + WifiStaIface staIface = mock(WifiStaIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName(); + doAnswer(new CreateStaIfaceAnswer(chipMock, true, staIface)) + .when(chipMock.chip).createStaIface(); List<Pair<Integer, WorkSource>> staDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_STA, false, TEST_WORKSOURCE_0); assertTrue("Expecting nothing to destroy on creating STA", staDetails.isEmpty()); @@ -1508,25 +1190,21 @@ public class HalDeviceManagerTest extends WifiBaseTest { // Now Create AP Iface. when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_FG_APP); - IWifiApIface apIface = mock(IWifiApIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(apIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.AP)).when(apIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, apIface)).when( - chipMock.chip).createApIface( - any(IWifiChip.createApIfaceCallback.class)); + WifiApIface apIface = mock(WifiApIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(apIface).getName(); + doAnswer(new CreateApIfaceAnswer(chipMock, true, apIface)) + .when(chipMock.chip).createApIface(); List<Pair<Integer, WorkSource>> apDetails = mDut.reportImpactToCreateIface( - HDM_CREATE_IFACE_AP, false, TEST_WORKSOURCE_1); + HDM_CREATE_IFACE_AP, false, TEST_WORKSOURCE_0); assertEquals("Should get STA destroy details", 1, apDetails.size()); - assertEquals("Need to destroy the STA", Pair.create(IfaceType.STA, TEST_WORKSOURCE_0), - apDetails.get(0)); - apDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_1); + assertEquals("Need to destroy the STA", + Pair.create(WifiChip.IFACE_TYPE_STA, TEST_WORKSOURCE_0), apDetails.get(0)); + apDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_0); assertEquals("Should get STA destroy details", 1, apDetails.size()); - assertEquals("Need to destroy the STA", Pair.create(IfaceType.STA, TEST_WORKSOURCE_0), - apDetails.get(0)); + assertEquals("Need to destroy the STA", + Pair.create(WifiChip.IFACE_TYPE_STA, TEST_WORKSOURCE_0), apDetails.get(0)); assertEquals(apIface, mDut.createApIface( - CHIP_CAPABILITY_ANY, apIdl, mHandler, TEST_WORKSOURCE_1, false, mSoftApManager)); + CHIP_CAPABILITY_ANY, apIdl, mHandler, TEST_WORKSOURCE_0, false, mSoftApManager)); mInOrder.verify(chipMock.chip).removeStaIface(getName(staIface)); mInOrder.verify(staIdl).onDestroyed(getName(staIface)); mInOrder.verify(chipMock.chip).configureChip(TestChipV1.AP_CHIP_MODE_ID); @@ -1552,9 +1230,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener idl = mock( InterfaceDestroyedListener.class); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock, idl); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock, idl); // Register listener & start Wi-Fi mDut.registerStatusListener(mManagerStatusListenerMock, null); @@ -1562,47 +1238,32 @@ public class HalDeviceManagerTest extends WifiBaseTest { mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); // Create STA Iface will be failure because null handler. - IWifiStaIface staIface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(staIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, staIface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); + WifiStaIface staIface = mock(WifiStaIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(staIface).getName(); + doAnswer(new CreateStaIfaceAnswer(chipMock, true, staIface)) + .when(chipMock.chip).createStaIface(); assertNull(mDut.createStaIface(idl, null, TEST_WORKSOURCE_0)); // Create AP Iface will be failure because null handler. - IWifiApIface apIface = mock(IWifiApIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(apIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.AP)).when(apIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, apIface)).when( - chipMock.chip).createApIface( - any(IWifiChip.createApIfaceCallback.class)); + WifiApIface apIface = mock(WifiApIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(apIface).getName(); + doAnswer(new CreateApIfaceAnswer(chipMock, true, apIface)) + .when(chipMock.chip).createApIface(); assertNull(mDut.createApIface( CHIP_CAPABILITY_ANY, idl, null, TEST_WORKSOURCE_0, false, mSoftApManager)); // Create NAN Iface will be failure because null handler. - IWifiNanIface nanIface = mock(IWifiNanIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(nanIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.NAN)).when(nanIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, nanIface)).when( - chipMock.chip).createNanIface( - any(IWifiChip.createNanIfaceCallback.class)); + WifiNanIface nanIface = mock(WifiNanIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(nanIface).getName(); + doAnswer(new CreateNanIfaceAnswer(chipMock, true, nanIface)) + .when(chipMock.chip).createNanIface(); assertNull(mDut.createNanIface(idl, null, TEST_WORKSOURCE_0)); // Create P2P Iface will be failure because null handler. - IWifiP2pIface p2pIface = mock(IWifiP2pIface.class); - doAnswer(new GetNameAnswer("wlan0")).when(p2pIface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.P2P)).when(p2pIface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, p2pIface)).when( - chipMock.chip).createP2pIface( - any(IWifiChip.createP2pIfaceCallback.class)); + WifiP2pIface p2pIface = mock(WifiP2pIface.class); + doAnswer(new GetNameAnswer("wlan0")).when(p2pIface).getName(); + doAnswer(new CreateP2pIfaceAnswer(chipMock, true, p2pIface)) + .when(chipMock.chip).createP2pIface(); assertNull(mDut.createP2pIface(idl, null, TEST_WORKSOURCE_0)); // Stop Wi-Fi @@ -1624,15 +1285,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( InterfaceDestroyedListener.class); - IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock, + WifiApIface iface = (WifiApIface) validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV1.AP_CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -1681,9 +1340,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testDuplicateStaRequestsFromLowerPriorityAppTestChipV1() throws Exception { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener1 = mock( @@ -1693,7 +1350,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener.class); // get STA interface (from a privileged app) - IWifiIface staIface1 = validateInterfaceSequence(chipMock, + WifiInterface staIface1 = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -1714,7 +1371,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, staDetails.size()); staDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_1); assertNull("Should not be able to create a new STA", staDetails); - IWifiIface staIface2 = mDut.createStaIface( + WifiInterface staIface2 = mDut.createStaIface( staDestroyedListener2, mHandler, TEST_WORKSOURCE_1); collector.checkThat("STA created", staIface2, IsNull.nullValue()); @@ -1729,9 +1386,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesAllTestChipV1() throws Exception { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -1739,10 +1394,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -1754,9 +1409,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesOneChipTestChipV1() throws Exception { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -1764,10 +1417,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -1779,18 +1432,17 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testCanDeviceSupportCreateTypeComboChipV1() throws Exception { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + chipMock.allowGetCapsBeforeIfaceCreated = false; + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); // Try to query iface support before starting the HAL. Should return false without any // stored static chip info. when(mWifiMock.isStarted()).thenReturn(false); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); }} )); - verify(mWifiMock, never()).getChipIds(any()); + verify(mWifiMock, never()).getChipIds(); when(mWifiMock.isStarted()).thenReturn(true); executeAndValidateStartupSequence(); clearInvocations(mWifiMock); @@ -1811,45 +1463,45 @@ public class HalDeviceManagerTest extends WifiBaseTest { verify(mWifiSettingsConfigStore).put(eq(WifiSettingsConfigStore.WIFI_STATIC_CHIP_INFO), eq(new JSONArray(TestChipV1.STATIC_CHIP_INFO_JSON_STRING).toString())); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); }} )); // AP should now be supported after we read directly from the chip. assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 2); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 2); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.P2P, 1); - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); @@ -1865,9 +1517,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { throws Exception { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); // Try to query iface support before starting the HAL. Should return true with the stored // static chip info. @@ -1875,44 +1525,44 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mWifiSettingsConfigStore.get(WifiSettingsConfigStore.WIFI_STATIC_CHIP_INFO)) .thenReturn(TestChipV1.STATIC_CHIP_INFO_JSON_STRING); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 2); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 2); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.P2P, 1); - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); @@ -1926,15 +1576,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -1978,13 +1626,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV1 chipMock = new TestChipV1(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface. - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -2034,9 +1680,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assumeTrue(SdkLevel.isAtLeastS()); TestChipV2 chipMock = new TestChipV2(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener = mock( @@ -2057,7 +1701,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mClock.getUptimeSinceBootMillis()).thenReturn(15L); when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -2072,7 +1716,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // create P2P (system app) when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface p2pIface = validateInterfaceSequence(chipMock, + WifiInterface p2pIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV2.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_P2P, // ifaceTypeToCreate @@ -2085,13 +1729,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue()); // create NAN (system app) - IWifiIface nanIface = validateInterfaceSequence(chipMock, + WifiInterface nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV2.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate "wlan0", // ifaceName TestChipV2.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{p2pIface}, // tearDownList + new WifiInterface[]{p2pIface}, // tearDownList nanDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName( @@ -2100,7 +1744,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); // create AP (privileged app) - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV2.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -2119,7 +1763,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, staDetails.size()); staDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_0); assertNull("should not be able to create a new STA", staDetails); - IWifiIface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); + WifiInterface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); // request AP2 (system app): should fail @@ -2129,7 +1773,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, apDetails.size()); apDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_0); assertNull("Should not be able to create a new AP", apDetails); - IWifiIface apIface2 = mDut.createApIface( + WifiInterface apIface2 = mDut.createApIface( CHIP_CAPABILITY_ANY, null, null, TEST_WORKSOURCE_0, false, mSoftApManager); collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); @@ -2160,7 +1804,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, staDetails.size()); staDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_0); assertNull("should not create this STA", staDetails); - IWifiIface staIface3 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); + WifiInterface staIface3 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); collector.checkThat("STA3 should not be created", staIface3, IsNull.nullValue()); // create AP (privileged app) - this will destroy the last STA created, i.e. STA2 @@ -2170,7 +1814,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { HDM_CREATE_IFACE_AP, // ifaceTypeToCreate "wlan1", // ifaceName TestChipV2.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{staIface2}, // tearDownList + new WifiInterface[]{staIface2}, // tearDownList apDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs // destroyedInterfacesDestroyedListeners... @@ -2228,9 +1872,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesAllTestChipV2() throws Exception { TestChipV2 chipMock = new TestChipV2(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -2238,10 +1880,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -2253,9 +1895,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesOneChipTestChipV2() throws Exception { TestChipV2 chipMock = new TestChipV2(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -2263,10 +1903,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -2278,89 +1918,87 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testCanDeviceSupportIfaceComboTestChipV2() throws Exception { TestChipV2 chipMock = new TestChipV2(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + 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(TestChipV2.STATIC_CHIP_INFO_JSON_STRING); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); }} )); - verify(mWifiMock, never()).getChipIds(any()); + verify(mWifiMock, never()).getChipIds(); when(mWifiMock.isStarted()).thenReturn(true); executeAndValidateStartupSequence(); clearInvocations(mWifiMock); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 2); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 2); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.P2P, 1); - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.P2P, 1); - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP, 1); - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.P2P, 1); - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.AP, 2); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 2); }} )); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.STA, 2); - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 2); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); @@ -2374,15 +2012,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV2 chipMock = new TestChipV2(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -2397,7 +2033,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // get AP interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV2.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -2459,9 +2095,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assumeTrue(SdkLevel.isAtLeastS()); TestChipV3 chipMock = new TestChipV3(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener = mock( @@ -2482,7 +2116,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mClock.getUptimeSinceBootMillis()).thenReturn(15L); when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -2497,7 +2131,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // create P2P (system app) when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface p2pIface = validateInterfaceSequence(chipMock, + WifiInterface p2pIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV3.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_P2P, // ifaceTypeToCreate @@ -2510,13 +2144,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue()); // create NAN (privileged app): will destroy P2P - IWifiIface nanIface = validateInterfaceSequence(chipMock, + WifiInterface nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV3.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate "wlan0", // ifaceName TestChipV3.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{p2pIface}, // tearDownList + new WifiInterface[]{p2pIface}, // tearDownList nanDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(p2pIface), p2pDestroyedListener) @@ -2524,13 +2158,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); // create AP (privileged app): will destroy NAN - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV3.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate "wlan1", // ifaceName TestChipV3.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{nanIface}, // tearDownList + new WifiInterface[]{nanIface}, // tearDownList apDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(nanIface), nanDestroyedListener) @@ -2545,7 +2179,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, staDetails.size()); staDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_0); assertNull("should not create this STA", staDetails); - IWifiIface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); + WifiInterface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); // request AP2 (system app): should fail @@ -2555,7 +2189,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, apDetails.size()); apDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_0); assertNull("Should not create this AP", apDetails); - IWifiIface apIface2 = mDut.createApIface( + WifiInterface apIface2 = mDut.createApIface( CHIP_CAPABILITY_ANY, null, null, TEST_WORKSOURCE_0, false, mSoftApManager); collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); @@ -2563,15 +2197,15 @@ public class HalDeviceManagerTest extends WifiBaseTest { List<Pair<Integer, WorkSource>> p2pDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_0); assertNull("should not create this p2p", p2pDetails); - p2pIface = mDut.createP2pIface(null, null, TEST_WORKSOURCE_0); - collector.checkThat("P2P should not be created", p2pIface, IsNull.nullValue()); + String p2pIfaceName = mDut.createP2pIface(null, null, TEST_WORKSOURCE_0); + collector.checkThat("P2P should not be created", p2pIfaceName, IsNull.nullValue()); // request P2P (privileged app): should fail p2pDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_2); assertNull("should not create this p2p", p2pDetails); - p2pIface = mDut.createP2pIface(null, null, TEST_WORKSOURCE_2); - collector.checkThat("P2P should not be created", p2pIface, IsNull.nullValue()); + p2pIfaceName = mDut.createP2pIface(null, null, TEST_WORKSOURCE_2); + collector.checkThat("P2P should not be created", p2pIfaceName, IsNull.nullValue()); // tear down AP mDut.removeIface(apIface); @@ -2600,7 +2234,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, staDetails.size()); staDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_0); assertNull("should not create this STA", staDetails); - IWifiIface staIface3 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); + WifiInterface staIface3 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); collector.checkThat("STA3 should not be created", staIface3, IsNull.nullValue()); // create NAN (privileged app): should destroy the last created STA (STA2) @@ -2610,7 +2244,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate "wlan0", // ifaceName TestChipV3.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{staIface2}, // tearDownList + new WifiInterface[]{staIface2}, // tearDownList nanDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName( @@ -2661,9 +2295,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesAllTestChipV3() throws Exception { TestChipV3 chipMock = new TestChipV3(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -2671,10 +2303,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -2686,9 +2318,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesOneChipTestChipV3() throws Exception { TestChipV3 chipMock = new TestChipV3(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -2696,10 +2326,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -2711,15 +2341,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV3 chipMock = new TestChipV3(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -2734,7 +2362,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // get AP interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV3.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -2796,9 +2424,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assumeTrue(SdkLevel.isAtLeastS()); TestChipV4 chipMock = new TestChipV4(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener = mock( @@ -2819,7 +2445,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mClock.getUptimeSinceBootMillis()).thenReturn(15L); when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -2834,7 +2460,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // create P2P (system app) when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface p2pIface = validateInterfaceSequence(chipMock, + WifiInterface p2pIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_P2P, // ifaceTypeToCreate @@ -2847,13 +2473,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue()); // create NAN (privileged app): will destroy P2P - IWifiIface nanIface = validateInterfaceSequence(chipMock, + WifiInterface nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate "wlan0", // ifaceName TestChipV4.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{p2pIface}, // tearDownList + new WifiInterface[]{p2pIface}, // tearDownList nanDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(p2pIface), p2pDestroyedListener) @@ -2861,13 +2487,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("allocated NAN interface", nanIface, IsNull.notNullValue()); // create AP (privileged app): will destroy NAN - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate "wlan1", // ifaceName TestChipV4.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{nanIface}, // tearDownList + new WifiInterface[]{nanIface}, // tearDownList apDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(nanIface), nanDestroyedListener) @@ -2882,7 +2508,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, staDetails.size()); staDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_0); assertNull("should not create this STA", staDetails); - IWifiIface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); + WifiInterface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); // request AP2 (system app): should fail @@ -2892,7 +2518,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, apDetails.size()); apDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_0); assertNull("Should not create this AP", apDetails); - IWifiIface apIface2 = mDut.createApIface( + WifiInterface apIface2 = mDut.createApIface( CHIP_CAPABILITY_ANY, null, null, TEST_WORKSOURCE_0, false, mSoftApManager); collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); @@ -2900,15 +2526,15 @@ public class HalDeviceManagerTest extends WifiBaseTest { List<Pair<Integer, WorkSource>> p2pDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_0); assertNull("should not create this p2p", p2pDetails); - p2pIface = mDut.createP2pIface(null, null, TEST_WORKSOURCE_0); - collector.checkThat("P2P should not be created", p2pIface, IsNull.nullValue()); + String p2pIfaceName = mDut.createP2pIface(null, null, TEST_WORKSOURCE_0); + collector.checkThat("P2P should not be created", p2pIfaceName, IsNull.nullValue()); // request P2P (privileged app): should fail p2pDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_2); assertNull("should not create this p2p", p2pDetails); - p2pIface = mDut.createP2pIface(null, null, TEST_WORKSOURCE_2); - collector.checkThat("P2P should not be created", p2pIface, IsNull.nullValue()); + p2pIfaceName = mDut.createP2pIface(null, null, TEST_WORKSOURCE_2); + collector.checkThat("P2P should not be created", p2pIfaceName, IsNull.nullValue()); // tear down AP mDut.removeIface(apIface); @@ -2967,9 +2593,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assumeFalse(SdkLevel.isAtLeastS()); TestChipV4 chipMock = new TestChipV4(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener = mock( @@ -2987,7 +2611,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener.class); // create STA - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -3000,7 +2624,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("STA interface wasn't created", staIface, IsNull.notNullValue()); // create P2P - IWifiIface p2pIface = validateInterfaceSequence(chipMock, + WifiInterface p2pIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_P2P, // ifaceTypeToCreate @@ -3013,13 +2637,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue()); // create NAN: will destroy P2P - IWifiIface nanIface = validateInterfaceSequence(chipMock, + WifiInterface nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate "wlan0", // ifaceName TestChipV4.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{p2pIface}, // tearDownList + new WifiInterface[]{p2pIface}, // tearDownList nanDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(p2pIface), p2pDestroyedListener) @@ -3027,13 +2651,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); // create AP: will destroy NAN - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate "wlan1", // ifaceName TestChipV4.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{nanIface}, // tearDownList + new WifiInterface[]{nanIface}, // tearDownList apDestroyedListener, // destroyedListener TEST_WORKSOURCE_2, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(nanIface), nanDestroyedListener) @@ -3048,7 +2672,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, staDetails.size()); staDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_0); assertNull("Should not create this STA", staDetails); - IWifiIface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); + WifiInterface staIface2 = mDut.createStaIface(null, null, TEST_WORKSOURCE_0); collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue()); // request AP2: should fail @@ -3058,7 +2682,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(0, apDetails.size()); apDetails = mDut.reportImpactToCreateIface(HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_0); assertNull("Should not create this AP", apDetails); - IWifiIface apIface2 = mDut.createApIface( + WifiInterface apIface2 = mDut.createApIface( CHIP_CAPABILITY_ANY, null, null, TEST_WORKSOURCE_0, false, mSoftApManager); collector.checkThat("AP2 should not be created", apIface2, IsNull.nullValue()); @@ -3066,15 +2690,18 @@ public class HalDeviceManagerTest extends WifiBaseTest { List<Pair<Integer, WorkSource>> p2pDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_0); assertNull("should not create this p2p", p2pDetails); - p2pIface = mDut.createP2pIface(null, null, TEST_WORKSOURCE_0); - collector.checkThat("P2P should not be created", p2pIface, IsNull.nullValue()); + String p2pIfaceName = mDut.createP2pIface(null, null, TEST_WORKSOURCE_0); + collector.checkThat("P2P should not be created", p2pIfaceName, IsNull.nullValue()); // request NAN: should fail List<Pair<Integer, WorkSource>> nanDetails = mDut.reportImpactToCreateIface( HDM_CREATE_IFACE_NAN, true, TEST_WORKSOURCE_0); assertNull("Should not create this nan", nanDetails); - nanIface = mDut.createNanIface(null, null, TEST_WORKSOURCE_0); - collector.checkThat("NAN should not be created", nanIface, IsNull.nullValue()); + // Expect a WifiNanIface wrapper object this time, since we are calling + // createNanIface instead of createIface. + WifiNanIface nanIface2 = + mDut.createNanIface(null, null, TEST_WORKSOURCE_0); + collector.checkThat("NAN should not be created", nanIface2, IsNull.nullValue()); // tear down AP mDut.removeIface(apIface); @@ -3115,9 +2742,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testInterfaceCreationFlowTestChipV3WithInternalRequest() throws Exception { TestChipV3 chipMock = new TestChipV3(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener apDestroyedListener = mock( @@ -3130,7 +2755,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_INTERNAL); // create NAN (privileged app): will destroy P2P - IWifiIface nanIface = validateInterfaceSequence(chipMock, + WifiInterface nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV3.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate @@ -3143,13 +2768,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue()); // create AP (privileged app): will destroy NAN - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV3.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate "wlan1", // ifaceName TestChipV3.CHIP_MODE_ID, // finalChipMode - new IWifiIface[]{nanIface}, // tearDownList + new WifiInterface[]{nanIface}, // tearDownList apDestroyedListener, // destroyedListener TEST_WORKSOURCE_1, // requestorWs new InterfaceDestroyedListenerWithIfaceName(getName(nanIface), nanDestroyedListener) @@ -3193,9 +2818,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesAllTestChipV4() throws Exception { TestChipV4 chipMock = new TestChipV4(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -3203,10 +2826,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -3218,9 +2841,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testGetSupportedIfaceTypesOneChipTestChipV4() throws Exception { TestChipV4 chipMock = new TestChipV4(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // try API @@ -3228,10 +2849,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { // verify results Set<Integer> correctResults = new HashSet<>(); - correctResults.add(IfaceType.AP); - correctResults.add(IfaceType.STA); - correctResults.add(IfaceType.P2P); - correctResults.add(IfaceType.NAN); + correctResults.add(WifiChip.IFACE_TYPE_AP); + correctResults.add(WifiChip.IFACE_TYPE_STA); + correctResults.add(WifiChip.IFACE_TYPE_P2P); + correctResults.add(WifiChip.IFACE_TYPE_NAN); assertEquals(correctResults, results); } @@ -3243,15 +2864,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV4 chipMock = new TestChipV4(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -3266,7 +2885,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // get AP interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -3311,13 +2930,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV4 chipMock = new TestChipV4(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface. - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -3330,7 +2947,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("STA created", staIface, IsNull.notNullValue()); // get AP interface. - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV4.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -3358,23 +2975,15 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void verify60GhzIfaceCreation( ChipMockBase chipMock, int chipModeId, int finalChipModeId, boolean isWigigSupported) throws Exception { - long requiredChipCapabilities = - android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG; + long requiredChipCapabilities = WifiManager.WIFI_FEATURE_INFRA_60G; chipMock.initialize(); - if (mWifiChipV15 != null) { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - } else { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - } - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface staIface; + WifiInterface staIface; if (isWigigSupported) { staIface = validateInterfaceSequence(chipMock, false, // chipModeValid @@ -3401,7 +3010,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // get AP interface from system app. when(mWorkSourceHelper0.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface apIface; + WifiInterface apIface; if (isWigigSupported) { apIface = validateInterfaceSequence(chipMock, true, // chipModeValid @@ -3428,7 +3037,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_PRIVILEGED); assertThat(mDut.isItPossibleToCreateIface(HDM_CREATE_IFACE_P2P, - android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG, + WifiManager.WIFI_FEATURE_INFRA_60G, TEST_WORKSOURCE_1), is(isWigigSupported)); } } @@ -3440,49 +3049,34 @@ public class HalDeviceManagerTest extends WifiBaseTest { @Test public void testIsItPossibleToCreate60GhzIfaceTestChipV5() throws Exception { TestChipV5 chipMock = new TestChipV5(); - setupWifiChipV15(chipMock); verify60GhzIfaceCreation( chipMock, TestChipV5.CHIP_MODE_ID, TestChipV5.CHIP_MODE_ID, true); } /* - * Verify that 60GHz iface creation request could not be procceed by a chip does - * not supports WIGIG on V1.5 HAL. + * Verify that 60GHz iface creation request cannot be processed by a chip that does + * not support WIGIG. */ @Test public void testIsItPossibleToCreate60GhzIfaceTestChipV4() throws Exception { TestChipV4 chipMock = new TestChipV4(); - setupWifiChipV15(chipMock); verify60GhzIfaceCreation( chipMock, TestChipV4.CHIP_MODE_ID, TestChipV4.CHIP_MODE_ID, false); } - /* - * Verify that 60GHz iface creation request could be procceed by a chip does - * not supports WIGIG on a HAL older than v1.5. - */ - @Test - public void testIsItPossibleToCreate60GhzIfaceTestChipV4WithHalOlderThan1_5() throws Exception { - TestChipV4 chipMock = new TestChipV4(); - verify60GhzIfaceCreation( - chipMock, TestChipV4.CHIP_MODE_ID, TestChipV4.CHIP_MODE_ID, true); - } - /** - * Validate creation of AP interface from blank start-up in chip V1.5 + * Validate creation of AP interface from blank start-up. */ @Test public void testCreateApInterfaceNoInitModeTestChipV15() throws Exception { - mWifiChipV15 = mock(android.hardware.wifi.V1_5.IWifiChip.class); runCreateSingleXxxInterfaceNoInitMode(new TestChipV5(), HDM_CREATE_IFACE_AP, "wlan0", TestChipV5.CHIP_MODE_ID); } /** - * Validate creation of AP Bridge interface from blank start-up in chip V1.5 + * Validate creation of AP Bridge interface from blank start-up. */ @Test public void testCreateApBridgeInterfaceNoInitModeTestChipV15() throws Exception { - mWifiChipV15 = mock(android.hardware.wifi.V1_5.IWifiChip.class); mIsBridgedSoftApSupported = true; mIsStaWithBridgedSoftApConcurrencySupported = true; runCreateSingleXxxInterfaceNoInitMode(new TestChipV5(), HDM_CREATE_IFACE_AP_BRIDGE, "wlan0", @@ -3498,18 +3092,15 @@ public class HalDeviceManagerTest extends WifiBaseTest { mIsBridgedSoftApSupported = true; mIsStaWithBridgedSoftApConcurrencySupported = false; TestChipV5 chipMock = new TestChipV5(); - setupWifiChipV15(chipMock); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( InterfaceDestroyedListener.class); // Create the STA - IWifiIface iface = validateInterfaceSequence(chipMock, + WifiInterface iface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, @@ -3536,17 +3127,14 @@ public class HalDeviceManagerTest extends WifiBaseTest { mIsBridgedSoftApSupported = true; mIsStaWithBridgedSoftApConcurrencySupported = true; TestChipV5 chipMock = new TestChipV5(); - setupWifiChipV15(chipMock); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( InterfaceDestroyedListener.class); - IWifiIface iface = validateInterfaceSequence(chipMock, + WifiInterface iface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, @@ -3571,9 +3159,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testCanDeviceSupportIfaceComboTestChipV6() throws Exception { TestChipV6 testChip = new TestChipV6(); testChip.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, testChip.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, testChip.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); @@ -3581,10 +3167,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { .thenReturn(TestChipV6.STATIC_CHIP_INFO_JSON_STRING); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); } })); - verify(mWifiMock, never()).getChipIds(any()); + verify(mWifiMock, never()).getChipIds(); when(mWifiMock.isStarted()).thenReturn(true); executeAndValidateStartupSequence(); @@ -3592,47 +3178,47 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); } })); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); } })); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); } })); assertTrue(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP_BRIDGED, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED, 1); } })); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.AP, 1); - put(IfaceConcurrencyType.AP_BRIDGED, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED, 1); } })); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.STA, 1); - put(IfaceConcurrencyType.AP, 1); - put(IfaceConcurrencyType.AP_BRIDGED, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_STA, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED, 1); } })); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.NAN, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1); } })); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() { { - put(IfaceConcurrencyType.P2P, 2); + put(WifiChip.IFACE_CONCURRENCY_TYPE_P2P, 2); } })); @@ -3645,7 +3231,6 @@ public class HalDeviceManagerTest extends WifiBaseTest { @Test public void testCreateApBridgeInterfaceNoInitModeTestChipV6() throws Exception { TestChipV6 testChip = new TestChipV6(); - setupWifiChipV15(testChip); runCreateSingleXxxInterfaceNoInitMode(testChip, HDM_CREATE_IFACE_AP_BRIDGE, "wlan0", TestChipV6.CHIP_MODE_ID); } @@ -3659,11 +3244,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mIsBridgedSoftApSupported = true; mIsStaWithBridgedSoftApConcurrencySupported = false; TestChipV6 chipMock = new TestChipV6(); - setupWifiChipV15(chipMock); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( @@ -3674,7 +3256,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { bridgedApInstances.add("instance0"); bridgedApInstances.add("instance1"); chipMock.bridgedApInstancesByName.put("wlan0", bridgedApInstances); - IWifiIface iface = validateInterfaceSequence(chipMock, + WifiInterface iface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP_BRIDGE, @@ -3702,25 +3284,23 @@ public class HalDeviceManagerTest extends WifiBaseTest { assertEquals(2, bridgedApInstances.size()); } - private IWifiIface setupDbsSupportTest(ChipMockBase testChip, int onlyChipMode, + private WifiInterface setupDbsSupportTest(ChipMockBase testChip, int onlyChipMode, ImmutableList<ArrayList<Integer>> radioCombinationMatrix) throws Exception { - WifiRadioCombinationMatrix matrix = new WifiRadioCombinationMatrix(); - for (ArrayList<Integer> comb: radioCombinationMatrix) { - WifiRadioCombination combination = new WifiRadioCombination(); - for (Integer b: comb) { - WifiRadioConfiguration config = new WifiRadioConfiguration(); - config.bandInfo = b; - combination.radioConfigurations.add(config); + List<WifiChip.WifiRadioCombination> combos = new ArrayList<>(); + for (ArrayList<Integer> comb : radioCombinationMatrix) { + List<WifiChip.WifiRadioConfiguration> configs = new ArrayList<>(); + for (Integer b : comb) { + configs.add(new WifiChip.WifiRadioConfiguration(b, 0)); } - matrix.radioCombinations.add(combination); + combos.add(new WifiChip.WifiRadioCombination(new ArrayList<>(configs))); } + WifiChip.WifiRadioCombinationMatrix matrix = + new WifiChip.WifiRadioCombinationMatrix(combos); testChip.chipSupportedRadioCombinationsMatrix = matrix; testChip.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, testChip.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, testChip.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener = mock( @@ -3730,7 +3310,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener.class); // Request STA - IWifiIface staIface = validateInterfaceSequence(testChip, + WifiInterface staIface = validateInterfaceSequence(testChip, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // createIfaceType @@ -3743,7 +3323,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("STA can't be created", staIface, IsNull.notNullValue()); // Request P2P - IWifiIface p2pIface = validateInterfaceSequence(testChip, + WifiInterface p2pIface = validateInterfaceSequence(testChip, true, // chipModeValid onlyChipMode, // chipModeId HDM_CREATE_IFACE_P2P, // ifaceTypeToCreate @@ -3766,8 +3346,9 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void test24g5gDbsSupport() throws Exception { TestChipV6 testChip = new TestChipV6(); ImmutableList<ArrayList<Integer>> radioCombinationMatrix = ImmutableList.of( - new ArrayList(Arrays.asList(WifiBand.BAND_24GHZ, WifiBand.BAND_5GHZ))); - IWifiIface iface = setupDbsSupportTest(testChip, TestChipV6.CHIP_MODE_ID, + new ArrayList(Arrays.asList( + WifiScanner.WIFI_BAND_24_GHZ, WifiScanner.WIFI_BAND_5_GHZ))); + WifiInterface iface = setupDbsSupportTest(testChip, TestChipV6.CHIP_MODE_ID, radioCombinationMatrix); assertTrue(mDut.is24g5gDbsSupported(iface)); @@ -3781,8 +3362,9 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void test5g6gDbsSupport() throws Exception { TestChipV6 testChip = new TestChipV6(); ImmutableList<ArrayList<Integer>> radioCombinationMatrix = ImmutableList.of( - new ArrayList(Arrays.asList(WifiBand.BAND_5GHZ, WifiBand.BAND_6GHZ))); - IWifiIface iface = setupDbsSupportTest(testChip, TestChipV6.CHIP_MODE_ID, + new ArrayList(Arrays.asList( + WifiScanner.WIFI_BAND_5_GHZ, WifiScanner.WIFI_BAND_6_GHZ))); + WifiInterface iface = setupDbsSupportTest(testChip, TestChipV6.CHIP_MODE_ID, radioCombinationMatrix); assertFalse(mDut.is24g5gDbsSupported(iface)); @@ -3796,9 +3378,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void test24g5gAnd5g6gDbsSupport() throws Exception { TestChipV6 testChip = new TestChipV6(); ImmutableList<ArrayList<Integer>> radioCombinationMatrix = ImmutableList.of( - new ArrayList(Arrays.asList(WifiBand.BAND_24GHZ, WifiBand.BAND_5GHZ)), - new ArrayList(Arrays.asList(WifiBand.BAND_5GHZ, WifiBand.BAND_6GHZ))); - IWifiIface iface = setupDbsSupportTest(testChip, TestChipV6.CHIP_MODE_ID, + new ArrayList(Arrays.asList( + WifiScanner.WIFI_BAND_24_GHZ, WifiScanner.WIFI_BAND_5_GHZ)), + new ArrayList(Arrays.asList( + WifiScanner.WIFI_BAND_5_GHZ, WifiScanner.WIFI_BAND_6_GHZ))); + WifiInterface iface = setupDbsSupportTest(testChip, TestChipV6.CHIP_MODE_ID, radioCombinationMatrix); assertTrue(mDut.is24g5gDbsSupported(iface)); @@ -3815,13 +3399,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV7 chipMock = new TestChipV7(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get STA interface from privileged app. - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // ifaceTypeToCreate @@ -3871,10 +3453,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { TestChipV8 chipMock = new TestChipV8(); chipMock.initialize(); - setupWifiChipV15(chipMock); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); // get AP_BRIDGED interface for a privileged app. @@ -3882,7 +3461,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { bridgedApInstances.add("instance0"); bridgedApInstances.add("instance1"); chipMock.bridgedApInstancesByName.put("wlan0", bridgedApInstances); - IWifiIface apBridgedIface = validateInterfaceSequence(chipMock, + WifiInterface apBridgedIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP_BRIDGE, // ifaceTypeToCreate @@ -3897,7 +3476,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // get AP interface for a system app. when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_SYSTEM); - IWifiIface apIface = validateInterfaceSequence(chipMock, + WifiInterface apIface = validateInterfaceSequence(chipMock, true, // chipModeValid TestChipV8.CHIP_MODE_ID, // chipModeId HDM_CREATE_IFACE_AP, // ifaceTypeToCreate @@ -3927,11 +3506,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mIsBridgedSoftApSupported = true; mIsStaWithBridgedSoftApConcurrencySupported = false; TestChipV9 chipMock = new TestChipV9(); - setupWifiChipV15(chipMock); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( @@ -3942,7 +3518,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { bridgedApInstances.add("instance0"); bridgedApInstances.add("instance1"); chipMock.bridgedApInstancesByName.put("wlan0", bridgedApInstances); - IWifiIface iface = validateInterfaceSequence(chipMock, + WifiInterface iface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP_BRIDGE, @@ -3974,11 +3550,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mIsBridgedSoftApSupported = true; mIsStaWithBridgedSoftApConcurrencySupported = false; TestChipV9 chipMock = new TestChipV9(); - setupWifiChipV15(chipMock); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( @@ -3989,7 +3562,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { bridgedApInstances.add("instance0"); bridgedApInstances.add("instance1"); chipMock.bridgedApInstancesByName.put("wlan0", bridgedApInstances); - IWifiIface iface = validateInterfaceSequence(chipMock, + WifiInterface iface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_AP_BRIDGE, @@ -4023,18 +3596,17 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void testCanDeviceSupportCreateTypeComboAfterDriverReadyChipV10() throws Exception { TestChipV10 chipMock = new TestChipV10(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + chipMock.allowGetCapsBeforeIfaceCreated = false; + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); // Try to query AP support before starting the HAL. Should return false without any // stored static chip info. when(mWifiMock.isStarted()).thenReturn(false); assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); - verify(mWifiMock, never()).getChipIds(any()); + verify(mWifiMock, never()).getChipIds(); when(mWifiMock.isStarted()).thenReturn(true); // Start the HAL @@ -4042,7 +3614,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // Still can't create AP since driver isn't ready. assertFalse(mDut.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ - put(IfaceConcurrencyType.AP, 1); + put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1); }} )); @@ -4075,9 +3647,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { // Stop and start Wifi and re-initialize the chip to the default available modes. mDut.stop(); chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); // Try creating an AP again -- should succeed since we're using the cached // available modes we loaded from the driver. @@ -4093,106 +3663,15 @@ public class HalDeviceManagerTest extends WifiBaseTest { ); } - /** - * Validate only one Bridged AP can be created with TestChipV11, which supports AP + AP. - */ - @Test - public void testCreateOnlyOneApBridgedInterfaceTestChipV11() throws Exception { - mIsBridgedSoftApSupported = true; - TestChipV11 chipMock = new TestChipV11(); - chipMock.initialize(); - setupWifiChipV15(chipMock); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); - executeAndValidateStartupSequence(); - - // Get the first Bridged AP - ArrayList<String> bridgedApInstances = new ArrayList<>(); - bridgedApInstances.add("instance0"); - bridgedApInstances.add("instance1"); - chipMock.bridgedApInstancesByName.put("wlan0", bridgedApInstances); - IWifiIface apBridgedIface = validateInterfaceSequence(chipMock, - false, // chipModeValid - -1000, // chipModeId (only used if chipModeValid is true) - HDM_CREATE_IFACE_AP_BRIDGE, // ifaceTypeToCreate - "wlan0", // ifaceName - TestChipV11.CHIP_MODE_ID, // finalChipMode - null, // tearDownList - mock(InterfaceDestroyedListener.class), // destroyedListener - TEST_WORKSOURCE_0 // requestorWs - ); - collector.checkThat("Bridged AP not created", apBridgedIface, IsNull.notNullValue()); - - // Should not be able to create a second Bridged AP. - assertNull(mDut.reportImpactToCreateIface( - HDM_CREATE_IFACE_AP_BRIDGE, true, 0, TEST_WORKSOURCE_0)); - } - /////////////////////////////////////////////////////////////////////////////////////// // utilities /////////////////////////////////////////////////////////////////////////////////////// - private void setupWifiChipV15(ChipMockBase chipMock) throws RemoteException { - mWifiChipV15 = mock(android.hardware.wifi.V1_5.IWifiChip.class); - doAnswer(new GetCapabilities_1_5Answer(chipMock)) - .when(mWifiChipV15).getCapabilities_1_5(any( - android.hardware.wifi.V1_5.IWifiChip.getCapabilities_1_5Callback.class)); - when(mWifiChipV15.removeIfaceInstanceFromBridgedApIface(any(), any())) - .thenAnswer((invocation) -> { - chipMock.bridgedApInstancesByName.get(invocation.getArgument(0)) - .remove(invocation.getArgument(1)); - return getStatus(WifiStatusCode.SUCCESS); - }); - } - - private void setupWifiV15(IWifi iWifiMock) throws RemoteException { - mWifiMockV15 = mock(android.hardware.wifi.V1_5.IWifi.class); - when(mWifiMockV15.registerEventCallback_1_5( - any(android.hardware.wifi.V1_5.IWifiEventCallback.class))).thenReturn(mStatusOk); - } - private void dumpDut(String prefix) { StringWriter sw = new StringWriter(); mDut.dump(null, new PrintWriter(sw), null); Log.e("HalDeviceManager", prefix + sw.toString()); } - private void executeAndValidateInitializationSequence() throws Exception { - executeAndValidateInitializationSequence(true); - } - - private void executeAndValidateInitializationSequence(boolean isSupported) throws Exception { - // act: - mDut.initialize(); - - // verify: service manager initialization sequence - mInOrder.verify(mServiceManagerMock).linkToDeath(any(IHwBinder.DeathRecipient.class), - anyLong()); - mInOrder.verify(mServiceManagerMock).registerForNotifications(eq(IWifi.kInterfaceName), - eq(""), mServiceNotificationCaptor.capture()); - - // If not using the lazy version of the IWifi service, the process should already be up at - // this point. - mInOrder.verify(mServiceManagerMock).listManifestByInterface(eq(IWifi.kInterfaceName)); - - // verify: wifi initialization sequence if vendor HAL is supported. - if (isSupported) { - mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); - // verify: onStop called as a part of initialize. - mInOrder.verify(mWifiMock).stop(); - if (null != mWifiMockV15) { - mInOrder.verify(mWifiMockV15).registerEventCallback_1_5( - mWifiEventCallbackCaptorV15.capture()); - } else { - mInOrder.verify(mWifiMock).registerEventCallback( - mWifiEventCallbackCaptor.capture()); - } - collector.checkThat("isReady is true", mDut.isReady(), equalTo(true)); - } else { - collector.checkThat("isReady is false", mDut.isReady(), equalTo(false)); - } - } - private void executeAndValidateStartupSequence() throws Exception { executeAndValidateStartupSequence(1, true); } @@ -4200,19 +3679,17 @@ public class HalDeviceManagerTest extends WifiBaseTest { private void executeAndValidateStartupSequence(int numAttempts, boolean success) throws Exception { // act: register listener & start Wi-Fi + mDut.initialize(); mDut.registerStatusListener(mManagerStatusListenerMock, mHandler); collector.checkThat(mDut.start(), equalTo(success)); // verify + verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); mInOrder.verify(mWifiMock, times(numAttempts)).start(); if (success) { // act: trigger onStart callback of IWifiEventCallback - if (mWifiMockV15 != null) { - mWifiEventCallbackCaptorV15.getValue().onStart(); - } else { - mWifiEventCallbackCaptor.getValue().onStart(); - } + mWifiEventCallbackCaptor.getValue().onStart(); mTestLooper.dispatchAll(); // verify: onStart called on registered listener @@ -4223,20 +3700,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { private void runCreateSingleXxxInterfaceNoInitMode(ChipMockBase chipMock, int ifaceTypeToCreate, String ifaceName, int finalChipMode) throws Exception { chipMock.initialize(); - if (mWifiChipV15 != null) { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mWifiChipV15, mManagerStatusListenerMock); - } else { - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - } - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener idl = mock( InterfaceDestroyedListener.class); - IWifiIface iface = validateInterfaceSequence(chipMock, + WifiInterface iface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) ifaceTypeToCreate, @@ -4292,9 +3762,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void runP2pAndNanExclusiveInteractionsTestChip(ChipMockBase chipMock, int onlyChipMode) throws Exception { chipMock.initialize(); - mInOrder = inOrder(mServiceManagerMock, mWifiMock, mWifiMockV15, chipMock.chip, - mManagerStatusListenerMock); - executeAndValidateInitializationSequence(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); InterfaceDestroyedListener staDestroyedListener = mock( @@ -4307,7 +3775,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { InterfaceDestroyedListener.class); // Request STA - IWifiIface staIface = validateInterfaceSequence(chipMock, + WifiInterface staIface = validateInterfaceSequence(chipMock, false, // chipModeValid -1000, // chipModeId (only used if chipModeValid is true) HDM_CREATE_IFACE_STA, // createIfaceType @@ -4320,7 +3788,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { collector.checkThat("STA can't be created", staIface, IsNull.notNullValue()); // Request NAN - IWifiIface nanIface = validateInterfaceSequence(chipMock, + WifiInterface nanIface = validateInterfaceSequence(chipMock, true, // chipModeValid onlyChipMode, // chipModeId HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate @@ -4332,13 +3800,13 @@ public class HalDeviceManagerTest extends WifiBaseTest { ); // Request P2P - IWifiIface p2pIface = validateInterfaceSequence(chipMock, + WifiInterface p2pIface = validateInterfaceSequence(chipMock, true, // chipModeValid onlyChipMode, // chipModeId HDM_CREATE_IFACE_P2P, // ifaceTypeToCreate "p2p0", // ifaceName onlyChipMode, // finalChipMode - new IWifiIface[]{nanIface}, // tearDownList + new WifiInterface[]{nanIface}, // tearDownList p2pDestroyedListener, // destroyedListener TEST_WORKSOURCE_0, // requestorWs // destroyedInterfacesDestroyedListeners... @@ -4356,7 +3824,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { HDM_CREATE_IFACE_NAN, // ifaceTypeToCreate "wlan0", // ifaceName onlyChipMode, // finalChipMode - new IWifiIface[]{p2pIface}, // tearDownList + new WifiInterface[]{p2pIface}, // tearDownList nanDestroyedListener, // destroyedListener TEST_WORKSOURCE_0 // requestorWs ); @@ -4369,11 +3837,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { nanDestroyedListener, p2pDestroyedListener); } - private IWifiIface validateInterfaceSequence(ChipMockBase chipMock, + private WifiInterface validateInterfaceSequence(ChipMockBase chipMock, boolean chipModeValid, int chipModeId, int createIfaceType, String ifaceName, int finalChipMode, long requiredChipCapabilities, - IWifiIface[] tearDownList, + WifiInterface[] tearDownList, InterfaceDestroyedListener destroyedListener, WorkSource requestorWs, InterfaceDestroyedListenerWithIfaceName...destroyedInterfacesDestroyedListeners) @@ -4393,93 +3861,66 @@ public class HalDeviceManagerTest extends WifiBaseTest { HAL_IFACE_MAP.get(details.get(0).first.intValue())); } - IWifiIface iface = null; + WifiInterface iface = null; // configure: interface to be created // act: request the interface switch (createIfaceType) { case HDM_CREATE_IFACE_STA: - iface = mock(IWifiStaIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.STA)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); - + iface = mock(WifiStaIface.class); + doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(); + doAnswer(new CreateStaIfaceAnswer(chipMock, true, iface)) + .when(chipMock.chip).createStaIface(); mDut.createStaIface(requiredChipCapabilities, destroyedListener, mHandler, requestorWs); break; case HDM_CREATE_IFACE_AP_BRIDGE: case HDM_CREATE_IFACE_AP: - iface = mock(IWifiApIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.AP)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - if (mWifiChipV15 != null && createIfaceType == HDM_CREATE_IFACE_AP_BRIDGE) { - android.hardware.wifi.V1_5.IWifiApIface ifaceApV15 = - mock(android.hardware.wifi.V1_5.IWifiApIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(ifaceApV15).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.AP)).when(ifaceApV15).getType( - any(IWifiIface.getTypeCallback.class)); + iface = mock(WifiApIface.class); + doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(); + if (createIfaceType == HDM_CREATE_IFACE_AP_BRIDGE) { doAnswer(new GetBridgedInstancesAnswer(chipMock, ifaceName)) - .when(ifaceApV15).getBridgedInstances( - any(android.hardware.wifi.V1_5.IWifiApIface - .getBridgedInstancesCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, ifaceApV15)).when( - mWifiChipV15).createBridgedApIface( - any(android.hardware.wifi.V1_5.IWifiChip - .createBridgedApIfaceCallback.class)); - } else { - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createApIface( - any(IWifiChip.createApIfaceCallback.class)); + .when((WifiApIface) iface).getBridgedInstances(); } + doAnswer(new CreateApIfaceAnswer(chipMock, true, iface)) + .when(chipMock.chip).createApIface(); + doAnswer(new CreateApIfaceAnswer(chipMock, true, iface)) + .when(chipMock.chip).createBridgedApIface(); mDut.createApIface(requiredChipCapabilities, destroyedListener, mHandler, requestorWs, createIfaceType == HDM_CREATE_IFACE_AP_BRIDGE, mSoftApManager); break; case HDM_CREATE_IFACE_P2P: - iface = mock(IWifiP2pIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.P2P)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createP2pIface(any(IWifiChip.createP2pIfaceCallback.class)); - + iface = mock(WifiP2pIface.class); + doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(); + doAnswer(new CreateP2pIfaceAnswer(chipMock, true, iface)) + .when(chipMock.chip).createP2pIface(); mDut.createP2pIface(requiredChipCapabilities, destroyedListener, mHandler, requestorWs); break; case HDM_CREATE_IFACE_NAN: - iface = mock(IWifiNanIface.class); - doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( - any(IWifiIface.getNameCallback.class)); - doAnswer(new GetTypeAnswer(IfaceType.NAN)).when(iface).getType( - any(IWifiIface.getTypeCallback.class)); - doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( - chipMock.chip).createNanIface(any(IWifiChip.createNanIfaceCallback.class)); - + iface = mock(WifiNanIface.class); + doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(); + doAnswer(new CreateNanIfaceAnswer(chipMock, true, iface)) + .when(chipMock.chip).createNanIface(); mDut.createNanIface(destroyedListener, mHandler, requestorWs); break; } // validate: optional tear down of interfaces if (tearDownList != null) { - for (IWifiIface tearDownIface: tearDownList) { + for (WifiInterface tearDownIface: tearDownList) { switch (getType(tearDownIface)) { - case IfaceType.STA: + case WifiChip.IFACE_TYPE_STA: mInOrder.verify(chipMock.chip).removeStaIface(getName(tearDownIface)); break; - case IfaceType.AP: + case WifiChip.IFACE_TYPE_AP: mInOrder.verify(chipMock.chip).removeApIface(getName(tearDownIface)); break; - case IfaceType.P2P: + case WifiChip.IFACE_TYPE_P2P: mInOrder.verify(chipMock.chip).removeP2pIface(getName(tearDownIface)); break; - case IfaceType.NAN: + case WifiChip.IFACE_TYPE_NAN: mInOrder.verify(chipMock.chip).removeNanIface(getName(tearDownIface)); break; } @@ -4496,27 +3937,19 @@ public class HalDeviceManagerTest extends WifiBaseTest { // validate: create interface switch (createIfaceType) { case HDM_CREATE_IFACE_STA: - mInOrder.verify(chipMock.chip).createStaIface( - any(IWifiChip.createStaIfaceCallback.class)); + mInOrder.verify(chipMock.chip).createStaIface(); break; case HDM_CREATE_IFACE_AP_BRIDGE: + mInOrder.verify(chipMock.chip).createBridgedApIface(); + break; case HDM_CREATE_IFACE_AP: - if (mWifiChipV15 != null && createIfaceType == HDM_CREATE_IFACE_AP_BRIDGE) { - mInOrder.verify(mWifiChipV15) - .createBridgedApIface(any(android.hardware.wifi.V1_5.IWifiChip - .createBridgedApIfaceCallback.class)); - } else { - mInOrder.verify(chipMock.chip).createApIface( - any(IWifiChip.createApIfaceCallback.class)); - } + mInOrder.verify(chipMock.chip).createApIface(); break; case HDM_CREATE_IFACE_P2P: - mInOrder.verify(chipMock.chip).createP2pIface( - any(IWifiChip.createP2pIfaceCallback.class)); + mInOrder.verify(chipMock.chip).createP2pIface(); break; case HDM_CREATE_IFACE_NAN: - mInOrder.verify(chipMock.chip).createNanIface( - any(IWifiChip.createNanIfaceCallback.class)); + mInOrder.verify(chipMock.chip).createNanIface(); break; } @@ -4528,10 +3961,10 @@ public class HalDeviceManagerTest extends WifiBaseTest { return iface; } - private IWifiIface validateInterfaceSequence(ChipMockBase chipMock, + private WifiInterface validateInterfaceSequence(ChipMockBase chipMock, boolean chipModeValid, int chipModeId, int createIfaceType, String ifaceName, int finalChipMode, - IWifiIface[] tearDownList, + WifiInterface[] tearDownList, InterfaceDestroyedListener destroyedListener, WorkSource requestorWs, InterfaceDestroyedListenerWithIfaceName...destroyedInterfacesDestroyedListeners) @@ -4543,26 +3976,12 @@ public class HalDeviceManagerTest extends WifiBaseTest { destroyedInterfacesDestroyedListeners); } - private int getType(IWifiIface iface) throws Exception { - Mutable<Integer> typeResp = new Mutable<>(); - iface.getType((WifiStatus status, int type) -> { - typeResp.value = type; - }); - return typeResp.value; - } - - private String getName(IWifiIface iface) throws Exception { - Mutable<String> nameResp = new Mutable<>(); - iface.getName((WifiStatus status, String name) -> { - nameResp.value = name; - }); - return nameResp.value; + private int getType(WifiInterface iface) throws Exception { + return mDut.getType(iface); } - private WifiStatus getStatus(int code) { - WifiStatus status = new WifiStatus(); - status.code = code; - return status; + private String getName(WifiInterface iface) throws Exception { + return mDut.getName(iface); } private static class InterfaceDestroyedListenerWithIfaceName { @@ -4580,44 +3999,33 @@ public class HalDeviceManagerTest extends WifiBaseTest { } } - private static class Mutable<E> { - public E value; - - Mutable() { - value = null; - } - - Mutable(E value) { - this.value = value; - } - } - // Answer objects private class GetChipIdsAnswer extends MockAnswerUtil.AnswerWithArguments { - private WifiStatus mStatus; + private boolean mSuccess; private ArrayList<Integer> mChipIds; - GetChipIdsAnswer(WifiStatus status, ArrayList<Integer> chipIds) { - mStatus = status; + GetChipIdsAnswer(boolean success, ArrayList<Integer> chipIds) { + mSuccess = success; mChipIds = chipIds; } - public void answer(IWifi.getChipIdsCallback cb) { - cb.onValues(mStatus, mChipIds); + public List<Integer> answer() { + List<Integer> ret = mSuccess ? mChipIds : null; + return ret; } } private class GetChipAnswer extends MockAnswerUtil.AnswerWithArguments { - private WifiStatus mStatus; - private IWifiChip mChip; + private boolean mSuccess; + private WifiChip mChip; - GetChipAnswer(WifiStatus status, IWifiChip chip) { - mStatus = status; + GetChipAnswer(boolean success, WifiChip chip) { + mSuccess = success; mChip = chip; } - public void answer(int chipId, IWifi.getChipCallback cb) { - cb.onValues(mStatus, mChip); + public WifiChip answer(int chipId) { + return mSuccess ? mChip : null; } } @@ -4628,21 +4036,12 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public void answer(IWifiChip.getCapabilitiesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.chipCapabilities); - } - } - - private class GetCapabilities_1_5Answer extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - GetCapabilities_1_5Answer(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public void answer( - android.hardware.wifi.V1_5.IWifiChip.getCapabilities_1_5Callback cb) { - cb.onValues(mStatusOk, mChipMockBase.chipCapabilities); + public WifiChip.Response<Long> answer() { + WifiChip.Response<Long> response = + new WifiChip.Response<>(mChipMockBase.chipCapabilities); + response.setStatusCode(mChipMockBase.allowGetCapsBeforeIfaceCreated + ? WifiHal.WIFI_STATUS_SUCCESS : WifiHal.WIFI_STATUS_ERROR_UNKNOWN); + return response; } } @@ -4653,8 +4052,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public void answer(IWifiChip.getIdCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.chipId); + public int answer() { + return mChipMockBase.chipId; } } @@ -4665,20 +4064,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public void answer(IWifiChip.getAvailableModesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.availableModes); - } - } - - private class GetAvailableModesAnswer_1_6 extends MockAnswerUtil.AnswerWithArguments { - private ChipMockBase mChipMockBase; - - GetAvailableModesAnswer_1_6(ChipMockBase chipMockBase) { - mChipMockBase = chipMockBase; - } - - public void answer(android.hardware.wifi.V1_6.IWifiChip.getAvailableModes_1_6Callback cb) { - cb.onValues(mStatusOk, mChipMockBase.availableModes_1_6); + public List<WifiChip.ChipMode> answer() { + return mChipMockBase.availableModes; } } @@ -4689,9 +4076,11 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public void answer(IWifiChip.getModeCallback cb) { - cb.onValues(mChipMockBase.chipModeValid ? mStatusOk - : getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE), mChipMockBase.chipModeId); + public WifiChip.Response<Integer> answer() { + WifiChip.Response<Integer> response = new WifiChip.Response<>(mChipMockBase.chipModeId); + response.setStatusCode(mChipMockBase.chipModeValid + ? WifiHal.WIFI_STATUS_SUCCESS : WifiHal.WIFI_STATUS_ERROR_NOT_AVAILABLE); + return response; } } @@ -4702,143 +4091,165 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public WifiStatus answer(int chipMode) { + public boolean answer(int chipMode) { mChipMockBase.chipModeValid = true; mChipMockBase.chipModeId = chipMode; mChipMockBase.onChipConfigured(); - return mStatusOk; + return true; } } private class GetXxxIfaceNamesAnswer extends MockAnswerUtil.AnswerWithArguments { private ChipMockBase mChipMockBase; + private @WifiChip.IfaceType int mIfaceType; - GetXxxIfaceNamesAnswer(ChipMockBase chipMockBase) { + GetXxxIfaceNamesAnswer(ChipMockBase chipMockBase, @WifiChip.IfaceType int ifaceType) { mChipMockBase = chipMockBase; + mIfaceType = ifaceType; } - public void answer(IWifiChip.getStaIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.STA)); + public List<String> answer() { + return mChipMockBase.interfaceNames.get(mIfaceType); } + } - public void answer(IWifiChip.getApIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.AP)); - } + private class GetStaIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { + private ChipMockBase mChipMockBase; - public void answer(IWifiChip.getP2pIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.P2P)); + GetStaIfaceAnswer(ChipMockBase chipMockBase) { + mChipMockBase = chipMockBase; } - public void answer(IWifiChip.getNanIfaceNamesCallback cb) { - cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.NAN)); + public WifiStaIface answer(String name) { + return (WifiStaIface) + mChipMockBase.interfacesByName.get(WifiChip.IFACE_TYPE_STA).get(name); } } - private class GetXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { + private class GetApIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { private ChipMockBase mChipMockBase; - GetXxxIfaceAnswer(ChipMockBase chipMockBase) { + GetApIfaceAnswer(ChipMockBase chipMockBase) { mChipMockBase = chipMockBase; } - public void answer(String name, IWifiChip.getStaIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.STA).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiStaIface) iface); + public WifiApIface answer(String name) { + return (WifiApIface) + mChipMockBase.interfacesByName.get(WifiChip.IFACE_TYPE_AP).get(name); } + } - public void answer(String name, IWifiChip.getApIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.AP).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiApIface) iface); - } + private class GetP2pIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { + private ChipMockBase mChipMockBase; - public void answer(String name, IWifiChip.getP2pIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.P2P).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiP2pIface) iface); + GetP2pIfaceAnswer(ChipMockBase chipMockBase) { + mChipMockBase = chipMockBase; } - public void answer(String name, IWifiChip.getNanIfaceCallback cb) { - IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.NAN).get(name); - cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiNanIface) iface); + public WifiP2pIface answer(String name) { + return (WifiP2pIface) + mChipMockBase.interfacesByName.get(WifiChip.IFACE_TYPE_P2P).get(name); } } - private class CreateXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { + private class GetNanIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { private ChipMockBase mChipMockBase; - private WifiStatus mStatus; - private IWifiIface mWifiIface; - CreateXxxIfaceAnswer(ChipMockBase chipMockBase, WifiStatus status, IWifiIface wifiIface) { + GetNanIfaceAnswer(ChipMockBase chipMockBase) { mChipMockBase = chipMockBase; - mStatus = status; + } + + public WifiNanIface answer(String name) { + return (WifiNanIface) + mChipMockBase.interfacesByName.get(WifiChip.IFACE_TYPE_NAN).get(name); + } + } + + private class CreateXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { + protected ChipMockBase mChipMockBase; + protected boolean mSuccess; + protected WifiInterface mWifiIface; + private @WifiChip.IfaceType int mType; + + CreateXxxIfaceAnswer(ChipMockBase chipMockBase, boolean success, WifiInterface wifiIface, + @WifiChip.IfaceType int type) { + mChipMockBase = chipMockBase; + mSuccess = success; mWifiIface = wifiIface; + mType = type; } - private void addInterfaceInfo(int type) { - if (mStatus.code == WifiStatusCode.SUCCESS) { + protected void addInterfaceInfo() { + if (mSuccess) { try { - mChipMockBase.interfaceNames.get(type).add(getName(mWifiIface)); - mChipMockBase.interfacesByName.get(type).put(getName(mWifiIface), mWifiIface); + String ifaceName = getName(mWifiIface); + mChipMockBase.interfaceNames.get(mType).add(ifaceName); + mChipMockBase.interfacesByName.get(mType).put(ifaceName, mWifiIface); } catch (Exception e) { // do nothing } } } + } + + private class CreateStaIfaceAnswer extends CreateXxxIfaceAnswer { + CreateStaIfaceAnswer(ChipMockBase chipMockBase, boolean success, WifiInterface wifiIface) { + super(chipMockBase, success, wifiIface, WifiChip.IFACE_TYPE_STA); + } - public void answer(IWifiChip.createStaIfaceCallback cb) { - cb.onValues(mStatus, (IWifiStaIface) mWifiIface); - addInterfaceInfo(IfaceType.STA); + public WifiStaIface answer() { + addInterfaceInfo(); + return mSuccess ? (WifiStaIface) mWifiIface : null; } + } - public void answer(IWifiChip.createApIfaceCallback cb) { - cb.onValues(mStatus, (IWifiApIface) mWifiIface); - addInterfaceInfo(IfaceType.AP); + private class CreateApIfaceAnswer extends CreateXxxIfaceAnswer { + CreateApIfaceAnswer(ChipMockBase chipMockBase, boolean success, WifiInterface wifiIface) { + super(chipMockBase, success, wifiIface, WifiChip.IFACE_TYPE_AP); } - public void answer(android.hardware.wifi.V1_5.IWifiChip.createBridgedApIfaceCallback cb) { - cb.onValues(mStatus, (android.hardware.wifi.V1_5.IWifiApIface) mWifiIface); - addInterfaceInfo(IfaceType.AP); + public WifiApIface answer() { + addInterfaceInfo(); + return mSuccess ? (WifiApIface) mWifiIface : null; } + } - public void answer(IWifiChip.createP2pIfaceCallback cb) { - cb.onValues(mStatus, (IWifiP2pIface) mWifiIface); - addInterfaceInfo(IfaceType.P2P); + private class CreateP2pIfaceAnswer extends CreateXxxIfaceAnswer { + CreateP2pIfaceAnswer(ChipMockBase chipMockBase, boolean success, WifiInterface wifiIface) { + super(chipMockBase, success, wifiIface, WifiChip.IFACE_TYPE_P2P); } - public void answer(IWifiChip.createNanIfaceCallback cb) { - cb.onValues(mStatus, (IWifiNanIface) mWifiIface); - addInterfaceInfo(IfaceType.NAN); + public WifiP2pIface answer() { + addInterfaceInfo(); + return mSuccess ? (WifiP2pIface) mWifiIface : null; + } + } + + private class CreateNanIfaceAnswer extends CreateXxxIfaceAnswer { + CreateNanIfaceAnswer(ChipMockBase chipMockBase, boolean success, WifiInterface wifiIface) { + super(chipMockBase, success, wifiIface, WifiChip.IFACE_TYPE_NAN); + } + + public WifiNanIface answer() { + addInterfaceInfo(); + return mSuccess ? (WifiNanIface) mWifiIface : null; } } private class CreateRttControllerAnswer extends MockAnswerUtil.AnswerWithArguments { private final ChipMockBase mChipMockBase; - private final IWifiRttController mRttController; + private final WifiRttController mRttController; - CreateRttControllerAnswer(ChipMockBase chipMockBase, IWifiRttController rttController) { + CreateRttControllerAnswer(ChipMockBase chipMockBase, WifiRttController rttController) { mChipMockBase = chipMockBase; mRttController = rttController; } - public void answer(IWifiIface boundIface, IWifiChip.createRttControllerCallback cb) { + public WifiRttController answer() { if (mChipMockBase.chipModeIdValidForRtt == mChipMockBase.chipModeId) { - cb.onValues(mStatusOk, mRttController); - } else { - cb.onValues(mStatusFail, null); - } - } - } - private class GetBoundIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { - private final boolean mIsValid; - - GetBoundIfaceAnswer(boolean isValid) { - mIsValid = isValid; - } - - public void answer(IWifiRttController.getBoundIfaceCallback cb) { - if (mIsValid) { - cb.onValues(mStatusOk, null); + return mRttController; } else { - cb.onValues(mStatusFail, null); + return null; } } } @@ -4847,27 +4258,23 @@ public class HalDeviceManagerTest extends WifiBaseTest { private ChipMockBase mChipMockBase; private int mType; - RemoveXxxIfaceAnswer(ChipMockBase chipMockBase, int type) { + RemoveXxxIfaceAnswer(ChipMockBase chipMockBase, @WifiChip.IfaceType int type) { mChipMockBase = chipMockBase; mType = type; } - private WifiStatus removeIface(int type, String ifname) { + public boolean answer(String ifname) { try { - if (!mChipMockBase.interfaceNames.get(type).remove(ifname)) { - return mStatusFail; + if (!mChipMockBase.interfaceNames.get(mType).remove(ifname)) { + return false; } - if (mChipMockBase.interfacesByName.get(type).remove(ifname) == null) { - return mStatusFail; + if (mChipMockBase.interfacesByName.get(mType).remove(ifname) == null) { + return false; } } catch (Exception e) { - return mStatusFail; + return false; } - return mStatusOk; - } - - public WifiStatus answer(String ifname) { - return removeIface(mType, ifname); + return true; } } @@ -4878,20 +4285,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mName = name; } - public void answer(IWifiIface.getNameCallback cb) { - cb.onValues(mStatusOk, mName); - } - } - - private class GetTypeAnswer extends MockAnswerUtil.AnswerWithArguments { - private int mType; - - GetTypeAnswer(int type) { - mType = type; - } - - public void answer(IWifiIface.getTypeCallback cb) { - cb.onValues(mStatusOk, mType); + public String answer() { + return mName; } } @@ -4903,10 +4298,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public void answer( - android.hardware.wifi.V1_6.IWifiChip.getSupportedRadioCombinationsMatrixCallback - cb) { - cb.onValues(mStatusOk, mChipMockBase.chipSupportedRadioCombinationsMatrix); + public WifiChip.WifiRadioCombinationMatrix answer() { + return mChipMockBase.chipSupportedRadioCombinationsMatrix; } } @@ -4919,18 +4312,33 @@ public class HalDeviceManagerTest extends WifiBaseTest { mName = name; } - public void answer(android.hardware.wifi.V1_5.IWifiApIface.getBridgedInstancesCallback cb) { + public List<String> answer() { ArrayList<String> bridgedApInstances = mChipMockBase.bridgedApInstancesByName.get(mName); if (bridgedApInstances == null) { bridgedApInstances = new ArrayList<>(); } - cb.onValues(mStatusOk, bridgedApInstances); + return bridgedApInstances; } } // chip configuration + WifiChip.ChipConcurrencyCombinationLimit createConcurrencyComboLimit( + int maxIfaces, Integer... ifaceTypes) { + // Assume we will always get at least 1 iface type. + return new WifiChip.ChipConcurrencyCombinationLimit(maxIfaces, Arrays.asList(ifaceTypes)); + } + + WifiChip.ChipConcurrencyCombination createConcurrencyCombo( + WifiChip.ChipConcurrencyCombinationLimit... limits) { + return new WifiChip.ChipConcurrencyCombination(Arrays.asList(limits)); + } + + WifiChip.ChipMode createChipMode(int modeId, WifiChip.ChipConcurrencyCombination... combos) { + return new WifiChip.ChipMode(modeId, Arrays.asList(combos)); + } + private static final int CHIP_MOCK_V1 = 0; private static final int CHIP_MOCK_V2 = 1; private static final int CHIP_MOCK_V3 = 2; @@ -4941,76 +4349,72 @@ public class HalDeviceManagerTest extends WifiBaseTest { private class ChipMockBase { public int chipMockId; - public android.hardware.wifi.V1_6.IWifiChip chip; + public WifiChip chip; public int chipId; public boolean chipModeValid = false; public int chipModeId = -1000; public int chipModeIdValidForRtt = -1; // single chip mode ID where RTT can be created - public int chipCapabilities = 0; - public WifiRadioCombinationMatrix chipSupportedRadioCombinationsMatrix = null; + public long chipCapabilities = 0L; + public boolean allowGetCapsBeforeIfaceCreated = true; + public WifiChip.WifiRadioCombinationMatrix chipSupportedRadioCombinationsMatrix = null; public Map<Integer, ArrayList<String>> interfaceNames = new HashMap<>(); - public Map<Integer, Map<String, IWifiIface>> interfacesByName = new HashMap<>(); + public Map<Integer, Map<String, WifiInterface>> interfacesByName = new HashMap<>(); public Map<String, ArrayList<String>> bridgedApInstancesByName = new HashMap<>(); - public ArrayList<IWifiChip.ChipMode> availableModes; - public ArrayList<android.hardware.wifi.V1_6.IWifiChip.ChipMode> availableModes_1_6; + public ArrayList<WifiChip.ChipMode> availableModes; void initialize() throws Exception { - chip = mock(android.hardware.wifi.V1_6.IWifiChip.class); + chip = mock(WifiChip.class); - interfaceNames.put(IfaceType.STA, new ArrayList<>()); - interfaceNames.put(IfaceType.AP, new ArrayList<>()); - interfaceNames.put(IfaceType.P2P, new ArrayList<>()); - interfaceNames.put(IfaceType.NAN, new ArrayList<>()); + interfaceNames.put(WifiChip.IFACE_TYPE_STA, new ArrayList<>()); + interfaceNames.put(WifiChip.IFACE_TYPE_AP, new ArrayList<>()); + interfaceNames.put(WifiChip.IFACE_TYPE_P2P, new ArrayList<>()); + interfaceNames.put(WifiChip.IFACE_TYPE_NAN, new ArrayList<>()); - interfacesByName.put(IfaceType.STA, new HashMap<>()); - interfacesByName.put(IfaceType.AP, new HashMap<>()); - interfacesByName.put(IfaceType.P2P, new HashMap<>()); - interfacesByName.put(IfaceType.NAN, new HashMap<>()); + interfacesByName.put(WifiChip.IFACE_TYPE_STA, new HashMap<>()); + interfacesByName.put(WifiChip.IFACE_TYPE_AP, new HashMap<>()); + interfacesByName.put(WifiChip.IFACE_TYPE_P2P, new HashMap<>()); + interfacesByName.put(WifiChip.IFACE_TYPE_NAN, new HashMap<>()); - when(chip.registerEventCallback(any(IWifiChipEventCallback.class))).thenReturn( - mStatusOk); + when(chip.registerCallback(any(WifiChip.Callback.class))).thenReturn(true); when(chip.configureChip(anyInt())).thenAnswer(new ConfigureChipAnswer(this)); doAnswer(new GetCapabilitiesAnswer(this)) - .when(chip).getCapabilities(any(IWifiChip.getCapabilitiesCallback.class)); - doAnswer(new GetIdAnswer(this)).when(chip).getId(any(IWifiChip.getIdCallback.class)); - doAnswer(new GetModeAnswer(this)).when(chip).getMode( - any(IWifiChip.getModeCallback.class)); - GetXxxIfaceNamesAnswer getXxxIfaceNamesAnswer = new GetXxxIfaceNamesAnswer(this); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getStaIfaceNames( - any(IWifiChip.getStaIfaceNamesCallback.class)); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getApIfaceNames( - any(IWifiChip.getApIfaceNamesCallback.class)); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getP2pIfaceNames( - any(IWifiChip.getP2pIfaceNamesCallback.class)); - doAnswer(getXxxIfaceNamesAnswer).when(chip).getNanIfaceNames( - any(IWifiChip.getNanIfaceNamesCallback.class)); - GetXxxIfaceAnswer getXxxIfaceAnswer = new GetXxxIfaceAnswer(this); - doAnswer(getXxxIfaceAnswer).when(chip).getStaIface(anyString(), - any(IWifiChip.getStaIfaceCallback.class)); - doAnswer(getXxxIfaceAnswer).when(chip).getApIface(anyString(), - any(IWifiChip.getApIfaceCallback.class)); - doAnswer(getXxxIfaceAnswer).when(chip).getP2pIface(anyString(), - any(IWifiChip.getP2pIfaceCallback.class)); - doAnswer(getXxxIfaceAnswer).when(chip).getNanIface(anyString(), - any(IWifiChip.getNanIfaceCallback.class)); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.STA)).when(chip).removeStaIface( - anyString()); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.AP)).when(chip).removeApIface( - anyString()); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.P2P)).when(chip).removeP2pIface( - anyString()); - doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.NAN)).when(chip).removeNanIface( - anyString()); - - doAnswer(new CreateRttControllerAnswer(this, mRttControllerMock)).when( - chip).createRttController(any(), any()); - - doAnswer(new GetBoundIfaceAnswer(true)).when(mRttControllerMock).getBoundIface(any()); + .when(chip).getCapabilitiesBeforeIfacesExist(); + doAnswer(new GetIdAnswer(this)).when(chip).getId(); + doAnswer(new GetModeAnswer(this)).when(chip).getMode(); + doAnswer(new GetXxxIfaceNamesAnswer(this, WifiChip.IFACE_TYPE_STA)) + .when(chip).getStaIfaceNames(); + doAnswer(new GetXxxIfaceNamesAnswer(this, WifiChip.IFACE_TYPE_AP)) + .when(chip).getApIfaceNames(); + doAnswer(new GetXxxIfaceNamesAnswer(this, WifiChip.IFACE_TYPE_P2P)) + .when(chip).getP2pIfaceNames(); + doAnswer(new GetXxxIfaceNamesAnswer(this, WifiChip.IFACE_TYPE_NAN)) + .when(chip).getNanIfaceNames(); + doAnswer(new GetStaIfaceAnswer(this)).when(chip).getStaIface(anyString()); + doAnswer(new GetApIfaceAnswer(this)).when(chip).getApIface(anyString()); + doAnswer(new GetP2pIfaceAnswer(this)).when(chip).getP2pIface(anyString()); + doAnswer(new GetNanIfaceAnswer(this)).when(chip).getNanIface(anyString()); + doAnswer(new RemoveXxxIfaceAnswer(this, WifiChip.IFACE_TYPE_STA)) + .when(chip).removeStaIface(anyString()); + doAnswer(new RemoveXxxIfaceAnswer(this, WifiChip.IFACE_TYPE_AP)) + .when(chip).removeApIface(anyString()); + doAnswer(new RemoveXxxIfaceAnswer(this, WifiChip.IFACE_TYPE_P2P)) + .when(chip).removeP2pIface(anyString()); + doAnswer(new RemoveXxxIfaceAnswer(this, WifiChip.IFACE_TYPE_NAN)) + .when(chip).removeNanIface(anyString()); + when(chip.removeIfaceInstanceFromBridgedApIface(anyString(), anyString())) + .thenAnswer((invocation) -> { + this.bridgedApInstancesByName.get(invocation.getArgument(0)) + .remove(invocation.getArgument(1)); + return true; + }); + + doAnswer(new CreateRttControllerAnswer(this, mRttControllerMock)) + .when(chip).createRttController(); + when(mRttControllerMock.setup()).thenReturn(true); + when(mRttControllerMock.validate()).thenReturn(true); doAnswer(new GetSupportedRadioCombinationsMatrixAnswer(this)) - .when(chip).getSupportedRadioCombinationsMatrix( - any(android.hardware.wifi.V1_6.IWifiChip - .getSupportedRadioCombinationsMatrixCallback.class)); + .when(chip).getSupportedRadioCombinationsMatrix(); } void onChipConfigured() { @@ -5073,52 +4477,26 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 10; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(10), - any(IWifi.getChipCallback.class)); + // Initialize availableModes + availableModes = new ArrayList<>(); - // initialize placeholder chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; + // Mode 0: 1xSTA + 1x{P2P,NAN} + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P, + WifiChip.IFACE_CONCURRENCY_TYPE_NAN)); + availableModes.add(createChipMode(STA_CHIP_MODE_ID, combo1)); - // Mode 0: 1xSTA + 1x{P2P,NAN} - // Mode 1: 1xAP - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = STA_CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - cm.availableCombinations.add(cic); - availableModes.add(cm); - - cm = new IWifiChip.ChipMode(); - cm.id = AP_CHIP_MODE_ID; - cic = new IWifiChip.ChipIfaceCombination(); - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - cm.availableCombinations.add(cic); - availableModes.add(cm); + // Mode 1: 1xAP + WifiChip.ChipConcurrencyCombination combo2 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + availableModes.add(createChipMode(AP_CHIP_MODE_ID, combo2)); chipModeIdValidForRtt = STA_CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5167,47 +4545,23 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 12; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(12), - any(IWifi.getChipCallback.class)); - - // initialize placeholder chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - // Mode 0 (only one): 1xSTA + 1x{STA,AP} + 1x{P2P,NAN} + // Initialize availableModes availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - cm.availableCombinations.add(cic); - availableModes.add(cm); - chipModeIdValidForRtt = CHIP_MODE_ID; + // Mode (only one): 1xSTA + 1x{STA,AP} + 1x{P2P,NAN} + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA, + WifiChip.IFACE_CONCURRENCY_TYPE_AP), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P, + WifiChip.IFACE_CONCURRENCY_TYPE_NAN)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1)); - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); + chipModeIdValidForRtt = CHIP_MODE_ID; + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5229,57 +4583,25 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 15; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(15), - any(IWifi.getChipCallback.class)); - - // initialize placeholder chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - // Mode 0 (only one): 1xSTA + 1x{STA,AP}, 1xSTA + 1x{P2P,NAN} + // Initialize availableModes availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - availableModes.add(cm); + // Mode (only one): 1xSTA + 1x{STA,AP}, 1xSTA + 1x{P2P,NAN} + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA, + WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + WifiChip.ChipConcurrencyCombination combo2 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P, + WifiChip.IFACE_CONCURRENCY_TYPE_NAN)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1, combo2)); chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5301,56 +4623,24 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 23; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(23), - any(IWifi.getChipCallback.class)); - - // initialize placeholder chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - // Mode 0 (only one): 1xSTA + 1xAP, 1xSTA + 1x{P2P,NAN} + // Initialize availableModes availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - availableModes.add(cm); + // Mode (only one): 1xSTA + 1xAP, 1xSTA + 1x{P2P,NAN} + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + WifiChip.ChipConcurrencyCombination combo2 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P, + WifiChip.IFACE_CONCURRENCY_TYPE_NAN)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1, combo2)); chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5367,63 +4657,49 @@ public class HalDeviceManagerTest extends WifiBaseTest { super.initialize(); chipMockId = CHIP_MOCK_V5; - chipCapabilities |= android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG; + chipCapabilities |= WifiManager.WIFI_FEATURE_INFRA_60G; // chip Id configuration ArrayList<Integer> chipIds; chipId = CHIP_ID; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(CHIP_ID), - any(IWifi.getChipCallback.class)); - - // initialize placeholder chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - // Mode 0 (only one): 1xSTA + 1xAP, 1xSTA + 1x{P2P,NAN} + // Initialize availableModes availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); + List<WifiChip.ChipConcurrencyCombination> combos = new ArrayList<>(); + + // Mode (only one): 1xSTA + 1xAP, 1xSTA + 1x{P2P,NAN} + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + combos.add(combo1); + + // Simulate HIDL 1.0 to 1.6 conversion for the 1xSTA + 1xAP combo. + if (mIsBridgedSoftApSupported) { + List<WifiChip.ChipConcurrencyCombinationLimit> limits = new ArrayList<>(); + limits.add(createConcurrencyComboLimit( + 1, WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED)); + if (mIsStaWithBridgedSoftApConcurrencySupported) { + limits.add(createConcurrencyComboLimit( + 1, WifiChip.IFACE_CONCURRENCY_TYPE_STA)); + } + WifiChip.ChipConcurrencyCombination combo2 = + new WifiChip.ChipConcurrencyCombination(limits); + combos.add(combo2); + } - cm.availableCombinations.add(cic); - availableModes.add(cm); + WifiChip.ChipConcurrencyCombination combo3 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P, + WifiChip.IFACE_CONCURRENCY_TYPE_NAN)); + combos.add(combo3); + availableModes.add(new WifiChip.ChipMode(CHIP_MODE_ID, combos)); chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5470,61 +4746,25 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = CHIP_ID; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(CHIP_ID), - any(IWifi.getChipCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - // initialize placeholder chip modes - android.hardware.wifi.V1_6.IWifiChip.ChipMode cm; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination ccc; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit cccl; + // Initialize availableModes + availableModes = new ArrayList<>(); // Mode 60 (only one): 1xSTA + 1x{AP,AP_BRIDGED}, 1xSTA + 1x{P2P,NAN} - availableModes_1_6 = new ArrayList<>(); - cm = new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.STA); - ccc.limits.add(cccl); - - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP); - cccl.types.add(IfaceConcurrencyType.AP_BRIDGED); - ccc.limits.add(cccl); - - cm.availableCombinations.add(ccc); - - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceType.STA); - ccc.limits.add(cccl); - - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceType.P2P); - cccl.types.add(IfaceType.NAN); - ccc.limits.add(cccl); - - cm.availableCombinations.add(ccc); - - availableModes_1_6.add(cm); + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP, + WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED)); + WifiChip.ChipConcurrencyCombination combo2 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P, + WifiChip.IFACE_CONCURRENCY_TYPE_NAN)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1, combo2)); chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer_1_6(this)) - .when(chip).getAvailableModes_1_6(any( - android.hardware.wifi.V1_6.IWifiChip.getAvailableModes_1_6Callback - .class)); - mWifiChipV16 = chip; + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5545,70 +4785,33 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 70; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(chipId), - any(IWifi.getChipCallback.class)); + // Initialize availableModes + availableModes = new ArrayList<>(); - // initialize placeholder chip modes - android.hardware.wifi.V1_6.IWifiChip.ChipMode cm; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination ccc; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit cccl; - - availableModes_1_6 = new ArrayList<>(); - - cm = new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - cm.id = DUAL_STA_CHIP_MODE_ID; - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 2; - cccl.types.add(IfaceConcurrencyType.STA); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - availableModes_1_6.add(cm); - - cm = new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - cm.id = AP_CHIP_MODE_ID; - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - availableModes_1_6.add(cm); - - cm = new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - cm.id = AP_AP_BRIDGED_CHIP_MODE_ID; - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.STA); - ccc.limits.add(cccl); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP); - ccc.limits.add(cccl); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP_BRIDGED); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - availableModes_1_6.add(cm); + // Mode: 2xSTA + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(2, WifiChip.IFACE_CONCURRENCY_TYPE_STA)); + availableModes.add(createChipMode(DUAL_STA_CHIP_MODE_ID, combo1)); + + // Mode: 1xAP + WifiChip.ChipConcurrencyCombination combo2 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + availableModes.add(createChipMode(AP_CHIP_MODE_ID, combo2)); + + // Mode: 1xSTA + 1xAP, 1xAP + 1xAP_BRIDGED + WifiChip.ChipConcurrencyCombination combo3 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + WifiChip.ChipConcurrencyCombination combo4 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED)); + availableModes.add(createChipMode(AP_AP_BRIDGED_CHIP_MODE_ID, combo3, combo4)); chipModeIdValidForRtt = DUAL_STA_CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer_1_6(this)) - .when(chip).getAvailableModes_1_6(any( - android.hardware.wifi.V1_6.IWifiChip.getAvailableModes_1_6Callback - .class)); - mWifiChipV16 = chip; + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5625,50 +4828,24 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 80; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(chipId), - any(IWifi.getChipCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); // initialize placeholder chip modes - android.hardware.wifi.V1_6.IWifiChip.ChipMode cm; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination ccc; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit cccl; - - availableModes_1_6 = new ArrayList<>(); - - cm = new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.STA); - ccc.limits.add(cccl); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP); - ccc.limits.add(cccl); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP_BRIDGED); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - availableModes_1_6.add(cm); + availableModes = new ArrayList<>(); + List<WifiChip.ChipConcurrencyCombinationLimit> limits = new ArrayList<>(); - chipModeIdValidForRtt = CHIP_MODE_ID; + // Mode: 1xSTA + 1xAP, 1xAP + 1xAP_BRIDGED + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + WifiChip.ChipConcurrencyCombination combo2 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1, combo2)); - doAnswer(new GetAvailableModesAnswer_1_6(this)) - .when(chip).getAvailableModes_1_6(any( - android.hardware.wifi.V1_6.IWifiChip.getAvailableModes_1_6Callback - .class)); - mWifiChipV16 = chip; + chipModeIdValidForRtt = CHIP_MODE_ID; + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5686,57 +4863,26 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 9; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(chipId), - any(IWifi.getChipCallback.class)); - - // initialize placeholder chip modes - android.hardware.wifi.V1_6.IWifiChip.ChipMode cm; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination ccc; - android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit cccl; + // Initialize availableModes + availableModes = new ArrayList<>(); // Mode 90 (only one): (1xSTA + 1xAP) || (1xAP_BRIDGED) - availableModes_1_6 = new ArrayList<>(); - cm = new android.hardware.wifi.V1_6.IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.STA); - ccc.limits.add(cccl); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 1; - cccl.types.add(IfaceConcurrencyType.AP_BRIDGED); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + WifiChip.ChipConcurrencyCombination combo2 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED)); // Add a combo which doesn't allow any AP. - ccc = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombination(); - cccl = new android.hardware.wifi.V1_6.IWifiChip.ChipConcurrencyCombinationLimit(); - cccl.maxIfaces = 2; - cccl.types.add(IfaceConcurrencyType.STA); - ccc.limits.add(cccl); - cm.availableCombinations.add(ccc); - - availableModes_1_6.add(cm); + WifiChip.ChipConcurrencyCombination combo3 = createConcurrencyCombo( + createConcurrencyComboLimit(2, WifiChip.IFACE_CONCURRENCY_TYPE_STA)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1, combo2, combo3)); chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer_1_6(this)) - .when(chip).getAvailableModes_1_6(any( - android.hardware.wifi.V1_6.IWifiChip.getAvailableModes_1_6Callback - .class)); - mWifiChipV16 = chip; + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } } @@ -5782,66 +4928,31 @@ public class HalDeviceManagerTest extends WifiBaseTest { chipId = 10; chipIds = new ArrayList<>(); chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(10), - any(IWifi.getChipCallback.class)); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); // initialize placeholder chip modes configureDefaultAvailableModes(); chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); } // STA void configureDefaultAvailableModes() { - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - availableModes.add(cm); + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1)); } // STA + AP void configureDriverAvailableModes() { - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - availableModes.add(cm); + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1)); } @Override @@ -5849,90 +4960,4 @@ public class HalDeviceManagerTest extends WifiBaseTest { configureDriverAvailableModes(); } } - - // Test chip configuration V11 to test HAL V1.0 AP + AP combination with bridged AP: - private class TestChipV11 extends ChipMockBase { - static final int CHIP_MODE_ID = 110; - - void initialize() throws Exception { - super.initialize(); - // chip Id configuration - ArrayList<Integer> chipIds; - chipId = 11; - chipIds = new ArrayList<>(); - chipIds.add(chipId); - doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( - any(IWifi.getChipIdsCallback.class)); - - doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(chipId), - any(IWifi.getChipCallback.class)); - - // initialize placeholder chip modes - IWifiChip.ChipMode cm; - IWifiChip.ChipIfaceCombination cic; - IWifiChip.ChipIfaceCombinationLimit cicl; - - availableModes = new ArrayList<>(); - cm = new IWifiChip.ChipMode(); - cm.id = CHIP_MODE_ID; - - // STA + AP - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - // STA + (P2P || NAN) - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 1; - cicl.types.add(IfaceType.P2P); - cicl.types.add(IfaceType.NAN); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - // STA + STA - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 2; - cicl.types.add(IfaceType.STA); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - // AP + AP - cic = new IWifiChip.ChipIfaceCombination(); - - cicl = new IWifiChip.ChipIfaceCombinationLimit(); - cicl.maxIfaces = 2; - cicl.types.add(IfaceType.AP); - cic.limits.add(cicl); - - cm.availableCombinations.add(cic); - - availableModes.add(cm); - - chipModeIdValidForRtt = CHIP_MODE_ID; - - doAnswer(new GetAvailableModesAnswer(this)).when(chip) - .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); - } - } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/InterfaceConflictManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/InterfaceConflictManagerTest.java index 81cfd3e76a..387b5c54dc 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/InterfaceConflictManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/InterfaceConflictManagerTest.java @@ -16,11 +16,17 @@ 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_NAN; +import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P; + import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -88,6 +94,7 @@ public class InterfaceConflictManagerTest { private static final WorkSource TEST_WS = new WorkSource(TEST_UID, TEST_PACKAGE_NAME); private static final int EXISTING_UID = 5678; private static final String EXISTING_PACKAGE_NAME = "existing.package.name"; + private static final String EXISTING_APP_NAME = "Existing App Name"; private static final WorkSource EXISTING_WS = new WorkSource(EXISTING_UID, EXISTING_PACKAGE_NAME); @@ -107,14 +114,21 @@ public class InterfaceConflictManagerTest { when(mResources.getBoolean( R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)).thenReturn(true); - when(mHdm.needsUserApprovalToDelete(anyInt(), any(), anyInt(), any())).thenReturn(true); - - when(mFrameworkFacade.getAppName(any(), anyString(), anyInt())).thenReturn(TEST_APP_NAME); + when(mFrameworkFacade.getAppName(any(), eq(TEST_PACKAGE_NAME), anyInt())) + .thenReturn(TEST_APP_NAME); + when(mFrameworkFacade.getAppName(any(), eq(EXISTING_PACKAGE_NAME), anyInt())) + .thenReturn(EXISTING_APP_NAME); when(mWifiDialogManager.createSimpleDialog( any(), any(), any(), any(), any(), any(), any())).thenReturn(mDialogHandle); when(mWifiInjector.makeWsHelper(eq(TEST_WS))).thenReturn(mWsHelper); when(mWifiInjector.makeWsHelper(eq(EXISTING_WS))).thenReturn(mExistingWsHelper); + when(mWsHelper.getRequestorWsPriority()) + .thenReturn(WorkSourceHelper.PRIORITY_FG_APP); + when(mExistingWsHelper.getRequestorWsPriority()) + .thenReturn(WorkSourceHelper.PRIORITY_FG_APP); + when(mWsHelper.getWorkSource()).thenReturn(TEST_WS); + when(mExistingWsHelper.getWorkSource()).thenReturn(EXISTING_WS); } private void initInterfaceConflictManager() { @@ -226,30 +240,6 @@ public class InterfaceConflictManagerTest { } /** - * Verify that if interface cannot be created or if interface can be created w/o side effects - * then command simply proceeds. - */ - @Test - public void testUserApprovalNotNeeded() { - initInterfaceConflictManager(); - - int interfaceType = HalDeviceManager.HDM_CREATE_IFACE_P2P; - Message msg = Message.obtain(); - - // can delete iface without user approval - when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, - new WorkSource(10, "something else")))); - when(mHdm.needsUserApprovalToDelete(anyInt(), any(), anyInt(), any())).thenReturn(false); - - // request should pass through without the dialog - assertEquals(InterfaceConflictManager.ICM_EXECUTE_COMMAND, - mDut.manageInterfaceConflictForStateMachine("Some Tag", msg, - mStateMachine, mWaitingState, mTargetState, - interfaceType, TEST_WS, false)); - } - - /** * Verify flow with user approval. */ @Test @@ -261,8 +251,7 @@ public class InterfaceConflictManagerTest { // can create interface - but with side effects when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, - new WorkSource(10, "something else")))); + Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, EXISTING_WS))); // send request assertEquals(InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER, @@ -302,8 +291,7 @@ public class InterfaceConflictManagerTest { // can create interface - but with side effects when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, - new WorkSource(10, "something else")))); + Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, EXISTING_WS))); // send request assertEquals(InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER, @@ -343,8 +331,7 @@ public class InterfaceConflictManagerTest { // can create interface - but with side effects when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, - new WorkSource(10, "something else")))); + Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, EXISTING_WS))); // send request assertEquals(InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER, @@ -395,7 +382,7 @@ public class InterfaceConflictManagerTest { // Unexpected impact to create, launch the dialog again when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))) .thenReturn(Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, - new WorkSource(10, "something else")))); + EXISTING_WS))); assertEquals(InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER, mDut.manageInterfaceConflictForStateMachine("Some Tag", waitingMsg, mStateMachine, mWaitingState, mTargetState, interfaceType, TEST_WS, @@ -422,8 +409,7 @@ public class InterfaceConflictManagerTest { // can create interface - but with side effects when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, - new WorkSource(10, "something else")))); + Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, EXISTING_WS))); // send request assertEquals(InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER, @@ -503,8 +489,7 @@ public class InterfaceConflictManagerTest { // can create interface - but with side effects when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_P2P, - new WorkSource(10, "something else")))); + Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_P2P, EXISTING_WS))); // send request assertEquals(InterfaceConflictManager.ICM_EXECUTE_COMMAND, @@ -543,8 +528,7 @@ public class InterfaceConflictManagerTest { // can create interface - but with side effects when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_P2P, - new WorkSource(10, "something else")))); + Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_P2P, EXISTING_WS))); // send request assertEquals(InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER, @@ -571,8 +555,7 @@ public class InterfaceConflictManagerTest { // can create interface - but with side effects when(mHdm.reportImpactToCreateIface(eq(interfaceType), eq(false), eq(TEST_WS))).thenReturn( - Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, - new WorkSource(10, "something else")))); + Arrays.asList(Pair.create(HalDeviceManager.HDM_CREATE_IFACE_NAN, EXISTING_WS))); // send request assertEquals(InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER, @@ -604,4 +587,137 @@ public class InterfaceConflictManagerTest { any(), any(), any(), any(), any(), any(), any()); verify(mDialogHandle, times(2)).launchDialog(); } + + /** + * Tests that + * {@link InterfaceConflictManager#needsUserApprovalToDelete(int, WorkSourceHelper, int, + * WorkSourceHelper)} returns true on the following conditions: + * 1) Requested interface is AP, AP_BRIDGED, P2P, or NAN. + * 2) Existing interface is AP, AP_BRIDGED, P2P, or NAN (but not the same as the requested). + * 3) Requestor worksource has higher priority than PRIORITY_BG. + * 4) Existing worksource is not PRIORITY_INTERNAL. + * 5) User approval is required (by overlay or override). + * 6) Requestor package is not exempt from user approval. + */ + @Test + public void testCanDeleteWithUserApproval() throws Exception { + // No dialog if dialogs aren't enabled. + when(mResources.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)) + .thenReturn(false); + initInterfaceConflictManager(); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_P2P, mWsHelper, + HDM_CREATE_IFACE_AP, mExistingWsHelper)); + + // No dialog if requesting package is exempt. + when(mResources.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)) + .thenReturn(true); + when(mResources.getStringArray( + R.array.config_wifiExcludedFromUserApprovalForD2dInterfacePriority)).thenReturn( + new String[]{TEST_PACKAGE_NAME}); + initInterfaceConflictManager(); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_P2P, mWsHelper, + HDM_CREATE_IFACE_AP, mExistingWsHelper)); + + // No dialog if override is set to false. + when(mResources.getStringArray( + R.array.config_wifiExcludedFromUserApprovalForD2dInterfacePriority)) + .thenReturn(null); + initInterfaceConflictManager(); + mDut.setUserApprovalNeededOverride(true, false); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_P2P, mWsHelper, + HDM_CREATE_IFACE_AP, mExistingWsHelper)); + + // Dialog if overlay is false but override is true. + when(mResources.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)) + .thenReturn(false); + initInterfaceConflictManager(); + mDut.setUserApprovalNeededOverride(true, true); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP, mWsHelper, + HDM_CREATE_IFACE_NAN, mExistingWsHelper)); + + // No dialog if overlay is false and override is changed from true to false. + mDut.setUserApprovalNeededOverride(false, false); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP, mWsHelper, + HDM_CREATE_IFACE_NAN, mExistingWsHelper)); + + // Should show dialog for appropriate types if overlay is set to true. + when(mResources.getBoolean(R.bool.config_wifiUserApprovalRequiredForD2dInterfacePriority)) + .thenReturn(true); + initInterfaceConflictManager(); + + // Requesting AP + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP, mWsHelper, + HDM_CREATE_IFACE_AP, mExistingWsHelper)); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP, mWsHelper, + HDM_CREATE_IFACE_AP_BRIDGE, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP, mWsHelper, + HDM_CREATE_IFACE_NAN, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP, mWsHelper, + HDM_CREATE_IFACE_P2P, mExistingWsHelper)); + + // Requesting AP_BRIDGE + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP_BRIDGE, mWsHelper, + HDM_CREATE_IFACE_AP, mExistingWsHelper)); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP_BRIDGE, mWsHelper, + HDM_CREATE_IFACE_AP_BRIDGE, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP_BRIDGE, mWsHelper, + HDM_CREATE_IFACE_NAN, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_AP_BRIDGE, mWsHelper, + HDM_CREATE_IFACE_P2P, mExistingWsHelper)); + + // Requesting P2P + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_P2P, mWsHelper, + HDM_CREATE_IFACE_AP, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_P2P, mWsHelper, + HDM_CREATE_IFACE_AP_BRIDGE, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_P2P, mWsHelper, + HDM_CREATE_IFACE_NAN, mExistingWsHelper)); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_P2P, mWsHelper, + HDM_CREATE_IFACE_P2P, mExistingWsHelper)); + + // Requesting NAN + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_NAN, mWsHelper, + HDM_CREATE_IFACE_AP, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_NAN, mWsHelper, + HDM_CREATE_IFACE_AP_BRIDGE, mExistingWsHelper)); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_NAN, mWsHelper, + HDM_CREATE_IFACE_NAN, mExistingWsHelper)); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_NAN, mWsHelper, + HDM_CREATE_IFACE_P2P, mExistingWsHelper)); + + // Foreground should show dialog over Privileged + when(mExistingWsHelper.getRequestorWsPriority()) + .thenReturn(WorkSourceHelper.PRIORITY_PRIVILEGED); + assertTrue(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_NAN, mWsHelper, + HDM_CREATE_IFACE_P2P, mExistingWsHelper)); + + // Foreground should delete Internal without showing dialog + when(mExistingWsHelper.getRequestorWsPriority()) + .thenReturn(WorkSourceHelper.PRIORITY_INTERNAL); + assertFalse(mDut.needsUserApprovalToDelete( + HDM_CREATE_IFACE_NAN, mWsHelper, + HDM_CREATE_IFACE_P2P, mExistingWsHelper)); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/MemoryStoreImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/MemoryStoreImplTest.java index 926fe544f5..b3c655c20e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/MemoryStoreImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/MemoryStoreImplTest.java @@ -30,8 +30,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -//import java.util.HashMap; -//import java.util.Map; +import java.util.Arrays; /** * Unit tests for {@link com.android.server.wifi.MemoryStoreImpl}. @@ -106,7 +105,7 @@ public class MemoryStoreImplTest extends WifiBaseTest { @Test public void wifiScoreCardReadShouldCallIpMemoryStoreRetrieveBlob() throws Exception { final byte[] myBlob = new byte[]{0x0, 0x3}; - final String myL2Key = "L2Key:" + myBlob; + final String myL2Key = "L2Key:" + Arrays.toString(myBlob); final android.net.ipmemorystore.Status statusSuccess = new android.net.ipmemorystore.Status(android.net.ipmemorystore.Status.SUCCESS); @@ -144,7 +143,7 @@ public class MemoryStoreImplTest extends WifiBaseTest { @Test public void wifiScoreCardWriteShouldCallIpMemoryStoreStoreBlob() throws Exception { final byte[] myBlob = new byte[]{0x0, 0x3, 0x1}; - final String myL2Key = "L2Key:" + myBlob; + final String myL2Key = "L2Key:" + Arrays.toString(myBlob); when(mWifiInjector.getIpMemoryStore()).thenReturn(mIpMemoryStore); mMemoryStoreImpl.start(); mMemoryStoreImpl.write(myL2Key, DATA_NAME, myBlob); @@ -167,7 +166,7 @@ public class MemoryStoreImplTest extends WifiBaseTest { @Test public void exceptionDisablesFurtherOperations() throws Exception { final byte[] myBlob = new byte[]{0x0, 0x3, 0x1}; - final String myL2Key = "L2Key:" + myBlob; + final String myL2Key = "L2Key:" + Arrays.toString(myBlob); when(mWifiInjector.getIpMemoryStore()).thenReturn(mIpMemoryStore); when(mActiveModeWarden.isShuttingDown()).thenReturn(false); doThrow(new RuntimeException("Just a test")) diff --git a/service/tests/wifitests/src/com/android/server/wifi/MultiInternetManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/MultiInternetManagerTest.java index 4a3d649a20..77e185c854 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/MultiInternetManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/MultiInternetManagerTest.java @@ -22,6 +22,7 @@ import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LO import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -52,6 +53,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** Unit tests for {@link MultiInternetManager}. */ @SmallTest @@ -159,9 +161,9 @@ public class MultiInternetManagerTest extends WifiBaseTest { when(mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet()).thenReturn(true); when(mPrimaryCmm.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); - when(mPrimaryCmm.syncRequestConnectionInfo()).thenReturn(null); + when(mPrimaryCmm.getConnectionInfo()).thenReturn(null); when(mSecondaryCmm.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED); - when(mSecondaryCmm.syncRequestConnectionInfo()).thenReturn(null); + when(mSecondaryCmm.getConnectionInfo()).thenReturn(mock(WifiInfo.class)); when(mSecondaryCmm.isSecondaryInternet()).thenReturn(true); when(mActiveModeWarden.getPrimaryClientModeManagerNullable()).thenReturn(mPrimaryCmm); @@ -171,8 +173,6 @@ public class MultiInternetManagerTest extends WifiBaseTest { List.of(mPrimaryCmm, mSecondaryCmm)); when(mActiveModeWarden.getClientModeManagersInRoles(ROLE_CLIENT_PRIMARY)) .thenReturn(List.of(mPrimaryCmm)); - when(mActiveModeWarden.getClientModeManagersInRoles(ROLE_CLIENT_SECONDARY_LONG_LIVED)) - .thenReturn(List.of(mSecondaryCmm)); when(mActiveModeWarden.getClientModeManagerInRole(ROLE_CLIENT_SECONDARY_LONG_LIVED)) .thenReturn(mSecondaryCmm); @@ -188,14 +188,16 @@ public class MultiInternetManagerTest extends WifiBaseTest { } private void fakePrimaryCmmConnected(boolean isConnected) { - when(mPrimaryCmm.syncRequestConnectionInfo()).thenReturn(isConnected ? mPrimaryInfo : null); + when(mPrimaryCmm.getConnectionInfo()).thenReturn(isConnected ? mPrimaryInfo : null); when(mPrimaryCmm.isConnected()).thenReturn(isConnected); } private void fakeSecondaryCmmConnected(boolean isConnected) { - when(mSecondaryCmm.syncRequestConnectionInfo()).thenReturn( + when(mSecondaryCmm.getConnectionInfo()).thenReturn( isConnected ? mSecondaryInfo : null); when(mSecondaryCmm.isConnected()).thenReturn(isConnected); + when(mSecondaryCmm.getConnectedBssid()).thenReturn( + isConnected ? mSecondaryInfo.getBSSID() : null); } @Test @@ -207,7 +209,7 @@ public class MultiInternetManagerTest extends WifiBaseTest { mModeChangeCallbackCaptor.getValue().onActiveModeManagerRoleChanged(mSecondaryCmm); mModeChangeCallbackCaptor.getValue().onActiveModeManagerAdded(mSecondaryCmm); - verify(mSecondaryCmm, never()).syncRequestConnectionInfo(); + verify(mSecondaryCmm, never()).getConnectionInfo(); assertEquals(0, mMultiInternetManager.getNetworkConnectionState().size()); } @@ -263,13 +265,14 @@ public class MultiInternetManagerTest extends WifiBaseTest { assertTrue(mMultiInternetManager.isStaConcurrencyForMultiInternetEnabled()); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); assertTrue(mMultiInternetManager.getNetworkConnectionState() .contains(ScanResult.WIFI_BAND_5_GHZ)); verify(mConnectionStatusListener).onStatusChange( MultiInternetManager.MULTI_INTERNET_STATE_CONNECTION_REQUESTED, TEST_WORKSOURCE); verify(mConnectionStatusListener).onStartScan(TEST_WORKSOURCE); + assertEquals(0, mMultiInternetManager.getSpecifiedBssids().size()); } @Test @@ -286,7 +289,7 @@ public class MultiInternetManagerTest extends WifiBaseTest { // Set for 2.4G mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); assertTrue(mMultiInternetManager.getNetworkConnectionState() .contains(ScanResult.WIFI_BAND_24_GHZ)); @@ -295,7 +298,7 @@ public class MultiInternetManagerTest extends WifiBaseTest { verify(mConnectionStatusListener).onStartScan(TEST_WORKSOURCE); // Set for 5G mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); assertTrue(mMultiInternetManager.getNetworkConnectionState() .contains(ScanResult.WIFI_BAND_5_GHZ)); verify(mConnectionStatusListener).onStatusChange( @@ -303,11 +306,12 @@ public class MultiInternetManagerTest extends WifiBaseTest { verify(mConnectionStatusListener, times(2)).onStartScan(TEST_WORKSOURCE); // Clear the WorkSource mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, - null); + null, null); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - null); + null, null); assertFalse(mMultiInternetManager.hasPendingConnectionRequests()); assertEquals(0, mMultiInternetManager.getNetworkConnectionState().size()); + assertEquals(0, mMultiInternetManager.getSpecifiedBssids().size()); } @Test @@ -315,7 +319,7 @@ public class MultiInternetManagerTest extends WifiBaseTest { assertTrue(mMultiInternetManager.setStaConcurrencyForMultiInternetMode( WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP)); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - TEST_WORKSOURCE); + TEST_BSSID2, TEST_WORKSOURCE); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); fakePrimaryCmmConnected(true); fakeSecondaryCmmConnected(true); @@ -325,6 +329,23 @@ public class MultiInternetManagerTest extends WifiBaseTest { .contains(ScanResult.WIFI_BAND_5_GHZ)); assertTrue(mMultiInternetManager.getNetworkConnectionState() .get(ScanResult.WIFI_BAND_5_GHZ).isValidated()); + assertEquals(1, mMultiInternetManager.getSpecifiedBssids().size()); + + // Add another request with the same band and BSSID specified and verify no disconnect + mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, + TEST_BSSID2, TEST_WORKSOURCE); + verify(mSecondaryCmm, never()).disconnect(); + + // Add another request with a different band and BSSID specified and verify no disconnect + mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, + TEST_BSSID2, TEST_WORKSOURCE); + verify(mSecondaryCmm, never()).disconnect(); + + // Add another request with the same band but different BSSID and verify disconnect + mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, + TEST_BSSID3, TEST_WORKSOURCE); + verify(mSecondaryCmm).disconnect(); + assertEquals(2, mMultiInternetManager.getSpecifiedBssids().size()); } @Test @@ -332,9 +353,9 @@ public class MultiInternetManagerTest extends WifiBaseTest { assertTrue(mMultiInternetManager.setStaConcurrencyForMultiInternetMode( WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP)); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); fakePrimaryCmmConnected(true); fakeSecondaryCmmConnected(true); @@ -342,6 +363,7 @@ public class MultiInternetManagerTest extends WifiBaseTest { assertFalse(mMultiInternetManager.hasPendingConnectionRequests()); assertTrue(mMultiInternetManager.getNetworkConnectionState() .get(ScanResult.WIFI_BAND_5_GHZ).isConnected()); + assertEquals(0, mMultiInternetManager.getSpecifiedBssids().size()); } @Test @@ -349,9 +371,9 @@ public class MultiInternetManagerTest extends WifiBaseTest { assertTrue(mMultiInternetManager.setStaConcurrencyForMultiInternetMode( WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP)); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); fakePrimaryCmmConnected(true); fakeSecondaryCmmConnected(true); @@ -362,6 +384,7 @@ public class MultiInternetManagerTest extends WifiBaseTest { mCmiListenerCaptor.getValue().onConnectionEnd(mPrimaryCmm); verify(mSecondaryCmm).disconnect(); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); + assertEquals(0, mMultiInternetManager.getSpecifiedBssids().size()); } @Test @@ -373,9 +396,9 @@ public class MultiInternetManagerTest extends WifiBaseTest { long currentTimeStamp = 1000; when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - TEST_WORKSOURCE2); + null, TEST_WORKSOURCE2); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); for (int i = 0; i < 5; i++) { currentTimeStamp += SCAN_INTERVAL; @@ -385,6 +408,7 @@ public class MultiInternetManagerTest extends WifiBaseTest { verify(mConnectionStatusListener, times(1)).onStatusChange( MultiInternetManager.MULTI_INTERNET_STATE_CONNECTION_REQUESTED, TEST_WORKSOURCE2); verify(mConnectionStatusListener, times(1)).onStartScan(TEST_WORKSOURCE2); + assertEquals(0, mMultiInternetManager.getSpecifiedBssids().size()); } @Test @@ -392,9 +416,9 @@ public class MultiInternetManagerTest extends WifiBaseTest { assertTrue(mMultiInternetManager.setStaConcurrencyForMultiInternetMode( WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP)); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, - TEST_WORKSOURCE); + null, TEST_WORKSOURCE); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); fakePrimaryCmmConnected(true); fakeSecondaryCmmConnected(true); @@ -403,9 +427,32 @@ public class MultiInternetManagerTest extends WifiBaseTest { // Primary roamed to same frequency as secondary mPrimaryInfo.setBSSID(TEST_BSSID3); mPrimaryInfo.setFrequency(TEST_FREQUENCY2); - when(mPrimaryCmm.syncRequestConnectionInfo()).thenReturn(mPrimaryInfo); + when(mPrimaryCmm.getConnectionInfo()).thenReturn(mPrimaryInfo); mMultiInternetManager.notifyBssidAssociatedEvent(mPrimaryCmm); verify(mSecondaryCmm).disconnect(); assertTrue(mMultiInternetManager.hasPendingConnectionRequests()); + assertEquals(0, mMultiInternetManager.getSpecifiedBssids().size()); + } + + @Test + public void testGetSpecifiedBssids() { + assertTrue(mMultiInternetManager.setStaConcurrencyForMultiInternetMode( + WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP)); + mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_24_GHZ, + TEST_BSSID1, TEST_WORKSOURCE); + mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, + TEST_BSSID2, TEST_WORKSOURCE); + Map<Integer, String> specifiedBssids = mMultiInternetManager.getSpecifiedBssids(); + assertEquals(2, specifiedBssids.size()); + assertEquals(TEST_BSSID1, specifiedBssids.get(ScanResult.WIFI_BAND_24_GHZ)); + assertEquals(TEST_BSSID2, specifiedBssids.get(ScanResult.WIFI_BAND_5_GHZ)); + + // verify overriding existing BSSID mapping + mMultiInternetManager.setMultiInternetConnectionWorksource(ScanResult.WIFI_BAND_5_GHZ, + TEST_BSSID3, TEST_WORKSOURCE); + specifiedBssids = mMultiInternetManager.getSpecifiedBssids(); + assertEquals(2, specifiedBssids.size()); + assertEquals(TEST_BSSID1, specifiedBssids.get(ScanResult.WIFI_BAND_24_GHZ)); + assertEquals(TEST_BSSID3, specifiedBssids.get(ScanResult.WIFI_BAND_5_GHZ)); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/MultiInternetWifiNetworkFactoryTest.java b/service/tests/wifitests/src/com/android/server/wifi/MultiInternetWifiNetworkFactoryTest.java index a3ece062e5..70412573f0 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/MultiInternetWifiNetworkFactoryTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/MultiInternetWifiNetworkFactoryTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyObject; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.validateMockitoUsage; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -121,14 +122,19 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { @Test public void testIsWifiMultiInternetRequest() { - assertFalse(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(mNetworkRequest2G)); - assertFalse(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(mNetworkRequest5G)); + // Test when caller is no settings + assertFalse(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( + mNetworkRequest2G, false)); + assertFalse(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( + mNetworkRequest5G, false)); mNetworkRequest2G.networkCapabilities.addCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET); mNetworkRequest5G.networkCapabilities.addCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET); - assertTrue(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(mNetworkRequest2G)); - assertTrue(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest(mNetworkRequest5G)); + assertTrue(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( + mNetworkRequest2G, false)); + assertTrue(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( + mNetworkRequest5G, false)); final NetworkRequest networkRequestNoBandSpecifier = new NetworkRequest.Builder() .setCapabilities(mNetworkCapabilities) .setNetworkSpecifier(new WifiNetworkSpecifier.Builder() @@ -136,7 +142,7 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { .build()) .build(); assertFalse(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( - networkRequestNoBandSpecifier)); + networkRequestNoBandSpecifier, false)); final NetworkRequest networkRequestSSIDSpecifier = new NetworkRequest.Builder() .setCapabilities(mNetworkCapabilities) .setNetworkSpecifier(new WifiNetworkSpecifier.Builder() @@ -146,7 +152,7 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { .build()) .build(); assertFalse(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( - networkRequestSSIDSpecifier)); + networkRequestSSIDSpecifier, false)); final NetworkRequest networkRequestBSSIDSpecifier = new NetworkRequest.Builder() .setCapabilities(mNetworkCapabilities) .setNetworkSpecifier(new WifiNetworkSpecifier.Builder() @@ -154,8 +160,14 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { .setBand(ScanResult.WIFI_BAND_5_GHZ) .build()) .build(); + networkRequestBSSIDSpecifier.networkCapabilities.addCapability( + NetworkCapabilities.NET_CAPABILITY_INTERNET); assertFalse(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( - networkRequestBSSIDSpecifier)); + networkRequestBSSIDSpecifier, false)); + + // test when the caller is settings + assertTrue(MultiInternetWifiNetworkFactory.isWifiMultiInternetRequest( + networkRequestBSSIDSpecifier, true)); } /** @@ -170,7 +182,7 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest2G); // First network request should notify MultiInternetManager. verify(mMultiInternetManager).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_24_GHZ, TEST_WORKSOURCE); + ScanResult.WIFI_BAND_24_GHZ, null, TEST_WORKSOURCE); // Subsequent ones should do nothing. mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest2G); @@ -178,6 +190,34 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { } /** + * Validates handling of needNetworkFor. + */ + @Test + public void testMultiInternetHandleNetworkRequestFromSettingsWithBssid() { + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); + when(mMultiInternetManager.isStaConcurrencyForMultiInternetEnabled()).thenReturn(true); + final NetworkRequest networkRequestBSSIDSpecifier = new NetworkRequest.Builder() + .setCapabilities(mNetworkCapabilities) + .setNetworkSpecifier(new WifiNetworkSpecifier.Builder() + .setBssid(MacAddress.fromString(TEST_BSSID)) + .setBand(ScanResult.WIFI_BAND_5_GHZ) + .build()) + .build(); + networkRequestBSSIDSpecifier.networkCapabilities.addCapability( + NetworkCapabilities.NET_CAPABILITY_INTERNET); + + mMultiInternetWifiNetworkFactory.needNetworkFor(networkRequestBSSIDSpecifier); + // First network request should notify MultiInternetManager. + verify(mMultiInternetManager).setMultiInternetConnectionWorksource( + ScanResult.WIFI_BAND_5_GHZ, TEST_BSSID, TEST_WORKSOURCE); + + // Subsequent ones send it to MultiInternetManagerAgain since it's from Settings. + mMultiInternetWifiNetworkFactory.needNetworkFor(networkRequestBSSIDSpecifier); + verify(mMultiInternetManager, times(2)).setMultiInternetConnectionWorksource( + ScanResult.WIFI_BAND_5_GHZ, TEST_BSSID, TEST_WORKSOURCE); + } + + /** * Validates handling of needNetworkFor of dual bands. */ @Test @@ -192,16 +232,16 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest5G); // First network request should notify MultiInternetManager. verify(mMultiInternetManager).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_24_GHZ, TEST_WORKSOURCE); + ScanResult.WIFI_BAND_24_GHZ, null, TEST_WORKSOURCE); verify(mMultiInternetManager).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_5_GHZ, TEST_WORKSOURCE); + ScanResult.WIFI_BAND_5_GHZ, null, TEST_WORKSOURCE); reset(mMultiInternetManager); // Subsequent ones should do nothing. mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest2G); mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest5G); verify(mMultiInternetManager, never()).setMultiInternetConnectionWorksource(anyInt(), - anyObject()); + anyObject(), anyObject()); verifyNoMoreInteractions(mWifiConnectivityManager); } @@ -219,11 +259,11 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { // Now request & then release the network request mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest2G); verify(mMultiInternetManager).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_24_GHZ, TEST_WORKSOURCE); + ScanResult.WIFI_BAND_24_GHZ, null, TEST_WORKSOURCE); mMultiInternetWifiNetworkFactory.releaseNetworkFor(mNetworkRequest2G); verify(mMultiInternetManager).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_24_GHZ, null); + ScanResult.WIFI_BAND_24_GHZ, null, null); } /** @@ -240,7 +280,7 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { // Now request & then release the network request mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest5G); verify(mMultiInternetManager).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_5_GHZ, TEST_WORKSOURCE); + ScanResult.WIFI_BAND_5_GHZ, null, TEST_WORKSOURCE); // Now request the network again for 2 times. mMultiInternetWifiNetworkFactory.needNetworkFor(mNetworkRequest5G); @@ -248,10 +288,10 @@ public class MultiInternetWifiNetworkFactoryTest extends WifiBaseTest { mMultiInternetWifiNetworkFactory.releaseNetworkFor(mNetworkRequest5G); verify(mMultiInternetManager, never()).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_5_GHZ, null); + ScanResult.WIFI_BAND_5_GHZ, null, null); mMultiInternetWifiNetworkFactory.releaseNetworkFor(mNetworkRequest5G); mMultiInternetWifiNetworkFactory.releaseNetworkFor(mNetworkRequest5G); verify(mMultiInternetManager).setMultiInternetConnectionWorksource( - ScanResult.WIFI_BAND_5_GHZ, null); + ScanResult.WIFI_BAND_5_GHZ, null, null); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/service/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java index 694638ebab..84cca7fd50 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java @@ -267,6 +267,7 @@ public class NetworkListStoreDataTest extends WifiBaseTest { ? "<null name=\"DecoratedIdentityPrefix\" />\n" : "") + "<boolean name=\"TrustOnFirstUse\" value=\"false\" />\n" + "<boolean name=\"UserApproveNoCaCert\" value=\"false\" />\n" + + "<int name=\"MinimumTlsVersion\" value=\"3\" />\n" + "</WifiEnterpriseConfiguration>\n" + "</Network>\n";; @@ -457,6 +458,7 @@ public class NetworkListStoreDataTest extends WifiBaseTest { ? "<null name=\"DecoratedIdentityPrefix\" />\n" : "") + "<boolean name=\"TrustOnFirstUse\" value=\"false\" />\n" + "<boolean name=\"UserApproveNoCaCert\" value=\"false\" />\n" + + "<int name=\"MinimumTlsVersion\" value=\"0\" />\n" + "</WifiEnterpriseConfiguration>\n" + "</Network>\n";; @@ -594,6 +596,7 @@ public class NetworkListStoreDataTest extends WifiBaseTest { eapNetwork.setIpConfiguration( WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy()); eapNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); + eapNetwork.enterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_V1_3); WifiConfiguration saeNetwork = WifiConfigurationTestUtil.createSaeNetwork(); saeNetwork.shared = shared; saeNetwork.creatorName = TEST_CREATOR_NAME; @@ -943,20 +946,6 @@ public class NetworkListStoreDataTest extends WifiBaseTest { saeNetwork.shared, saeNetwork.creatorUid, saeNetwork.creatorName, saeNetwork.getRandomizedMacAddress()); - saeNetworkWithOpenAuthXml.replaceAll("name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>", - "<name=\"AllowedAuthAlgos\" num=\"1\">01</byte-array>"); - - saeNetworkWithOpenAuthXml.replaceAll("name=\"AllowedProtocols\" num=\"1\">02</byte-array>", - "name=\"AllowedProtocols\" num=\"1\">03</byte-array>"); - - saeNetworkWithOpenAuthXml.replaceAll( - "name=\"AllowedGroupCiphers\" num=\"1\">28</byte-array>", - "name=\"AllowedGroupCiphers\" num=\"1\">0f</byte-array>"); - - saeNetworkWithOpenAuthXml.replaceAll( - "name=\"AllowedPairwiseCiphers\" num=\"1\">0c</byte-array>", - "name=\"AllowedPairwiseCiphers\" num=\"1\">06</byte-array>"); - List<WifiConfiguration> retrievedNetworkList = deserializeData(saeNetworkWithOpenAuthXml.getBytes(StandardCharsets.UTF_8)); @@ -1006,7 +995,7 @@ public class NetworkListStoreDataTest extends WifiBaseTest { pskNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC); pskNetwork.creatorName = TEST_CREATOR_NAME; String invalidConfigKey = pskNetwork.getKey(); - invalidConfigKey.replace("WPA_PSK", "NONE"); + invalidConfigKey = invalidConfigKey.replace("WPA_PSK", "NONE"); // XML data has 2 things that needs to be corrected: // - ConfigKey is set to "SSID"NONE instead of "SSID"WPA_PSK // - KeyMgmt has KeyMgmt.OSEN bit set instead of KeyMgmt.WPA_PSK diff --git a/service/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java b/service/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java index 904b578f73..37639825ab 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java @@ -42,7 +42,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -117,9 +116,8 @@ public class NetworkRequestStoreDataTest extends WifiBaseTest { AccessPoint accessPoint = new AccessPoint( WifiConfigurationTestUtil.createPskNetwork().SSID, MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_PSK); - Set<AccessPoint> accessPoints = new HashSet<AccessPoint>() {{ - add(accessPoint); - }}; + Set<AccessPoint> accessPoints = Set.of(accessPoint); + approvedAccessPointsMap.put(TEST_PACKAGE_NAME_1, accessPoints); assertSerializeDeserialize(approvedAccessPointsMap); @@ -135,17 +133,15 @@ public class NetworkRequestStoreDataTest extends WifiBaseTest { AccessPoint accessPoint1 = new AccessPoint( WifiConfigurationTestUtil.createPskNetwork().SSID, MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_PSK); - Set<AccessPoint> accessPoints1 = new HashSet<AccessPoint>() {{ - add(accessPoint1); - }}; + Set<AccessPoint> accessPoints1 = Set.of(accessPoint1); + approvedAccessPointsMap.put(TEST_PACKAGE_NAME_1, accessPoints1); AccessPoint accessPoint2 = new AccessPoint( WifiConfigurationTestUtil.createPskNetwork().SSID, MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_PSK); - Set<AccessPoint> accessPoints2 = new HashSet<AccessPoint>() {{ - add(accessPoint2); - }}; + Set<AccessPoint> accessPoints2 = Set.of(accessPoint2); + approvedAccessPointsMap.put(TEST_PACKAGE_NAME_2, accessPoints2); assertSerializeDeserialize(approvedAccessPointsMap); @@ -164,10 +160,10 @@ public class NetworkRequestStoreDataTest extends WifiBaseTest { AccessPoint accessPoint2 = new AccessPoint( WifiConfigurationTestUtil.createOpenNetwork().SSID, MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_OPEN); - Set<AccessPoint> accessPoints1 = new HashSet<AccessPoint>() {{ - add(accessPoint1); - add(accessPoint2); - }}; + Set<AccessPoint> accessPoints1 = Set.of( + accessPoint1, + accessPoint2); + approvedAccessPointsMap.put(TEST_PACKAGE_NAME_1, accessPoints1); AccessPoint accessPoint3 = new AccessPoint( @@ -176,10 +172,10 @@ public class NetworkRequestStoreDataTest extends WifiBaseTest { AccessPoint accessPoint4 = new AccessPoint( WifiConfigurationTestUtil.createOpenNetwork().SSID, MacAddressUtils.createRandomUnicastAddress(), WifiConfiguration.SECURITY_TYPE_OPEN); - Set<AccessPoint> accessPoints2 = new HashSet<AccessPoint>() {{ - add(accessPoint3); - add(accessPoint4); - }}; + Set<AccessPoint> accessPoints2 = Set.of( + accessPoint3, + accessPoint4); + approvedAccessPointsMap.put(TEST_PACKAGE_NAME_2, accessPoints2); assertSerializeDeserialize(approvedAccessPointsMap); diff --git a/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java b/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java index 6e9f26c79b..5b2e901c95 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java @@ -1792,12 +1792,9 @@ public class NetworkSuggestionNominatorTest extends WifiBaseTest { for (int i = 0; i < minLength; i++) { ScanDetail scanDetail = scanDetails[i]; final ExtendedWifiNetworkSuggestion matchingSuggestion = suggestions[i]; - HashSet<ExtendedWifiNetworkSuggestion> matchingSuggestions = - new HashSet<ExtendedWifiNetworkSuggestion>() {{ - add(matchingSuggestion); - }}; + Set<ExtendedWifiNetworkSuggestion> matchingSuggestions = Set.of(matchingSuggestion); when(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail(eq(scanDetail))) - .thenReturn((matchingSuggestions)); + .thenReturn(matchingSuggestions); } if (scanDetails.length > suggestions.length) { // No match for the remaining scan details. @@ -1812,7 +1809,7 @@ public class NetworkSuggestionNominatorTest extends WifiBaseTest { Arrays.asList(suggestions).subList(minLength - 1, suggestions.length)); ScanDetail lastScanDetail = scanDetails[minLength - 1]; when(mWifiNetworkSuggestionsManager.getNetworkSuggestionsForScanDetail( - eq(lastScanDetail))).thenReturn((matchingSuggestions)); + eq(lastScanDetail))).thenReturn(matchingSuggestions); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java b/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java index de777a1e8c..abaa8e4e8a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java @@ -447,7 +447,7 @@ public class NetworkSuggestionStoreDataTest extends WifiBaseTest { // Old format with empty suggestion String preRFormatXml = String.format( - TEST_PRE_R_APP_WITH_EMPTY_SUGGESTION, TEST_PACKAGE_NAME_1, TEST_UID_1); + TEST_PRE_R_APP_WITH_EMPTY_SUGGESTION, TEST_PACKAGE_NAME_1); deserializeData(preRFormatXml.getBytes()); // New format with empty suggestion diff --git a/service/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java b/service/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java index ef2c0fac11..430099e603 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java @@ -39,13 +39,13 @@ import android.net.wifi.WifiScanner.ScanSettings.HiddenNetwork; import android.os.Handler; import android.os.IBinder; import android.os.UserHandle; -import android.os.WorkSource; import android.os.test.TestLooper; import android.text.TextUtils; import androidx.test.filters.SmallTest; import com.android.modules.utils.build.SdkLevel; +import com.android.server.wifi.scanner.WifiScannerInternal; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.wifi.resources.R; @@ -71,24 +71,19 @@ public class ScanRequestProxyTest extends WifiBaseTest { private static final String TEST_PACKAGE_NAME_2 = "com.test.2"; private static final String TEST_HIDDEN_NETWORK_MAC = "10:22:34:56:78:92"; private static final String TEST_HIDDEN_NETWORK_SSID = "HideMe"; - private static final List<HiddenNetwork> TEST_HIDDEN_NETWORKS_LIST = - new ArrayList<HiddenNetwork>() {{ - add(new HiddenNetwork("test_ssid_1")); - add(new HiddenNetwork("test_ssid_2")); - - }}; - private static final List<HiddenNetwork> TEST_HIDDEN_NETWORKS_LIST_NS = - new ArrayList<HiddenNetwork>() {{ - add(new HiddenNetwork("test_ssid_3")); - add(new HiddenNetwork("test_ssid_4")); - }}; + private static final List<HiddenNetwork> TEST_HIDDEN_NETWORKS_LIST = List.of( + new HiddenNetwork("test_ssid_1"), + new HiddenNetwork("test_ssid_2")); + private static final List<HiddenNetwork> TEST_HIDDEN_NETWORKS_LIST_NS = List.of( + new HiddenNetwork("test_ssid_3"), + new HiddenNetwork("test_ssid_4")); @Mock private Context mContext; @Mock private AppOpsManager mAppOps; @Mock private ActivityManager mActivityManager; @Mock private WifiInjector mWifiInjector; @Mock private WifiConfigManager mWifiConfigManager; - @Mock private WifiScanner mWifiScanner; + @Mock private WifiScannerInternal mWifiScanner; @Mock private WifiPermissionsUtil mWifiPermissionsUtil; @Mock private WifiMetrics mWifiMetrics; @Mock private WifiMetrics.ScanMetrics mScanMetrics; @@ -97,23 +92,20 @@ public class ScanRequestProxyTest extends WifiBaseTest { @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; @Mock private IScanResultsCallback mScanResultsCallback; @Mock private IScanResultsCallback mAnotherScanResultsCallback; - @Mock private TestLooper mLooper; @Mock private IBinder mBinder; @Mock private IBinder mAnotherBinder; - private ArgumentCaptor<WorkSource> mWorkSourceArgumentCaptor = - ArgumentCaptor.forClass(WorkSource.class); private ArgumentCaptor<WifiScanner.ScanSettings> mScanSettingsArgumentCaptor = ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); - private ArgumentCaptor<WifiScanner.ScanListener> mScanRequestListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); - private ArgumentCaptor<WifiScanner.ScanListener> mGlobalScanListenerArgumentCaptor = - ArgumentCaptor.forClass(WifiScanner.ScanListener.class); + private ArgumentCaptor<WifiScannerInternal.ScanListener> mScanRequestListenerArgumentCaptor = + ArgumentCaptor.forClass(WifiScannerInternal.ScanListener.class); + private ArgumentCaptor<WifiScannerInternal.ScanListener> mGlobalScanListenerArgumentCaptor = + ArgumentCaptor.forClass(WifiScannerInternal.ScanListener.class); private WifiScanner.ScanData[] mTestScanDatas1; private WifiScanner.ScanData[] mTestScanDatas2; private WifiScanner.ScanData[] mTestHiddenNetworkScanDatas; private InOrder mInOrder; - + private TestLooper mLooper; private ScanRequestProxy mScanRequestProxy; private MockResources mResources; @@ -125,10 +117,11 @@ public class ScanRequestProxyTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - + mLooper = new TestLooper(); mResources = getMockResources(); when(mContext.getResources()).thenReturn(mResources); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); + WifiLocalServices.removeServiceForTest(WifiScannerInternal.class); + WifiLocalServices.addService(WifiScannerInternal.class, mWifiScanner); when(mWifiInjector.getWifiNetworkSuggestionsManager()) .thenReturn(mWifiNetworkSuggestionsManager); when(mWifiConfigManager.retrieveHiddenNetworkList(false /* autoJoinOnly */)) @@ -137,13 +130,10 @@ public class ScanRequestProxyTest extends WifiBaseTest { .thenReturn(TEST_HIDDEN_NETWORKS_LIST_NS); when(mWifiMetrics.getScanMetrics()).thenReturn(mScanMetrics); doNothing().when(mWifiScanner).registerScanListener( - any(), mGlobalScanListenerArgumentCaptor.capture()); doNothing().when(mWifiScanner).startScan( mScanSettingsArgumentCaptor.capture(), - any(), - mScanRequestListenerArgumentCaptor.capture(), - mWorkSourceArgumentCaptor.capture()); + mScanRequestListenerArgumentCaptor.capture(), any()); mInOrder = inOrder(mWifiScanner, mWifiConfigManager, mContext, mWifiNetworkSuggestionsManager); @@ -158,7 +148,6 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Scan throttling is enabled by default. when(mWifiSettingsConfigStore.get(eq(WIFI_SCAN_THROTTLE_ENABLED))).thenReturn(true); - mLooper = new TestLooper(); mScanRequestProxy = new ScanRequestProxy(mContext, mAppOps, mActivityManager, mWifiInjector, mWifiConfigManager, mWifiPermissionsUtil, mWifiMetrics, mClock, @@ -176,7 +165,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { private void enableScanning() { // Enable scanning mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); + mInOrder.verify(mWifiScanner).registerScanListener(any()); mInOrder.verify(mWifiScanner).setScanningEnabled(true); validateScanAvailableBroadcastSent(true); @@ -205,7 +194,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { @Test public void testEnableScanning() { mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); + mInOrder.verify(mWifiScanner).registerScanListener(any()); mInOrder.verify(mWifiScanner).setScanningEnabled(true); validateScanAvailableBroadcastSent(true); } @@ -216,7 +205,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { @Test public void testDisableScanning() { mScanRequestProxy.enableScanning(false, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); + mInOrder.verify(mWifiScanner).registerScanListener(any()); mInOrder.verify(mWifiScanner).setScanningEnabled(false); validateScanAvailableBroadcastSent(false); } @@ -238,10 +227,8 @@ public class ScanRequestProxyTest extends WifiBaseTest { public void testStartScanSuccess() { enableScanning(); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); - assertTrue(mWorkSourceArgumentCaptor.getValue().equals( - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1))); validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false); verifyScanMetricsDataWasSet(); @@ -255,10 +242,8 @@ public class ScanRequestProxyTest extends WifiBaseTest { enableScanning(); when(mWifiPermissionsUtil.checkNetworkSettingsPermission(TEST_UID)).thenReturn(true); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); - assertTrue(mWorkSourceArgumentCaptor.getValue().equals( - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1))); validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false, true); verifyScanMetricsDataWasSet(0, 1); if (SdkLevel.isAtLeastS()) { @@ -275,10 +260,8 @@ public class ScanRequestProxyTest extends WifiBaseTest { enableScanning(); when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(TEST_UID)).thenReturn(true); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); - assertEquals(mWorkSourceArgumentCaptor.getValue(), - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)); validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false, true); verifyScanMetricsDataWasSet(0, 1); } @@ -289,7 +272,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { @Test public void testStartScanWithHiddenNetworkScanningDisabled() { mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); + mInOrder.verify(mWifiScanner).registerScanListener(any()); mInOrder.verify(mWifiScanner).setScanningEnabled(true); validateScanAvailableBroadcastSent(true); @@ -298,10 +281,8 @@ public class ScanRequestProxyTest extends WifiBaseTest { .retrieveHiddenNetworkList(false /* autoJoinOnly */); mInOrder.verify(mWifiNetworkSuggestionsManager, never()) .retrieveHiddenNetworkList(false /* autoJoinOnly */); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); - assertEquals(mWorkSourceArgumentCaptor.getValue(), - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)); validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false); verifyScanMetricsDataWasSet(); @@ -313,7 +294,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { @Test public void testStartScanWithHiddenNetworkScanningEnabled() { mScanRequestProxy.enableScanning(true, true); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); + mInOrder.verify(mWifiScanner).registerScanListener(any()); mInOrder.verify(mWifiScanner).setScanningEnabled(true); validateScanAvailableBroadcastSent(true); @@ -323,10 +304,8 @@ public class ScanRequestProxyTest extends WifiBaseTest { .retrieveHiddenNetworkList(false /* autoJoinOnly */); mInOrder.verify(mWifiNetworkSuggestionsManager) .retrieveHiddenNetworkList(false /* autoJoinOnly */); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); - assertEquals(mWorkSourceArgumentCaptor.getValue(), - new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)); validateScanSettings(mScanSettingsArgumentCaptor.getValue(), true); verifyScanMetricsDataWasSet(); @@ -336,12 +315,13 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify a successful scan request and processing of scan results. */ @Test - public void testScanSuccess() { + public void testScanSuccess() throws Exception { // Make a scan request. testStartScanSuccess(); // Verify the scan results processing. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. @@ -358,12 +338,13 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify a successful scan request and processing of scan failure. */ @Test - public void testScanFailure() { + public void testScanFailure() throws Exception { // Make a scan request. testStartScanSuccess(); // Verify the scan failure processing. mScanRequestListenerArgumentCaptor.getValue().onFailure(0, "failed"); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(false); // Ensure scan results in the cache is empty. @@ -377,13 +358,14 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify processing of successive successful scans. */ @Test - public void testScanSuccessOverwritesPreviousResults() { + public void testScanSuccessOverwritesPreviousResults() throws Exception { enableScanning(); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Verify the scan results processing for request 1. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -394,9 +376,10 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Make scan request 2. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Verify the scan results processing for request 2. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -412,13 +395,14 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify processing of a successful scan followed by a failure. */ @Test - public void testScanFailureDoesNotOverwritePreviousResults() { + public void testScanFailureDoesNotOverwritePreviousResults() throws Exception { enableScanning(); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Verify the scan results processing for request 1. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -429,9 +413,10 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Make scan request 2. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Verify the scan failure processing. mScanRequestListenerArgumentCaptor.getValue().onFailure(0, "failed"); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(false); // Validate the scan results from a previous successful scan in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -448,13 +433,14 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify that we send out two broadcasts (two successes). */ @Test - public void testNewScanRequestAfterPreviousScanSucceeds() { + public void testNewScanRequestAfterPreviousScanSucceeds() throws Exception { enableScanning(); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Now send the scan results for request 1. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -466,9 +452,10 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Make scan request 2. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Now send the scan results for request 2. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -486,15 +473,16 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify that we send out two broadcasts (one failure & one success). */ @Test - public void testNewScanRequestAfterPreviousScanSucceedsWithInvalidScanDatas() { + public void testNewScanRequestAfterPreviousScanSucceedsWithInvalidScanDatas() throws Exception { enableScanning(); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Now send scan success for request 1, but with invalid scan datas. mGlobalScanListenerArgumentCaptor.getValue().onResults( new WifiScanner.ScanData[] {mTestScanDatas1[0], mTestScanDatas2[0]}); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(false); // Validate the scan results in the cache. assertTrue(mScanRequestProxy.getScanResults().isEmpty()); @@ -503,9 +491,10 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Make scan request 2. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Now send the scan results for request 2. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -523,14 +512,15 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify that we send out two broadcasts (one failure & one success). */ @Test - public void testNewScanRequestAfterPreviousScanFailure() { + public void testNewScanRequestAfterPreviousScanFailure() throws Exception { enableScanning(); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Now send scan failure for request 1. mScanRequestListenerArgumentCaptor.getValue().onFailure(0, "failed"); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(false); // Validate the scan results in the cache. assertTrue(mScanRequestProxy.getScanResults().isEmpty()); @@ -539,9 +529,10 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Make scan request 2. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Now send the scan results for request 2. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -557,18 +548,19 @@ public class ScanRequestProxyTest extends WifiBaseTest { * Verify that we clear scan results when scan state is toggled. */ @Test - public void testToggleScanStateClearsScanResults() { + public void testToggleScanStateClearsScanResults() throws Exception { // Enable scanning mScanRequestProxy.enableScanning(true, false); - mInOrder.verify(mWifiScanner).registerScanListener(any(), any()); + mInOrder.verify(mWifiScanner).registerScanListener(any()); mInOrder.verify(mWifiScanner).setScanningEnabled(true); validateScanAvailableBroadcastSent(true); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Verify the scan results processing for request 1. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -606,17 +598,17 @@ public class ScanRequestProxyTest extends WifiBaseTest { @Test public void testSuccessiveScanRequestsDontUseSameListener() { enableScanning(); - WifiScanner.ScanListener listener1; - WifiScanner.ScanListener listener2; + WifiScannerInternal.ScanListener listener1; + WifiScannerInternal.ScanListener listener2; // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); listener1 = mScanRequestListenerArgumentCaptor.getValue(); // Make scan request 2. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); // Ensure that we did send a second scan request to scanner. - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); listener2 = mScanRequestListenerArgumentCaptor.getValue(); assertNotEquals(listener1, listener2); @@ -638,11 +630,11 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Make next scan request from the same package name & ensure that it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1); if (SdkLevel.isAtLeastS()) { assertTrue("6Ghz PSC should be enabled for scan requests from normal apps.", @@ -663,7 +655,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Make next scan request from the same package name & ensure that it is throttled. assertFalse(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); @@ -687,13 +679,13 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } long lastRequestMs = firstRequestMs + SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS + 1; when(mClock.getElapsedSinceBootMillis()).thenReturn(lastRequestMs); // Make next scan request from the same package name & ensure that it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1); } @@ -712,11 +704,11 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Make next scan request from the same package name & ensure that it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(0, SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1); } @@ -735,11 +727,11 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Make next scan request from the same package name & ensure that it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(0, SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1); } @@ -760,11 +752,11 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Make next scan request from the same package name & ensure that it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(0, SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1); } @@ -780,18 +772,18 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS / 2; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS / 2; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Make next scan request from both the package name & ensure that it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 2); } @@ -809,7 +801,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Now simulate removing the app. mScanRequestProxy.clearScanRequestTimestampsForApp(TEST_PACKAGE_NAME_1, TEST_UID); @@ -817,7 +809,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Make next scan request from the same package name (simulating a reinstall) & ensure that // it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS + 1); } @@ -835,7 +827,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { for (int i = 0; i < SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS; i++) { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs + i); assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); } // Now simulate removing the app for another user (User 1). mScanRequestProxy.clearScanRequestTimestampsForApp( @@ -875,11 +867,11 @@ public class ScanRequestProxyTest extends WifiBaseTest { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Make scan request 2 from the different package name & ensure that it is not throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(2); } @@ -899,7 +891,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Make scan request 2 from the different package name & ensure that it is throttled. assertFalse(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); @@ -925,14 +917,14 @@ public class ScanRequestProxyTest extends WifiBaseTest { when(mClock.getElapsedSinceBootMillis()).thenReturn(firstRequestMs); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); long secondRequestMs = firstRequestMs + ScanRequestProxy.SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS + 1; when(mClock.getElapsedSinceBootMillis()).thenReturn(secondRequestMs); // Make scan request 2 from the different package name & ensure that it is throttled. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_2)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); verifyScanMetricsDataWasSet(2); } @@ -942,13 +934,14 @@ public class ScanRequestProxyTest extends WifiBaseTest { * internal scans. */ @Test - public void testFullInternalScanResultsOverwritesPreviousResults() { + public void testFullInternalScanResultsOverwritesPreviousResults() throws Exception { enableScanning(); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Verify the scan results processing for request 1. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -958,6 +951,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { // Now send results from an internal full scan request. // Verify the scan failure processing. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -972,13 +966,14 @@ public class ScanRequestProxyTest extends WifiBaseTest { * internal scans. */ @Test - public void testPartialInternalScanResultsDoesNotOverwritePreviousResults() { + public void testPartialInternalScanResultsDoesNotOverwritePreviousResults() throws Exception { enableScanning(); // Make scan request 1. assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1)); - mInOrder.verify(mWifiScanner).startScan(any(), any(), any(), any()); + mInOrder.verify(mWifiScanner).startScan(any(), any(), any()); // Verify the scan results processing for request 1. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas1); + mLooper.dispatchAll(); validateScanResultsAvailableBroadcastSent(true); // Validate the scan results in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( @@ -991,6 +986,7 @@ public class ScanRequestProxyTest extends WifiBaseTest { new int[]{WifiScanner.WIFI_BAND_24_GHZ}); // Verify the scan failure processing. mGlobalScanListenerArgumentCaptor.getValue().onResults(mTestScanDatas2); + mLooper.dispatchAll(); // Validate the scan results from a previous successful scan in the cache. ScanTestUtil.assertScanResultsEqualsAnyOrder( mTestScanDatas1[0].getResults(), 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 f04195e85f..824303655e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java @@ -78,6 +78,7 @@ import android.os.UserHandle; import android.os.WorkSource; import android.os.test.TestLooper; import android.provider.Settings; +import android.util.LocalLog; import android.util.SparseIntArray; import androidx.test.filters.SmallTest; @@ -166,10 +167,10 @@ public class SoftApManagerTest extends WifiBaseTest { private SoftApInfo mTestSoftApInfoOnSecondInstance; // Use for briged Ap mode test case private Map<String, SoftApInfo> mTestSoftApInfoMap = new HashMap<>(); private Map<String, List<WifiClient>> mTestWifiClientsMap = new HashMap<>(); - private Map<String, List<WifiClient>> mTempConnectedClientListMap = new HashMap<>() {{ - put(TEST_INTERFACE_NAME, new ArrayList()); - put(TEST_FIRST_INSTANCE_NAME, new ArrayList()); - put(TEST_SECOND_INSTANCE_NAME, new ArrayList()); }}; + private Map<String, List<WifiClient>> mTempConnectedClientListMap = Map.of( + TEST_INTERFACE_NAME, new ArrayList(), + TEST_FIRST_INSTANCE_NAME, new ArrayList(), + TEST_SECOND_INSTANCE_NAME, new ArrayList()); private SoftApCapability mTestSoftApCapability; private List<ClientModeManager> mTestClientModeManagers = new ArrayList<>(); @@ -195,6 +196,8 @@ public class SoftApManagerTest extends WifiBaseTest { @Mock WifiInfo mSecondWifiInfo; @Mock BatteryManager mBatteryManager; @Mock InterfaceConflictManager mInterfaceConflictManager; + @Mock WifiInjector mWifiInjector; + @Mock LocalLog mLocalLog; final ArgumentCaptor<WifiNative.InterfaceCallback> mWifiNativeInterfaceCallbackCaptor = ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); @@ -344,11 +347,13 @@ public class SoftApManagerTest extends WifiBaseTest { when(mActiveModeWarden.getClientModeManagers()) .thenReturn(mTestClientModeManagers); mTestClientModeManagers.add(mPrimaryConcreteClientModeManager); - when(mPrimaryConcreteClientModeManager.syncRequestConnectionInfo()) + when(mPrimaryConcreteClientModeManager.getConnectionInfo()) .thenReturn(mPrimaryWifiInfo); - when(mConcreteClientModeManager.syncRequestConnectionInfo()) + when(mConcreteClientModeManager.getConnectionInfo()) .thenReturn(mPrimaryWifiInfo); when(mWifiNative.forceClientDisconnect(any(), any(), anyInt())).thenReturn(true); + when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog); + when(mContext.getResources()).thenReturn(mResources); // Init Test SoftAp infos mTestSoftApInfo = new SoftApInfo(); @@ -395,10 +400,7 @@ public class SoftApManagerTest extends WifiBaseTest { private SoftApManager createSoftApManager(SoftApModeConfiguration config, ActiveModeManager.SoftApRole role) { SoftApManager newSoftApManager = new SoftApManager( - mContext, - mLooper.getLooper(), - mFrameworkFacade, - mWifiNative, + mContext, mLooper.getLooper(), mFrameworkFacade, mWifiNative, mWifiInjector, mCoexManager, mBatteryManager, mInterfaceConflictManager, @@ -1001,7 +1003,7 @@ public class SoftApManagerTest extends WifiBaseTest { new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, mTestSoftApCapability, TEST_COUNTRY_CODE); startSoftApAndVerifyEnabled(softApModeConfig); - + verify(mListener, never()).onStopped(mSoftApManager); mSoftApManager.stop(); mLooper.dispatchAll(); verify(mListener).onStopped(mSoftApManager); @@ -3154,7 +3156,7 @@ public class SoftApManagerTest extends WifiBaseTest { // Prepare second ClientModeManager List<ClientModeManager> testClientModeManagers = new ArrayList<>(mTestClientModeManagers); testClientModeManagers.add(mSecondConcreteClientModeManager); - when(mSecondConcreteClientModeManager.syncRequestConnectionInfo()) + when(mSecondConcreteClientModeManager.getConnectionInfo()) .thenReturn(mSecondWifiInfo); when(mActiveModeWarden.getClientModeManagers()).thenReturn(testClientModeManagers); // TEST_SUPPORTED_5G_CHANNELS = 36, 149, mark to unsafe. Let Wifi connect to 5200 (CH40) 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 44c46634b1..4f44d4a2b1 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java @@ -74,6 +74,8 @@ import android.hardware.wifi.supplicant.IfaceInfo; import android.hardware.wifi.supplicant.IfaceType; import android.hardware.wifi.supplicant.KeyMgmtMask; import android.hardware.wifi.supplicant.LegacyMode; +import android.hardware.wifi.supplicant.MloLink; +import android.hardware.wifi.supplicant.MloLinksInfo; import android.hardware.wifi.supplicant.OceRssiBasedAssocRejectAttr; import android.hardware.wifi.supplicant.OsuMethod; import android.hardware.wifi.supplicant.PortRange; @@ -129,6 +131,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -142,11 +145,10 @@ import java.util.Set; */ @SmallTest public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { - private static final Map<Integer, String> NETWORK_ID_TO_SSID = new HashMap<Integer, String>() {{ - put(1, "\"ssid1\""); - put(2, "\"ssid2\""); - put(3, "\"ssid3\""); - }}; + private static final Map<Integer, String> NETWORK_ID_TO_SSID = Map.of( + 1, "\"ssid1\"", + 2, "\"ssid2\"", + 3, "\"ssid3\""); private static final int SUPPLICANT_NETWORK_ID = 2; private static final String SUPPLICANT_SSID = NETWORK_ID_TO_SSID.get(SUPPLICANT_NETWORK_ID); private static final WifiSsid TRANSLATED_SUPPLICANT_SSID = @@ -231,6 +233,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { mIfaceInfoList[2] = createIfaceInfo(IfaceType.P2P, P2P_IFACE_NAME); doReturn(CONNECTED_MAC_ADDRESS_BYTES).when(mISupplicantStaIfaceMock).getMacAddress(); mHandler = spy(new Handler(mLooper.getLooper())); + when(mISupplicantMock.asBinder()).thenReturn(mServiceBinderMock); when(mSsidTranslator.getTranslatedSsid(any())).thenReturn(TRANSLATED_SUPPLICANT_SSID); when(mSsidTranslator.getOriginalSsid(any())).thenAnswer((Answer<WifiSsid>) invocation -> WifiSsid.fromString(((WifiConfiguration) invocation.getArgument(0)).SSID)); @@ -991,7 +994,38 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent( eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(false), - eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID)); + eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID), eq(null)); + wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( + eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), + eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID), eq(SupplicantState.COMPLETED)); + } + + /** + * Tests the handling of state change notification with key management + * to completed after configuring a network. + */ + @Test + public void testStateChangeToCompletedCallbackWithAkm() throws Exception { + InOrder wifiMonitorInOrder = inOrder(mWifiMonitor); + executeAndValidateInitializationSequence(); + int frameworkNetworkId = 6; + executeAndValidateConnectSequence(frameworkNetworkId, false, + TRANSLATED_SUPPLICANT_SSID.toString()); + assertNotNull(mISupplicantStaIfaceCallback); + + int supplicantAkmMask = android.hardware.wifi.supplicant.KeyMgmtMask.WPA_PSK; + BitSet expectedAkmMask = new BitSet(); + expectedAkmMask.set(WifiConfiguration.KeyMgmt.WPA_PSK); + + mISupplicantStaIfaceCallback.onStateChangedWithAkm( + StaIfaceCallbackState.COMPLETED, + NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, + NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(SUPPLICANT_SSID)), false, + supplicantAkmMask); + + wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent( + eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(false), + eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID), eq(expectedAkmMask)); wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID), eq(SupplicantState.COMPLETED)); @@ -1446,7 +1480,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { assertTrue(mDut.isInitializationComplete()); assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler)); - mSupplicantDeathCaptor.getValue().binderDied(); + mSupplicantDeathCaptor.getValue().binderDied(mServiceBinderMock); mLooper.dispatchAll(); assertFalse(mDut.isInitializationComplete()); @@ -1478,7 +1512,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { // Now trigger a death notification and ensure it's handled. assertNotNull(mSupplicantDeathCaptor.getValue()); - mSupplicantDeathCaptor.getValue().binderDied(); + mSupplicantDeathCaptor.getValue().binderDied(mServiceBinderMock); mLooper.dispatchAll(); // External death notification fires only once! @@ -1641,7 +1675,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { // Check that all internal state is cleared once the death notification is received. assertTrue(mDut.isInitializationComplete()); - mSupplicantDeathCaptor.getValue().binderDied(); + mSupplicantDeathCaptor.getValue().binderDied(mServiceBinderMock); assertFalse(mDut.isInitializationComplete()); } @@ -2123,7 +2157,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent( eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(true), - eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID)); + eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID), eq(null)); wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(TRANSLATED_SUPPLICANT_SSID), eq(BSSID), eq(SupplicantState.COMPLETED)); @@ -2803,4 +2837,63 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { } return true; } + + /** + * Test getConnectionMloLinkInfo returns WifiNative.ConnectionMloLinksInfo from interface name. + */ + @Test + public void testGetConnectionMloLinksInfo() throws Exception { + final int mDownlinkTid = 3; + final int mUplinkTid = 6; + // initialize MLO Links + MloLinksInfo info = new MloLinksInfo(); + MloLink[] links = new MloLink[3]; + links[0] = new android.hardware.wifi.supplicant.MloLink(); + links[0].linkId = 1; + links[0].staLinkMacAddress = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x01}; + links[0].tidsDownlinkMap = Byte.MAX_VALUE; + links[0].tidsDownlinkMap = Byte.MIN_VALUE; + links[1] = new android.hardware.wifi.supplicant.MloLink(); + links[1].linkId = 2; + links[1].staLinkMacAddress = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x02}; + links[1].tidsDownlinkMap = 1 << mDownlinkTid; + links[1].tidsUplinkMap = 1 << mUplinkTid; + links[2] = new android.hardware.wifi.supplicant.MloLink(); + links[2].linkId = 3; + links[2].staLinkMacAddress = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x03}; + links[2].tidsDownlinkMap = 0; + links[2].tidsUplinkMap = 0; + info.links = links; + executeAndValidateInitializationSequence(); + // Mock MloLinksInfo as null. + when(mISupplicantStaIfaceMock.getConnectionMloLinksInfo()).thenReturn(null); + // Pass wrong interface. + assertNull(mDut.getConnectionMloLinksInfo(WLAN1_IFACE_NAME)); + // Pass correct interface. + assertNull(mDut.getConnectionMloLinksInfo(WLAN0_IFACE_NAME)); + // Mock MloLinksInfo. + when(mISupplicantStaIfaceMock.getConnectionMloLinksInfo()).thenReturn(info); + // Pass wrong interface with mock MloLinksInfo. + assertNull(mDut.getConnectionMloLinksInfo(WLAN1_IFACE_NAME)); + // Pass correct interface with mock MloLinksInfo. + WifiNative.ConnectionMloLinksInfo nativeInfo = mDut.getConnectionMloLinksInfo( + WLAN0_IFACE_NAME); + // Check all return values. + assertNotNull(nativeInfo); + assertEquals(nativeInfo.links.length, info.links.length); + assertEquals(nativeInfo.links[0].getLinkId(), info.links[0].linkId); + assertEquals(nativeInfo.links[0].getMacAddress(), + MacAddress.fromBytes(info.links[0].staLinkMacAddress)); + assertTrue(nativeInfo.links[0].isAnyTidMapped()); + assertEquals(nativeInfo.links[1].getLinkId(), info.links[1].linkId); + assertEquals(nativeInfo.links[1].getMacAddress(), + MacAddress.fromBytes(info.links[1].staLinkMacAddress)); + assertTrue(nativeInfo.links[1].isAnyTidMapped()); + assertTrue(nativeInfo.links[1].isTidMappedtoDownlink((byte) mDownlinkTid)); + assertTrue(nativeInfo.links[1].isTidMappedToUplink((byte) mUplinkTid)); + assertEquals(nativeInfo.links[2].getLinkId(), info.links[2].linkId); + assertEquals(nativeInfo.links[2].getMacAddress(), + MacAddress.fromBytes(info.links[2].staLinkMacAddress)); + assertFalse(nativeInfo.links[2].isAnyTidMapped()); + } } 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 87d881cffb..be9a64378e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java @@ -118,11 +118,10 @@ import java.util.Random; */ @SmallTest public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { - private static final Map<Integer, String> NETWORK_ID_TO_SSID = new HashMap<Integer, String>() {{ - put(1, "\"ssid1\""); - put(2, "\"ssid2\""); - put(3, "\"ssid3\""); - }}; + private static final Map<Integer, String> NETWORK_ID_TO_SSID = Map.of( + 1, "\"ssid1\"", + 2, "\"ssid2\"", + 3, "\"ssid3\""); private static final int SUPPLICANT_NETWORK_ID = 2; private static final String SUPPLICANT_SSID = NETWORK_ID_TO_SSID.get(SUPPLICANT_NETWORK_ID); private static final WifiSsid TRANSLATED_SUPPLICANT_SSID = @@ -2035,13 +2034,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { public void testTerminateV1_0() throws Exception { executeAndValidateInitializationSequence(); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public boolean answer(IHwBinder.DeathRecipient cb, long cookie) throws RemoteException { - mHandler.post(() -> cb.serviceDied(cookie)); - return true; - } - }).when(mISupplicantMock).linkToDeath(any(IHwBinder.DeathRecipient.class), any(long.class)); mDut.terminate(); + mSupplicantDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue()); mLooper.dispatchAll(); verify(mFrameworkFacade).stopSupplicant(); @@ -2057,16 +2051,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { setupMocksForHalV1_1(); executeAndValidateInitializationSequenceV1_1(false, false); - - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public boolean answer(IHwBinder.DeathRecipient cb, long cookie) throws RemoteException { - mHandler.post(() -> cb.serviceDied(cookie)); - return true; - } - }).when(mISupplicantMockV11).linkToDeath(any(IHwBinder.DeathRecipient.class), - any(long.class)); - mDut.terminate(); + mSupplicantDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue()); mLooper.dispatchAll(); verify(mFrameworkFacade, never()).stopSupplicant(); verify(mISupplicantMockV11).terminate(); @@ -2797,7 +2783,7 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { assertTrue(mDut.isInitializationComplete()); assertTrue(mDut.setupIface(WLAN0_IFACE_NAME) == shouldSucceed); mInOrder.verify(mISupplicantMockV11).linkToDeath(mSupplicantDeathCaptor.capture(), - anyLong()); + mDeathRecipientCookieCaptor.capture()); // verify: addInterface is called mInOrder.verify(mISupplicantMockV11) .addInterface(any(ISupplicant.IfaceInfo.class), 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 500ceaeb13..bd528df028 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java @@ -24,6 +24,7 @@ import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; @@ -46,6 +47,7 @@ import android.hardware.wifi.supplicant.NetworkResponseEapSimUmtsAuthParams; import android.hardware.wifi.supplicant.PairwiseCipherMask; import android.hardware.wifi.supplicant.SaeH2eMode; import android.hardware.wifi.supplicant.SupplicantStatusCode; +import android.hardware.wifi.supplicant.TlsVersion; import android.net.wifi.SecurityParams; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; @@ -99,6 +101,7 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { @Mock private WifiMonitor mWifiMonitor; @Mock private WifiGlobals mWifiGlobals; private long mAdvanceKeyMgmtFeatures = 0; + private long mWpaDriverFeatures = 0; private SupplicantNetworkVariables mSupplicantVariables; private MockResources mResources; @@ -115,9 +118,9 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); mAdvanceKeyMgmtFeatures |= WifiManager.WIFI_FEATURE_WPA3_SUITE_B; - mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl( + mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(1, mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, - mWifiGlobals, mAdvanceKeyMgmtFeatures); + mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures); } /** @@ -751,6 +754,98 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { } /** + * Tests ciphers are merged when the device supports auto upgrade offload feature + * and when candidate security type is PSK. + */ + @Test + public void testCiphersMergedWhenAutoUpgradeOffloadIsSupportedAndPskSelected() + throws Exception { + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_PSK)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(PairwiseCipherMask.CCMP | PairwiseCipherMask.TKIP + | PairwiseCipherMask.GCMP_128 | PairwiseCipherMask.GCMP_256, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(GroupCipherMask.CCMP | GroupCipherMask.TKIP + | GroupCipherMask.WEP40 | GroupCipherMask.WEP104 + | GroupCipherMask.GCMP_128 | GroupCipherMask.GCMP_256, + mSupplicantVariables.groupCipherMask); + } + + /** + * Tests ciphers are not changed when the device does not supports auto upgrade offload feature + * and when candidate security type is PSK. + */ + @Test + public void testCiphersNotChangedWhenAutoUpgradeOffloadNotSupportedAndPskSelected() + throws Exception { + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_PSK)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(PairwiseCipherMask.CCMP | PairwiseCipherMask.TKIP, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(GroupCipherMask.CCMP | GroupCipherMask.TKIP + | GroupCipherMask.WEP40 | GroupCipherMask.WEP104, + mSupplicantVariables.groupCipherMask); + } + + /** + * Tests ciphers are merged when the device supports auto upgrade offload feature + * and when candidate security type is SAE. + */ + @Test + public void testCiphersMergedWhenAutoUpgradeOffloadIsSupportedAndSaeSelected() + throws Exception { + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_SAE)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(PairwiseCipherMask.CCMP | PairwiseCipherMask.TKIP + | PairwiseCipherMask.GCMP_128 | PairwiseCipherMask.GCMP_256, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(GroupCipherMask.CCMP | GroupCipherMask.TKIP + | GroupCipherMask.WEP40 | GroupCipherMask.WEP104 + | GroupCipherMask.GCMP_128 | GroupCipherMask.GCMP_256, + mSupplicantVariables.groupCipherMask); + } + + /** + * Tests ciphers are not changed when the device does not supports auto upgrade offload feature + * and when candidate security type is SAE. + */ + @Test + public void testCiphersNotChangedWhenAutoUpgradeOffloadNotSupportedAndSaeSelected() + throws Exception { + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_SAE)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(PairwiseCipherMask.CCMP | PairwiseCipherMask.GCMP_128 + | PairwiseCipherMask.GCMP_256, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(GroupCipherMask.CCMP | GroupCipherMask.GCMP_128 | GroupCipherMask.GCMP_256, + mSupplicantVariables.groupCipherMask); + } + + /** * Tests the retrieval of WPS NFC token. */ @Test @@ -1075,9 +1170,9 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { public void testSupportedCiphersNoGcmp256() throws Exception { // Reinitialize mSupplicantNetwork without support for WPA3 SUITE-B mAdvanceKeyMgmtFeatures = 0; - mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl( + mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(1, mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, - mWifiGlobals, mAdvanceKeyMgmtFeatures); + mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures); WifiConfiguration config = WifiConfigurationTestUtil.createSaeNetwork(); int expectedHalPairwiseCiphers = getExpectedPairwiseCiphers(config); expectedHalPairwiseCiphers &= ~PairwiseCipherMask.GCMP_256; @@ -1135,6 +1230,62 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { } /** + * Tests setting TLS minimum version API with AIDL v1 + */ + @Test + public void testEapMinimumTlsVersionWifiConfigurationSaveLoadWithAidlV1() throws Exception { + // Default is AIDL v1 + WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); + config.enterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_V1_3); + // Assume that the default params is used for this test. + config.getNetworkSelectionStatus().setCandidateSecurityParams( + config.getDefaultSecurityParams()); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + verify(mISupplicantStaNetworkMock, never()).setMinimumTlsVersionEapPhase1Param(anyInt()); + } + + /** + * Tests setting TLS minimum version API with AIDL v2, but TLS v1.3 is not supported. + */ + @Test + public void testEapMinimumTlsVersionWifiConfigurationSaveLoadWithAidlV2TlsV13NotSupported() + throws Exception { + // Re-init mock to AIDL v2 without TLS v1.3 support. + mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(2, + mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, + mWifiGlobals, mAdvanceKeyMgmtFeatures, 0); + WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); + config.enterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_V1_3); + // Assume that the default params is used for this test. + config.getNetworkSelectionStatus().setCandidateSecurityParams( + config.getDefaultSecurityParams()); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + // Should fallback to TLS v1.2 + verify(mISupplicantStaNetworkMock).setMinimumTlsVersionEapPhase1Param(TlsVersion.TLS_V1_2); + } + + /** + * Tests setting TLS minimum version API with AIDL v2, and TLS v1.3 is supported. + */ + @Test + public void testEapMinimumTlsVersionWifiConfigurationSaveLoadWithAidlV2TlsV13Supported() + throws Exception { + // Re-init mock to AIDL v2 with TLS v1.3 support. + mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(2, + mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, + mWifiGlobals, mAdvanceKeyMgmtFeatures, + WifiManager.WIFI_FEATURE_TLS_V1_3); + WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); + config.enterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_V1_3); + // Assume that the default params is used for this test. + config.getNetworkSelectionStatus().setCandidateSecurityParams( + config.getDefaultSecurityParams()); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + // Should fallback to TLS v1.2 + verify(mISupplicantStaNetworkMock).setMinimumTlsVersionEapPhase1Param(TlsVersion.TLS_V1_3); + } + + /** * Sets up the AIDL interface mock with all the setters/getter values. * Note: This only sets up the mock to return success on all methods. */ 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 9f1a5f4644..052eb4673c 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java @@ -1027,6 +1027,130 @@ public class SupplicantStaNetworkHalHidlImplTest extends WifiBaseTest { } /** + * Tests ciphers are merged when the device supports auto upgrade offload feature + * and when candidate security type is PSK. + */ + @Test + public void testCiphersMergedWhenAutoUpgradeOffloadIsSupportedAndPskSelected() + throws Exception { + createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_4); + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_PSK)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(ISupplicantStaNetwork.PairwiseCipherMask.CCMP + | ISupplicantStaNetwork.PairwiseCipherMask.TKIP + | android.hardware.wifi.supplicant.V1_4 + .ISupplicantStaNetwork.PairwiseCipherMask.GCMP_128 + | android.hardware.wifi.supplicant.V1_2 + .ISupplicantStaNetwork.PairwiseCipherMask.GCMP_256, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(ISupplicantStaNetwork.GroupCipherMask.CCMP + | ISupplicantStaNetwork.GroupCipherMask.TKIP + | ISupplicantStaNetwork.GroupCipherMask.WEP40 + | ISupplicantStaNetwork.GroupCipherMask.WEP104 + | android.hardware.wifi.supplicant.V1_4 + .ISupplicantStaNetwork.GroupCipherMask.GCMP_128 + | android.hardware.wifi.supplicant.V1_2 + .ISupplicantStaNetwork.GroupCipherMask.GCMP_256, + mSupplicantVariables.groupCipherMask); + } + + /** + * Tests ciphers are not changed when the device does not supports auto upgrade offload feature + * and when candidate security type is PSK. + */ + @Test + public void testCiphersNotChangedWhenAutoUpgradeOffloadNotSupportedAndPskSelected() + throws Exception { + createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_4); + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_PSK)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(ISupplicantStaNetwork.PairwiseCipherMask.CCMP + | ISupplicantStaNetwork.PairwiseCipherMask.TKIP, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(ISupplicantStaNetwork.GroupCipherMask.CCMP + | ISupplicantStaNetwork.GroupCipherMask.TKIP + | ISupplicantStaNetwork.GroupCipherMask.WEP40 + | ISupplicantStaNetwork.GroupCipherMask.WEP104, + mSupplicantVariables.groupCipherMask); + } + + /** + * Tests ciphers are merged when the device supports auto upgrade offload feature + * and when candidate security type is SAE. + */ + @Test + public void testCiphersMergedWhenAutoUpgradeOffloadIsSupportedAndSaeSelected() + throws Exception { + createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_4); + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_SAE)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(ISupplicantStaNetwork.PairwiseCipherMask.CCMP + | ISupplicantStaNetwork.PairwiseCipherMask.TKIP + | android.hardware.wifi.supplicant.V1_4 + .ISupplicantStaNetwork.PairwiseCipherMask.GCMP_128 + | android.hardware.wifi.supplicant.V1_2 + .ISupplicantStaNetwork.PairwiseCipherMask.GCMP_256, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(ISupplicantStaNetwork.GroupCipherMask.CCMP + | ISupplicantStaNetwork.GroupCipherMask.TKIP + | ISupplicantStaNetwork.GroupCipherMask.WEP40 + | ISupplicantStaNetwork.GroupCipherMask.WEP104 + | android.hardware.wifi.supplicant.V1_4 + .ISupplicantStaNetwork.GroupCipherMask.GCMP_128 + | android.hardware.wifi.supplicant.V1_2 + .ISupplicantStaNetwork.GroupCipherMask.GCMP_256, + mSupplicantVariables.groupCipherMask); + } + + /** + * Tests ciphers are not changed when the device does not supports auto upgrade offload feature + * and when candidate security type is SAE. + */ + @Test + public void testCiphersNotChangedWhenAutoUpgradeOffloadNotSupportedAndSaeSelected() + throws Exception { + createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_4); + when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false); + + WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork(); + config.getNetworkSelectionStatus().setCandidateSecurityParams( + SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_SAE)); + assertTrue(mSupplicantNetwork.saveWifiConfiguration(config)); + + assertEquals(ISupplicantStaNetwork.PairwiseCipherMask.CCMP + | android.hardware.wifi.supplicant.V1_4 + .ISupplicantStaNetwork.PairwiseCipherMask.GCMP_128 + | android.hardware.wifi.supplicant.V1_2 + .ISupplicantStaNetwork.PairwiseCipherMask.GCMP_256, + mSupplicantVariables.pairwiseCipherMask); + assertEquals(ISupplicantStaNetwork.GroupCipherMask.CCMP + | android.hardware.wifi.supplicant.V1_4 + .ISupplicantStaNetwork.GroupCipherMask.GCMP_128 + | android.hardware.wifi.supplicant.V1_2 + .ISupplicantStaNetwork.GroupCipherMask.GCMP_256, + mSupplicantVariables.groupCipherMask); + } + + /** * Tests the retrieval of WPS NFC token. */ @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java index acd2b923e5..0023ebfb98 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java @@ -497,10 +497,9 @@ public class WakeupControllerTest extends WifiBaseTest { unknownScanResult)); // intersection of most recent scan + saved configs/suggestions - Set<ScanResultMatchInfo> expectedMatchInfos = new HashSet<ScanResultMatchInfo>() {{ - add(ScanResultMatchInfo.fromScanResult(savedScanResult)); - add(ScanResultMatchInfo.fromScanResult(suggestionScanResult)); - }}; + Set<ScanResultMatchInfo> expectedMatchInfos = Set.of( + ScanResultMatchInfo.fromScanResult(savedScanResult), + ScanResultMatchInfo.fromScanResult(suggestionScanResult)); initializeWakeupController(true /* enabled */); mWakeupController.start(); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java index cd9938fb14..57d2f00eb6 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java @@ -1067,9 +1067,7 @@ public class WifiBackupRestoreTest extends WifiBaseTest { expectedConfiguration.preSharedKey = WifiConfigurationTestUtil.TEST_PSK; expectedConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); - ArrayList<WifiConfiguration> expectedConfigurations = new ArrayList<WifiConfiguration>() {{ - add(expectedConfiguration); - }}; + List<WifiConfiguration> expectedConfigurations = List.of(expectedConfiguration); WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( expectedConfigurations, retrievedConfigurations); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiBlocklistMonitorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiBlocklistMonitorTest.java index 6000573073..5b9faf9844 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiBlocklistMonitorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiBlocklistMonitorTest.java @@ -48,6 +48,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -80,6 +81,8 @@ public class WifiBlocklistMonitorTest { private static final long BASE_BLOCKLIST_DURATION = TimeUnit.MINUTES.toMillis(5); // 5 minutes private static final long BASE_CONNECTED_SCORE_BLOCKLIST_DURATION = TimeUnit.SECONDS.toMillis(30); + private static final long BASE_VALIDATION_FAILURE_BSSID_BLOCKLIST_DURATION = + TimeUnit.SECONDS.toMillis(60); private static final long ABNORMAL_DISCONNECT_TIME_WINDOW_MS = TimeUnit.SECONDS.toMillis(30); private static final long ABNORMAL_DISCONNECT_RESET_TIME_MS = TimeUnit.HOURS.toMillis(3); private static final int FAILURE_STREAK_CAP = 7; @@ -100,6 +103,29 @@ public class WifiBlocklistMonitorTest { Map.entry(WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING, 2), Map.entry(WifiBlocklistMonitor.REASON_FAILURE_NO_RESPONSE, 1) ); + private static final Map<Integer, Integer> CONFIG_DISABLE_REASON_TO_THRESHOLD_OVERLAY_MAP = + Map.ofEntries( + Map.entry(NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION, + R.integer.config_wifiDisableReasonAssociationRejectionThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE, + R.integer.config_wifiDisableReasonAuthenticationFailureThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_DHCP_FAILURE, + R.integer.config_wifiDisableReasonDhcpFailureThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_NETWORK_NOT_FOUND, + R.integer.config_wifiDisableReasonNetworkNotFoundThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY, + R.integer.config_wifiDisableReasonNoInternetTemporaryThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS, + R.integer.config_wifiDisableReasonAuthenticationNoCredentialsThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT, + R.integer.config_wifiDisableReasonNoInternetPermanentThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD, + R.integer.config_wifiDisableReasonByWrongPasswordThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES, + R.integer.config_wifiDisableReasonConsecutiveFailuresThreshold), + Map.entry(NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION, + R.integer.config_wifiDisableReasonAuthenticationNoSubscriptionThreshold) + ); private static final int NUM_FAILURES_TO_BLOCKLIST = BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(TEST_L2_FAILURE); @@ -112,6 +138,7 @@ public class WifiBlocklistMonitorTest { @Mock private ScoringParams mScoringParams; @Mock private WifiMetrics mWifiMetrics; @Mock private WifiPermissionsUtil mWifiPermissionsUtil; + @Mock private ScanRequestProxy mScanRequestProxy; @Mock private WifiScoreCard.PerNetwork mPerNetwork; @Mock private WifiScoreCard.NetworkConnectionStats mRecentStats; @@ -135,6 +162,9 @@ public class WifiBlocklistMonitorTest { mResources.setInteger( R.integer.config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs, (int) BASE_CONNECTED_SCORE_BLOCKLIST_DURATION); + mResources.setInteger( + R.integer.config_wifiBssidBlocklistMonitorValidationFailureBaseBlockDurationMs, + (int) BASE_VALIDATION_FAILURE_BSSID_BLOCKLIST_DURATION); mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorFailureStreakCap, FAILURE_STREAK_CAP); mResources.setInteger(R.integer.config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs, @@ -181,24 +211,35 @@ public class WifiBlocklistMonitorTest { BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get( WifiBlocklistMonitor.REASON_FAILURE_NO_RESPONSE)); + for (Map.Entry<Integer, Integer> entry : + CONFIG_DISABLE_REASON_TO_THRESHOLD_OVERLAY_MAP.entrySet()) { + mResources.setInteger( + entry.getValue(), + NetworkSelectionStatus.DISABLE_REASON_INFOS.get(entry.getKey()) + .mDisableThreshold); + } + + mResources.setInteger( + R.integer.config_wifiDisableReasonNoInternetTemporaryDurationMs, 600000); + mResources.setInteger( + R.integer.config_wifiDisableReasonAssociationRejectionDurationMs, 300000); + mResources.setInteger( + R.integer.config_wifiDisableReasonAuthenticationFailureDurationMs, 300000); + mResources.setInteger( + R.integer.config_wifiDisableReasonDhcpFailureDurationMs, 300000); + mResources.setInteger( + R.integer.config_wifiDisableReasonNetworkNotFoundDurationMs, 300000); mResources.setInteger( - R.integer.config_wifiDisableReasonAssociationRejectionThreshold, - NetworkSelectionStatus.DISABLE_REASON_INFOS - .get(NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION) - .mDisableThreshold); + R.integer.config_wifiDisableReasonConsecutiveFailuresDurationMs, 300000); mResources.setInteger( - R.integer.config_wifiDisableReasonAuthenticationFailureThreshold, - NetworkSelectionStatus.DISABLE_REASON_INFOS - .get(NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE) - .mDisableThreshold); + R.integer.config_wifiDisableReasonAuthenticationNoCredentialsDurationMs, -1); mResources.setInteger( - R.integer.config_wifiDisableReasonDhcpFailureThreshold, - NetworkSelectionStatus.DISABLE_REASON_INFOS - .get(NetworkSelectionStatus.DISABLED_DHCP_FAILURE).mDisableThreshold); + R.integer.config_wifiDisableReasonNoInternetPermanentDurationMs, -1); mResources.setInteger( - R.integer.config_wifiDisableReasonNetworkNotFoundThreshold, - NetworkSelectionStatus.DISABLE_REASON_INFOS - .get(NetworkSelectionStatus.DISABLED_NETWORK_NOT_FOUND).mDisableThreshold); + R.integer.config_wifiDisableReasonByWrongPasswordDurationMs, -1); + mResources.setInteger( + R.integer.config_wifiDisableReasonAuthenticationNoSubscriptionDurationMs, -1); + when(mContext.getResources()).thenReturn(mResources); when(mPerNetwork.getRecentStats()).thenReturn(mRecentStats); when(mWifiScoreCard.lookupNetwork(anyString())).thenReturn(mPerNetwork); @@ -208,6 +249,7 @@ public class WifiBlocklistMonitorTest { mWifiBlocklistMonitor = new WifiBlocklistMonitor(mContext, mWifiConnectivityHelper, mWifiLastResortWatchdog, mClock, mLocalLog, mWifiScoreCard, mScoringParams, mWifiMetrics, mWifiPermissionsUtil); + mWifiBlocklistMonitor.setScanRequestProxy(mScanRequestProxy); } private void verifyAddTestBssidToBlocklist() { @@ -719,7 +761,8 @@ public class WifiBlocklistMonitorTest { verify(mWifiMetrics).incrementBssidBlocklistCount(reason); // Verify that TEST_BSSID_1 is removed from the blocklist after the timeout duration. - when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1); + when(mClock.getWallClockMillis()).thenReturn( + getExpectedBaseBssidBlockDurationMillis(reason) + 1); assertEquals(0, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); // But the blocklist streak count is not cleared @@ -728,6 +771,17 @@ public class WifiBlocklistMonitorTest { } } + private long getExpectedBaseBssidBlockDurationMillis(int blockReason) { + switch (blockReason) { + case WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE: + return BASE_CONNECTED_SCORE_BLOCKLIST_DURATION; + case WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE: + return BASE_VALIDATION_FAILURE_BSSID_BLOCKLIST_DURATION; + default: + return BASE_BLOCKLIST_DURATION; + } + } + /** * Verify that when a failure signal is received for a BSSID with different SSID from before, * then the failure counts are reset. @@ -922,6 +976,230 @@ public class WifiBlocklistMonitorTest { } /** + * Verify that blockBssidForDurationMs adds a BSSID, and it's affiliated BSSIDs to blocklist for + * the specified duration. + */ + @Test + public void testBlockAffiliatedBssidsForDurationMs() { + List<String> bssidList = Arrays.asList(TEST_BSSID_2, TEST_BSSID_3); + // Affiliated BSSID mapping: TEST_BSSID_1 -> {TEST_BSSID_2, TEST_BSSID_3} + mWifiBlocklistMonitor.setAffiliatedBssids(TEST_BSSID_1, bssidList); + + // Add to block list + WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID_1); + when(mClock.getWallClockMillis()).thenReturn(0L); + long testDuration = 5500L; + mWifiBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, config, testDuration, + TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI); + assertEquals(3, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + + // Verify that the BSSIDs are removed from blocklist by clearBssidBlocklistForSsid + mWifiBlocklistMonitor.clearBssidBlocklistForSsid(TEST_SSID_1); + assertEquals(0, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + + // Add to blocklist again. + mWifiBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, config, testDuration, + TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI); + assertEquals(3, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + + // Verify that the BSSIDs are removed from blocklist once the specified duration is over. + when(mClock.getWallClockMillis()).thenReturn(testDuration + 1); + assertEquals(0, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + } + + /** + * Verify that connection failure block list all affiliated bssids. + */ + @Test + public void testHandleAffiliatedBssidsConnectionFailure() { + List<String> bssidList = Arrays.asList(TEST_BSSID_2, TEST_BSSID_3); + // Affiliated BSSID mapping: TEST_BSSID_1 -> {TEST_BSSID_2, TEST_BSSID_3} + mWifiBlocklistMonitor.setAffiliatedBssids(TEST_BSSID_1, bssidList); + + // Connection failure, reason REASON_AP_UNABLE_TO_HANDLE_NEW_STA + WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID_1); + mWifiBlocklistMonitor.handleBssidConnectionFailure( + TEST_BSSID_1, config, + WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, TEST_GOOD_RSSI); + + // Make sure affiliated BSSIDs are also in the block list + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_2)); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_3)); + + // Verify incrementBssidBlocklistStreak() API is called + verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, + TEST_BSSID_1, WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA); + verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, + TEST_BSSID_2, WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA); + verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, + TEST_BSSID_3, WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA); + } + + private void verifyResetBssidBlockStreak(String ssid, String bssid) { + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_WRONG_PASSWORD); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_EAP_FAILURE); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_AUTHENTICATION_FAILURE); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE); + verify(mWifiScoreCard).resetBssidBlocklistStreak(ssid, bssid, + WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING); + } + + /** + * Verify that connection success clears the block list for all affiliated bssids. + */ + @Test + public void testHandleAffiliatedBssidConnectionSuccess() { + List<String> bssidList = Arrays.asList(TEST_BSSID_2, TEST_BSSID_3); + // Affiliated BSSID mapping: TEST_BSSID_1 -> {TEST_BSSID_2, TEST_BSSID_3} + mWifiBlocklistMonitor.setAffiliatedBssids(TEST_BSSID_1, bssidList); + + // Multiple failures, add bssid to block list along with affiliated bssids + handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_L2_FAILURE, + NUM_FAILURES_TO_BLOCKLIST); + when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_RESET_TIME_MS + 1); + + // Connection success + mWifiBlocklistMonitor.handleBssidConnectionSuccess(TEST_BSSID_1, TEST_SSID_1); + + // Verify resetBssidBlocklistStreak() API is called + verifyResetBssidBlockStreak(TEST_SSID_1, TEST_BSSID_1); + verifyResetBssidBlockStreak(TEST_SSID_1, TEST_BSSID_2); + verifyResetBssidBlockStreak(TEST_SSID_1, TEST_BSSID_3); + + verify(mWifiScoreCard).setBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_1, + ABNORMAL_DISCONNECT_RESET_TIME_MS + 1); + verify(mWifiScoreCard).setBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_2, + ABNORMAL_DISCONNECT_RESET_TIME_MS + 1); + verify(mWifiScoreCard).setBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_3, + ABNORMAL_DISCONNECT_RESET_TIME_MS + 1); + + } + + /** + * Verify that network validation success clears the block list for all affiliated bssids. + */ + @Test + public void testHandleNetworkValidationSuccess() { + List<String> bssidList = Arrays.asList(TEST_BSSID_2, TEST_BSSID_3); + // Affiliated BSSID mapping: TEST_BSSID_1 -> {TEST_BSSID_2, TEST_BSSID_3} + mWifiBlocklistMonitor.setAffiliatedBssids(TEST_BSSID_1, bssidList); + + // Add to block list with reason code REASON_AP_UNABLE_TO_HANDLE_NEW_STA + verifyAddTestBssidToBlocklist(); + + // Network validation success resets with resetBssidBlocklistStreak() + mWifiBlocklistMonitor.handleNetworkValidationSuccess(TEST_BSSID_1, TEST_SSID_1); + verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, + WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE); + verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_2, + WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE); + verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_3, + WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE); + + // All BSSID's are removed from block list + assertEquals(0, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + } + + /** + * Verify that DHCP provisioning success clears the block list for all affiliated bssids. + */ + @Test + public void testHandleDhcpProvisioningSuccess() { + List<String> bssidList = Arrays.asList(TEST_BSSID_2, TEST_BSSID_3); + // Affiliated BSSID mapping: TEST_BSSID_1 -> {TEST_BSSID_2, TEST_BSSID_3} + mWifiBlocklistMonitor.setAffiliatedBssids(TEST_BSSID_1, bssidList); + + // DHCP failures leads to block list + handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_DHCP_FAILURE, + NUM_FAILURES_TO_BLOCKLIST); + assertEquals(3, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + + // DHCP success clears appropriate failure counters + mWifiBlocklistMonitor.handleDhcpProvisioningSuccess(TEST_BSSID_1, TEST_SSID_1); + verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, + WifiBlocklistMonitor.REASON_DHCP_FAILURE); + verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_2, + WifiBlocklistMonitor.REASON_DHCP_FAILURE); + verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_3, + WifiBlocklistMonitor.REASON_DHCP_FAILURE); + } + + @Test + public void testReadRssiFromLatestScanResultsWhenInvalid() { + // mock latest scan results with GOOD RSSI for TEST_BSSID_1 + ScanResult fakeScanResult = mock(ScanResult.class); + fakeScanResult.level = TEST_GOOD_RSSI; + when(mScanRequestProxy.getScanResult(TEST_BSSID_1)).thenReturn(fakeScanResult); + + // verify TEST_BSSID_1, 2 and 3 are block listed after connection failure using + // INVALID RSSI. + WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID_1); + when(mClock.getWallClockMillis()).thenReturn(0L); + mWifiBlocklistMonitor.handleBssidConnectionFailure( + TEST_BSSID_1, config, WifiBlocklistMonitor.REASON_EAP_FAILURE, + WifiConfiguration.INVALID_RSSI); + mWifiBlocklistMonitor.handleBssidConnectionFailure( + TEST_BSSID_2, config, WifiBlocklistMonitor.REASON_EAP_FAILURE, + WifiConfiguration.INVALID_RSSI); + mWifiBlocklistMonitor.handleBssidConnectionFailure( + TEST_BSSID_3, config, WifiBlocklistMonitor.REASON_EAP_FAILURE, + WifiConfiguration.INVALID_RSSI); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_2)); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_3)); + assertEquals(3, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + + // Simulate both TEST_BSSID_1 and TEST_BSSID_2 improving RSSI, but only TEST_BSSID_2 should + // be removed from blocklist. + List<ScanDetail> enabledDetails = simulateRssiUpdate(TEST_BSSID_1, TEST_GOOD_RSSI); + assertEquals(0, enabledDetails.size()); + assertEquals(3, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + + enabledDetails = simulateRssiUpdate(TEST_BSSID_2, TEST_GOOD_RSSI); + assertEquals(1, enabledDetails.size()); + assertEquals(2, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + } + + /** + * Verify that if the RSSI is low when the BSSID is blocked, a RSSI improvement to sufficient + * RSSI will remove the BSSID from blocklist along with affiliated BSSIDs. + */ + @Test + public void testUnblockAffiliatedBssidAfterRssiBreachSufficient() { + List<String> bssidList = Arrays.asList(TEST_BSSID_2, TEST_BSSID_3); + // Affiliated BSSID mapping: TEST_BSSID_1 -> {TEST_BSSID_2, TEST_BSSID_3} + mWifiBlocklistMonitor.setAffiliatedBssids(TEST_BSSID_1, bssidList); + + // verify TEST_BSSID_1, 2 and 3 are block listed after connection failure + WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID_1); + when(mClock.getWallClockMillis()).thenReturn(0L); + mWifiBlocklistMonitor.handleBssidConnectionFailure( + TEST_BSSID_1, config, WifiBlocklistMonitor.REASON_EAP_FAILURE, + TEST_SUFFICIENT_RSSI - MIN_RSSI_DIFF_TO_UNBLOCK_BSSID); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1)); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_2)); + assertTrue(mWifiBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_3)); + + // verify TEST_BSSID_1 is removed from the blocklist after RSSI improves + List<ScanDetail> enabledDetails = simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI); + assertEquals(1, enabledDetails.size()); + assertEquals(0, mWifiBlocklistMonitor.updateAndGetBssidBlocklist().size()); + } + + /** * Verify that |blockBssidForDurationMs| adds a BSSID to blocklist for the specified duration. */ @Test @@ -1069,6 +1347,7 @@ public class WifiBlocklistMonitorTest { /** * Verify the failure reasons for all blocked BSSIDs are retrieved. */ + @SuppressWarnings("ReturnValueIgnored") @Test public void testGetFailureReasonsForSsid() { WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(TEST_SSID_1); @@ -1383,23 +1662,47 @@ public class WifiBlocklistMonitorTest { */ @Test public void testNetworkSelectionDisableReasonCustomConfigOverride() { - int oldThreshold = NetworkSelectionStatus.DISABLE_REASON_INFOS - .get(NetworkSelectionStatus.DISABLED_DHCP_FAILURE).mDisableThreshold; - - // Modify the overlay value and create WifiConfigManager again. - int newThreshold = oldThreshold + 1; - mResources.setInteger( - R.integer.config_wifiDisableReasonDhcpFailureThreshold, newThreshold); - mWifiBlocklistMonitor = new WifiBlocklistMonitor(mContext, mWifiConnectivityHelper, - mWifiLastResortWatchdog, mClock, mLocalLog, mWifiScoreCard, mScoringParams, - mWifiMetrics, mWifiPermissionsUtil); + for (Map.Entry<Integer, Integer> entry : + CONFIG_DISABLE_REASON_TO_THRESHOLD_OVERLAY_MAP.entrySet()) { + int disableReason = entry.getKey(); + int oldThreshold = NetworkSelectionStatus.DISABLE_REASON_INFOS + .get(disableReason).mDisableThreshold; + assertEquals(oldThreshold, mWifiBlocklistMonitor.getNetworkSelectionDisableThreshold( + disableReason)); + assertEquals(getExpectedBaseConfigDisableTimeoutMillis(disableReason), + mWifiBlocklistMonitor.getNetworkSelectionDisableTimeoutMillis(disableReason)); + + // Modify the overlay value and create WifiConfigManager again. + int newThreshold = oldThreshold + 1; + mResources.setInteger(entry.getValue(), newThreshold); + mWifiBlocklistMonitor = new WifiBlocklistMonitor(mContext, mWifiConnectivityHelper, + mWifiLastResortWatchdog, mClock, mLocalLog, mWifiScoreCard, mScoringParams, + mWifiMetrics, mWifiPermissionsUtil); + mWifiBlocklistMonitor.setScanRequestProxy(mScanRequestProxy); + + // Verify that the threshold is updated in the copied version + assertEquals(newThreshold, mWifiBlocklistMonitor.getNetworkSelectionDisableThreshold( + disableReason)); + // Verify the original DISABLE_REASON_INFOS is unchanged + assertEquals(oldThreshold, NetworkSelectionStatus.DISABLE_REASON_INFOS + .get(disableReason).mDisableThreshold); + } + } - // Verify that the threshold is updated in the copied version - assertEquals(newThreshold, mWifiBlocklistMonitor.getNetworkSelectionDisableThreshold( - NetworkSelectionStatus.DISABLED_DHCP_FAILURE)); - // Verify the original DISABLE_REASON_INFOS is unchanged - assertEquals(oldThreshold, NetworkSelectionStatus.DISABLE_REASON_INFOS - .get(NetworkSelectionStatus.DISABLED_DHCP_FAILURE).mDisableThreshold); + private int getExpectedBaseConfigDisableTimeoutMillis(int disableReason) { + switch (disableReason) { + case NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY: + return 10 * 60 * 1000; // 10 minutes - should match value configured via overlay + case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS: + case NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT: + case NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER: + case NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD: + case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION: + case NetworkSelectionStatus.DISABLED_TRANSITION_DISABLE_INDICATION: + return -1; + default: + return 5 * 60 * 1000; // 5 minutes + } } /** 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 3559c6a304..655693bf74 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java @@ -1953,6 +1953,7 @@ public class WifiCarrierInfoManagerTest extends WifiBaseTest { public void testSetAndGetUnmergedCarrierNetworkOffload() { assertTrue(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(DATA_SUBID, false)); mWifiCarrierInfoManager.setCarrierNetworkOffloadEnabled(DATA_SUBID, false, false); + mLooper.dispatchAll(); verify(mWifiConfigManager).saveToStore(true); assertFalse(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(DATA_SUBID, false)); } @@ -1974,6 +1975,7 @@ public class WifiCarrierInfoManagerTest extends WifiBaseTest { listenerCaptor.getValue().onDataEnabledChanged(true, DATA_ENABLED_REASON_USER); mWifiCarrierInfoManager.setCarrierNetworkOffloadEnabled(DATA_SUBID, true, false); + mLooper.dispatchAll(); verify(mWifiConfigManager).saveToStore(true); assertFalse(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(DATA_SUBID, true)); @@ -2023,9 +2025,7 @@ public class WifiCarrierInfoManagerTest extends WifiBaseTest { when(mContext.getPackageManager()).thenReturn(mockPackageManager); PackageInfo pi = new PackageInfo(); pi.packageName = "com.example.app"; - List<PackageInfo> pis = new ArrayList<>() {{ - add(pi); - }}; + List<PackageInfo> pis = List.of(pi); when(mockPackageManager.getPackagesHoldingPermissions( eq(new String[] {android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}), anyInt())).thenReturn(pis); @@ -2201,6 +2201,7 @@ public class WifiCarrierInfoManagerTest extends WifiBaseTest { verify(mDataTelephonyManager).registerTelephonyCallback(any(), captor.capture()); mWifiCarrierInfoManager.setCarrierNetworkOffloadEnabled(DATA_SUBID, true, false); + mLooper.dispatchAll(); verify(mOnCarrierOffloadDisabledListener).onCarrierOffloadDisabled(DATA_SUBID, true); captor.getValue().onDataEnabledChanged(false, DATA_ENABLED_REASON_CARRIER); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoStoreManagerDataTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoStoreManagerDataTest.java index d0409beb49..5ba6c1af60 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoStoreManagerDataTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoStoreManagerDataTest.java @@ -17,11 +17,13 @@ package com.android.server.wifi; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import android.util.SparseBooleanArray; import android.util.Xml; import com.android.internal.util.FastXmlSerializer; @@ -49,8 +51,8 @@ public class WifiCarrierInfoStoreManagerDataTest { private WifiCarrierInfoStoreManagerData mWifiCarrierInfoStoreManagerData; private final Map<Integer, Boolean> mImsiPrivacyProtectionExemptionMap = new HashMap<>(); - private final Map<Integer, Boolean> mMergedCarrierOffloadMap = new HashMap<>(); - private final Map<Integer, Boolean> mUnmergedCarrierOffloadMap = new HashMap<>(); + private final SparseBooleanArray mMergedCarrierOffloadMap = new SparseBooleanArray(); + private final SparseBooleanArray mUnmergedCarrierOffloadMap = new SparseBooleanArray(); @Before public void setUp() throws Exception { @@ -126,25 +128,24 @@ public class WifiCarrierInfoStoreManagerDataTest { private void assertSerializeDeserialize() throws Exception { InOrder inOrder = inOrder(mDataSource); // Setup the data to serialize. - when(mDataSource.toSerializeMergedCarrierNetworkOffloadMap()).thenReturn( + when(mDataSource.getCarrierNetworkOffloadMap(true)).thenReturn( mMergedCarrierOffloadMap); - when(mDataSource.toSerializeUnmergedCarrierNetworkOffloadMap()) + when(mDataSource.getCarrierNetworkOffloadMap(false)) .thenReturn(mUnmergedCarrierOffloadMap); // Serialize/deserialize data. deserializeData(serializeData()); inOrder.verify(mDataSource).serializeComplete(); // Verify the deserialized data. - ArgumentCaptor<HashMap> deserializedMap = - ArgumentCaptor.forClass(HashMap.class); + ArgumentCaptor<SparseBooleanArray> deserializedMap = + ArgumentCaptor.forClass(SparseBooleanArray.class); - verify(mDataSource) - .fromMergedCarrierNetworkOffloadMapDeserialized(deserializedMap.capture()); + verify(mDataSource).setCarrierNetworkOffloadMap(deserializedMap.capture(), eq(true)); assertEquals(mMergedCarrierOffloadMap, deserializedMap.getValue()); verify(mDataSource) - .fromUnmergedCarrierNetworkOffloadMapDeserialized(deserializedMap.capture()); + .setCarrierNetworkOffloadMap(deserializedMap.capture(), eq(false)); assertEquals(mUnmergedCarrierOffloadMap, deserializedMap.getValue()); } 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 fb3e668a91..0183a09194 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -829,34 +829,32 @@ public class WifiConfigManagerTest extends WifiBaseTest { openNetwork.SSID)); } - /** - * Verifies that the organization owned device admin could modify other other fields in the - * Wificonfiguration but not the macRandomizationSetting field for networks they do not own. - */ @Test - public void testCannotUpdateMacRandomizationSettingWithoutPermissionDO() { + public void testOverrideWifiConfigModifyAllNetworks() { ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = ArgumentCaptor.forClass(WifiConfiguration.class); when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); - mockIsOrganizationOwnedDeviceAdmin(true); WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO; verifyAddNetworkToWifiConfigManager(openNetwork); verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); + assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, openNetwork.networkId); reset(mWcmListener); - // Change BSSID for the network and verify success - assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); - NetworkUpdateResult networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); - assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); + // try to modify the network with another UID and assert failure + WifiConfiguration configToUpdate = wifiConfigCaptor.getValue(); + configToUpdate.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; + NetworkUpdateResult result = + mWifiConfigManager.addOrUpdateNetwork(configToUpdate, TEST_OTHER_USER_UID); + assertEquals(WifiConfiguration.INVALID_NETWORK_ID, result.getNetworkId()); - // Now change the macRandomizationSetting and verify failure - openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; - networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); - assertEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); + // give the override wifi config permission and verify success + when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); + result = mWifiConfigManager.addOrUpdateNetwork(configToUpdate, TEST_OTHER_USER_UID); + assertEquals(configToUpdate.networkId, result.getNetworkId()); } @Test @@ -875,6 +873,36 @@ public class WifiConfigManagerTest extends WifiBaseTest { } /** + * Verifies that the organization owned device admin could modify other other fields in the + * Wificonfiguration but not the macRandomizationSetting field for networks they do not own. + */ + @Test + public void testCannotUpdateMacRandomizationSettingWithoutPermissionDO() { + ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = + ArgumentCaptor.forClass(WifiConfiguration.class); + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); + when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); + mockIsOrganizationOwnedDeviceAdmin(true); + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO; + + verifyAddNetworkToWifiConfigManager(openNetwork); + verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture()); + assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId); + reset(mWcmListener); + + // Change BSSID for the network and verify success + assertAndSetNetworkBSSID(openNetwork, TEST_BSSID); + NetworkUpdateResult networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); + assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); + + // Now change the macRandomizationSetting and verify failure + openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; + networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); + assertEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); + } + + /** * Verifies that the admin could set and modify the macRandomizationSetting field * for networks they own. */ @@ -1892,9 +1920,9 @@ public class WifiConfigManagerTest extends WifiBaseTest { WifiConfiguration originalNetwork = new WifiConfiguration(network); // Now set all the public fields to null and try updating the network. + // except for allowedKeyManagement which is not allowed to be empty. network.allowedAuthAlgorithms.clear(); network.allowedProtocols.clear(); - network.allowedKeyManagement.clear(); network.allowedPairwiseCiphers.clear(); network.allowedGroupCiphers.clear(); @@ -2600,7 +2628,6 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testNonPersistentRandomizationDbsMacAddress() { setUpWifiConfigurationForNonPersistentRandomization(); WifiConfiguration config = getFirstInternalWifiConfiguration(); - config.dbsSecondaryInternet = true; MacAddress randomMac = config.getRandomizedMacAddress(); MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config, true); @@ -7586,18 +7613,18 @@ public class WifiConfigManagerTest extends WifiBaseTest { mWifiConfigManager.addCustomDhcpOptions(WifiSsid.fromString(TEST_SSID), oui3, option3); mLooper.dispatchAll(); assertEquals(1, mWifiConfigManager.getCustomDhcpOptions( - WifiSsid.fromString(TEST_SSID), Arrays.asList(oui1)).size()); + WifiSsid.fromString(TEST_SSID), Collections.singletonList(oui1)).size()); assertEquals(1, mWifiConfigManager.getCustomDhcpOptions( - WifiSsid.fromString(TEST_SSID), Arrays.asList(oui2)).size()); + WifiSsid.fromString(TEST_SSID), Collections.singletonList(oui2)).size()); assertEquals(2, mWifiConfigManager.getCustomDhcpOptions( WifiSsid.fromString(TEST_SSID), Arrays.asList(oui2, oui3)).size()); mWifiConfigManager.removeCustomDhcpOptions(WifiSsid.fromString(TEST_SSID), oui1); mLooper.dispatchAll(); assertEquals(0, mWifiConfigManager.getCustomDhcpOptions( - WifiSsid.fromString(TEST_SSID), Arrays.asList(oui1)).size()); - List<DhcpOption> actual2 = mWifiConfigManager - .getCustomDhcpOptions(WifiSsid.fromString(TEST_SSID), Arrays.asList(oui2)); + WifiSsid.fromString(TEST_SSID), Collections.singletonList(oui1)).size()); + List<DhcpOption> actual2 = mWifiConfigManager.getCustomDhcpOptions( + WifiSsid.fromString(TEST_SSID), Collections.singletonList(oui2)); assertEquals(option2, actual2); List<DhcpOption> actual23 = mWifiConfigManager .getCustomDhcpOptions(WifiSsid.fromString(TEST_SSID), Arrays.asList(oui2, oui3)); 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 29c85417b5..65b130838a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java @@ -301,6 +301,7 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { @Test public void testValidatePositiveCases_OnlyUpdateIgnoresNullSsid() { WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); assertFalse(WifiConfigurationUtil.validate(config, SUPPORTED_FEATURES_ALL, WifiConfigurationUtil.VALIDATE_FOR_ADD)); assertTrue(WifiConfigurationUtil.validate( @@ -699,8 +700,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenNetwork()); - assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -713,8 +714,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB), Pair.create(MacAddress.fromString(TEST_BSSID), MacAddress.BROADCAST_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenNetwork()); - assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -727,8 +728,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID), MacAddress.BROADCAST_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenNetwork()); - assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -742,8 +743,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID), MacAddress.BROADCAST_ADDRESS), ScanResult.WIFI_BAND_5_GHZ, - WifiConfigurationTestUtil.createOpenNetwork()); - assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertTrue(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } @@ -757,8 +758,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB), Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -771,8 +772,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher("", PatternMatcher.PATTERN_LITERAL), Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -785,8 +786,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), Pair.create(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -799,8 +800,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID), WifiManager.ALL_ZEROS_MAC_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -813,8 +814,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_PREFIX), Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS), ScanResult.UNSPECIFIED, - WifiConfigurationTestUtil.createOpenHiddenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenHiddenNetwork(), new int[0]); + assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** @@ -826,8 +827,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL), Pair.create(MacAddress.fromString(TEST_BSSID), MacAddress.BROADCAST_ADDRESS), 42, // invalid - WifiConfigurationTestUtil.createOpenNetwork()); - assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier)); + WifiConfigurationTestUtil.createOpenNetwork(), new int[0]); + assertFalse(WifiConfigurationUtil.validateNetworkSpecifier(specifier, 5)); } /** 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 9d7b5ec0e0..a7c5b51b8f 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java @@ -66,6 +66,7 @@ import android.app.test.TestAlarmManager; import android.content.BroadcastReceiver; import android.content.Intent; import android.content.pm.PackageManager; +import android.net.IpConfiguration; import android.net.MacAddress; import android.net.wifi.IPnoScanResultsCallback; import android.net.wifi.ScanResult; @@ -73,14 +74,13 @@ import android.net.wifi.ScanResult.InformationElement; import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiContext; +import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; -import android.net.wifi.WifiScanner.PnoScanListener; import android.net.wifi.WifiScanner.PnoSettings; import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanListener; import android.net.wifi.WifiScanner.ScanSettings; import android.net.wifi.WifiSsid; import android.net.wifi.hotspot2.PasspointConfiguration; @@ -96,6 +96,7 @@ import android.os.Process; import android.os.SystemClock; import android.os.WorkSource; import android.os.test.TestLooper; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.LocalLog; @@ -106,7 +107,9 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.ActiveModeWarden.ExternalClientModeManagerRequestListener; import com.android.server.wifi.hotspot2.PasspointManager; 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.resources.R; import org.junit.After; @@ -135,7 +138,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.Executor; import java.util.stream.Collectors; /** @@ -158,12 +160,13 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConfigManager = mockWifiConfigManager(); mWifiInfo = getWifiInfo(); mScanData = mockScanData(); - mWifiScanner = mockWifiScanner(); + mockWifiScanner(); mWifiConnectivityHelper = mockWifiConnectivityHelper(); mWifiNS = mockWifiNetworkSelector(); mLooper = new TestLooper(mClock::getElapsedSinceBootMillis); mTestHandler = new TestHandler(mLooper.getLooper()); - when(mContext.getSystemService(WifiScanner.class)).thenReturn(mWifiScanner); + WifiLocalServices.removeServiceForTest(WifiScannerInternal.class); + WifiLocalServices.addService(WifiScannerInternal.class, mWifiScanner); when(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList(anyBoolean())) .thenReturn(new ArrayList<>()); when(mWifiNetworkSuggestionsManager.getAllApprovedNetworkSuggestions()) @@ -177,7 +180,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mContext.getSystemService(PowerManager.class)).thenReturn(powerManager); when(powerManager.isInteractive()).thenReturn(false); when(mPrimaryClientModeManager.getRole()).thenReturn(ActiveModeManager.ROLE_CLIENT_PRIMARY); - when(mPrimaryClientModeManager.syncRequestConnectionInfo()).thenReturn(mWifiInfo); + when(mPrimaryClientModeManager.getConnectionInfo()).thenReturn(mWifiInfo); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); doAnswer(new AnswerWithArguments() { public void answer(ExternalClientModeManagerRequestListener listener, @@ -280,13 +283,13 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { private TestHandler mTestHandler; private WifiConnectivityManager mWifiConnectivityManager; private WifiNetworkSelector mWifiNS; - private WifiScanner mWifiScanner; private WifiConnectivityHelper mWifiConnectivityHelper; private ScanData mScanData; private WifiConfigManager mWifiConfigManager; private WifiInfo mWifiInfo; private LocalLog mLocalLog; private LruConnectionTracker mLruConnectionTracker; + @Mock private WifiScannerInternal mWifiScanner; @Mock private Clock mClock; @Mock private WifiLastResortWatchdog mWifiLastResortWatchdog; @Mock private OpenNetworkNotifier mOpenNetworkNotifier; @@ -312,8 +315,12 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { @Mock private WifiGlobals mWifiGlobals; @Mock private ExternalPnoScanRequestManager mExternalPnoScanRequestManager; @Mock private SsidTranslator mSsidTranslator; + @Mock private WifiPermissionsUtil mWifiPermissionsUtil; + @Mock private WifiCarrierInfoManager mWifiCarrierInfoManager; @Mock WifiCandidates.Candidate mCandidate1; @Mock WifiCandidates.Candidate mCandidate2; + @Mock WifiCandidates.Candidate mCandidate3; + @Mock WifiCandidates.Candidate mCandidate4; private WifiConfiguration mCandidateWifiConfig1; private WifiConfiguration mCandidateWifiConfig2; private List<WifiCandidates.Candidate> mCandidateList; @@ -332,8 +339,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { private static final int CANDIDATE_NETWORK_ID = 0; private static final int CANDIDATE_NETWORK_ID_2 = 2; private static final String CANDIDATE_SSID = "\"AnSsid\""; + private static final String CANDIDATE_SSID_2 = "\"AnSsid2\""; private static final String CANDIDATE_BSSID = "6c:f3:7f:ae:8c:f3"; private static final String CANDIDATE_BSSID_2 = "6c:f3:7f:ae:8d:f3"; + private static final String CANDIDATE_BSSID_3 = "6c:f3:7f:ae:8c:f4"; + private static final String CANDIDATE_BSSID_4 = "6c:f3:7f:ae:8c:f5"; private static final String INVALID_SCAN_RESULT_BSSID = "6c:f3:7f:ae:8c:f4"; private static final int TEST_FREQUENCY = 2420; private static final long CURRENT_SYSTEM_TIME_MS = 1000; @@ -385,12 +395,12 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { * scheduled at a time. The scheduled delayed message intervals are recorded and returned by * {@link #getIntervals}. The intervals are cleared by calling {@link #reset}. */ - private class TestHandler extends Handler { + private class TestHandler extends RunnerHandler { private ArrayList<Long> mIntervals = new ArrayList<>(); private Message mMessage; TestHandler(Looper looper) { - super(looper); + super(looper, 100, new LocalLog(128)); } public List<Long> getIntervals() { @@ -446,38 +456,30 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { return scanData; } - WifiScanner mockWifiScanner() { - WifiScanner scanner = mock(WifiScanner.class); - ArgumentCaptor<ScanListener> allSingleScanListenerCaptor = - ArgumentCaptor.forClass(ScanListener.class); + void mockWifiScanner() { + ArgumentCaptor<WifiScannerInternal.ScanListener> allSingleScanListenerCaptor = + ArgumentCaptor.forClass(WifiScannerInternal.ScanListener.class); - doNothing().when(scanner).registerScanListener( - any(), allSingleScanListenerCaptor.capture()); + doNothing().when(mWifiScanner).registerScanListener(allSingleScanListenerCaptor.capture()); ScanData[] scanDatas = new ScanData[1]; scanDatas[0] = mScanData; - // do a synchronous answer for the ScanListener callbacks doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onResults(scanDatas); - }}).when(scanner).startBackgroundScan(anyObject(), anyObject(), anyObject()); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { - listener.onResults(scanDatas); + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { + listener.getWifiScannerListener().onResults(scanDatas); // WCM processes scan results received via onFullResult (even though they're the // same as onResult for single scans). if (mScanData != null && mScanData.getResults() != null) { for (int i = 0; i < mScanData.getResults().length; i++) { - allSingleScanListenerCaptor.getValue().onFullResult( - mScanData.getResults()[i]); + allSingleScanListenerCaptor.getValue().getWifiScannerListener() + .onFullResult(mScanData.getResults()[i]); } } - allSingleScanListenerCaptor.getValue().onResults(scanDatas); - }}).when(scanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + allSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults( + scanDatas); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); // This unfortunately needs to be a somewhat valid scan result, otherwise // |ScanDetailUtil.toScanDetail| raises exceptions. @@ -493,12 +495,13 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { doAnswer(new AnswerWithArguments() { public void answer(ScanSettings settings, PnoSettings pnoSettings, - Executor executor, PnoScanListener listener) throws Exception { - listener.onPnoNetworkFound(scanResults); - }}).when(scanner).startDisconnectedPnoScan( - anyObject(), anyObject(), anyObject(), anyObject()); + WifiScannerInternal.ScanListener listener) throws Exception { + WifiScanner.PnoScanListener l = + (WifiScanner.PnoScanListener) listener.getWifiScannerListener(); + l.onPnoNetworkFound(scanResults); + }}).when(mWifiScanner).startPnoScan( + anyObject(), anyObject(), anyObject()); - return scanner; } WifiConnectivityHelper mockWifiConnectivityHelper() { @@ -593,7 +596,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiMetrics, mTestHandler, mClock, mLocalLog, mWifiScoreCard, mWifiBlocklistMonitor, mWifiChannelUtilization, mPasspointManager, mMultiInternetManager, mDeviceConfigFacade, mActiveModeWarden, - mFacade, mWifiGlobals, mExternalPnoScanRequestManager, mSsidTranslator); + mFacade, mWifiGlobals, mExternalPnoScanRequestManager, mSsidTranslator, + mWifiPermissionsUtil, mWifiCarrierInfoManager); mLooper.dispatchAll(); verify(mActiveModeWarden, atLeastOnce()).registerModeChangeCallback( mModeChangeCallbackCaptor.capture()); @@ -624,6 +628,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); + mLooper.dispatchAll(); } /** @@ -673,7 +678,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mActiveModeWarden, never()).requestSecondaryTransientClientModeManager( any(), any(), any(), any()); verify(mPrimaryClientModeManager, never()).startConnectToNetwork( @@ -694,7 +699,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); verify(mPrimaryClientModeManager).enableRoaming(true); @@ -727,7 +732,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mActiveModeWarden).requestSecondaryTransientClientModeManager( any(), eq(ActiveModeWarden.INTERNAL_REQUESTOR_WS), @@ -771,7 +776,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mActiveModeWarden).requestSecondaryTransientClientModeManager( any(), eq(ActiveModeWarden.INTERNAL_REQUESTOR_WS), @@ -810,7 +815,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - + mLooper.dispatchAll(); // Request secondary STA and connect using it. verify(mActiveModeWarden).requestSecondaryTransientClientModeManager( any(), @@ -851,7 +856,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - + mLooper.dispatchAll(); // Don't request secondary STA, fallback to primary STA. verify(mActiveModeWarden, never()).requestSecondaryTransientClientModeManager( any(), any(), any(), any()); @@ -904,7 +909,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); verify(mActiveModeWarden, never()).requestSecondaryLongLivedClientModeManager( @@ -931,7 +936,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); verify(mActiveModeWarden, never()).requestSecondaryLongLivedClientModeManager( @@ -958,7 +963,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); verify(mActiveModeWarden, never()).requestSecondaryLongLivedClientModeManager( @@ -985,7 +990,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); verify(mActiveModeWarden, never()).requestSecondaryLongLivedClientModeManager( @@ -1013,7 +1018,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); verify(mActiveModeWarden, never()).requestSecondaryLongLivedClientModeManager( @@ -1043,7 +1048,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // No connection triggered (even on primary since wifi is off). verify(mPrimaryClientModeManager, never()).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); @@ -1074,7 +1079,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // connection triggered on primary verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); @@ -1102,7 +1107,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // connection triggered on secondary verify(mPrimaryClientModeManager, never()).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); @@ -1147,7 +1152,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // connection triggered on secondary verify(mPrimaryClientModeManager, never()).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); @@ -1188,7 +1193,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // connection triggered on primary & secondary verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID_2, Process.WIFI_UID, "any"); @@ -1237,7 +1242,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // connection triggered on only on primary to CANDIDATE_NETWORK_ID_2. verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID_2, Process.WIFI_UID, "any"); @@ -1258,38 +1263,76 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { return scanDatas[0]; } + private WifiConfiguration getTestWifiConfig(int networkId, String ssid) { + WifiConfiguration config = generateWifiConfig( + networkId, 0, ssid, false, true, null, null, + WifiConfigurationTestUtil.SECURITY_PSK); + config.BSSID = ClientModeImpl.SUPPLICANT_BSSID_ANY; + config.oemPaid = false; + config.oemPrivate = false; + config.ephemeral = true; + when(mWifiConfigManager.getConfiguredNetwork(networkId)).thenReturn(config); + return config; + } + + private WifiCandidates.Candidate getTestWifiCandidate(int networkId, String ssid, String bssid, + int rssi, int frequency) { + WifiCandidates.Candidate candidate = mock(WifiCandidates.Candidate.class); + when(candidate.isOemPaid()).thenReturn(false); + when(candidate.isOemPrivate()).thenReturn(false); + + // Set up the scan candidates + ScanResult result = new ScanResult(WifiSsid.fromString(ssid), + ssid, bssid, 1245, 0, "some caps", rssi, frequency, + 1025, 22, 33, 20, 0, 0, true); + ScanResultMatchInfo matchInfo = ScanResultMatchInfo.fromScanResult(result); + WifiCandidates.Key key = new WifiCandidates.Key(matchInfo, MacAddress.fromString(bssid), + networkId, WifiConfiguration.SECURITY_TYPE_PSK); + when(candidate.getKey()).thenReturn(key); + when(candidate.getScanRssi()).thenReturn(rssi); + when(candidate.getFrequency()).thenReturn(frequency); + return candidate; + } + /** - * Setup all the mocks for the positive case, individual negative test cases below override - * specific params. + * Set up the mocks for the multi internet use case unit tests. */ - private void setupMocksForMultiInternetTests() { + private void setupMocksForMultiInternetTests(boolean isDbs) { + mCandidateWifiConfig1 = getTestWifiConfig(CANDIDATE_NETWORK_ID, CANDIDATE_SSID); + mCandidateWifiConfig2 = getTestWifiConfig(CANDIDATE_NETWORK_ID_2, CANDIDATE_SSID_2); + mScanData = createScanDataWithDifferentBands(); when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true); when(mActiveModeWarden.isStaStaConcurrencySupportedForMultiInternet()).thenReturn(true); when(mActiveModeWarden.getPrimaryClientModeManagerNullable()) .thenReturn(mPrimaryClientModeManager); - when(mCandidate1.isOemPaid()).thenReturn(false); - when(mCandidate1.isOemPrivate()).thenReturn(false); - ScanResultMatchInfo matchInfo = mock(ScanResultMatchInfo.class); - when(matchInfo.getDefaultSecurityParams()).thenReturn( - mCandidateWifiConfig1.getDefaultSecurityParams()); - WifiCandidates.Key key = new WifiCandidates.Key(matchInfo, - MacAddress.fromString(CANDIDATE_BSSID), 0); - when(mCandidate1.getKey()).thenReturn(key); - when(mCandidate1.getScanRssi()).thenReturn(-40); - when(mCandidate1.getFrequency()).thenReturn(TEST_FREQUENCY); - when(mCandidate1.getKey()).thenReturn(key); - - mCandidateWifiConfig1.oemPaid = false; - mCandidateWifiConfig1.oemPrivate = false; - mCandidateWifiConfig1.ephemeral = true; - mCandidateWifiConfig1.dbsSecondaryInternet = true; - when(mWifiNS.selectNetwork(argThat( - candidates -> (candidates != null)), eq(false))).thenReturn(mCandidateWifiConfig1); when(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()) .thenReturn(true); when(mActiveModeWarden.canRequestMoreClientModeManagersInRole( any(), eq(ROLE_CLIENT_SECONDARY_LONG_LIVED), eq(false))).thenReturn(true); + mCandidate1 = getTestWifiCandidate(CANDIDATE_NETWORK_ID, CANDIDATE_SSID, CANDIDATE_BSSID, + -40, + TEST_FREQUENCY); + mCandidate2 = getTestWifiCandidate(CANDIDATE_NETWORK_ID_2, CANDIDATE_SSID_2, + CANDIDATE_BSSID_2, -60, + TEST_FREQUENCY_2); + mCandidate4 = getTestWifiCandidate(CANDIDATE_NETWORK_ID_2, + CANDIDATE_SSID_2, CANDIDATE_BSSID_4, + -40, + TEST_FREQUENCY_3); + + // A DBS candidate with same SSID as mCandidate1 + mCandidate3 = getTestWifiCandidate(CANDIDATE_NETWORK_ID, CANDIDATE_SSID, CANDIDATE_BSSID_3, + -40, + TEST_FREQUENCY_3); + mCandidateList = new ArrayList<WifiCandidates.Candidate>( + Arrays.asList(mCandidate1, mCandidate2, mCandidate4)); + if (isDbs) { + mCandidateList.add(mCandidate3); + } + when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), + anyBoolean(), any(), anyBoolean())).thenReturn(mCandidateList); + doAnswer(new AnswerWithArguments() { public void answer(ExternalClientModeManagerRequestListener listener, WorkSource requestorWs, String ssid, String bssid) { @@ -1300,36 +1343,91 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mSecondaryClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED); } - @Test - public void multiInternetSecondaryConnectionRequestSucceedsWithDbsApOnly() { - setupMocksForMultiInternetTests(); - when(mMultiInternetManager.isStaConcurrencyForMultiInternetMultiApAllowed()) - .thenReturn(false); + /** + * Set up the primary network selection mocks for the multi internet use case unit tests. + */ + private void setupMockPrimaryNetworkSelect(int networkId, String bssid, int rssi, + int frequency) { + WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); + config.getNetworkSelectionStatus().setCandidate( + new ScanResult(WifiSsid.fromUtf8Text(config.SSID), + config.SSID, bssid, 1245, 0, "some caps", rssi, frequency, + 1025, 22, 33, 20, 0, 0, true)); + // Selection for primary + when(mWifiNS.selectNetwork(any())) + .then(new AnswerWithArguments() { + public WifiConfiguration answer(List<WifiCandidates.Candidate> candidateList) { + if (candidateList != null) { + for (WifiCandidates.Candidate candidate : candidateList) { + if (networkId == candidate.getKey().networkId) { + return config; + } + } + } + return null; + } + }); + } + /** + * Set up the secondary network selection mocks for the multi internet use case unit tests. + */ + private void setupMockSecondaryNetworkSelect(int networkId, int rssi) { + WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); + // Selection for secondary + when(mWifiNS.selectNetwork(any(), anyBoolean())) + .then(new AnswerWithArguments() { + public WifiConfiguration answer(List<WifiCandidates.Candidate> candidateList, + boolean override) { + if (candidateList != null) { + for (WifiCandidates.Candidate candidate : candidateList) { + // Will return the first candidate matching networkId + if (networkId == candidate.getKey().networkId) { + config.getNetworkSelectionStatus().setCandidate( + new ScanResult(WifiSsid.fromUtf8Text(config.SSID), + config.SSID, candidate.getKey().bssid + .toString(), 1245, 0, "some caps", rssi, + candidate.getFrequency(), 1025, 22, 33, + 20, 0, 0, true)); + return config; + } + } + } + return null; + } + }); + } + + /** + * Set up the client manager wifi info mocks for the multi internet use case unit tests. + */ + private void mockClientManagerInfo(ConcreteClientModeManager clientManager, + WifiConfiguration configuration) { + WifiInfo wifiInfo = getWifiInfo(); + wifiInfo.setNetworkId(configuration.networkId); + wifiInfo.setSSID(WifiSsid.fromString(configuration.SSID)); + wifiInfo.setBSSID(configuration.BSSID); + wifiInfo.setFrequency( + configuration.getNetworkSelectionStatus().getCandidate().frequency); + wifiInfo.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_PSK); + when(clientManager.isConnected()).thenReturn(true); + when(clientManager.isDisconnected()).thenReturn(false); + when(clientManager.getConnectionInfo()).thenReturn(wifiInfo); + } + + private void testMultiInternetSecondaryConnectionRequest(boolean isDbsOnly, boolean isDhcp, + boolean success, String expectedBssidToConnect) { + when(mMultiInternetManager.isStaConcurrencyForMultiInternetMultiApAllowed()) + .thenReturn(!isDbsOnly); + setupMockPrimaryNetworkSelect(CANDIDATE_NETWORK_ID, CANDIDATE_BSSID, -50, TEST_FREQUENCY); + WifiConfiguration targetConfig = isDbsOnly ? mCandidateWifiConfig1 : mCandidateWifiConfig2; + String targetBssid = expectedBssidToConnect; + targetConfig.setIpAssignment( + isDhcp ? IpConfiguration.IpAssignment.DHCP : IpConfiguration.IpAssignment.STATIC); + setupMockSecondaryNetworkSelect(targetConfig.networkId, -50); // Set screen to on setScreenState(true); - when(mCandidate1.isSecondaryInternet()).thenReturn(true); - mCandidateWifiConfig1.ephemeral = true; - mCandidateWifiConfig1.dbsSecondaryInternet = true; - - // Set up the scan candidates - MacAddress macAddress = MacAddress.fromString(CANDIDATE_BSSID); - ScanResult result1 = new ScanResult(WifiSsid.fromUtf8Text(CANDIDATE_SSID), - TEST_SSID, TEST_CONNECTED_BSSID, 1245, 0, "some caps", -78, 2450, - 1025, 22, 33, 20, 0, 0, true); - ScanResultMatchInfo matchInfo1 = ScanResultMatchInfo.fromScanResult(result1); - WifiCandidates.Key key = new WifiCandidates.Key(matchInfo1, macAddress, - TEST_CONNECTED_NETWORK_ID, - 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, @@ -1337,27 +1435,30 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mLooper.dispatchAll(); // Verify a connection starting verify(mWifiNS).selectNetwork((List<WifiCandidates.Candidate>) - argThat(new WifiCandidatesListSizeMatcher(2))); + argThat(new WifiCandidatesListSizeMatcher(mCandidateList.size()))); verify(mPrimaryClientModeManager).startConnectToNetwork(anyInt(), anyInt(), any()); - WifiInfo info1 = getWifiInfo(); - info1.setNetworkId(TEST_CONNECTED_NETWORK_ID); - info1.setSSID(WifiSsid.fromUtf8Text(TEST_SSID)); - info1.setBSSID(TEST_CONNECTED_BSSID); - info1.setFrequency(TEST_FREQUENCY_5G); - info1.setCurrentSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN); - when(mPrimaryClientModeManager.isConnected()).thenReturn(true); - when(mPrimaryClientModeManager.isDisconnected()).thenReturn(false); - when(mPrimaryClientModeManager.syncRequestConnectionInfo()).thenReturn(info1); + // mCandidateWifiConfig1 is connected as primary + mockClientManagerInfo(mPrimaryClientModeManager, mCandidateWifiConfig1); + when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(true); - WorkSource testWorkSource = new WorkSource(); // Set the connection pending status mMultiInternetConnectionStatusListenerCaptor.getValue().onStatusChange( MultiInternetManager.MULTI_INTERNET_STATE_CONNECTION_REQUESTED, - testWorkSource); - mMultiInternetConnectionStatusListenerCaptor.getValue().onStartScan(testWorkSource); + new WorkSource()); + mMultiInternetConnectionStatusListenerCaptor.getValue().onStartScan(new WorkSource()); + mLooper.dispatchAll(); + if (!success) { + verify(mSecondaryClientModeManager, never()).startConnectToNetwork( + targetConfig.networkId, Process.WIFI_UID, targetBssid); + verify(mSecondaryClientModeManager, never()).enableRoaming(false); + verify(mActiveModeWarden, never()).requestSecondaryLongLivedClientModeManager( + any(), any(), any(), any()); + return; + } + verify(mSecondaryClientModeManager, times(2)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + targetConfig.networkId, Process.WIFI_UID, targetBssid); verify(mSecondaryClientModeManager, times(2)).enableRoaming(false); verify(mActiveModeWarden, times(2)).requestSecondaryLongLivedClientModeManager( any(), any(), any(), any()); @@ -1378,71 +1479,64 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { } @Test - public void multiInternetSecondaryConnectionRequestSucceedsWithMultiApAllowed() { - setupMocksForMultiInternetTests(); - when(mMultiInternetManager.isStaConcurrencyForMultiInternetMultiApAllowed()) - .thenReturn(true); - - // Set screen to on - setScreenState(true); + public void multiInternetSecondaryConnectionRequestSucceedsWithDbsApOnly() { + setupMocksForMultiInternetTests(true); + testMultiInternetSecondaryConnectionRequest(true, true, true, CANDIDATE_BSSID_3); + } - when(mCandidate1.isSecondaryInternet()).thenReturn(true); - mCandidateWifiConfig1.ephemeral = true; - mCandidateWifiConfig1.dbsSecondaryInternet = true; + @Test + public void multiInternetSecondaryConnectionRequestSucceedsWithDbsApOnlyFailOnStaticIp() { + setupMocksForMultiInternetTests(true); + testMultiInternetSecondaryConnectionRequest(true, false, false, CANDIDATE_BSSID_3); + } - // Set up the scan candidates - MacAddress macAddress = MacAddress.fromString(CANDIDATE_BSSID); - 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); + @Test + public void multiInternetSecondaryConnectionRequestSucceedsWithMultiApAllowed() { + setupMocksForMultiInternetTests(false); + testMultiInternetSecondaryConnectionRequest(false, true, true, CANDIDATE_BSSID_2); + } - // 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()); + @Test + public void multiInternetSecondaryConnectionDisconnectedBeforeNetworkSelection() { + setupMocksForMultiInternetTests(false); + testMultiInternetSecondaryConnectionRequest(false, true, true, CANDIDATE_BSSID_2); + setupMockPrimaryNetworkSelect(CANDIDATE_NETWORK_ID_2, CANDIDATE_BSSID_2, -50, + TEST_FREQUENCY); + when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(false); + when(mSecondaryClientModeManager.isConnected()).thenReturn(true); + when(mSecondaryClientModeManager.getConnectedWifiConfiguration()).thenReturn( + mCandidateWifiConfig2); + when(mActiveModeWarden.getClientModeManagerInRole( + ROLE_CLIENT_SECONDARY_LONG_LIVED)).thenReturn(mSecondaryClientModeManager); + mMultiInternetConnectionStatusListenerCaptor.getValue().onStartScan(new WorkSource()); + verify(mSecondaryClientModeManager).disconnect(); + } - WifiInfo info1 = getWifiInfo(); - info1.setFrequency(TEST_FREQUENCY_5G); - when(mPrimaryClientModeManager.isConnected()).thenReturn(true); - when(mPrimaryClientModeManager.isDisconnected()).thenReturn(false); - when(mPrimaryClientModeManager.syncRequestConnectionInfo()).thenReturn(info1); - when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(true); - WorkSource testWorkSource = new WorkSource(); - // Set the connection pending status - mMultiInternetConnectionStatusListenerCaptor.getValue().onStatusChange( - MultiInternetManager.MULTI_INTERNET_STATE_CONNECTION_REQUESTED, - testWorkSource); - mMultiInternetConnectionStatusListenerCaptor.getValue().onStartScan(testWorkSource); - verify(mSecondaryClientModeManager, times(2)).startConnectToNetwork( - CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); - verify(mSecondaryClientModeManager, times(2)).enableRoaming(false); - verify(mActiveModeWarden, times(2)).requestSecondaryLongLivedClientModeManager( - any(), any(), any(), any()); + @Test + public void multiInternetSecondaryConnectionRequest_filteredBssidExists() { + setupMocksForMultiInternetTests(false); + Map<Integer, String> specifiedBssids = new ArrayMap<>(); + // Verify connect to the filtered BSSID + specifiedBssids.put(ScanResult.toBand(mCandidate4.getFrequency()), + mCandidate4.getKey().bssid.toString()); + when(mMultiInternetManager.getSpecifiedBssids()).thenReturn(specifiedBssids); + testMultiInternetSecondaryConnectionRequest(false, true, true, + mCandidate4.getKey().bssid.toString()); + } - // Simulate connection failing on the secondary - clearInvocations(mSecondaryClientModeManager, mPrimaryClientModeManager, mWifiNS); - mWifiConnectivityManager.handleConnectionAttemptEnded( - mSecondaryClientModeManager, - WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, CANDIDATE_BSSID, - WifiConfigurationTestUtil.createPskNetwork(CANDIDATE_SSID)); - // verify connection is never restarted when a connection on the secondary STA fails. - verify(mWifiNS, never()).selectNetwork(any()); - verify(mSecondaryClientModeManager, never()).startConnectToNetwork( - anyInt(), anyInt(), any()); - verify(mPrimaryClientModeManager, never()).startConnectToNetwork( - anyInt(), anyInt(), any()); + @Test + public void multiInternetSecondaryConnectionRequest_filterBssidNotExist() { + setupMocksForMultiInternetTests(false); + Map<Integer, String> specifiedBssids = new ArrayMap<>(); + // Verify filtering by a BSSID that does not exist in the candidate list still + // results in a connection. + specifiedBssids.put(ScanResult.toBand(mCandidate2.getFrequency()), + mCandidate3.getKey().bssid.toString()); + specifiedBssids.put(ScanResult.toBand(mCandidate4.getFrequency()), + mCandidate3.getKey().bssid.toString()); + when(mMultiInternetManager.getSpecifiedBssids()).thenReturn(specifiedBssids); + testMultiInternetSecondaryConnectionRequest(false, true, true, + mCandidate2.getKey().bssid.toString()); } /** @@ -1461,7 +1555,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); } @@ -1483,7 +1577,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); } @@ -1501,7 +1595,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // Set screen to on setScreenState(true); @@ -1523,7 +1617,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Set screen to on setScreenState(true); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager, atLeastOnce()).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); } @@ -1579,6 +1673,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } // Now trigger another connection attempt before the rate interval, this should be @@ -1588,7 +1683,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // Verify that we attempt to connect upto the rate. verify(mPrimaryClientModeManager, times(numAttempts)).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); @@ -1620,6 +1715,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } // Now trigger another connection attempt after the rate interval, this should not be @@ -1630,6 +1726,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; // Verify that all the connection attempts went through @@ -1663,6 +1760,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } @@ -1675,6 +1773,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } @@ -1708,6 +1807,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } @@ -1720,6 +1820,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } @@ -1753,6 +1854,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } @@ -1766,6 +1868,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); numAttempts++; } @@ -1792,7 +1895,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mWifiMetrics).noteFirstNetworkSelectionAfterBoot(false); // Get the retry delay value after QNS didn't select a @@ -1808,6 +1911,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); } int lowRssiNetworkRetryDelayAfterThreePnoMs = mWifiConnectivityManager .getLowRssiNetworkRetryDelay(); @@ -1830,7 +1934,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // Now fire the watchdog alarm and verify the metrics were incremented. mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); mLooper.dispatchAll(); @@ -1857,7 +1961,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // Now fire the watchdog alarm and verify the metrics were incremented. mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); mLooper.dispatchAll(); @@ -1875,7 +1979,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // Verify the watchdog alarm has been set assertTrue(mAlarmManager.isPending(WifiConnectivityManager.WATCHDOG_TIMER_TAG)); @@ -1965,7 +2069,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mWifiScanner).startScan((ScanSettings) argThat(new WifiPartialScanSettingMatcher()), - any(), any(), any()); + any()); } private class WifiPartialScanSettingMatcher implements ArgumentMatcher<ScanSettings> { @@ -2113,6 +2217,48 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { verify(mPrimaryClientModeManager).startConnectToNetwork(anyInt(), anyInt(), any()); } + /** + * Verify that we do not try to reconnect to an admin restricted network + */ + @Test + public void testRetryConnectionIgnoreNetworkWithAdminRestriction() { + // 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()); + + // mock the WifiConfiguration to have an admin restriction + WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(CANDIDATE_SSID); + when(mWifiPermissionsUtil.isAdminRestrictedNetwork(config)).thenReturn(true); + + // Simulate the connection failing + mWifiConnectivityManager.handleConnectionAttemptEnded( + mPrimaryClientModeManager, + WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, + WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, CANDIDATE_BSSID, + config); + + // Verify another connection do not start. + verify(mPrimaryClientModeManager).startConnectToNetwork(anyInt(), anyInt(), any()); + } + private class WifiCandidatesListSizeMatcher implements ArgumentMatcher<List<WifiCandidates.Candidate>> { int mSize; @@ -2569,8 +2715,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { int[] intervalSchedule, int[] scheduleScanType) { // Verify the scans actually happened for expected times, one scan for state change and // each for scan timer triggered. - verify(mWifiScanner, times(scanTimes)).startScan(anyObject(), anyObject(), anyObject(), - anyObject()); + verify(mWifiScanner, times(scanTimes)).startScan(anyObject(), anyObject()); // Verify scans are happening using the expected scan type. Map<Integer, Integer> scanTypeToTimesMap = new HashMap<>(); @@ -2585,7 +2730,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { public boolean matches(ScanSettings scanSettings) { return scanSettings.type == entry.getKey(); } - }), any(), any(), any()); + }), any()); } // Verify the scan intervals are same as expected interval schedule. @@ -2594,8 +2739,9 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // TestHandler#sendMessageAtTime is not perfectly mocked and uses // SystemClock.uptimeMillis() to generate |intervals|. This sometimes results in error // margins of ~1ms and cause flaky test failures. - assertTrue("Interval " + i + " not in 1ms error margin", - Math.abs(expected - intervals.get(i).longValue()) < 2); + final long delta = Math.abs(expected - intervals.get(i).longValue()); + assertTrue("Interval " + i + " (" + delta + ") not in 1ms error margin", + delta < 2); } } @@ -2603,8 +2749,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { int expectedInterval) { // Verify the scans actually happened for expected times, one scan for state change and // each for scan timer triggered. - verify(mWifiScanner, times(scanTimes)).startScan(anyObject(), anyObject(), anyObject(), - anyObject()); + verify(mWifiScanner, times(scanTimes)).startScan(anyObject(), anyObject()); // The actual interval should be same as scheduled. assertEquals(expectedInterval * 1000, intervals.get(0).longValue()); @@ -3175,8 +3320,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - verify(mWifiScanner, times(1)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); + verify(mWifiScanner, times(1)).startScan(anyObject(), anyObject()); // Set up time stamp for when entering CONNECTED state currentTimeStamp += 2000; @@ -3218,8 +3362,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - verify(mWifiScanner, never()).startScan(anyObject(), anyObject(), anyObject(), - anyObject()); + verify(mWifiScanner, never()).startScan(anyObject(), anyObject()); } /** @@ -3248,8 +3391,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Set WiFi to connected state to trigger the periodic scan setWifiStateConnected(); - verify(mWifiScanner, times(1)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); + verify(mWifiScanner, times(1)).startScan(anyObject(), anyObject()); // Set up the time stamp for when entering DISCONNECTED state currentTimeStamp += 2000; @@ -3343,11 +3485,19 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mPerNetwork.getFrequencies(anyLong())).thenReturn(new ArrayList<>()); doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, ScanListener listener, - WorkSource workSource) throws Exception { - assertEquals(settings.band, WifiScanner.WIFI_BAND_ALL); + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { + if (SdkLevel.isAtLeastS()) { + assertEquals(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ, settings.band); + assertEquals("RNR should be enabled for full scans", + WifiScanner.WIFI_RNR_ENABLED, settings.getRnrSetting()); + assertTrue("PSC should be enabled for full scans", + settings.is6GhzPscOnlyEnabled()); + } else { + assertEquals(WifiScanner.WIFI_BAND_ALL, settings.band); + } assertNull(settings.channels); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); // Set screen to ON @@ -3357,8 +3507,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + verify(mWifiScanner).startScan(anyObject(), anyObject()); // Verify case 2 when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(true); @@ -3371,8 +3521,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject(), anyObject(), - anyObject()); + verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject()); // Verify case 3 when(mWifiNS.isNetworkSufficient(eq(mWifiInfo))).thenReturn(false); @@ -3385,8 +3534,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject(), anyObject(), - anyObject()); + verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject()); } /** @@ -3419,8 +3567,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false); doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { assertEquals(settings.band, WifiScanner.WIFI_BAND_UNSPECIFIED); assertEquals(settings.channels.length, channelList.size()); if (SdkLevel.isAtLeastS()) { @@ -3432,7 +3580,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { for (int chanIdx = 0; chanIdx < settings.channels.length; chanIdx++) { assertTrue(channelList.contains(settings.channels[chanIdx].frequency)); } - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); // Set screen to ON setScreenState(true); @@ -3442,7 +3591,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + verify(mWifiScanner).startScan(anyObject(), anyObject()); } /** @@ -3475,14 +3624,15 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false); doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { assertEquals(settings.band, WifiScanner.WIFI_BAND_UNSPECIFIED); assertEquals(settings.channels.length, channelList.size()); for (int chanIdx = 0; chanIdx < settings.channels.length; chanIdx++) { assertTrue(channelList.contains(settings.channels[chanIdx].frequency)); } - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); // Set screen to ON setScreenState(true); @@ -3492,7 +3642,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + verify(mWifiScanner).startScan(anyObject(), anyObject()); } @@ -3521,8 +3671,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { .thenReturn(new WifiConfiguration()); doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { assertNull(settings.channels); if (SdkLevel.isAtLeastS()) { assertEquals(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ, settings.band); @@ -3533,7 +3683,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { } else { assertEquals(WifiScanner.WIFI_BAND_ALL, settings.band); } - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); // Set screen to ON setScreenState(true); @@ -3543,7 +3694,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_CONNECTED); - verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + verify(mWifiScanner).startScan(anyObject(), anyObject()); } /** @@ -3559,10 +3710,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { setScreenState(true); doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { listener.onFailure(-1, "ScanFailure"); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); // Set WiFi to disconnected state to trigger the single scan based periodic scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -3580,7 +3732,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // The very first scan is the initial one, and the other MAX_SCAN_RESTART_ALLOWED // are the retrial ones. verify(mWifiScanner, times(WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED + 1)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); + anyObject(), anyObject()); } @Test @@ -3589,10 +3741,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { setScreenState(true); doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { listener.onFailure(-1, "ScanFailure"); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); // Set WiFi to disconnected state to trigger the single scan based periodic scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -3611,8 +3764,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Verify that the connectivity scan has happened 2 times. Note, the first scan is due // to the initial request, and the second scan is the first retry after failure. // There are no more retries afterwards because the screen is off. - verify(mWifiScanner, times(2)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); + verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject()); } /** @@ -3630,32 +3782,35 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { setScreenState(true); // Setup WifiScanner to fail doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { listener.onFailure(-1, "ScanFailure"); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); mWifiConnectivityManager.forceConnectivityScan(null); // make the retry succeed doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { listener.onResults(null); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); mAlarmManager.dispatch(WifiConnectivityManager.RESTART_SINGLE_SCAN_TIMER_TAG); mLooper.dispatchAll(); // Verify that startScan is called once for the original scan, plus once for the retry. // The successful retry should have now cleared the restart count verify(mWifiScanner, times(2)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); + anyObject(), anyObject()); // Now force a new scan and verify we retry MAX_SCAN_RESTART_ALLOWED times doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, Executor executor, ScanListener listener, - WorkSource workSource) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { listener.onFailure(-1, "ScanFailure"); - }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject(), anyObject()); + mLooper.dispatchAll(); + }}).when(mWifiScanner).startScan(anyObject(), anyObject()); mWifiConnectivityManager.forceConnectivityScan(null); // Fire the alarm timer 2x timers for (int i = 0; i < (WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED * 2); i++) { @@ -3668,7 +3823,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // and additionally MAX_SCAN_RESTART_ALLOWED + 1 times from forceConnectivityScan and // subsequent retries. verify(mWifiScanner, times(WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED + 3)).startScan( - anyObject(), anyObject(), anyObject(), anyObject()); + anyObject(), anyObject()); } /** @@ -3682,11 +3837,12 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { @Test public void listenToAllSingleScanResults() { ScanSettings settings = new ScanSettings(); - ScanListener scanListener = mock(ScanListener.class); + WifiScannerInternal.ScanListener scanListener = new WifiScannerInternal.ScanListener(mock( + WifiScanner.ScanListener.class), mTestHandler); // Request a single scan outside of WifiConnectivityManager. - mWifiScanner.startScan(settings, mock(Executor.class), scanListener, WIFI_WORK_SOURCE); - + mWifiScanner.startScan(settings, scanListener); + mLooper.dispatchAll(); // Verify that WCM receives the scan results and initiates a connection // to the network. verify(mPrimaryClientModeManager).startConnectToNetwork( @@ -3712,7 +3868,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Force a connectivity scan which enables WifiConnectivityManager // to wait for full band scan results. mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - + mLooper.dispatchAll(); // No roaming because no full band scan results. verify(mPrimaryClientModeManager, times(0)).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); @@ -3723,7 +3879,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Force a connectivity scan which enables WifiConnectivityManager // to wait for full band scan results. mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - + mLooper.dispatchAll(); // Roaming attempt because full band scan results are available. verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); @@ -3754,6 +3910,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { .thenReturn(passpointNetworks); mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); + mLooper.dispatchAll(); ArgumentCaptor<ArrayList<String>> listArgumentCaptor = ArgumentCaptor.forClass(ArrayList.class); verify(mWifiConfigManager).updateUserDisabledList(listArgumentCaptor.capture()); @@ -3767,6 +3924,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { public void verifyClearExpiredRecentFailureStatusAfterScan() { // mWifiScanner is mocked to directly return scan results when a scan is triggered. mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); + mLooper.dispatchAll(); verify(mWifiConfigManager).cleanupExpiredRecentFailureReasons(); } @@ -3790,7 +3948,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { inOrder.verify(mWifiBlocklistMonitor, never()) .updateAndGetBssidBlocklistForSsids(anySet()); mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - + mLooper.dispatchAll(); inOrder.verify(mWifiBlocklistMonitor).tryEnablingBlockedBssids(any()); inOrder.verify(mWifiConfigManager).updateNetworkSelectionStatus(disabledConfig.networkId, WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE); @@ -3933,7 +4091,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, ClientModeImpl.SUPPLICANT_BSSID_ANY); } @@ -3970,7 +4128,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); verify(mPrimaryClientModeManager).enableRoaming(false); @@ -3995,7 +4153,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); } @@ -4023,12 +4181,12 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Set screen to on setScreenState(true); - + mLooper.dispatchAll(); // Set WiFi to disconnected state mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); } @@ -4047,7 +4205,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Set screen to on setScreenState(true); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager).startRoamToNetwork(eq(CANDIDATE_NETWORK_ID), mCandidateBssidCaptor.capture()); assertEquals(mCandidateBssidCaptor.getValue(), CANDIDATE_BSSID); @@ -4073,7 +4231,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Set screen to on setScreenState(true); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager, never()).startRoamToNetwork(anyInt(), anyObject()); verify(mPrimaryClientModeManager, never()).startConnectToNetwork( anyInt(), anyInt(), anyObject()); @@ -4108,7 +4266,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); verify(mPrimaryClientModeManager, times(0)).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); } @@ -4253,7 +4411,6 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - // We should have filtered out the 3rd scan result. assertEquals(3, capturedScanDetails.size()); List<ScanResult> capturedScanResults = @@ -4313,7 +4470,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( mPrimaryClientModeManager, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); // We should not filter any of the scan results. assertEquals(4, capturedScanDetails.size()); List<ScanResult> capturedScanResults = @@ -4354,16 +4511,16 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Enable trusted connection. This should NOT trigger a pno scan for auto-join. mWifiConnectivityManager.setTrustedConnectionAllowed(true); - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); + verify(mWifiScanner, never()).startPnoScan(any(), any(), any()); // End of processing a specific request. This should NOT trigger a new pno scan for // auto-join. mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); + verify(mWifiScanner, never()).startPnoScan(any(), any(), any()); // Enable untrusted connection. This should NOT trigger a pno scan for auto-join. mWifiConnectivityManager.setUntrustedConnectionAllowed(true); - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); + verify(mWifiScanner, never()).startPnoScan(any(), any(), any()); } /** @@ -4390,7 +4547,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Enable trusted connection. This should trigger a pno scan for auto-join. mWifiConnectivityManager.setTrustedConnectionAllowed(true); - verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); + verify(mWifiScanner).startPnoScan(any(), any(), any()); // Start of processing a specific request. This should stop any pno scan for auto-join. mWifiConnectivityManager.setSpecificNetworkRequestInProgress(true); @@ -4399,7 +4556,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // End of processing a specific request. This should now trigger a new pno scan for // auto-join. mWifiConnectivityManager.setSpecificNetworkRequestInProgress(false); - verify(mWifiScanner, times(2)).startDisconnectedPnoScan(any(), any(), any(), any()); + verify(mWifiScanner, times(2)).startPnoScan(any(), any(), any()); // Disable trusted connection. This should stop any pno scan for auto-join. mWifiConnectivityManager.setTrustedConnectionAllowed(false); @@ -4407,7 +4564,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Enable untrusted connection. This should trigger a pno scan for auto-join. mWifiConnectivityManager.setUntrustedConnectionAllowed(true); - verify(mWifiScanner, times(3)).startDisconnectedPnoScan(any(), any(), any(), any()); + verify(mWifiScanner, times(3)).startPnoScan(any(), any(), any()); } /** @@ -4457,8 +4614,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { ScanSettings.class); InOrder inOrder = inOrder(mWifiScanner); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); + inOrder.verify(mWifiScanner).startPnoScan(scanSettingsCaptor.capture(), any(), any()); assertEquals(interval, scanSettingsCaptor.getValue().periodInMs); } @@ -4480,8 +4636,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { ScanSettings.class); InOrder inOrder = inOrder(mWifiScanner); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); + inOrder.verify(mWifiScanner).startPnoScan(scanSettingsCaptor.capture(), any(), any()); assertEquals(scanSettingsCaptor.getValue().periodInMs, MOVING_PNO_SCAN_INTERVAL_MILLIS); // initial connectivity state uses moving PNO scan interval, now set it to stationary @@ -4489,8 +4644,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); inOrder.verify(mWifiScanner).stopPnoScan(any()); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); + inOrder.verify(mWifiScanner).startPnoScan(scanSettingsCaptor.capture(), any(), any()); assertEquals(scanSettingsCaptor.getValue().periodInMs, STATIONARY_PNO_SCAN_INTERVAL_MILLIS); verify(mScoringParams, times(2)).getEntryRssi(ScanResult.BAND_6_GHZ_START_FREQ_MHZ); verify(mScoringParams, times(2)).getEntryRssi(ScanResult.BAND_5_GHZ_START_FREQ_MHZ); @@ -4515,8 +4669,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { ScanSettings.class); InOrder inOrder = inOrder(mWifiScanner); inOrder.verify(mWifiScanner, never()).stopPnoScan(any()); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); + inOrder.verify(mWifiScanner).startPnoScan(scanSettingsCaptor.capture(), any(), any()); assertEquals(scanSettingsCaptor.getValue().periodInMs, MOVING_PNO_SCAN_INTERVAL_MILLIS); mWifiConnectivityManager.setDeviceMobilityState( @@ -4540,7 +4693,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { WifiManager.DEVICE_MOBILITY_STATE_STATIONARY); // no scans should start or stop because no PNO scan is running - verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); + verify(mWifiScanner, never()).startPnoScan(any(), any(), any()); verify(mWifiScanner, never()).stopPnoScan(any()); // starts a PNO scan @@ -4552,8 +4705,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { ArgumentCaptor<ScanSettings> scanSettingsCaptor = ArgumentCaptor.forClass( ScanSettings.class); - verify(mWifiScanner).startDisconnectedPnoScan( - scanSettingsCaptor.capture(), any(), any(), any()); + verify(mWifiScanner).startPnoScan(scanSettingsCaptor.capture(), any(), any()); // check that now the PNO scan uses the stationary interval, even though it was set before // the PNO scan started assertEquals(scanSettingsCaptor.getValue().periodInMs, STATIONARY_PNO_SCAN_INTERVAL_MILLIS); @@ -4622,7 +4774,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Force a connectivity scan mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - + mLooper.dispatchAll(); verify(mWifiChannelUtilization).refreshChannelStatsAndChannelUtilization( llstats, WifiChannelUtilization.UNKNOWN_FREQ); } @@ -4667,17 +4819,17 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Auto-join enabled mWifiConnectivityManager.setAutoJoinEnabledExternal(true, false); mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - verify(mWifiScanner).startScan(any(), any(), any(), any()); + verify(mWifiScanner).startScan(any(), any()); // Auto-join disabled, no new scans mWifiConnectivityManager.setAutoJoinEnabledExternal(false, false); mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - verify(mWifiScanner, times(1)).startScan(any(), any(), any(), any()); + verify(mWifiScanner, times(1)).startScan(any(), any()); // Wifi disabled, no new scans setWifiEnabled(false); mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); - verify(mWifiScanner, times(1)).startScan(any(), any(), any(), any()); + verify(mWifiScanner, times(1)).startScan(any(), any()); } @Test @@ -4792,11 +4944,12 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { InOrder inOrder = inOrder(mWifiScanner, mExternalPnoScanRequestManager); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); + inOrder.verify(mWifiScanner).startPnoScan(any(), any(), any()); inOrder.verify(mExternalPnoScanRequestManager).onScanResultsAvailable(any()); // mock connectivity scan mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE); + mLooper.dispatchAll(); // verify mExternalPnoScanRequestManager is notified again inOrder.verify(mExternalPnoScanRequestManager).onScanResultsAvailable(any()); } @@ -4811,14 +4964,21 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { WifiConfiguration network1 = WifiConfigurationTestUtil.createEapNetwork(); WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork(); WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenHiddenNetwork(); + WifiConfiguration network4 = WifiConfigurationTestUtil.createEapNetwork( + WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); + network4.carrierId = 123; // Assign a valid carrier ID network1.getNetworkSelectionStatus().setHasEverConnected(true); network2.getNetworkSelectionStatus().setHasEverConnected(true); network3.getNetworkSelectionStatus().setHasEverConnected(true); + network4.getNetworkSelectionStatus().setHasEverConnected(true); + when(mWifiCarrierInfoManager.isSimReady(anyInt())).thenReturn(true); List<WifiConfiguration> networkList = new ArrayList<>(); networkList.add(network1); networkList.add(network2); networkList.add(network3); + networkList.add(network4); + mLruConnectionTracker.addNetwork(network4); mLruConnectionTracker.addNetwork(network3); mLruConnectionTracker.addNetwork(network2); mLruConnectionTracker.addNetwork(network1); @@ -4827,15 +4987,18 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { List<WifiScanner.PnoSettings.PnoNetwork> pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); verify(mWifiNetworkSuggestionsManager).getAllScanOptimizationSuggestionNetworks(); - assertEquals(4, pnoNetworks.size()); + assertEquals(5, 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); // Now permanently disable |network3|. This should remove network 3 from the list. network3.getNetworkSelectionStatus().setNetworkSelectionStatus( WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); + // Mock the SIM card to be not ready. This should remove network 4 from the list. + when(mWifiCarrierInfoManager.isSimReady(anyInt())).thenReturn(false); // Retrieve the Pno network list & verify. pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); @@ -5075,7 +5238,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { InOrder inOrder = inOrder(mWifiScanner); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); + inOrder.verify(mWifiScanner).startPnoScan(any(), any(), any()); // Add or update suggestions. mSuggestionUpdateListenerCaptor.getValue().onSuggestionsAddedOrUpdated( @@ -5084,7 +5247,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mNetworkUpdateListenerCaptor.getValue().onNetworkAdded(new WifiConfiguration()); // Ensure that we don't immediately restarted PNO. inOrder.verify(mWifiScanner, never()).stopPnoScan(any()); - inOrder.verify(mWifiScanner, never()).startDisconnectedPnoScan(any(), any(), any(), any()); + inOrder.verify(mWifiScanner, never()).startPnoScan(any(), any(), any()); // Verify there is only 1 delayed scan scheduled assertEquals(1, mTestHandler.getIntervals().size()); @@ -5096,7 +5259,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Ensure that we restarted PNO. inOrder.verify(mWifiScanner).stopPnoScan(any()); - inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any()); + inOrder.verify(mWifiScanner).startPnoScan(any(), any(), any()); } @Test @@ -5110,7 +5273,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(primaryCmm.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); when(primaryCmm.isConnected()).thenReturn(false); when(primaryCmm.isDisconnected()).thenReturn(true); - when(primaryCmm.syncRequestConnectionInfo()).thenReturn(wifiInfo1); + when(primaryCmm.getConnectionInfo()).thenReturn(wifiInfo1); ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class); WifiInfo wifiInfo2 = mock(WifiInfo.class); @@ -5118,7 +5281,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(secondaryCmm.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED); when(secondaryCmm.isConnected()).thenReturn(false); when(secondaryCmm.isDisconnected()).thenReturn(true); - when(secondaryCmm.syncRequestConnectionInfo()).thenReturn(wifiInfo2); + when(secondaryCmm.getConnectionInfo()).thenReturn(wifiInfo2); when(mActiveModeWarden.getInternetConnectivityClientModeManagers()) .thenReturn(Arrays.asList(primaryCmm, secondaryCmm)); @@ -5127,7 +5290,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( primaryCmm, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); List<WifiNetworkSelector.ClientModeManagerState> expectedCmmStates = Arrays.asList(new WifiNetworkSelector.ClientModeManagerState( "wlan0", false, true, wifiInfo1), @@ -5152,7 +5315,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(primaryCmm.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); when(primaryCmm.isConnected()).thenReturn(false); when(primaryCmm.isDisconnected()).thenReturn(true); - when(primaryCmm.syncRequestConnectionInfo()).thenReturn(wifiInfo1); + when(primaryCmm.getConnectionInfo()).thenReturn(wifiInfo1); when(mActiveModeWarden.getInternetConnectivityClientModeManagers()) .thenReturn(Arrays.asList(primaryCmm)); @@ -5164,7 +5327,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mWifiConnectivityManager.handleConnectionStateChanged( primaryCmm, WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - + mLooper.dispatchAll(); List<WifiNetworkSelector.ClientModeManagerState> expectedCmmStates = Arrays.asList(new WifiNetworkSelector.ClientModeManagerState( "wlan0", false, true, wifiInfo1), 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 bb90b345b6..3a23a66c7b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java @@ -115,7 +115,7 @@ public class WifiCountryCodeTest extends WifiBaseTest { when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); when(mClientModeManager.setCountryCode(anyString())).thenReturn(true); when(mClientModeManager.isConnected()).thenReturn(true); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(mWifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(mWifiInfo); when(mWifiInfo.getSuccessfulTxPacketsPerSecond()).thenReturn(10.0); when(mWifiInfo.getSuccessfulRxPacketsPerSecond()).thenReturn(5.0); when(mContext.getSystemService(Context.TELEPHONY_SERVICE)) diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java index c5b3d06b54..fca154f2bc 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AlertDialog; import android.content.BroadcastReceiver; @@ -82,12 +83,14 @@ public class WifiDialogManagerTest extends WifiBaseTest { @Mock FrameworkFacade mFrameworkFacade; @Mock Resources mResources; @Mock PowerManager mPowerManager; + @Mock ActivityManager mActivityManager; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mWifiContext.getWifiDialogApkPkgName()).thenReturn(WIFI_DIALOG_APK_PKG_NAME); when(mWifiContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); + when(mWifiContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager); when(mWifiContext.getResources()).thenReturn(mResources); when(mPowerManager.isInteractive()).thenReturn(true); doThrow(SecurityException.class).when(mWifiContext).startActivityAsUser(any(), any(), @@ -326,6 +329,7 @@ public class WifiDialogManagerTest extends WifiBaseTest { dismissDialogSynchronous(dialogHandle, mWifiThreadRunner); intent = verifyStartActivityAsUser(2, mWifiContext); verifyDismissIntent(intent); + verify(mActivityManager).forceStopPackage(WIFI_DIALOG_APK_PKG_NAME); // A reply to the same dialog id should not trigger callback wifiDialogManager.replyToSimpleDialog(dialogId, WifiManager.DIALOG_REPLY_POSITIVE); @@ -1004,6 +1008,7 @@ public class WifiDialogManagerTest extends WifiBaseTest { dismissDialogSynchronous(dialogHandle, mWifiThreadRunner); intent = verifyStartActivityAsUser(2, mWifiContext); verifyDismissIntent(intent); + verify(mActivityManager).forceStopPackage(WIFI_DIALOG_APK_PKG_NAME); // A reply to the same dialog id should not trigger callback wifiDialogManager.replyToP2pInvitationReceivedDialog(dialogId, true, null); @@ -1119,6 +1124,7 @@ public class WifiDialogManagerTest extends WifiBaseTest { TEST_DEVICE_NAME, null); dismissDialogSynchronous(dialogHandle, mWifiThreadRunner); verifyDismissIntent(verifyStartActivityAsUser(2, mWifiContext)); + verify(mActivityManager).forceStopPackage(WIFI_DIALOG_APK_PKG_NAME); // Another call to dismiss should not send another dismiss intent. dismissDialogSynchronous(dialogHandle, mWifiThreadRunner); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java index b186ab7e6d..5509711bfc 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java @@ -37,12 +37,11 @@ import android.net.wifi.ScanResult.InformationElement; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiScanner; import android.net.wifi.WifiScanner.ScanData; -import android.net.wifi.WifiScanner.ScanListener; import android.net.wifi.WifiScanner.ScanSettings; import android.net.wifi.WifiSsid; import android.os.Build; -import android.os.Handler; import android.os.test.TestLooper; +import android.util.LocalLog; import androidx.test.filters.SmallTest; @@ -56,6 +55,7 @@ import com.android.server.wifi.WifiScoreCard.PerNetwork; import com.android.server.wifi.proto.WifiScoreCardProto.SystemInfoStats; import com.android.server.wifi.proto.WifiStatsLog; import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics; +import com.android.server.wifi.scanner.WifiScannerInternal; import com.android.wifi.resources.R; import org.junit.Before; @@ -127,9 +127,10 @@ public class WifiHealthMonitorTest extends WifiBaseTest { private TestAlarmManager mAlarmManager; private TestLooper mLooper = new TestLooper(); private List<WifiConfiguration> mConfiguredNetworks; - private WifiScanner mWifiScanner; + private WifiScannerInternal mWifiScanner; private ScanData mScanData; - private ScanListener mScanListener; + private ArgumentCaptor<WifiScannerInternal.ScanListener> mScanListenerArgumentCaptor = + ArgumentCaptor.forClass(WifiScannerInternal.ScanListener.class); private OnNetworkUpdateListener mOnNetworkUpdateListener; private ModeChangeCallback mModeChangeCallback; @@ -183,7 +184,6 @@ public class WifiHealthMonitorTest extends WifiBaseTest { mScanData = mockScanData(); mWifiScanner = mockWifiScanner(WifiScanner.WIFI_BAND_ALL); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); when(mWifiNative.getDriverVersion()).thenReturn(mDriverVersion); when(mWifiNative.getFirmwareVersion()).thenReturn(mFirmwareVersion); when(mDeviceConfigFacade.getConnectionFailureHighThrPercent()).thenReturn( @@ -236,7 +236,8 @@ public class WifiHealthMonitorTest extends WifiBaseTest { when(mResources.getIntArray(R.array.config_wifiRssiLevelThresholds)) .thenReturn(new int[]{-88, -77, -66, -55}); mWifiHealthMonitor = new WifiHealthMonitor(mContext, mWifiInjector, mClock, - mWifiConfigManager, mWifiScoreCard, new Handler(mLooper.getLooper()), mWifiNative, + mWifiConfigManager, mWifiScoreCard, + new RunnerHandler(mLooper.getLooper(), 100, new LocalLog(128)), mWifiNative, "some seed", mDeviceConfigFacade, mActiveModeWarden); mLooper.dispatchAll(); ArgumentCaptor<ModeChangeCallback> modeChangeCallbackArgumentCaptor = @@ -299,20 +300,16 @@ public class WifiHealthMonitorTest extends WifiBaseTest { return scanDatas[0]; } - WifiScanner mockWifiScanner(@WifiScanner.WifiBand int wifiBand) { - WifiScanner scanner = mock(WifiScanner.class); - - doAnswer(new AnswerWithArguments() { - public void answer(ScanListener listener) throws Exception { - mScanListener = listener; - } - }).when(scanner).registerScanListener(anyObject()); + WifiScannerInternal mockWifiScanner(@WifiScanner.WifiBand int wifiBand) { + WifiScannerInternal scanner = mock(WifiScannerInternal.class); + doNothing().when(scanner).registerScanListener(mScanListenerArgumentCaptor.capture()); ScanData[] scanDatas = new ScanData[1]; scanDatas[0] = mock(ScanData.class); when(scanDatas[0].getScannedBandsInternal()).thenReturn(wifiBand); doAnswer(new AnswerWithArguments() { - public void answer(ScanSettings settings, ScanListener listener) throws Exception { + public void answer(ScanSettings settings, WifiScannerInternal.ScanListener listener) + throws Exception { if (mScanData != null && mScanData.getResults() != null) { for (int i = 0; i < mScanData.getResults().length; i++) { listener.onFullResult( @@ -322,7 +319,8 @@ public class WifiHealthMonitorTest extends WifiBaseTest { listener.onResults(scanDatas); } }).when(scanner).startScan(anyObject(), anyObject()); - + WifiLocalServices.removeServiceForTest(WifiScannerInternal.class); + WifiLocalServices.addService(WifiScannerInternal.class, scanner); return scanner; } @@ -367,7 +365,7 @@ public class WifiHealthMonitorTest extends WifiBaseTest { assertEquals(MODULE_VERSION, mWifiHealthMonitor.getWifiStackVersion()); millisecondsPass(5000); - mWifiScanner.startScan(mScanSettings, mScanListener); + mWifiScanner.startScan(mScanSettings, mScanListenerArgumentCaptor.getValue()); mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); mLooper.dispatchAll(); // serialized now has currSoftwareBuildInfo and scan results @@ -443,7 +441,7 @@ public class WifiHealthMonitorTest extends WifiBaseTest { mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore); setWifiEnabled(true); millisecondsPass(5000); - mWifiScanner.startScan(mScanSettings, mScanListener); + mWifiScanner.startScan(mScanSettings, mScanListenerArgumentCaptor.getValue()); mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); mLooper.dispatchAll(); WifiSystemInfoStats wifiSystemInfoStats = mWifiHealthMonitor.getWifiSystemInfoStats(); @@ -707,7 +705,8 @@ public class WifiHealthMonitorTest extends WifiBaseTest { public void testFullBandScan() throws Exception { millisecondsPass(5000); setWifiEnabled(true); - mWifiScanner.startScan(mScanSettings, mScanListener); + mWifiScanner.startScan(mScanSettings, mScanListenerArgumentCaptor.getValue()); + mLooper.dispatchAll(); ScanStats scanStats = mWifiHealthMonitor.getWifiSystemInfoStats().getCurrScanStats(); assertEquals(1_500_000_005_000L, scanStats.getLastScanTimeMs()); assertEquals(2, scanStats.getNumBssidLastScanAbove2g()); @@ -720,10 +719,9 @@ public class WifiHealthMonitorTest extends WifiBaseTest { @Test public void test2GScan() throws Exception { mWifiScanner = mockWifiScanner(WifiScanner.WIFI_BAND_24_GHZ); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); millisecondsPass(5000); setWifiEnabled(true); - mWifiScanner.startScan(mScanSettings, mScanListener); + mWifiScanner.startScan(mScanSettings, mScanListenerArgumentCaptor.getValue()); ScanStats scanStats = mWifiHealthMonitor.getWifiSystemInfoStats().getCurrScanStats(); assertEquals(TS_NONE, scanStats.getLastScanTimeMs()); assertEquals(0, scanStats.getNumBssidLastScanAbove2g()); @@ -779,10 +777,10 @@ public class WifiHealthMonitorTest extends WifiBaseTest { // Add Above2G only scan data mScanData = mockScanDataAbove2GOnly(); mWifiScanner = mockWifiScanner(WifiScanner.WIFI_BAND_ALL); - when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); + millisecondsPass(5000); setWifiEnabled(true); - mWifiScanner.startScan(mScanSettings, mScanListener); + mWifiScanner.startScan(mScanSettings, mScanListenerArgumentCaptor.getValue()); mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG); mLooper.dispatchAll(); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java index ba1dc64f07..97e2675989 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java @@ -88,7 +88,7 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(mWifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(mWifiInfo); when(mDeviceConfigFacade.isAbnormalConnectionBugreportEnabled()).thenReturn(true); when(mDeviceConfigFacade.getAbnormalConnectionDurationMs()).thenReturn( DEFAULT_ABNORMAL_CONNECTION_DURATION_MS); @@ -293,7 +293,6 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { Arrays.copyOfRange(isEphemeral, 0, 2)); for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE - 1; i++) { mLastResortWatchdog.updateAvailableNetworks(candidates); - mLastResortWatchdog.toString(); assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[0]).age, 0); assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[1]).age, 0); assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().get(mBssids[2]).age, @@ -306,7 +305,6 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { // One more buffering should age and cull candidates 2 & 3 mLastResortWatchdog.updateAvailableNetworks(candidates); assertEquals(mLastResortWatchdog.getRecentAvailableNetworks().size(), 2); - mLastResortWatchdog.toString(); }; /** @@ -2238,7 +2236,8 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { Handler handler = mHandlerCaptor.getValue(); handler.sendMessage(handler.obtainMessage( WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false))); + new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false, + null))); mLooper.dispatchAll(); verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString()); @@ -2249,7 +2248,8 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { 2L * DEFAULT_ABNORMAL_CONNECTION_DURATION_MS + 1); handler.sendMessage(handler.obtainMessage( WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false))); + new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false, + null))); mLooper.dispatchAll(); verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); @@ -2259,7 +2259,8 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { 4L * DEFAULT_ABNORMAL_CONNECTION_DURATION_MS); handler.sendMessage(handler.obtainMessage( WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false))); + new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false, + null))); mLooper.dispatchAll(); verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); } @@ -2280,14 +2281,16 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { 2L * DEFAULT_ABNORMAL_CONNECTION_DURATION_MS + 1); handler.sendMessage(handler.obtainMessage( WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(TEST_NETWORK_ID_2, TEST_WIFI_SSID, null, false))); + new NetworkConnectionEventInfo(TEST_NETWORK_ID_2, TEST_WIFI_SSID, null, false, + null))); mLooper.dispatchAll(); verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString()); // network1 connected after a long time, should trigger BR handler.sendMessage(handler.obtainMessage( WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false))); + new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false, + null))); mLooper.dispatchAll(); verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); } @@ -2310,7 +2313,8 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { Handler handler = mHandlerCaptor.getValue(); handler.sendMessage(handler.obtainMessage( WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false))); + new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false, + null))); mLooper.dispatchAll(); verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); } @@ -2333,7 +2337,8 @@ public class WifiLastResortWatchdogTest extends WifiBaseTest { Handler handler = mHandlerCaptor.getValue(); handler.sendMessage(handler.obtainMessage( WifiMonitor.NETWORK_CONNECTION_EVENT, - new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false))); + new NetworkConnectionEventInfo(TEST_NETWORK_ID, TEST_WIFI_SSID, null, false, + null))); mLooper.dispatchAll(); verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString()); } 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 f17ff64565..9618f620ab 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java @@ -1142,7 +1142,7 @@ public class WifiMetricsTest extends WifiBaseTest { // Channel switch info should be added to the last Soft AP UP event in the list - mWifiMetrics.addSoftApChannelSwitchedEvent(new ArrayList<>() {{ add(testSoftApInfo_2G); }}, + mWifiMetrics.addSoftApChannelSwitchedEvent(List.of(testSoftApInfo_2G), WifiManager.IFACE_IP_MODE_TETHERED, false); SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder() .setSsid("Test_Metric_SSID") @@ -1172,10 +1172,8 @@ public class WifiMetricsTest extends WifiBaseTest { // Bridged mode test, total NUM_SOFT_AP_EVENT_ENTRIES_FOR_BRIDGED_AP events for bridged mode mWifiMetrics.addSoftApUpChangedEvent(true, WifiManager.IFACE_IP_MODE_TETHERED, SOFT_AP_SHUTDOWN_TIMEOUT_DEFAULT_SETTING, true); - mWifiMetrics.addSoftApChannelSwitchedEvent(new ArrayList<>() {{ - add(testSoftApInfo_2G); - add(testSoftApInfo_5G); - }}, + mWifiMetrics.addSoftApChannelSwitchedEvent( + List.of(testSoftApInfo_2G, testSoftApInfo_5G), WifiManager.IFACE_IP_MODE_TETHERED, true); mWifiMetrics.updateSoftApConfiguration(testSoftApConfig, @@ -5046,19 +5044,17 @@ public class WifiMetricsTest extends WifiBaseTest { WifiNetworkSuggestionsManager.APP_TYPE_NETWORK_PROVISIONING); - mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{ - add(5); - add(100); - add(50); - add(120); - }}); + mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(List.of( + 5, + 100, + 50, + 120)); // Second update should overwrite the prevous write. - mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(new ArrayList<Integer>() {{ - add(7); - add(110); - add(40); - add(60); - }}); + mWifiMetrics.noteNetworkSuggestionApiListSizeHistogram(List.of( + 7, + 110, + 40, + 60)); mWifiMetrics.incrementNetworkSuggestionUserRevokePermission(); mWifiMetrics.incrementNetworkSuggestionUserRevokePermission(); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java index d6454b4c7e..2fa5fffad4 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java @@ -31,6 +31,7 @@ import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback.WpsErro import android.net.DscpPolicy; import android.net.MacAddress; import android.net.wifi.SupplicantState; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; @@ -53,6 +54,7 @@ import org.mockito.ArgumentCaptor; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; /** @@ -474,6 +476,33 @@ public class WifiMonitorTest extends WifiBaseTest { } /** + * Broadcast network connection with akm test. + */ + @Test + public void testBroadcastNetworkConnectionEventWithAkm() { + mWifiMonitor.registerHandler( + WLAN_IFACE_NAME, WifiMonitor.NETWORK_CONNECTION_EVENT, mHandlerSpy); + int networkId = NETWORK_ID; + WifiSsid wifiSsid = WifiSsid.fromBytes(new byte[]{'a', 'b', 'c'}); + String bssid = BSSID; + BitSet akm = new BitSet(); + akm.set(WifiConfiguration.KeyMgmt.WPA_PSK); + mWifiMonitor.broadcastNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, false, + wifiSsid, bssid, akm); + mLooper.dispatchAll(); + + ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(mHandlerSpy).handleMessage(messageCaptor.capture()); + assertEquals(WifiMonitor.NETWORK_CONNECTION_EVENT, messageCaptor.getValue().what); + NetworkConnectionEventInfo info = (NetworkConnectionEventInfo) messageCaptor.getValue().obj; + assertEquals(networkId, info.networkId); + assertFalse(info.isFilsConnection); + assertEquals(wifiSsid, info.wifiSsid); + assertEquals(bssid, info.bssid); + assertEquals(akm, info.keyMgmtMask); + } + + /** * Broadcast network disconnection test. */ @Test 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 f6215c4252..e79cd054dc 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java @@ -64,6 +64,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.List; import java.util.Set; /** @@ -76,6 +77,15 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { private static final String IFACE_NAME_1 = "mockWlan1"; private static final WorkSource TEST_WORKSOURCE = new WorkSource(); private static final long TEST_SUPPORTED_FEATURES = 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; + private static final int STA_FAILURE_CODE_CREAT_IFACE = 4; + private static final int SOFTAP_FAILURE_CODE_SETUP_INTERFACE = 1; + private static final int SOFTAP_FAILURE_CODE_START_DAEMON = 2; + private static final int SOFTAP_FAILURE_CODE_CREATE_IFACE = 3; + private static final int SOFTAP_FAILURE_CODE_BRIDGED_AP_INSTANCES = 4; + private static final int TEST_SUPPORTED_BANDS = 15; MockResources mResources; @@ -142,10 +152,12 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { when(mWifiVendorHal.createApIface(any(), any(), anyInt(), anyBoolean(), any())).thenReturn(IFACE_NAME_0); when(mWifiVendorHal.getBridgedApInstances(any())).thenReturn( - new ArrayList<String>() {{ add((IFACE_NAME_0)); }}); + List.of(IFACE_NAME_0)); when(mWifiVendorHal.removeStaIface(any())).thenReturn(true); when(mWifiVendorHal.removeApIface(any())).thenReturn(true); when(mWifiVendorHal.replaceStaIfaceRequestorWs(any(), any())).thenReturn(true); + when(mWifiVendorHal.getUsableChannels(anyInt(), anyInt(), anyInt())).thenReturn( + new ArrayList<>()); when(mBuildProperties.isEngBuild()).thenReturn(false); when(mBuildProperties.isUserdebugBuild()).thenReturn(false); @@ -192,6 +204,9 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { when(mWifiSettingsConfigStore.get( eq(WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES))) .thenReturn(TEST_SUPPORTED_FEATURES); + when(mWifiSettingsConfigStore.get( + eq(WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS))) + .thenReturn(TEST_SUPPORTED_BANDS); mInOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, mHostapdHal, mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mWifiMetrics); @@ -284,7 +299,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { executeAndValidateSetupSoftApInterface( false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0, true); + mNetworkObserverCaptor0, true, true, 0); assertEquals(Set.of(IFACE_NAME_0), mWifiNative.getSoftApInterfaceNames()); assertEquals(Set.of(), mWifiNative.getClientInterfaceNames()); } @@ -508,6 +523,31 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); + validateHostApdStart(); + // Creation of AP interface should trigger the STA interface destroy + validateOnDestroyedClientInterface( + false, true, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); + // Now continue with rest of AP interface setup. + validateSetupInterfaceForSoftAp(IFACE_NAME_0, mNetworkObserverCaptor1); + + // Execute a teardown of the interface to ensure that the new iface removal works. + executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback1, + mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); + } + + private void validateSwitchInterfaceToScan(String ifaceName, WorkSource workSource) { + mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); + mInOrder.verify(mWifiVendorHal).replaceStaIfaceRequestorWs(ifaceName, workSource); + mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(ifaceName); + mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); + mInOrder.verify(mSupplicantStaIfaceHal).terminate(); + mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); + mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); + } + + private void validateHostApdStart() { mInOrder.verify(mHostapdHal).isInitializationStarted(); mInOrder.verify(mHostapdHal).initialize(); mInOrder.verify(mHostapdHal).startDaemon(); @@ -517,20 +557,31 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mWifiVendorHal).createApIface( mIfaceDestroyedListenerCaptor1.capture(), eq(TEST_WORKSOURCE), anyInt(), eq(false), eq(mSoftApManager)); - // Creation of AP interface should trigger the STA interface destroy - validateOnDestroyedClientInterface( - false, true, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); - // Now continue with rest of AP interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + } - // Execute a teardown of the interface to ensure that the new iface removal works. - executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); + private void validateSetupInterfaceForScan(String ifaceName, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor) { + mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(ifaceName), any(), + any(), any()); + mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); + mInOrder.verify(mWifiMonitor).startMonitoring(ifaceName); + 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).getUsableChannels(anyInt(), anyInt(), anyInt()); + } + + private void validateSetupInterfaceForSoftAp(String ifaceName, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor) { + mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(ifaceName); + 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).getUsableChannels(anyInt(), anyInt(), anyInt()); } /** @@ -554,14 +605,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { }).when(mWifiVendorHal).createStaIface(any(), any()); assertEquals(IFACE_NAME_0, - mWifiNative.setupInterfaceForClientInConnectivityMode( - mIfaceCallback1, TEST_WORKSOURCE)); - - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); + mWifiNative.setupInterfaceForClientInScanMode(mIfaceCallback1, TEST_WORKSOURCE)); mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); mInOrder.verify(mWifiVendorHal).createStaIface( mIfaceDestroyedListenerCaptor1.capture(), eq(TEST_WORKSOURCE)); @@ -569,23 +613,12 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { validateOnDestroyedSoftApInterface( true, false, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); // Now continue with rest of STA interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(IFACE_NAME_0), any(), - any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).enableLinkLayerStats(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true); - mInOrder.verify(mNetdWrapper).disableIpv6(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + validateSetupInterfaceForScan(IFACE_NAME_0, mNetworkObserverCaptor1); // Execute a teardown of the interface to ensure that the new iface removal works. - executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback1, - mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue()); + executeAndValidateTeardownClientInterfaceForScan(false, false, IFACE_NAME_0, + mIfaceCallback1, mIfaceDestroyedListenerCaptor1.getValue(), + mNetworkObserverCaptor1.getValue()); } /** @@ -779,25 +812,12 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface( - mIfaceDestroyedListenerCaptor1.capture(), eq(TEST_WORKSOURCE), anyInt(), eq(false), - eq(mSoftApManager)); + validateHostApdStart(); // Creation of AP interface should trigger the STA interface destroy validateOnDestroyedClientInterface( false, true, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); // Now continue with rest of AP interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + validateSetupInterfaceForSoftAp(IFACE_NAME_0, mNetworkObserverCaptor1); // Step (c) - Iface up on old iface, ignored! mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, true); @@ -875,7 +895,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { when(mHostapdHal.isApInfoCallbackSupported()).thenReturn(true); executeAndValidateSetupSoftApInterface( false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0, false); + mNetworkObserverCaptor0, false, true, 0); // Start softap assertTrue(mWifiNative.startSoftAp(IFACE_NAME_0, new SoftApConfiguration.Builder().build(), @@ -902,7 +922,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { public void testStartSoftApWithWifiCondCallbackAndHostapdDied() throws Exception { executeAndValidateSetupSoftApInterface( false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, - mNetworkObserverCaptor0, false); + mNetworkObserverCaptor0, false, true, 0); // Start softap assertTrue(mWifiNative.startSoftAp(IFACE_NAME_0, new SoftApConfiguration.Builder().build(), @@ -922,23 +942,36 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { verify(mStatusListener).onStatusChanged(true); } + private void validateInterfaceTearDown(String ifaceName) { + // To test if the failure is handled cleanly, invoke teardown and ensure that + // none of the mocks are used because the iface does not exist in the internal + // database. + if (mWifiNative.hasAnyIface()) { + mWifiNative.teardownInterface(ifaceName); + mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); + if (mWifiNative.hasAnyStaIfaceForScan()) { + mInOrder.verify(mWifiVendorHal).removeStaIface(anyString()); + } + if (mWifiNative.hasAnyApIface()) { + mInOrder.verify(mWifiVendorHal).removeApIface(anyString()); + } + } + } + /** * Verifies failure handling in setup of a client interface. */ @Test public void testSetupClientInterfaceFailureInStartHal() throws Exception { when(mWifiVendorHal.startVendorHal()).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode( + assertNull(mWifiNative.setupInterfaceForClientInScanMode( mIfaceCallback0, TEST_WORKSOURCE)); mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); mInOrder.verify(mWifiVendorHal).startVendorHal(); mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToHal(); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -946,25 +979,14 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { */ @Test public void testSetupClientInterfaceFailureInStartSupplicant() throws Exception { + executeAndValidateSetupClientInterfaceForScan( + false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0); when(mSupplicantStaIfaceHal.startDaemon()).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode( - mIfaceCallback0, TEST_WORKSOURCE)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToSupplicant(); + executeAndValidateSwitchClientInterfaceToConnectivityMode(false, false, IFACE_NAME_0, + TEST_WORKSOURCE, true, STA_FAILURE_CODE_START_DAEMON); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -973,28 +995,11 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { @Test public void testSetupClientInterfaceFailureInHalCreateStaIface() throws Exception { when(mWifiVendorHal.createStaIface(any(), any())).thenReturn(null); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode( - mIfaceCallback0, TEST_WORKSOURCE)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface(any(), any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToHal(); + executeAndValidateSetupClientInterfaceForScan( + false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0, true, STA_FAILURE_CODE_CREAT_IFACE); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1005,37 +1010,17 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { throws Exception { when(mWificondControl.setupInterfaceForClientMode(any(), any(), any(), any())).thenReturn( false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode( - mIfaceCallback0, TEST_WORKSOURCE)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - mIfaceDestroyedListenerCaptor0.capture(), eq(TEST_WORKSOURCE)); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(any(), any(), any(), any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeStaIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToWificond(); + assertNull(mWifiNative.setupInterfaceForClientInScanMode(mIfaceCallback0, TEST_WORKSOURCE)); + validateSetupClientInterfaceForScan( + false, false, IFACE_NAME_0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0, true, STA_FAILURE_CODE_WIFICOND_SETUP_INTERFACE); // Trigger the HAL interface destroyed callback to verify the whole removal sequence. mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0, + validateOnDestroyedClientInterfaceForScan(false, false, IFACE_NAME_0, mIfaceCallback0, null); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1043,39 +1028,19 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { */ @Test public void testSetupClientInterfaceFailureInSupplicantSetupIface() throws Exception { + executeAndValidateSetupClientInterfaceForScan( + false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0); when(mSupplicantStaIfaceHal.setupIface(any())).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForClientInConnectivityMode( - mIfaceCallback0, TEST_WORKSOURCE)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - mIfaceDestroyedListenerCaptor0.capture(), eq(TEST_WORKSOURCE)); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(any(), any(), any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeStaIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToSupplicant(); + executeAndValidateSwitchClientInterfaceToConnectivityMode(false, false, IFACE_NAME_0, + TEST_WORKSOURCE, true, STA_FAILURE_CODE_SETUP_INTERFACE); // Trigger the HAL interface destroyed callback to verify the whole removal sequence. mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); - validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0, - null); + validateOnDestroyedClientInterfaceForScan(false, false, IFACE_NAME_0, mIfaceCallback0, + mNetworkObserverCaptor0.getValue()); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1091,10 +1056,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mWifiVendorHal).startVendorHal(); mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHal(); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1103,24 +1065,10 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { @Test public void testSetupSoftApInterfaceFailureInStartHostapd() throws Exception { when(mHostapdHal.startDaemon()).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0, TEST_WORKSOURCE, - SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHostapd(); - - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + executeAndValidateSetupSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0, + mIfaceDestroyedListenerCaptor0, mNetworkObserverCaptor0, + false, true, SOFTAP_FAILURE_CODE_START_DAEMON); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1128,31 +1076,11 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { */ @Test public void testSetupSoftApInterfaceFailureInHalCreateApIface() throws Exception { - when(mWifiVendorHal.createApIface(any(), any(), anyInt(), anyBoolean(), any())) - .thenReturn(null); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0, TEST_WORKSOURCE, - SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface(any(), any(), anyInt(), anyBoolean(), - eq(mSoftApManager)); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHal(); + executeAndValidateSetupSoftApInterface( + false, false, null, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0, false, true, SOFTAP_FAILURE_CODE_CREATE_IFACE); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1161,39 +1089,16 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { @Test public void testSetupSoftApInterfaceFailureInHalGetBridgedInstances() throws Exception { when(mWifiVendorHal.getBridgedApInstances(any())).thenReturn(null); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0, TEST_WORKSOURCE, - SoftApConfiguration.BAND_2GHZ, true, mSoftApManager)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface( - mIfaceDestroyedListenerCaptor0.capture(), eq(TEST_WORKSOURCE), anyInt(), eq(true), - eq(mSoftApManager)); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).getBridgedApInstances(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeApIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHal(); + executeAndValidateSetupSoftApInterface( + false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0, true, true, SOFTAP_FAILURE_CODE_BRIDGED_AP_INSTANCES); // Trigger the HAL interface destroyed callback to verify the whole removal sequence. mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); validateOnDestroyedSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0, null); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1203,38 +1108,16 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { public void testSetupSoftApInterfaceFailureInWificondSetupInterfaceForSoftapMode() throws Exception { when(mWificondControl.setupInterfaceForSoftApMode(any())).thenReturn(false); - assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0, TEST_WORKSOURCE, - SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface( - mIfaceDestroyedListenerCaptor0.capture(), eq(TEST_WORKSOURCE), anyInt(), eq(false), - eq(mSoftApManager)); - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).removeApIface(any()); - mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToWificond(); + executeAndValidateSetupSoftApInterface( + false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0, false, true, SOFTAP_FAILURE_CODE_SETUP_INTERFACE); // Trigger the HAL interface destroyed callback to verify the whole removal sequence. mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); validateOnDestroyedSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0, null); - // To test if the failure is handled cleanly, invoke teardown and ensure that - // none of the mocks are used because the iface does not exist in the internal - // database. - mWifiNative.teardownInterface(IFACE_NAME_0); + validateInterfaceTearDown(IFACE_NAME_0); } /** @@ -1312,61 +1195,13 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { when(mPropertyService.getString(any(), any())).thenReturn(IFACE_NAME_0); // First setup a STA interface and verify. - assertEquals(IFACE_NAME_0, - mWifiNative.setupInterfaceForClientInConnectivityMode( - mIfaceCallback0, TEST_WORKSOURCE)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(IFACE_NAME_0), any(), - any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor0.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).enableLinkLayerStats(eq(IFACE_NAME_0)); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true); - mInOrder.verify(mNetdWrapper).disableIpv6(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + executeAndValidateSetupClientInterfaceForScan(false, false, IFACE_NAME_0, + mIfaceCallback0, mIfaceDestroyedListenerCaptor0, mNetworkObserverCaptor0, false, 0); // Now setup an AP interface. - assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1, - TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - // Creation of AP interface should trigger the STA interface destroy - verify(mWifiMonitor).stopMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).unregisterObserver( - mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(IFACE_NAME_0); - mInOrder.verify(mWificondControl).tearDownClientInterface(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); - mInOrder.verify(mSupplicantStaIfaceHal).terminate(); - mInOrder.verify(mWifiVendorHal).isVendorHalReady(); - mInOrder.verify(mIfaceCallback0).onDestroyed(IFACE_NAME_0); - // Now continue with rest of AP interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + executeAndValidateSetupSoftApInterface(true, false, IFACE_NAME_0, + mIfaceCallback1, mIfaceDestroyedListenerCaptor1, mNetworkObserverCaptor1, false, + false, 0); } /** @@ -1379,62 +1214,15 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { throws Exception { when(mWifiVendorHal.isVendorHalSupported()).thenReturn(false); when(mPropertyService.getString(any(), any())).thenReturn(IFACE_NAME_0); - // First setup an AP interface and verify. - assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0, - TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - mInOrder.verify(mHostapdHal).isInitializationStarted(); - mInOrder.verify(mHostapdHal).initialize(); - mInOrder.verify(mHostapdHal).startDaemon(); - mInOrder.verify(mHostapdHal).isInitializationComplete(); - mInOrder.verify(mHostapdHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor0.capture()); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + executeAndValidateSetupSoftApInterface(false, false, IFACE_NAME_0, + mIfaceCallback0, mIfaceDestroyedListenerCaptor0, mNetworkObserverCaptor0, false, + false, 0); // Now setup a STA interface. - assertEquals(IFACE_NAME_0, - mWifiNative.setupInterfaceForClientInConnectivityMode( - mIfaceCallback1, TEST_WORKSOURCE)); - - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - // Creation of STA interface should trigger the AP interface destroy. - mInOrder.verify(mNetdWrapper).unregisterObserver( - mNetworkObserverCaptor0.getValue()); - mInOrder.verify(mHostapdHal).removeAccessPoint(IFACE_NAME_0); - mInOrder.verify(mWificondControl).tearDownSoftApInterface(IFACE_NAME_0); - mInOrder.verify(mHostapdHal).deregisterDeathHandler(); - mInOrder.verify(mHostapdHal).terminate(); - mInOrder.verify(mWifiVendorHal).isVendorHalReady(); - mInOrder.verify(mIfaceCallback0).onDestroyed(IFACE_NAME_0); - // Now continue with rest of STA interface setup. - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(IFACE_NAME_0), any(), - any(), any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).registerObserver(mNetworkObserverCaptor1.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).isInterfaceUp(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).enableLinkLayerStats(eq(IFACE_NAME_0)); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(IFACE_NAME_0); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(IFACE_NAME_0, true); - mInOrder.verify(mNetdWrapper).disableIpv6(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + executeAndValidateSetupClientInterface( + false, true, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0, false, 0); } /** @@ -1467,15 +1255,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, mNetworkObserverCaptor0); assertTrue(mWifiNative.switchClientInterfaceToScanMode(IFACE_NAME_0, TEST_WORKSOURCE)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).replaceStaIfaceRequestorWs(IFACE_NAME_0, TEST_WORKSOURCE); - mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); - mInOrder.verify(mSupplicantStaIfaceHal).terminate(); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + validateSwitchInterfaceToScan(IFACE_NAME_0, TEST_WORKSOURCE); } /** @@ -1489,6 +1269,43 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { assertTrue(mWifiNative.switchClientInterfaceToScanMode(IFACE_NAME_0, TEST_WORKSOURCE)); } + private void executeAndValidateSwitchClientInterfaceToConnectivityMode( + boolean hasStaIface, boolean hasApIface, String ifaceName, WorkSource workSource, + boolean vendorHalSupported, int failureCode) { + assertEquals(failureCode == 0 ? true : false, + mWifiNative.switchClientInterfaceToConnectivityMode(ifaceName, workSource)); + + mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); + if (vendorHalSupported) { + mInOrder.verify(mWifiVendorHal).replaceStaIfaceRequestorWs(ifaceName, workSource); + } + if (!hasStaIface) { + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); + mInOrder.verify(mSupplicantStaIfaceHal).initialize(); + mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); + if (failureCode == STA_FAILURE_CODE_START_DAEMON) { + mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); + mInOrder.verify(mWifiVendorHal).removeStaIface(ifaceName); + mInOrder.verify( + mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToSupplicant(); + return; + } + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); + mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); + } + mInOrder.verify(mSupplicantStaIfaceHal).setupIface(ifaceName); + if (failureCode == STA_FAILURE_CODE_SETUP_INTERFACE) { + mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); + mInOrder.verify(mWifiVendorHal).removeStaIface(ifaceName); + mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToSupplicant(); + } else { + mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); + mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); + } + } + /** * Verifies the switch of existing client interface in scan mode to connectivity mode. */ @@ -1497,20 +1314,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { executeAndValidateSetupClientInterfaceForScan( false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, mNetworkObserverCaptor0); - assertTrue(mWifiNative.switchClientInterfaceToConnectivityMode( - IFACE_NAME_0, TEST_WORKSOURCE)); - - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).replaceStaIfaceRequestorWs(IFACE_NAME_0, TEST_WORKSOURCE); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(IFACE_NAME_0); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(IFACE_NAME_0); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(IFACE_NAME_0); + executeAndValidateSwitchClientInterfaceToConnectivityMode(false, false, IFACE_NAME_0, + TEST_WORKSOURCE, true, 0); } /** @@ -1543,54 +1348,27 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { } private void executeAndValidateSetupClientInterface( - boolean existingStaIface, boolean existingApIface, + boolean hasStaIface, boolean hasApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - when(mWifiVendorHal.createStaIface(any(), any())).thenReturn(ifaceName); - assertEquals(ifaceName, mWifiNative.setupInterfaceForClientInConnectivityMode( - callback, TEST_WORKSOURCE)); - - validateSetupClientInterface( - existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor, - networkObserverCaptor); + executeAndValidateSetupClientInterface(hasStaIface, hasApIface, ifaceName, callback, + destroyedListenerCaptor, + networkObserverCaptor, true, 0); } - private void validateSetupClientInterface( - boolean existingStaIface, boolean existingApIface, - String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - if (!existingStaIface && !existingApIface) { - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - } - if (!existingStaIface) { - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); - mInOrder.verify(mSupplicantStaIfaceHal).initialize(); - mInOrder.verify(mSupplicantStaIfaceHal).startDaemon(); - mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); - mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); - } - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - destroyedListenerCaptor.capture(), eq(TEST_WORKSOURCE)); - mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(ifaceName), any(), any(), - any()); - mInOrder.verify(mSupplicantStaIfaceHal).setupIface(ifaceName); - mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); - mInOrder.verify(mWifiMonitor).startMonitoring(ifaceName); - mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); - mInOrder.verify(mWifiVendorHal).enableLinkLayerStats(ifaceName); - mInOrder.verify(mNetdWrapper).clearInterfaceAddresses(ifaceName); - mInOrder.verify(mNetdWrapper).setInterfaceIpv6PrivacyExtensions(ifaceName, true); - mInOrder.verify(mNetdWrapper).disableIpv6(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); - mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + private void executeAndValidateSetupClientInterface( + boolean hasStaIface, boolean hasApIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean vendorHalSupported, + int failureCode) throws Exception { + when(mWifiVendorHal.createStaIface(any(), any())).thenReturn(ifaceName); + executeAndValidateSetupClientInterfaceForScan( + hasStaIface, hasApIface, ifaceName, callback, destroyedListenerCaptor, + networkObserverCaptor, vendorHalSupported, failureCode); + executeAndValidateSwitchClientInterfaceToConnectivityMode(hasStaIface, hasApIface, + ifaceName, TEST_WORKSOURCE, vendorHalSupported, failureCode); } private void executeAndValidateTeardownClientInterface( @@ -1635,36 +1413,81 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { } private void executeAndValidateSetupClientInterfaceForScan( - boolean existingStaIface, boolean existingApIface, + boolean hasStaIface, boolean hasApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - when(mWifiVendorHal.createStaIface(any(), any())).thenReturn(ifaceName); - assertEquals(ifaceName, mWifiNative.setupInterfaceForClientInScanMode( - callback, TEST_WORKSOURCE)); + executeAndValidateSetupClientInterfaceForScan(hasStaIface, hasApIface, ifaceName, callback, + destroyedListenerCaptor, networkObserverCaptor, true, 0); + } + + private void executeAndValidateSetupClientInterfaceForScan( + boolean hasStaIface, boolean hasApIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, + boolean vendorHalSupported, int failureCode) throws Exception { + if (failureCode != STA_FAILURE_CODE_CREAT_IFACE) { + when(mWifiVendorHal.createStaIface(any(), any())).thenReturn(ifaceName); + } + assertEquals(failureCode == 0 ? ifaceName : null, + mWifiNative.setupInterfaceForClientInScanMode(callback, TEST_WORKSOURCE)); validateSetupClientInterfaceForScan( - existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor, - networkObserverCaptor); + hasStaIface, hasApIface, ifaceName, destroyedListenerCaptor, + networkObserverCaptor, vendorHalSupported, failureCode); + } + + private void validateStartHal(boolean hasAnyIface, boolean vendorHalSupported) { + verify(mWifiVendorHal, atLeastOnce()).isVendorHalSupported(); + if (!hasAnyIface) { + if (vendorHalSupported) { + mInOrder.verify(mWifiVendorHal).startVendorHal(); + if (SdkLevel.isAtLeastS()) { + mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); + } + } + if (SdkLevel.isAtLeastS()) { + mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), + any()); + } + } } private void validateSetupClientInterfaceForScan( - boolean existingStaIface, boolean existingApIface, + boolean hasStaIface, boolean hasApIface, String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - if (!existingStaIface && !existingApIface) { - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean vendorHalSupported, + int failureCode) throws Exception { + validateStartHal(hasStaIface || hasApIface, vendorHalSupported); + if (vendorHalSupported) { + mInOrder.verify(mWifiVendorHal).createStaIface( + destroyedListenerCaptor.capture(), eq(TEST_WORKSOURCE)); + if (failureCode == STA_FAILURE_CODE_CREAT_IFACE) { + verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToHal(); + return; + } + } else { + if (hasApIface) { + // Creation of STA interface should trigger the AP interface destroy. + mInOrder.verify(mNetdWrapper).unregisterObserver( + mNetworkObserverCaptor0.getValue()); + mInOrder.verify(mHostapdHal).removeAccessPoint(ifaceName); + mInOrder.verify(mWificondControl).tearDownSoftApInterface(ifaceName); + mInOrder.verify(mHostapdHal).deregisterDeathHandler(); + mInOrder.verify(mHostapdHal).terminate(); + mInOrder.verify(mWifiVendorHal).isVendorHalReady(); + mInOrder.verify(mIfaceCallback0).onDestroyed(ifaceName); } } - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createStaIface( - destroyedListenerCaptor.capture(), eq(TEST_WORKSOURCE)); mInOrder.verify(mWificondControl).setupInterfaceForClientMode(eq(ifaceName), any(), any(), any()); + if (failureCode == STA_FAILURE_CODE_WIFICOND_SETUP_INTERFACE) { + mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); + verify(mWifiVendorHal).removeStaIface(ifaceName); + verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToWificond(); + return; + } mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); mInOrder.verify(mWifiMonitor).startMonitoring(ifaceName); mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); @@ -1672,6 +1495,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); } private void executeAndValidateTeardownClientInterfaceForScan( @@ -1711,65 +1535,95 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { } private void executeAndValidateSetupSoftApInterface( - boolean existingStaIface, boolean existingApIface, + boolean hasStaIface, boolean hasApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor) throws Exception { - executeAndValidateSetupSoftApInterface(existingStaIface, existingApIface, ifaceName, - callback, destroyedListenerCaptor, networkObserverCaptor, false); + executeAndValidateSetupSoftApInterface(hasStaIface, hasApIface, ifaceName, + callback, destroyedListenerCaptor, networkObserverCaptor, false, true, 0); } private void executeAndValidateSetupSoftApInterface( - boolean existingStaIface, boolean existingApIface, + boolean hasStaIface, boolean hasApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged) - throws Exception { + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged, + boolean vendorHalSupported, int failureCode) throws Exception { when(mWifiVendorHal.createApIface(any(), any(), anyInt(), eq(isBridged), any())) .thenReturn(ifaceName); - assertEquals(ifaceName, mWifiNative.setupInterfaceForSoftApMode( + assertEquals(failureCode == 0 ? ifaceName : null, mWifiNative.setupInterfaceForSoftApMode( callback, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, isBridged, mSoftApManager)); validateSetupSoftApInterface( - existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor, - networkObserverCaptor, isBridged); + hasStaIface, hasApIface, ifaceName, destroyedListenerCaptor, + networkObserverCaptor, isBridged, vendorHalSupported, failureCode); } private void validateSetupSoftApInterface( - boolean existingStaIface, boolean existingApIface, + boolean hasStaIface, boolean hasApIface, String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, - ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged) - throws Exception { - if (!existingStaIface && !existingApIface) { - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).startVendorHal(); - if (SdkLevel.isAtLeastS()) { - mInOrder.verify(mWifiVendorHal).setCoexUnsafeChannels(any(), anyInt()); - mInOrder.verify(mWificondControl).registerCountryCodeChangedListener(any(), any()); - } - } - if (!existingApIface) { + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged, + boolean vendorHalSupported, int failureCode) throws Exception { + validateStartHal(hasStaIface || hasApIface, vendorHalSupported); + if (!hasApIface) { mInOrder.verify(mHostapdHal).isInitializationStarted(); mInOrder.verify(mHostapdHal).initialize(); mInOrder.verify(mHostapdHal).startDaemon(); + if (failureCode == SOFTAP_FAILURE_CODE_START_DAEMON) { + mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHostapd(); + return; + } mInOrder.verify(mHostapdHal).isInitializationComplete(); mInOrder.verify(mHostapdHal).registerDeathHandler(any()); } - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); - mInOrder.verify(mWifiVendorHal).createApIface( - destroyedListenerCaptor.capture(), eq(TEST_WORKSOURCE), - eq(SoftApConfiguration.BAND_2GHZ), eq(isBridged), eq(mSoftApManager)); + if (vendorHalSupported) { + mInOrder.verify(mWifiVendorHal).createApIface( + destroyedListenerCaptor.capture(), eq(TEST_WORKSOURCE), + eq(SoftApConfiguration.BAND_2GHZ), eq(isBridged), eq(mSoftApManager)); + if (failureCode == SOFTAP_FAILURE_CODE_CREATE_IFACE) { + mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHal(); + return; + } + } else { + if (hasStaIface) { + // Creation of AP interface should trigger the STA interface destroy + mInOrder.verify(mWifiMonitor).stopMonitoring(ifaceName); + mInOrder.verify(mNetdWrapper).unregisterObserver( + mNetworkObserverCaptor0.getValue()); + if (mWifiNative.hasAnyStaIfaceForConnectivity()) { + mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(ifaceName); + } + mInOrder.verify(mWificondControl).tearDownClientInterface(ifaceName); + if (mWifiNative.hasAnyStaIfaceForConnectivity()) { + mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); + mInOrder.verify(mSupplicantStaIfaceHal).terminate(); + } + mInOrder.verify(mWifiVendorHal).isVendorHalReady(); + mInOrder.verify(mIfaceCallback0).onDestroyed(ifaceName); + } + } if (isBridged) { - mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); mInOrder.verify(mWifiVendorHal).getBridgedApInstances(eq(ifaceName)); + if (failureCode == SOFTAP_FAILURE_CODE_BRIDGED_AP_INSTANCES) { + mInOrder.verify(mWifiVendorHal).removeApIface(ifaceName); + mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHal(); + return; + } } mInOrder.verify(mWificondControl).setupInterfaceForSoftApMode(ifaceName); + if (failureCode == SOFTAP_FAILURE_CODE_SETUP_INTERFACE) { + mInOrder.verify(mWifiVendorHal).removeApIface(ifaceName); + mInOrder.verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToWificond(); + return; + } + // Now continue with rest of AP interface setup. 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).getUsableChannels(anyInt(), anyInt(), anyInt()); } private void executeAndValidateTeardownSoftApInterface( 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 04f1210a30..2b094462d8 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java @@ -46,6 +46,7 @@ import android.net.MacAddress; import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; +import android.net.wifi.WifiAvailableChannel; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiContext; import android.net.wifi.WifiScanner; @@ -79,7 +80,6 @@ import org.mockito.stubbing.Answer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Random; import java.util.Set; @@ -155,27 +155,23 @@ public class WifiNativeTest extends WifiBaseTest { private static final WifiNl80211Manager.SignalPollResult SIGNAL_POLL_RESULT = new WifiNl80211Manager.SignalPollResult(-60, 12, 6, 5240); - private static final Set<Integer> SCAN_FREQ_SET = - new HashSet<Integer>() {{ - add(2410); - add(2450); - add(5050); - add(5200); - }}; + private static final Set<Integer> SCAN_FREQ_SET = Set.of( + 2410, + 2450, + 5050, + 5200); + private static final String TEST_QUOTED_SSID_1 = "\"testSsid1\""; private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\""; private static final int[] TEST_FREQUENCIES_1 = {}; private static final int[] TEST_FREQUENCIES_2 = {2500, 5124}; - private static final List<String> SCAN_HIDDEN_NETWORK_SSID_SET = - new ArrayList<String>() {{ - add(TEST_QUOTED_SSID_1); - add(TEST_QUOTED_SSID_2); - }}; - private static final List<byte[]> SCAN_HIDDEN_NETWORK_BYTE_SSID_SET = - new ArrayList<byte[]>() {{ - add(NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_1))); - add(NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_2))); - }}; + private static final List<String> SCAN_HIDDEN_NETWORK_SSID_SET = List.of( + TEST_QUOTED_SSID_1, + TEST_QUOTED_SSID_2); + + private static final List<byte[]> SCAN_HIDDEN_NETWORK_BYTE_SSID_SET = List.of( + NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_1)), + NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_2))); private static final WifiNative.PnoSettings TEST_PNO_SETTINGS = new WifiNative.PnoSettings() {{ @@ -674,7 +670,7 @@ public class WifiNativeTest extends WifiBaseTest { */ @Test public void testGetWifiLinkLayerStatsForClientInConnectivityMode() throws Exception { - mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME); mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME); verify(mWifiVendorHal, times(2)).getWifiLinkLayerStats(eq(WIFI_IFACE_NAME)); @@ -686,7 +682,7 @@ public class WifiNativeTest extends WifiBaseTest { @Test public void testClientModeScanSuccess() { InOrder order = inOrder(mWificondControl, mNetdWrapper, mWifiVendorHal); - mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); order.verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), mScanCallbackCaptor.capture(), any()); order.verify(mNetdWrapper).isInterfaceUp(eq(WIFI_IFACE_NAME)); @@ -701,7 +697,7 @@ public class WifiNativeTest extends WifiBaseTest { */ @Test public void testClientModeScanFailure() { - mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), mScanCallbackCaptor.capture(), any()); @@ -714,7 +710,7 @@ public class WifiNativeTest extends WifiBaseTest { */ @Test public void testClientModePnoScanSuccess() { - mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), any(), mScanCallbackCaptor.capture()); @@ -728,7 +724,7 @@ public class WifiNativeTest extends WifiBaseTest { */ @Test public void testClientModePnoScanFailure() { - mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(), any(), mScanCallbackCaptor.capture()); @@ -829,7 +825,7 @@ public class WifiNativeTest extends WifiBaseTest { when(mCoexManager.getCoexRestrictions()).thenReturn(restrictions); mWifiNative.setCoexUnsafeChannels(unsafeChannels, restrictions); - mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); verify(mWifiVendorHal, times(2)).setCoexUnsafeChannels(unsafeChannels, restrictions); mWifiNative.teardownAllInterfaces(); @@ -1075,15 +1071,6 @@ public class WifiNativeTest extends WifiBaseTest { * Verifies that isSetMacAddressSupported() calls underlying WifiVendorHal. */ @Test - public void testIsStaSetMacAddressSupported() throws Exception { - mWifiNative.isStaSetMacAddressSupported(WIFI_IFACE_NAME); - verify(mWifiVendorHal).isStaSetMacAddressSupported(WIFI_IFACE_NAME); - } - - /** - * Verifies that isSetMacAddressSupported() calls underlying WifiVendorHal. - */ - @Test public void testIsApSetMacAddressSupported() throws Exception { mWifiNative.isApSetMacAddressSupported(WIFI_IFACE_NAME); verify(mWifiVendorHal).isApSetMacAddressSupported(WIFI_IFACE_NAME); @@ -1313,7 +1300,7 @@ public class WifiNativeTest extends WifiBaseTest { @Test public void testReplaceStaIfaceRequestorWs() { assertEquals(WIFI_IFACE_NAME, - mWifiNative.setupInterfaceForClientInConnectivityMode( + mWifiNative.setupInterfaceForClientInScanMode( mInterfaceCallback, TEST_WORKSOURCE)); when(mWifiVendorHal.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE2)) .thenReturn(true); @@ -1520,6 +1507,45 @@ public class WifiNativeTest extends WifiBaseTest { } /** + * Verifies that getSupportedBandsForSta() calls underlying vendor HAL. + */ + @Test + public void testGetSupportedBandsFromHal() throws Exception { + List<WifiAvailableChannel> usableChannelList = new ArrayList<>(); + usableChannelList.add(new WifiAvailableChannel(2412, WifiAvailableChannel.OP_MODE_STA)); + usableChannelList.add(new WifiAvailableChannel(5160, WifiAvailableChannel.OP_MODE_STA)); + when(mWifiVendorHal.getUsableChannels(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ, + WifiAvailableChannel.OP_MODE_STA, + WifiAvailableChannel.FILTER_REGULATORY)).thenReturn(usableChannelList); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); + mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE); + assertEquals(3, mWifiNative.getSupportedBandsForSta(WIFI_IFACE_NAME)); + } + + /** + * Verifies that getSupportedBandsForStaFromWifiCond() calls underlying wificond. + */ + @Test + public void testGetSupportedBands() throws Exception { + when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ)).thenReturn( + new int[]{2412}); + when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ)).thenReturn( + new int[]{5160}); + when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn( + new int[0]); + when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_60_GHZ)).thenReturn( + new int[0]); + when(mWifiVendorHal.getUsableChannels(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ, + WifiAvailableChannel.OP_MODE_STA, + WifiAvailableChannel.FILTER_REGULATORY)).thenReturn(null); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE); + mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE); + verify(mWificondControl).getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ); + verify(mWificondControl).getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ); + assertEquals(3, mWifiNative.getSupportedBandsForSta(WIFI_IFACE_NAME)); + } + + /** * Verifies that isSoftApInstanceDiedHandlerSupported() calls underlying HostapdHal. */ @Test 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 a856e14de9..6378178a25 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -125,7 +125,6 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -251,6 +250,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { when(mResources.getBoolean( eq(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled))) .thenReturn(false); + when(mResources.getInteger(R.integer.config_wifiNetworkSpecifierMaxPreferredChannels)) + .thenReturn(5); when(mPackageManager.getNameForUid(TEST_UID_1)).thenReturn(TEST_PACKAGE_NAME_1); when(mPackageManager.getNameForUid(TEST_UID_2)).thenReturn(TEST_PACKAGE_NAME_2); when(mPackageManager.getApplicationInfoAsUser(any(), anyInt(), any())) @@ -270,6 +271,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { when(mActiveModeWarden.hasPrimaryClientModeManager()).thenReturn(true); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); + when(mPrimaryClientModeManager.getRole()).thenReturn(ActiveModeManager.ROLE_CLIENT_PRIMARY); doAnswer(invocation -> { Object[] args = invocation.getArguments(); ActiveModeWarden.ExternalClientModeManagerRequestListener requestListener = @@ -434,7 +436,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { .thenReturn(true); doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString()); - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); mLooper.dispatchAll(); @@ -448,7 +450,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { public void testHandleAcceptNetworkRequestFromWithInternetCapability() throws Exception { mockPackageImportance(TEST_PACKAGE_NAME_1, true, true); - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mNetworkRequest.networkCapabilities.addCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET); @@ -465,7 +467,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { public void testHandleAcceptNetworkRequestFromNonFgAppOrSvcWithSpecifier() throws Exception { mockPackageImportance(TEST_PACKAGE_NAME_1, false, false); - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); mLooper.dispatchAll(); @@ -480,7 +482,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { public void testHandleAcceptNetworkRequestFromFgAppWithSpecifier() { mockPackageImportance(TEST_PACKAGE_NAME_1, true, true); - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); } @@ -495,7 +497,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { when(mWifiPermissionsUtil.checkNetworkSettingsPermission(TEST_UID_1)) .thenReturn(true); - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); } @@ -509,12 +511,12 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { mockPackageImportance(TEST_PACKAGE_NAME_2, true, true); // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Make request 2 which will be accepted because a fg app request can // override a fg service request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); } @@ -526,12 +528,12 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { public void testHandleAcceptNetworkRequestFromFgSvcWithSpecifierWithPendingRequestFromFgSvc() { // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Make request 2 which will be accepted because a fg service request can // override an existing fg service request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); } @@ -545,12 +547,12 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { mockPackageImportance(TEST_PACKAGE_NAME_2, true, true); // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Make request 2 which will be accepted because a fg app request can // override an existing fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); } @@ -564,12 +566,12 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { mockPackageImportance(TEST_PACKAGE_NAME_1, true, true); // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Make request 2 which will be rejected because a fg service request cannot // override a fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); mLooper.dispatchAll(); verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); @@ -588,7 +590,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { mockPackageImportance(TEST_PACKAGE_NAME_1, true, true); // Handle request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Resend the request from a fg service (should be accepted since it is already being @@ -617,7 +619,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { // Make request 2 which will be accepted because a fg app request can // override an existing fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); assertTrue(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); } @@ -640,7 +642,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { // Make request 2 which will be rejected because a fg service request cannot // override a fg app request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); assertFalse(mWifiNetworkFactory.acceptRequest(mNetworkRequest)); mLooper.dispatchAll(); verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); @@ -674,7 +676,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleNetworkRequestWithSpecifier() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify UI start. @@ -683,7 +685,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { // Verify scan settings. verify(mWifiScanner).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), mWorkSourceArgumentCaptor.capture()); - validateScanSettings(null); + validateScanSettings(null, new int[0]); verify(mWifiMetrics).incrementNetworkRequestApiNumRequest(); } @@ -712,7 +714,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleNetworkRequestWithSpecifierAndInternetCapability() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mNetworkRequest.networkCapabilities.addCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET); @@ -726,7 +728,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleNetworkRequestWithSpecifierForHiddenNetwork() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify UI start. @@ -737,7 +739,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { mWorkSourceArgumentCaptor.capture()); validateScanSettings( ((WifiNetworkSpecifier) mNetworkCapabilities.getNetworkSpecifier()) - .ssidPatternMatcher.getPath()); + .ssidPatternMatcher.getPath(), new int[0]); verify(mWifiMetrics).incrementNetworkRequestApiNumRequest(); } @@ -751,25 +753,25 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { @Test public void testHandleNetworkRequestWithSpecifierAfterPreviousHiddenNetworkRequest() { // Hidden request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify scan settings. verify(mWifiScanner, times(1)).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), mWorkSourceArgumentCaptor.capture()); validateScanSettings( ((WifiNetworkSpecifier) mNetworkCapabilities.getNetworkSpecifier()) - .ssidPatternMatcher.getPath()); + .ssidPatternMatcher.getPath(), new int[0]); // Release request 1. mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); // Regular request 2. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify scan settings. verify(mWifiScanner, times(2)).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), mWorkSourceArgumentCaptor.capture()); - validateScanSettings(null); + validateScanSettings(null, new int[0]); verify(mWifiMetrics, times(2)).incrementNetworkRequestApiNumRequest(); } @@ -782,7 +784,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { // Make a generic request first to ensure that we re-enable auto-join after release. mWifiNetworkFactory.needNetworkFor(mNetworkRequest); - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); // Make the network request with specifier. mWifiNetworkFactory.needNetworkFor(mNetworkRequest); @@ -802,7 +804,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testPeriodicScanNetworkRequestWithSpecifier() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); verifyPeriodicScans(0, @@ -818,7 +820,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testPeriodicScanCancelOnReleaseNetworkRequestWithSpecifier() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); verifyPeriodicScans(0, @@ -836,7 +838,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testPeriodicScanCancelOnUserSelectNetwork() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); @@ -863,7 +865,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleCallbackRegistrationAndUnregistration() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); @@ -883,7 +885,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleCallbackRegistrationWithNoActiveRequest() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); @@ -917,7 +919,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(true); @@ -958,7 +960,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(true); @@ -999,7 +1001,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(false); @@ -1041,7 +1043,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(true); @@ -1083,7 +1085,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(false); @@ -1126,7 +1128,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(true); @@ -1171,7 +1173,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(true); @@ -1209,7 +1211,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(true); @@ -1259,7 +1261,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { assertNotNull(networkRequestUserSelectionCallback); // Now send another network request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Now trigger user selection to some network. @@ -1328,7 +1330,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); // request network, trigger scan and get matched set. mWifiNetworkFactory.needNetworkFor(mNetworkRequest); @@ -1433,7 +1435,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( @@ -1481,7 +1483,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( @@ -1542,7 +1544,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( @@ -1603,7 +1605,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( @@ -2360,7 +2362,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mLooper.dispatchAll(); @@ -2398,7 +2400,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleNewNetworkRequestWithSpecifierWhenScanning() throws Exception { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Register callback. @@ -2407,7 +2409,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mLooper.dispatchAll(); @@ -2443,7 +2445,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Ensure we don't request a new ClientModeManager. @@ -2484,7 +2486,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Ensure we don't request a new ClientModeManager. @@ -2532,7 +2534,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { NetworkRequest oldRequest = new NetworkRequest(mNetworkRequest); // Send second request. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_2, false, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Ensure we do request a new ClientModeManager. @@ -2770,7 +2772,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleNetworkRequestWithSpecifierWhenWifiOff() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); // wifi off when(mActiveModeWarden.hasPrimaryClientModeManager()).thenReturn(false); @@ -2825,7 +2827,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testFullHandleNetworkRequestWithSpecifierWhenWifiOff() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0]); // wifi off when(mActiveModeWarden.hasPrimaryClientModeManager()).thenReturn(false); @@ -2865,7 +2867,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); + WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1, + new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); when(mNetworkRequestMatchCallback.asBinder()).thenReturn(mAppBinder); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); @@ -2908,7 +2911,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); + TEST_UID_1, TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); when(mNetworkRequestMatchCallback.asBinder()).thenReturn(mAppBinder); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); @@ -2949,7 +2952,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createOpenNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); + TEST_UID_1, TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); when(mNetworkRequestMatchCallback.asBinder()).thenReturn(mAppBinder); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); @@ -2996,7 +2999,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); + TEST_UID_1, TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Connection does not happen yet since it is waiting for scan results. @@ -3068,7 +3071,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); + TEST_UID_1, TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); when(mNetworkRequestMatchCallback.asBinder()).thenReturn(mAppBinder); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); @@ -3112,7 +3115,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); + TEST_UID_1, TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); when(mNetworkRequestMatchCallback.asBinder()).thenReturn(mAppBinder); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); @@ -3146,11 +3149,9 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { assertTrue(approvedAccessPointsMapToWrite.keySet().contains(TEST_PACKAGE_NAME_1)); Set<AccessPoint> approvedAccessPointsToWrite = approvedAccessPointsMapToWrite.get(TEST_PACKAGE_NAME_1); - Set<AccessPoint> expectedApprovedAccessPoints = - new HashSet<AccessPoint>() {{ - add(new AccessPoint(TEST_SSID_1, MacAddress.fromString(TEST_BSSID_1), + Set<AccessPoint> expectedApprovedAccessPoints = Set.of( + new AccessPoint(TEST_SSID_1, MacAddress.fromString(TEST_BSSID_1), WifiConfiguration.SECURITY_TYPE_PSK)); - }}; assertEquals(expectedApprovedAccessPoints, approvedAccessPointsToWrite); // Ensure that the new data flag has been reset after read. assertFalse(mDataSource.hasNewDataToSerialize()); @@ -3163,11 +3164,9 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { public void testNetworkSpecifierUserApprovalConfigStoreLoad() throws Exception { Map<String, Set<AccessPoint>> approvedAccessPointsMapToRead = new HashMap<>(); - Set<AccessPoint> approvedAccessPoints = - new HashSet<AccessPoint>() {{ - add(new AccessPoint(TEST_SSID_1, MacAddress.fromString(TEST_BSSID_1), + Set<AccessPoint> approvedAccessPoints = Set.of( + new AccessPoint(TEST_SSID_1, MacAddress.fromString(TEST_BSSID_1), WifiConfiguration.SECURITY_TYPE_PSK)); - }}; approvedAccessPointsMapToRead.put(TEST_PACKAGE_NAME_1, approvedAccessPoints); mDataSource.fromDeserialized(approvedAccessPointsMapToRead); @@ -3179,7 +3178,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, WifiConfigurationTestUtil.createPskNetwork(), - TEST_UID_1, TEST_PACKAGE_NAME_1); + TEST_UID_1, TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); mWifiNetworkFactory.addCallback(mNetworkRequestMatchCallback); // Ensure we triggered a connect without issuing any scans. @@ -3245,7 +3244,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); + WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1, + new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify we did not trigger the UI for the second request. @@ -3306,7 +3306,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); + WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1, + new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify we did not trigger the UI for the second request. @@ -3365,7 +3366,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { MacAddress.BROADCAST_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, - WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); + WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1, + new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify we did not trigger the UI for the second request. @@ -3402,7 +3404,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); validateUiStartParams(true); @@ -3462,7 +3464,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, mSelectedNetwork, TEST_UID_2, - TEST_PACKAGE_NAME_2); + TEST_PACKAGE_NAME_2, new int[0]); mWifiNetworkFactory.needNetworkFor(new NetworkRequest(mNetworkRequest)); validateUiStartParams(true); @@ -3529,7 +3531,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { Pair.create(WifiManager.ALL_ZEROS_MAC_ADDRESS, WifiManager.ALL_ZEROS_MAC_ADDRESS); attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, mSelectedNetwork, TEST_UID_2, - TEST_PACKAGE_NAME_2); + TEST_PACKAGE_NAME_2, new int[0]); mWifiNetworkFactory.needNetworkFor(new NetworkRequest(mNetworkRequest)); validateUiStartParams(true); @@ -3559,6 +3561,67 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { .getSpecificNetworkRequestUids(mSelectedNetwork, TEST_BSSID_1).size()); } + /** + * Validates a new network request with Car Mode Priority for same network which is already + * a saved network, the connection will be on primary STA and the should have the internet + * capabilities + */ + @Test + public void testShareConnectedNetworkWithCarModePriorityAndSavedNetwork() throws Exception { + mockPackageImportance(TEST_PACKAGE_NAME_1, true, true); + when(mWifiPermissionsUtil.checkEnterCarModePrioritized(TEST_UID_1)).thenReturn(true); + + // Connect to request 1 + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + + sendNetworkRequestAndSetupForUserSelection(TEST_SSID_1, false); + + INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = + mNetworkRequestUserSelectionCallback.getValue(); + assertNotNull(networkRequestUserSelectionCallback); + + // Now trigger user selection to one of the network. + mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); + mSelectedNetwork.SSID = "\"" + TEST_SSID_1 + "\""; + mSelectedNetwork.preSharedKey = TEST_WPA_PRESHARED_KEY; + when(mWifiConfigManager.getConfiguredNetworksWithPasswords()) + .thenReturn(List.of(mSelectedNetwork)); + sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); + mLooper.dispatchAll(); + + verify(mActiveModeWarden, never()).requestLocalOnlyClientModeManager( + any(), any(), any(), any(), anyBoolean()); + verify(mActiveModeWarden, atLeastOnce()).getPrimaryClientModeManager(); + if (SdkLevel.isAtLeastS()) { + verify(mPrimaryClientModeManager, atLeastOnce()).getConnectedWifiConfiguration(); + verify(mPrimaryClientModeManager, atLeastOnce()).getConnectingWifiConfiguration(); + verify(mPrimaryClientModeManager, atLeastOnce()).getConnectingBssid(); + verify(mPrimaryClientModeManager, atLeastOnce()).getConnectedBssid(); + } + + // Cancel the periodic scan timer. + mInOrder.verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); + // Disable connectivity manager + verify(mWifiConnectivityManager, atLeastOnce()).setSpecificNetworkRequestInProgress(true); + + // Increment the number of unique apps. + verify(mWifiMetrics).incrementNetworkRequestApiNumApps(); + + verify(mPrimaryClientModeManager, atLeastOnce()).disconnect(); + verify(mConnectHelper, atLeastOnce()).connectToNetwork( + eq(mPrimaryClientModeManager), + eq(new NetworkUpdateResult(TEST_NETWORK_ID_1)), + mConnectListenerArgumentCaptor.capture(), anyInt(), any()); + verify(mWifiMetrics, atLeastOnce()).incrementNetworkRequestApiNumConnectOnPrimaryIface(); + + // Start the connection timeout alarm. + mInOrder.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), + eq((long) WifiNetworkFactory.NETWORK_CONNECTION_TIMEOUT_MS), any(), + mConnectionTimeoutAlarmListenerArgumentCaptor.capture(), any()); + assertNotNull(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); + assertTrue(mWifiNetworkFactory.shouldHaveInternetCapabilities()); + } + private void sendNetworkRequestAndSetupForConnectionStatus() throws RemoteException { sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); } @@ -3651,7 +3714,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; attachWifiNetworkSpecifierAndAppInfo( ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, - TEST_PACKAGE_NAME_1); + TEST_PACKAGE_NAME_1, new int[0]); mWifiNetworkFactory.needNetworkFor(new NetworkRequest(mNetworkRequest)); validateUiStartParams(true); @@ -3729,7 +3792,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { mInOrder.verifyNoMoreInteractions(); } - private void attachDefaultWifiNetworkSpecifierAndAppInfo(int uid, boolean isHidden) { + private void attachDefaultWifiNetworkSpecifierAndAppInfo(int uid, boolean isHidden, + int[] channels) { PatternMatcher ssidPatternMatch = new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); Pair<MacAddress, MacAddress> bssidPatternMatch = @@ -3749,17 +3813,17 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { fail(); } attachWifiNetworkSpecifierAndAppInfo(ssidPatternMatch, bssidPatternMatch, wifiConfiguration, - uid, packageName); + uid, packageName, channels); } private void attachWifiNetworkSpecifierAndAppInfo( PatternMatcher ssidPatternMatch, Pair<MacAddress, MacAddress> bssidPatternMatch, - WifiConfiguration wifiConfiguration, int uid, String packageName) { + WifiConfiguration wifiConfiguration, int uid, String packageName, int[] channels) { mNetworkCapabilities.setRequestorUid(uid); mNetworkCapabilities.setRequestorPackageName(packageName); mNetworkCapabilities.setNetworkSpecifier( new WifiNetworkSpecifier(ssidPatternMatch, bssidPatternMatch, - ScanResult.UNSPECIFIED, wifiConfiguration)); + ScanResult.UNSPECIFIED, wifiConfiguration, channels)); mNetworkRequest = new NetworkRequest.Builder() .setCapabilities(mNetworkCapabilities) .build(); @@ -3862,7 +3926,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { } } - private void validateScanSettings(@Nullable String hiddenSsid) { + private void validateScanSettings(@Nullable String hiddenSsid, int[] channels) { ScanSettings scanSettings = mScanSettingsArgumentCaptor.getValue(); assertNotNull(scanSettings); assertEquals(WifiScanner.WIFI_BAND_ALL, scanSettings.band); @@ -3877,6 +3941,10 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { WorkSource workSource = mWorkSourceArgumentCaptor.getValue(); assertNotNull(workSource); assertEquals(TEST_UID_1, workSource.getUid(0)); + assertEquals(scanSettings.channels.length, channels.length); + for (int i = 0; i < channels.length; i++) { + assertEquals(channels[i], scanSettings.channels[i].frequency); + } } class WifiConfigMatcher implements ArgumentMatcher<WifiConfiguration> { diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java index 02be2e7c56..4626de802d 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java @@ -70,6 +70,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; /** * Unit tests for {@link com.android.server.wifi.WifiNetworkSelector}. @@ -302,6 +303,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { private int mThresholdQualifiedRssi2G; private int mThresholdQualifiedRssi5G; private int mMinPacketRateActiveTraffic; + private int mLastMeteredSelectionWeightMinutes; + private int mLastUnmeteredSelectionWeightMinutes; private int mSufficientDurationAfterUserSelection; private CompatibilityScorer mCompatibilityScorer; private ScoreCardBasedScorer mScoreCardBasedScorer; @@ -336,6 +339,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { mThresholdQualifiedRssi5G = mScoringParams.getSufficientRssi( ScanResult.BAND_5_GHZ_START_FREQ_MHZ); mMinPacketRateActiveTraffic = mScoringParams.getActiveTrafficPacketsPerSecond(); + mLastMeteredSelectionWeightMinutes = mScoringParams.getLastMeteredSelectionMinutes(); + mLastUnmeteredSelectionWeightMinutes = mScoringParams.getLastUnmeteredSelectionMinutes(); } private void setupWifiInfo() { @@ -1307,6 +1312,110 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { } /** + * Verify that WifiNetworkSelector does not override NetworkSelector's choice with + * the user connect choice when override is disabled + */ + @Test + public void userConnectChoiceDoesNotOverrideWhenOverrideDisabled() { + String[] ssids = {"\"test1\"", "\"test2\""}; + String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; + int[] freqs = {2437, 5180}; + String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"}; + int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; + int[] securities = {SECURITY_PSK, SECURITY_PSK}; + ScanDetailsAndWifiConfigs scanDetailsAndConfigs = + WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, + freqs, caps, levels, securities, mWifiConfigManager, mClock); + List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); + WifiConfiguration[] wifiConfigs = scanDetailsAndConfigs.getWifiConfigs(); + HashSet<String> blocklist = new HashSet<>(); + + // PlaceholderNominator always selects the first network in the list. + WifiConfiguration networkSelectorChoice = wifiConfigs[0]; + networkSelectorChoice.getNetworkSelectionStatus() + .setSeenInLastQualifiedNetworkSelection(true); + + // set user connect choice + WifiConfiguration userChoice = wifiConfigs[1]; + userChoice.getNetworkSelectionStatus().setConnectChoice(null); + networkSelectorChoice.getNetworkSelectionStatus() + .setConnectChoice(userChoice.getProfileKey()); + + // Verify that the userChoice network is chosen when override is enabled by default + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blocklist, + Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo)), + false, true, true, Collections.emptySet(), false); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); + WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate); + + + // Verify that the networkSelectorChoice is chosen when override is disabled + mWifiNetworkSelector.setUserConnectChoiceOverrideEnabled(false); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blocklist, + Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo)), + false, true, true, Collections.emptySet(), false); + candidate = mWifiNetworkSelector.selectNetwork(candidates); + WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate); + } + + /** + * Tests last selection weight calculation returns 0.0 for the latest selected network + * when last selection weight is disabled + */ + @Test + public void testLastSelectionWeightForLatestSelectedNetwork() { + String[] ssids = {"\"test1\"", "\"test2\""}; + String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"}; + int[] freqs = {2437, 5180}; + String[] caps = {"[WPA2-PSK][ESS]", "[WPA2-PSK][ESS]"}; + int[] levels = {mThresholdMinimumRssi2G + RSSI_BUMP, mThresholdMinimumRssi5G + RSSI_BUMP}; + int[] securities = {SECURITY_PSK, SECURITY_PSK}; + ScanDetailsAndWifiConfigs scanDetailsAndConfigs = + WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, + freqs, caps, levels, securities, mWifiConfigManager, mClock); + List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); + WifiConfiguration[] wifiConfigs = scanDetailsAndConfigs.getWifiConfigs(); + HashSet<String> blocklist = new HashSet<>(); + + // Set the latest selected network + WifiConfiguration latestSelection = wifiConfigs[0]; + setupWifiConfigManager(latestSelection.networkId); + when(mWifiConfigManager.getLastSelectedTimeStamp()) + .thenReturn(SystemClock.elapsedRealtime()); + + // Verify that the last selection weight for the latest selected network is greater than 0 + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blocklist, + Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo)), + false, true, true, Collections.emptySet(), false); + + assertFalse(candidates.isEmpty()); + for (WifiCandidates.Candidate candidate: candidates) { + if (candidate.getNetworkConfigId() == latestSelection.networkId) { + assertTrue(candidate.getLastSelectionWeight() > 0.0); + } + } + + // Disable last selection weight + mWifiNetworkSelector.setLastSelectionWeightEnabled(false); + + // Verify that the last selection weight for the latest selected network is 0 + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blocklist, + Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo)), + false, true, true, Collections.emptySet(), false); + + assertFalse(candidates.isEmpty()); + for (WifiCandidates.Candidate candidate: candidates) { + if (candidate.getNetworkConfigId() == latestSelection.networkId) { + assertTrue(candidate.getLastSelectionWeight() == 0.0); + } + } + } + + /** * Tests when multiple Nominators nominate the same candidate, any one of the nominator IDs is * acceptable. */ @@ -1530,32 +1639,61 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { false); } - /** - * New network selection is not performed if the currently connected network - * was recently selected. - */ - @Test - public void networkIsSufficientWhenRecentlyUserSelected() { - // Approximate mClock.getElapsedSinceBootMillis value mocked by testStayOrTryToSwitch - long millisSinceBoot = SystemClock.elapsedRealtime() - + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000; + private void verifyLastSelectedWeight(boolean isMetered) { + String[] ssids = {"\"test1\""}; + String[] bssids = {"6c:f3:7f:ae:8c:f3"}; + int[] freqs = {5180}; + String[] caps = {"[WPA2-PSK][ESS]"}; + int[] levels = {mThresholdQualifiedRssi5G + 5}; + int[] securities = {SECURITY_PSK}; + + ScanDetailsAndWifiConfigs scanDetailsAndConfigs = + WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, + freqs, caps, levels, securities, mWifiConfigManager, mClock); + List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); + HashSet<String> blocklist = new HashSet<String>(); + WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs(); + if (isMetered) { + savedConfigs[0].meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED; + } + long startTimeMs = mClock.getElapsedSinceBootMillis(); + long expectedStickyTimeMinutes = isMetered ? mLastMeteredSelectionWeightMinutes + : mLastUnmeteredSelectionWeightMinutes; + setupWifiConfigManager(savedConfigs[0].networkId); // Set last connected network when(mWifiConfigManager.getLastSelectedTimeStamp()) - .thenReturn(millisSinceBoot - - WAIT_JUST_A_MINUTE - + 1000); - setupWifiConfigManager(0); // testStayOrTryToSwitch first connects to network 0 - // Rssi after connected. - when(mWifiInfo.getRssi()).thenReturn(mThresholdQualifiedRssi2G + 1); - // No streaming traffic. - when(mWifiInfo.getSuccessfulTxPacketsPerSecond()).thenReturn(0.0); - when(mWifiInfo.getSuccessfulRxPacketsPerSecond()).thenReturn(0.0); + .thenReturn(startTimeMs); - testStayOrTryToSwitch( - mThresholdQualifiedRssi2G + 1 /* rssi before connected */, - false /* not a 5G network */, - false /* not open network */, - // Should not try to switch. - false); + // lastSelectionWeight should be greater than 0 before expectedStickyTimeMinutes passes + when(mClock.getElapsedSinceBootMillis()).thenReturn(startTimeMs + + TimeUnit.MINUTES.toMillis(expectedStickyTimeMinutes) - 1); + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blocklist, + Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo)), + false, true, true, Collections.emptySet(), false); + //WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); + assertEquals(1, candidates.size()); + assertTrue(candidates.get(0).getLastSelectionWeight() > 0); + + // lastSelectionWeight should be 0 after expectedStickyTimeMinutes passes + when(mClock.getElapsedSinceBootMillis()).thenReturn(startTimeMs + + TimeUnit.MINUTES.toMillis(expectedStickyTimeMinutes)); + candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blocklist, + Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo)), + false, true, true, Collections.emptySet(), false); + //WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); + assertEquals(1, candidates.size()); + assertEquals(0, candidates.get(0).getLastSelectionWeight(), 0); + } + + @Test + public void testLastSelectedWeight() { + verifyLastSelectedWeight(false); + } + + @Test + public void testLastSelectedWeightMetered() { + verifyLastSelectedWeight(true); } /** 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 484ef4d49b..7d8eb15e98 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -80,7 +80,6 @@ import android.net.wifi.WifiSsid; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.pps.Credential; import android.net.wifi.hotspot2.pps.HomeSp; -import android.os.Handler; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; @@ -89,6 +88,7 @@ import android.os.test.TestLooper; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; +import android.util.LocalLog; import android.view.LayoutInflater; import com.android.dx.mockito.inline.extended.ExtendedMockito; @@ -300,7 +300,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { when(mWifiKeyStore.updateNetworkKeys(any(), any())).thenReturn(true); mWifiNetworkSuggestionsManager = - new WifiNetworkSuggestionsManager(mContext, new Handler(mLooper.getLooper()), + new WifiNetworkSuggestionsManager(mContext, + new RunnerHandler(mLooper.getLooper(), 100, new LocalLog(128)), mWifiInjector, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mWifiKeyStore, mLruConnectionTracker, mClock); 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 c7c78f362e..35c066dab2 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE; import static android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS; import static android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS; import static android.net.wifi.WifiAvailableChannel.FILTER_REGULATORY; +import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP; import static android.net.wifi.WifiAvailableChannel.OP_MODE_STA; import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT; @@ -126,6 +127,7 @@ import android.net.DhcpInfo; import android.net.DhcpOption; import android.net.DhcpResultsParcelable; import android.net.MacAddress; +import android.net.Network; import android.net.NetworkStack; import android.net.Uri; import android.net.wifi.CoexUnsafeChannel; @@ -569,10 +571,13 @@ public class WifiServiceImplTest extends WifiBaseTest { .thenReturn(Collections.emptyList()); when(mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(anyInt())) .thenReturn(true); - // Defaulting apps to target SDK level that's prior to T. This is need for to test for + // Defaulting apps to target SDK level that's prior to T. This is needed to test for // backward compatibility of API changes. when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), eq(Build.VERSION_CODES.TIRAMISU), anyInt())).thenReturn(true); + when(mWifiPermissionsUtil.isTargetSdkLessThan(any(), + eq(Build.VERSION_CODES.UPSIDE_DOWN_CAKE), + anyInt())).thenReturn(true); when(mWifiInjector.getWifiCarrierInfoManager()).thenReturn(mWifiCarrierInfoManager); when(mWifiInjector.getOpenNetworkNotifier()).thenReturn(mOpenNetworkNotifier); when(mClientSoftApCallback.asBinder()).thenReturn(mAppBinder); @@ -1634,7 +1639,6 @@ public class WifiServiceImplTest extends WifiBaseTest { SoftApConfiguration apConfig = createValidSoftApConfiguration(); assertTrue(mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME)); - mLooper.dispatchAll(); verify(mWifiApConfigStore).setApConfiguration(eq(apConfig)); verify(mActiveModeWarden).updateSoftApConfiguration(apConfig); verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt()); @@ -1649,7 +1653,6 @@ public class WifiServiceImplTest extends WifiBaseTest { SoftApConfiguration apConfig = createValidSoftApConfiguration(); assertTrue(mWifiServiceImpl.setSoftApConfiguration(apConfig, TEST_PACKAGE_NAME)); - mLooper.dispatchAll(); verify(mWifiApConfigStore).setApConfiguration(eq(apConfig)); verify(mActiveModeWarden).updateSoftApConfiguration(apConfig); verify(mWifiPermissionsUtil).checkConfigOverridePermission(anyInt()); @@ -2123,10 +2126,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testIsWifiBandSupported24gWithOverride() throws Exception { when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); - mLooper.startAutoDispatch(); assertTrue(mWifiServiceImpl.is24GHzBandSupported()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mWifiNative, never()).getChannelsForBand(anyInt()); + verify(mActiveModeWarden, never()).isBandSupportedForSta(anyInt()); } /** @@ -2135,10 +2136,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testIsWifiBandSupported5gWithOverride() throws Exception { when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); - mLooper.startAutoDispatch(); assertTrue(mWifiServiceImpl.is5GHzBandSupported()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mWifiNative, never()).getChannelsForBand(anyInt()); + verify(mActiveModeWarden, never()).isBandSupportedForSta(anyInt()); } /** @@ -2147,10 +2146,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testIsWifiBandSupported6gWithOverride() throws Exception { when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true); - mLooper.startAutoDispatch(); assertTrue(mWifiServiceImpl.is6GHzBandSupported()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); - verify(mWifiNative, never()).getChannelsForBand(anyInt()); + verify(mActiveModeWarden, never()).isBandSupportedForSta(anyInt()); } /** @@ -2158,13 +2155,10 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported24gNoOverrideNoChannels() throws Exception { - final int[] emptyArray = {}; when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray); - mLooper.startAutoDispatch(); + when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_24_GHZ)).thenReturn(false); assertFalse(mWifiServiceImpl.is24GHzBandSupported()); - mLooper.stopAutoDispatch(); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ); + verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ); } /** @@ -2172,13 +2166,10 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported5gNoOverrideNoChannels() throws Exception { - final int[] emptyArray = {}; when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray); - mLooper.startAutoDispatch(); + when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_5_GHZ)).thenReturn(false); assertFalse(mWifiServiceImpl.is5GHzBandSupported()); - mLooper.stopAutoDispatch(); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ); + verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ); } /** @@ -2186,13 +2177,10 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported24gNoOverrideWithChannels() throws Exception { - final int[] channelArray = {2412}; when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray); - mLooper.startAutoDispatch(); + when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_24_GHZ)).thenReturn(true); assertTrue(mWifiServiceImpl.is24GHzBandSupported()); - mLooper.stopAutoDispatch(); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ); + verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ); } /** @@ -2200,13 +2188,10 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported5gNoOverrideWithChannels() throws Exception { - final int[] channelArray = {5170}; when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray); - mLooper.startAutoDispatch(); + when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_5_GHZ)).thenReturn(true); assertTrue(mWifiServiceImpl.is5GHzBandSupported()); - mLooper.stopAutoDispatch(); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ); + verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ); } /** @@ -2214,13 +2199,11 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported6gNoOverrideNoChannels() throws Exception { - final int[] emptyArray = {}; when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray); - mLooper.startAutoDispatch(); + when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn( + false); assertFalse(mWifiServiceImpl.is6GHzBandSupported()); - mLooper.stopAutoDispatch(); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ); + verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ); } /** @@ -2228,13 +2211,11 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported6gNoOverrideWithChannels() throws Exception { - final int[] channelArray = {6420}; when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray); - mLooper.startAutoDispatch(); + when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn( + true); assertTrue(mWifiServiceImpl.is6GHzBandSupported()); - mLooper.stopAutoDispatch(); - verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ); + verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ); } private void setup24GhzSupported() { @@ -2246,8 +2227,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ)) - .thenReturn(new int[0]); + when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ)) + .thenReturn(false); } } @@ -2260,8 +2241,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mResources.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)) - .thenReturn(new int[0]); + when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ)) + .thenReturn(false); } } @@ -2274,8 +2255,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mResources.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ)) - .thenReturn(new int[0]); + when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)) + .thenReturn(false); } } @@ -2288,8 +2269,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mResources.getBoolean(R.bool.config_wifiSoftap60ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { when(mResources.getBoolean(R.bool.config_wifi60ghzSupport)).thenReturn(false); - when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ)) - .thenReturn(new int[0]); + when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_60_GHZ)) + .thenReturn(false); } } @@ -2698,6 +2679,8 @@ public class WifiServiceImplTest extends WifiBaseTest { assertFalse(mWifiServiceImpl.startScan(SCAN_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mScanRequestProxy, never()).startScan(anyInt(), eq(SCAN_PACKAGE_NAME)); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_START_SCAN), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -2738,7 +2721,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testConnectedIdsAreHiddenFromAppWithoutPermission() throws Exception { WifiInfo wifiInfo = setupForGetConnectionInfo(); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( anyString(), nullable(String.class), anyInt(), nullable(String.class)); @@ -2768,7 +2751,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testConnectedIdsAreHiddenOnSecurityException() throws Exception { WifiInfo wifiInfo = setupForGetConnectionInfo(); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceCanAccessScanResults( anyString(), nullable(String.class), anyInt(), nullable(String.class)); @@ -2792,7 +2775,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testConnectedIdsAreVisibleFromPermittedApp() throws Exception { WifiInfo wifiInfo = setupForGetConnectionInfo(); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mLooper.startAutoDispatch(); WifiInfo connectionInfo = parcelingRoundTrip( @@ -2817,7 +2800,7 @@ public class WifiServiceImplTest extends WifiBaseTest { ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class); when(secondaryCmm.getRequestorWs()) .thenReturn(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE)); - when(secondaryCmm.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(secondaryCmm.getConnectionInfo()).thenReturn(wifiInfo); when(mActiveModeWarden.getClientModeManagersInRoles( ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED)) .thenReturn(Arrays.asList(secondaryCmm)); @@ -2847,12 +2830,12 @@ public class WifiServiceImplTest extends WifiBaseTest { WorkSource ws = new WorkSource(Binder.getCallingUid(), TEST_PACKAGE); ws.add(SETTINGS_WORKSOURCE); when(secondaryCmm.getRequestorWs()).thenReturn(ws); - when(secondaryCmm.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(secondaryCmm.getConnectionInfo()).thenReturn(wifiInfo); when(mActiveModeWarden.getClientModeManagersInRoles( ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED)) .thenReturn(Arrays.asList(secondaryCmm)); ConcreteClientModeManager primaryCmm = mock(ConcreteClientModeManager.class); - when(primaryCmm.syncRequestConnectionInfo()).thenReturn(new WifiInfo()); + when(primaryCmm.getConnectionInfo()).thenReturn(new WifiInfo()); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(primaryCmm); when(mWifiPermissionsUtil.checkNetworkSettingsPermission(SETTINGS_WORKSOURCE.getUid(0))) .thenReturn(true); @@ -2876,7 +2859,7 @@ public class WifiServiceImplTest extends WifiBaseTest { assertEquals(WifiManager.UNKNOWN_SSID, connectionInfo.getSSID()); verify(mActiveModeWarden).getPrimaryClientModeManager(); - verify(primaryCmm).syncRequestConnectionInfo(); + verify(primaryCmm).getConnectionInfo(); } /** @@ -2887,7 +2870,7 @@ public class WifiServiceImplTest extends WifiBaseTest { public void testConnectedIdsFromPrimaryCmmAreVisibleFromAppNotRequestingSecondaryCmm() throws Exception { WifiInfo wifiInfo = setupForGetConnectionInfo(); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class); when(secondaryCmm.getRequestorWs()) .thenReturn(new WorkSource(Binder.getCallingUid(), TEST_PACKAGE_NAME_OTHER)); @@ -3173,12 +3156,9 @@ public class WifiServiceImplTest extends WifiBaseTest { new ArrayList<>(Arrays.asList(scanResults)); when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList); WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class); - List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{ - add(mockSuggestion); - }}; - Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{ - put(mockSuggestion, scanResultList); - }}; + List<WifiNetworkSuggestion> matchingSuggestions = List.of(mockSuggestion); + Map<WifiNetworkSuggestion, List<ScanResult>> result = Map.of( + mockSuggestion, scanResultList); when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions), eq(scanResultList))).thenReturn(result); @@ -3206,12 +3186,10 @@ public class WifiServiceImplTest extends WifiBaseTest { List<ScanResult> scanResultList = new ArrayList<>(Arrays.asList(scanResults)); WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class); - List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{ - add(mockSuggestion); - }}; - Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{ - put(mockSuggestion, scanResultList); - }}; + List<WifiNetworkSuggestion> matchingSuggestions = List.of(mockSuggestion); + Map<WifiNetworkSuggestion, List<ScanResult>> result = Map.of( + mockSuggestion, scanResultList); + when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions), eq(scanResultList))).thenReturn(result); @@ -3242,12 +3220,10 @@ public class WifiServiceImplTest extends WifiBaseTest { new ArrayList<>(Arrays.asList(scanResults)); when(mScanRequestProxy.getScanResults()).thenReturn(scanResultList); WifiNetworkSuggestion mockSuggestion = mock(WifiNetworkSuggestion.class); - List<WifiNetworkSuggestion> matchingSuggestions = new ArrayList<>() {{ - add(mockSuggestion); - }}; - Map<WifiNetworkSuggestion, List<ScanResult>> result = new HashMap<>() {{ - put(mockSuggestion, scanResultList); - }}; + List<WifiNetworkSuggestion> matchingSuggestions = List.of(mockSuggestion); + Map<WifiNetworkSuggestion, List<ScanResult>> result = Map.of( + mockSuggestion, scanResultList); + when(mWifiNetworkSuggestionsManager.getMatchingScanResults(eq(matchingSuggestions), eq(scanResultList))).thenReturn(result); @@ -4437,6 +4413,9 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mLohsCallback, never()).onHotspotStarted(any()); + verify(mLastCallerInfoManager, atLeastOnce()).put( + eq(WifiManager.API_START_LOCAL_ONLY_HOTSPOT), anyInt(), anyInt(), anyInt(), + anyString(), eq(true)); } /** @@ -5156,6 +5135,8 @@ public class WifiServiceImplTest extends WifiBaseTest { any(ActionListenerWrapper.class), anyInt(), any()); verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK), anyInt()); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_CONNECT_CONFIG), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -5290,6 +5271,8 @@ public class WifiServiceImplTest extends WifiBaseTest { eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt(), any()); verify(mContextAsUser, never()).sendBroadcastWithMultiplePermissions(any(), any()); verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_MANUAL_CONNECT), anyInt()); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_CONNECT_NETWORK_ID), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } @Test @@ -5409,6 +5392,8 @@ public class WifiServiceImplTest extends WifiBaseTest { any()); verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK), anyInt()); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_SAVE), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } @Test @@ -5479,6 +5464,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.dispatchAll(); inOrder.verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt(), any()); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_FORGET), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } @Test @@ -6672,6 +6659,8 @@ public class WifiServiceImplTest extends WifiBaseTest { verify(mConnectHelper).connectToNetwork( eq(new NetworkUpdateResult(TEST_NETWORK_ID)), any(), anyInt(), any()); verify(mWifiMetrics).incrementNumEnableNetworkCalls(); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_ENABLE_NETWORK), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -7944,6 +7933,8 @@ public class WifiServiceImplTest extends WifiBaseTest { verify(mWifiConfigManager).allowAutojoin(anyInt(), anyBoolean()); verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON), anyInt()); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_ALLOW_AUTOJOIN), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } @Test @@ -8644,11 +8635,9 @@ public class WifiServiceImplTest extends WifiBaseTest { .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService")); mWifiServiceImpl.setScanThrottleEnabled(true); - mLooper.dispatchAll(); verify(mScanRequestProxy).setScanThrottleEnabled(true); mWifiServiceImpl.setScanThrottleEnabled(false); - mLooper.dispatchAll(); verify(mScanRequestProxy).setScanThrottleEnabled(false); } @@ -8659,16 +8648,13 @@ public class WifiServiceImplTest extends WifiBaseTest { eq("WifiService")); mWifiServiceImpl.setScanThrottleEnabled(true); - mLooper.dispatchAll(); verify(mScanRequestProxy, never()).setScanThrottleEnabled(true); } @Test public void testIsScanThrottleEnabled() { when(mScanRequestProxy.isScanThrottleEnabled()).thenReturn(true); - mLooper.startAutoDispatch(); assertTrue(mWifiServiceImpl.isScanThrottleEnabled()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mScanRequestProxy).isScanThrottleEnabled(); } @@ -8678,11 +8664,9 @@ public class WifiServiceImplTest extends WifiBaseTest { .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), eq("WifiService")); mWifiServiceImpl.setAutoWakeupEnabled(true); - mLooper.dispatchAll(); verify(mWakeupController).setEnabled(true); mWifiServiceImpl.setAutoWakeupEnabled(false); - mLooper.dispatchAll(); verify(mWakeupController).setEnabled(false); } @@ -8700,9 +8684,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testIsAutoWakeupEnabled() { when(mWakeupController.isEnabled()).thenReturn(true); - mLooper.startAutoDispatch(); assertTrue(mWifiServiceImpl.isAutoWakeupEnabled()); - mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWakeupController).isEnabled(); } @@ -8903,6 +8885,33 @@ public class WifiServiceImplTest extends WifiBaseTest { } @Test + public void testSetCarrierNetworkOffloadEnabledWithoutPermissionThrowsException() + throws Exception { + try { + mWifiServiceImpl.setCarrierNetworkOffloadEnabled(10, true, true); + fail(); + } catch (SecurityException e) { } + } + + @Test + public void testSetCarrierNetworkOffloadEnabled() throws Exception { + when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), + anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); + mWifiServiceImpl.setCarrierNetworkOffloadEnabled(10, true, true); + verify(mWifiCarrierInfoManager).setCarrierNetworkOffloadEnabled(10, true, true); + + mWifiServiceImpl.setCarrierNetworkOffloadEnabled(5, false, false); + verify(mWifiCarrierInfoManager).setCarrierNetworkOffloadEnabled(5, false, false); + } + + @Test + public void testIsCarrierNetworkOffloadEnabled() throws Exception { + when(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(10, true)).thenReturn(true); + assertTrue(mWifiServiceImpl.isCarrierNetworkOffloadEnabled(10, true)); + verify(mWifiCarrierInfoManager).isCarrierNetworkOffloadEnabled(10, true); + } + + @Test public void testSetEmergencyScanRequestWithoutPermissionThrowsException() throws Exception { when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK)) .thenReturn(PackageManager.PERMISSION_DENIED); @@ -9150,11 +9159,51 @@ public class WifiServiceImplTest extends WifiBaseTest { doThrow(new SecurityException()).when(mWifiPermissionsUtil) .checkCallersHardwareLocationPermission(anyInt()); try { - mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY); + mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY, + TEST_PACKAGE_NAME, mExtras); fail("expected SecurityException"); } catch (SecurityException expected) { } } + @Test + public void testGetUsableChannelsThrowsSecurityExceptionOnMissingPermissionsAfterU() { + assumeTrue(SdkLevel.isAtLeastU()); + + // verify app targeting prior to Android U can call API with location permission + when(mWifiPermissionsUtil.isTargetSdkLessThan(any(), + eq(Build.VERSION_CODES.UPSIDE_DOWN_CAKE), + anyInt())).thenReturn(true); + when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); + when(mWifiPermissionsUtil.checkCallersHardwareLocationPermission(anyInt())) + .thenReturn(true); + + mLooper.startAutoDispatch(); + mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY, + TEST_PACKAGE_NAME, mExtras); + + // Verify app targeting prior to Android U fails to call API without location permission + when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); + assertThrows(SecurityException.class, + () -> mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, + FILTER_REGULATORY, TEST_PACKAGE_NAME, mExtras)); + + // Verify app targeting Android U no longer need location. + when(mWifiPermissionsUtil.isTargetSdkLessThan(any(), + eq(Build.VERSION_CODES.UPSIDE_DOWN_CAKE), + anyInt())).thenReturn(false); + mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY, + TEST_PACKAGE_NAME, mExtras); + + // Verify app targeting Android U will fail without nearby permission + doThrow(new SecurityException()) + .when(mWifiPermissionsUtil).enforceNearbyDevicesPermission( + any(), anyBoolean(), any()); + assertThrows(SecurityException.class, + () -> mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, + FILTER_REGULATORY, TEST_PACKAGE_NAME, mExtras)); + mLooper.stopAutoDispatch(); + } + /** * Verify the call to isValidBandForGetUsableChannels() */ @@ -9202,7 +9251,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mWifiPermissionsUtil.checkCallersHardwareLocationPermission(anyInt())) .thenReturn(true); try { - mWifiServiceImpl.getUsableChannels(WIFI_BAND_5_GHZ, OP_MODE_STA, FILTER_REGULATORY); + mWifiServiceImpl.getUsableChannels(WIFI_BAND_5_GHZ, OP_MODE_STA, FILTER_REGULATORY, + TEST_PACKAGE_NAME, mExtras); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { } @@ -9218,12 +9268,43 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mWifiPermissionsUtil.checkCallersHardwareLocationPermission(anyInt())) .thenReturn(true); mLooper.startAutoDispatch(); - mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY); + mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA, FILTER_REGULATORY, + TEST_PACKAGE_NAME, mExtras); mLooper.stopAutoDispatch(); verify(mWifiNative).getUsableChannels(anyInt(), anyInt(), anyInt()); } /** + * Verify the call to getUsableChannels() goes to cached SoftAp capabilities + */ + @Test + public void testGetUsableChannelsForApRegulation() throws Exception { + mWifiServiceImpl.handleBootCompleted(); + mLooper.dispatchAll(); + when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); + when(mWifiPermissionsUtil.checkCallersHardwareLocationPermission(anyInt())) + .thenReturn(true); + // Country code update with HAL started + when(mWifiNative.isHalStarted()).thenReturn(true); + // Channel 9 - 2452Mhz + WifiAvailableChannel channels2g = new WifiAvailableChannel(2452, + WifiAvailableChannel.OP_MODE_SAP); + when(mWifiNative.isHalSupported()).thenReturn(true); + when(mWifiNative.isHalStarted()).thenReturn(true); + when(mWifiNative.getUsableChannels(eq(WifiScanner.WIFI_BAND_24_GHZ), anyInt(), anyInt())) + .thenReturn(new ArrayList<>(Arrays.asList(channels2g))); + mWifiServiceImpl.mCountryCodeTracker.onDriverCountryCodeChanged(TEST_COUNTRY_CODE); + mLooper.dispatchAll(); + reset(mWifiNative); + List<WifiAvailableChannel> channels = mWifiServiceImpl.getUsableChannels(WIFI_BAND_24_GHZ, + OP_MODE_SAP, FILTER_REGULATORY, TEST_PACKAGE_NAME, mExtras); + assertEquals(1, channels.size()); + assertEquals(channels2g, channels.get(0)); + verify(mWifiNative, never()).getUsableChannels(eq(WifiScanner.WIFI_BAND_24_GHZ), anyInt(), + anyInt()); + } + + /** * Verify that if the caller has NETWORK_SETTINGS permission, and the overlay * config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW is set, then it can add an * insecure Enterprise network, with Root CA certificate not set and/or domain name not set. @@ -9486,7 +9567,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testGetPrivilegedConnectedNetworkNotConnected() { trySetTargetSdkToT(); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(new WifiInfo()); + when(mActiveModeWarden.getConnectionInfo()).thenReturn(new WifiInfo()); mLooper.startAutoDispatch(); assertNull(mWifiServiceImpl.getPrivilegedConnectedNetwork( @@ -9509,7 +9590,7 @@ public class WifiServiceImplTest extends WifiBaseTest { testConfig.setRandomizedMacAddress(TEST_FACTORY_MAC_ADDR); WifiInfo wifiInfo = new WifiInfo(); wifiInfo.setNetworkId(testConfig.networkId); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mActiveModeWarden.getConnectionInfo()).thenReturn(wifiInfo); when(mWifiConfigManager.getConfiguredNetworkWithPassword(testConfig.networkId)).thenReturn( testConfig); @@ -9664,8 +9745,8 @@ public class WifiServiceImplTest extends WifiBaseTest { .thenReturn(WifiManager.WIFI_FEATURE_PNO); when(mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission( anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkCallersLocationPermission( - any(), any(), anyInt(), anyBoolean(), any())).thenReturn(true); + when(mWifiPermissionsUtil.checkCallersLocationPermissionInManifest( + anyInt(), anyBoolean())).thenReturn(true); IPnoScanResultsCallback callback = mock(IPnoScanResultsCallback.class); List<WifiSsid> ssids = new ArrayList<>(); ssids.add(WifiSsid.fromString("\"TEST_SSID_1\"")); @@ -9684,8 +9765,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0L); when(mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission( anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkCallersLocationPermission( - any(), any(), anyInt(), anyBoolean(), any())).thenReturn(true); + when(mWifiPermissionsUtil.checkCallersLocationPermissionInManifest( + anyInt(), anyBoolean())).thenReturn(true); IPnoScanResultsCallback callback = mock(IPnoScanResultsCallback.class); List<WifiSsid> ssids = new ArrayList<>(); ssids.add(WifiSsid.fromString("\"TEST_SSID_1\"")); @@ -10203,13 +10284,15 @@ public class WifiServiceImplTest extends WifiBaseTest { when(attributionSource.getUid()).thenReturn(Process.SYSTEM_UID); when(attributionSource.getPackageName()).thenReturn(TEST_PACKAGE_NAME); WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(TEST_SSID); - + config.networkId = 1; mWifiThreadRunner.prepareForAutoDispatch(); mLooper.startAutoDispatch(); mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME, mAttribution); mLooper.stopAutoDispatch(); verify(mWifiConfigManager).addOrUpdateNetwork(config, Process.SYSTEM_UID, TEST_PACKAGE_NAME, false); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_UPDATE_NETWORK), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -10362,7 +10445,7 @@ public class WifiServiceImplTest extends WifiBaseTest { anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); when(mActiveModeWarden.getClientModeManagers()).thenReturn( Collections.singletonList(mClientModeManager)); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST, Arrays.asList(WifiSsid.fromUtf8Text("SSID"))); @@ -10390,7 +10473,7 @@ public class WifiServiceImplTest extends WifiBaseTest { anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); when(mActiveModeWarden.getClientModeManagers()).thenReturn( Collections.singletonList(mClientModeManager)); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST, Arrays.asList(WifiSsid.fromUtf8Text(TEST_SSID))); @@ -10415,7 +10498,7 @@ public class WifiServiceImplTest extends WifiBaseTest { anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); when(mActiveModeWarden.getClientModeManagers()).thenReturn( Collections.singletonList(mClientModeManager)); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST, Arrays.asList(WifiSsid.fromUtf8Text("SSID"))); @@ -10444,7 +10527,7 @@ public class WifiServiceImplTest extends WifiBaseTest { anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); when(mActiveModeWarden.getClientModeManagers()).thenReturn( Collections.singletonList(mClientModeManager)); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST, Arrays.asList(WifiSsid.fromUtf8Text(TEST_SSID))); @@ -10469,7 +10552,7 @@ public class WifiServiceImplTest extends WifiBaseTest { anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); when(mActiveModeWarden.getClientModeManagers()).thenReturn( Collections.singletonList(mClientModeManager)); - when(mClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyMinimumRequiredWifiSecurityLevelChanged( DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP); @@ -10679,4 +10762,27 @@ public class WifiServiceImplTest extends WifiBaseTest { assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME, mAttribution)); } + + /** + * Tests that {@link WifiServiceImpl#getCurrentNetwork} throws + * {@link SecurityException} if the caller doesn't have the necessary permissions. + */ + @Test(expected = SecurityException.class) + public void testGetCurrentNetworkNoPermission() throws Exception { + doThrow(SecurityException.class) + .when(mContext).enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE), any()); + mWifiServiceImpl.getCurrentNetwork(); + } + + /** + * Verifies that WifiServiceImpl#getCurrentNetwork() returns the current Wifi network. + */ + @Test + public void testGetCurrentNetworkWithNetworkSettingsPermission() throws Exception { + when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), + anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); + Network mockNetwork = mock(Network.class); + when(mActiveModeWarden.getCurrentNetwork()).thenReturn(mockNetwork); + assertEquals(mockNetwork, mWifiServiceImpl.getCurrentNetwork()); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiSettingsStoreTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiSettingsStoreTest.java index a825882100..0f78f921af 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiSettingsStoreTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiSettingsStoreTest.java @@ -38,6 +38,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -52,6 +53,7 @@ import android.provider.Settings; import androidx.test.filters.SmallTest; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.wifi.resources.R; import org.junit.Before; @@ -139,7 +141,8 @@ public class WifiSettingsStoreTest extends WifiBaseTest { Settings.Global.WIFI_ON, WIFI_ENABLED_APM_OVERRIDE); verify(mFrameworkFacade).setSecureIntegerSetting( mContext, WIFI_APM_STATE, WIFI_REMAINS_ON_IN_APM); - verify(mNotificationManager).notify(anyInt(), any(Notification.class)); + verify(mNotificationManager).notify(eq(SystemMessage.NOTE_WIFI_APM_NOTIFICATION), + any(Notification.class)); verify(mFrameworkFacade).setSecureIntegerSetting( mContext, APM_WIFI_ENABLED_NOTIFICATION, NOTIFICATION_SHOWN); @@ -176,7 +179,8 @@ public class WifiSettingsStoreTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mFrameworkFacade).setIntegerSetting(mContentResolver, Settings.Global.WIFI_ON, WIFI_ENABLED_APM_OVERRIDE); - verify(mNotificationManager, never()).notify(anyInt(), any(Notification.class)); + verify(mNotificationManager, never()).notify(eq(SystemMessage.NOTE_WIFI_APM_NOTIFICATION), + any(Notification.class)); verify(mFrameworkFacade, never()).setSecureIntegerSetting( mContext, APM_WIFI_NOTIFICATION, NOTIFICATION_SHOWN); @@ -187,7 +191,8 @@ public class WifiSettingsStoreTest extends WifiBaseTest { mWifiSettingsStore.handleAirplaneModeToggled(); mLooper.dispatchAll(); - verify(mNotificationManager).notify(anyInt(), any(Notification.class)); + verify(mNotificationManager).notify(eq(SystemMessage.NOTE_WIFI_APM_NOTIFICATION), + any(Notification.class)); verify(mFrameworkFacade).setSecureIntegerSetting( mContext, APM_WIFI_NOTIFICATION, NOTIFICATION_SHOWN); 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 a522d0531a..f0767e20d1 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java @@ -167,16 +167,12 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"get-ipreach-disconnect"}); verify(mWifiGlobals).getIpReachabilityDisconnectEnabled(); - mWifiShellCommand.getOutPrintWriter().toString().contains( - "IPREACH_DISCONNECT state is true"); when(mWifiGlobals.getIpReachabilityDisconnectEnabled()).thenReturn(false); mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"get-ipreach-disconnect"}); verify(mWifiGlobals, times(2)).getIpReachabilityDisconnectEnabled(); - mWifiShellCommand.getOutPrintWriter().toString().contains( - "IPREACH_DISCONNECT state is false"); } @Test @@ -219,8 +215,6 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"get-poll-rssi-interval-msecs"}); verify(mWifiGlobals).getPollRssiIntervalMillis(); - mWifiShellCommand.getOutPrintWriter().toString().contains( - "WifiGlobals.getPollRssiIntervalMillis() = 5"); } @Test @@ -348,7 +342,6 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"network-suggestions-has-user-approved", TEST_PACKAGE}); verify(mWifiNetworkSuggestionsManager).hasUserApprovedForApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("yes"); when(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE)) .thenReturn(false); @@ -356,7 +349,6 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"network-suggestions-has-user-approved", TEST_PACKAGE}); verify(mWifiNetworkSuggestionsManager, times(2)).hasUserApprovedForApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("no"); } @Test @@ -405,7 +397,6 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"imsi-protection-exemption-has-user-approved-for-carrier", "5"}); verify(mWifiCarrierInfoManager).hasUserApprovedImsiPrivacyExemptionForCarrier(5); - mWifiShellCommand.getOutPrintWriter().toString().contains("yes"); when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(5)) .thenReturn(false); @@ -413,7 +404,6 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"imsi-protection-exemption-has-user-approved-for-carrier", "5"}); verify(mWifiCarrierInfoManager, times(2)).hasUserApprovedImsiPrivacyExemptionForCarrier(5); - mWifiShellCommand.getOutPrintWriter().toString().contains("no"); } @Test @@ -456,7 +446,6 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"network-requests-has-user-approved", TEST_PACKAGE}); verify(mWifiNetworkFactory).hasUserApprovedApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("yes"); when(mWifiNetworkFactory.hasUserApprovedApp(TEST_PACKAGE)) .thenReturn(false); @@ -464,7 +453,6 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"network-requests-has-user-approved", TEST_PACKAGE}); verify(mWifiNetworkFactory, times(2)).hasUserApprovedApp(TEST_PACKAGE); - mWifiShellCommand.getOutPrintWriter().toString().contains("no"); } @Test @@ -738,7 +726,7 @@ public class WifiShellCommandTest extends WifiBaseTest { verify(mWifiService).isScanAlwaysAvailable(); verify(mWifiService).getConnectionInfo(SHELL_PACKAGE_NAME, null); - verify(mPrimaryClientModeManager, never()).syncRequestConnectionInfo(); + verify(mPrimaryClientModeManager, never()).getConnectionInfo(); verify(mActiveModeWarden, never()).getClientModeManagers(); // rooted shell. @@ -750,17 +738,17 @@ public class WifiShellCommandTest extends WifiBaseTest { WifiInfo wifiInfo = new WifiInfo(); wifiInfo.setSupplicantState(SupplicantState.COMPLETED); - when(mPrimaryClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); - when(additionalClientModeManager.syncRequestConnectionInfo()).thenReturn(wifiInfo); + when(mPrimaryClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); + when(additionalClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"status"}); verify(mActiveModeWarden).getClientModeManagers(); - verify(mPrimaryClientModeManager).syncRequestConnectionInfo(); - verify(mPrimaryClientModeManager).syncGetCurrentNetwork(); - verify(additionalClientModeManager).syncRequestConnectionInfo(); - verify(additionalClientModeManager).syncGetCurrentNetwork(); + verify(mPrimaryClientModeManager).getConnectionInfo(); + verify(mPrimaryClientModeManager).getCurrentNetwork(); + verify(additionalClientModeManager).getConnectionInfo(); + verify(additionalClientModeManager).getCurrentNetwork(); } @Test 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 273fe7d156..47c423736d 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java @@ -26,20 +26,14 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyByte; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.anyShort; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -53,55 +47,13 @@ import android.app.test.MockAnswerUtil.AnswerWithArguments; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; -import android.hardware.wifi.V1_0.IWifiApIface; -import android.hardware.wifi.V1_0.IWifiChip; -import android.hardware.wifi.V1_0.IWifiChipEventCallback; -import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiStaIface; -import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; -import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.StaApfPacketFilterCapabilities; -import android.hardware.wifi.V1_0.StaBackgroundScanCapabilities; -import android.hardware.wifi.V1_0.StaBackgroundScanParameters; -import android.hardware.wifi.V1_0.StaLinkLayerIfacePacketStats; -import android.hardware.wifi.V1_0.StaLinkLayerIfaceStats; -import android.hardware.wifi.V1_0.StaLinkLayerRadioStats; -import android.hardware.wifi.V1_0.StaLinkLayerStats; -import android.hardware.wifi.V1_0.StaRoamingCapabilities; -import android.hardware.wifi.V1_0.StaRoamingConfig; -import android.hardware.wifi.V1_0.StaRoamingState; -import android.hardware.wifi.V1_0.StaScanData; -import android.hardware.wifi.V1_0.StaScanDataFlagMask; -import android.hardware.wifi.V1_0.StaScanResult; -import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; -import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; -import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; -import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; -import android.hardware.wifi.V1_0.WifiDebugRingBufferVerboseLevel; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; -import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; -import android.hardware.wifi.V1_0.WifiInformationElement; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_2.IWifiChipEventCallback.IfaceInfo; -import android.hardware.wifi.V1_2.IWifiChipEventCallback.RadioModeInfo; -import android.hardware.wifi.V1_3.WifiChannelStats; -import android.hardware.wifi.V1_5.IWifiChip.MultiStaUseCase; -import android.hardware.wifi.V1_5.StaLinkLayerIfaceContentionTimeStats; -import android.hardware.wifi.V1_5.StaPeerInfo; -import android.hardware.wifi.V1_5.StaRateStat; -import android.hardware.wifi.V1_5.WifiUsableChannel; import android.net.InetAddresses; import android.net.KeepalivePacketData; import android.net.MacAddress; import android.net.NattKeepalivePacketData; import android.net.apf.ApfCapabilities; -import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiAvailableChannel; import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; @@ -110,25 +62,21 @@ import android.os.RemoteException; import android.os.WorkSource; import android.os.test.TestLooper; import android.system.OsConstants; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; -import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; -import com.android.server.wifi.WifiLinkLayerStats.ChannelStats; -import com.android.server.wifi.WifiLinkLayerStats.RadioStat; -import com.android.server.wifi.WifiNative.RoamingCapabilities; -import com.android.server.wifi.WifiNative.RxFateReport; -import com.android.server.wifi.WifiNative.TxFateReport; +import com.android.server.wifi.hal.WifiApIface; +import com.android.server.wifi.hal.WifiChip; +import com.android.server.wifi.hal.WifiHal; +import com.android.server.wifi.hal.WifiStaIface; import com.android.server.wifi.util.NativeUtil; import com.android.wifi.resources.R; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; @@ -147,18 +95,12 @@ import java.util.Set; */ @SmallTest public class WifiVendorHalTest extends WifiBaseTest { - private static final String TEST_IFACE_NAME = "wlan0"; private static final String TEST_IFACE_NAME_1 = "wlan1"; private static final MacAddress TEST_MAC_ADDRESS = MacAddress.fromString("ee:33:a2:94:10:92"); - private static final int[] TEST_FREQUENCIES = - {2412, 2417, 2422, 2427, 2432, 2437}; private static final WorkSource TEST_WORKSOURCE = new WorkSource(); private WifiVendorHal mWifiVendorHal; - private WifiStatus mWifiStatusSuccess; - private WifiStatus mWifiStatusFailure; - private WifiStatus mWifiStatusBusy; private WifiLog mWifiLog; private TestLooper mLooper; private Handler mHandler; @@ -173,35 +115,13 @@ public class WifiVendorHalTest extends WifiBaseTest { @Mock private WifiVendorHal.HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; @Mock - private IWifiApIface mIWifiApIface; - @Mock - private android.hardware.wifi.V1_4.IWifiApIface mIWifiApIfaceV14; - @Mock - private android.hardware.wifi.V1_5.IWifiApIface mIWifiApIfaceV15; - @Mock - private IWifiChip mIWifiChip; - @Mock - private android.hardware.wifi.V1_1.IWifiChip mIWifiChipV11; - @Mock - private android.hardware.wifi.V1_2.IWifiChip mIWifiChipV12; - @Mock - private android.hardware.wifi.V1_3.IWifiChip mIWifiChipV13; + private WifiApIface mWifiApIface; @Mock - private android.hardware.wifi.V1_4.IWifiChip mIWifiChipV14; + private WifiChip mWifiChip; @Mock - private android.hardware.wifi.V1_5.IWifiChip mIWifiChipV15; - @Mock - private IWifiStaIface mIWifiStaIface; - @Mock - private android.hardware.wifi.V1_2.IWifiStaIface mIWifiStaIfaceV12; - @Mock - private android.hardware.wifi.V1_3.IWifiStaIface mIWifiStaIfaceV13; - @Mock - private android.hardware.wifi.V1_5.IWifiStaIface mIWifiStaIfaceV15; - private IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; - private IWifiChipEventCallback mIWifiChipEventCallback; - private android.hardware.wifi.V1_2.IWifiChipEventCallback mIWifiChipEventCallbackV12; - private android.hardware.wifi.V1_4.IWifiChipEventCallback mIWifiChipEventCallbackV14; + private WifiStaIface mWifiStaIface; + private WifiStaIface.Callback mWifiStaIfaceEventCallback; + private WifiChip.Callback mWifiChipEventCallback; @Mock private WifiNative.VendorHalDeathEventHandler mVendorHalDeathHandler; @Mock @@ -213,144 +133,7 @@ public class WifiVendorHalTest extends WifiBaseTest { @Mock private SsidTranslator mSsidTranslator; - /** - * Spy used to return the V1_1 IWifiChip mock object to simulate the 1.1 HAL running on the - * device. - */ - private class WifiVendorHalSpyV1_1 extends WifiVendorHal { - WifiVendorHalSpyV1_1(Context context, HalDeviceManager halDeviceManager, Handler handler, - WifiGlobals wifiGlobals, - @NonNull SsidTranslator ssidTranslator) { - super(context, halDeviceManager, handler, wifiGlobals, ssidTranslator); - } - - @Override - protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { - return mIWifiChipV11; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - return null; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - String ifaceName) { - return null; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - String ifaceName) { - return null; - } - - @Override - protected android.hardware.wifi.V1_5.IWifiStaIface getWifiStaIfaceForV1_5Mockable( - String ifaceName) { - return null; - } - } - - /** - * Spy used to return the V1_2 IWifiChip and IWifiStaIface mock objects to simulate - * the 1.2 HAL running on the device. - */ - private class WifiVendorHalSpyV1_2 extends WifiVendorHalSpyV1_1 { - WifiVendorHalSpyV1_2(Context context, HalDeviceManager halDeviceManager, Handler handler, - WifiGlobals wifiGlobals) { - super(context, halDeviceManager, handler, wifiGlobals, mSsidTranslator); - } - - @Override - protected android.hardware.wifi.V1_2.IWifiChip getWifiChipForV1_2Mockable() { - return mIWifiChipV12; - } - - @Override - protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceForV1_2Mockable( - String ifaceName) { - return mIWifiStaIfaceV12; - } - } - - /** - * Spy used to return the V1_3 IWifiChip and V1_3 IWifiStaIface mock objects to simulate - * the 1.3 HAL running on the device. - */ - private class WifiVendorHalSpyV1_3 extends WifiVendorHalSpyV1_2 { - WifiVendorHalSpyV1_3(Context context, HalDeviceManager halDeviceManager, Handler handler, - WifiGlobals wifiGlobals) { - super(context, halDeviceManager, handler, wifiGlobals); - } - - @Override - protected android.hardware.wifi.V1_3.IWifiChip getWifiChipForV1_3Mockable() { - return mIWifiChipV13; - } - - @Override - protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceForV1_3Mockable( - String ifaceName) { - return mIWifiStaIfaceV13; - } - } - - /** - * Spy used to return the V1_4 IWifiChip and V1_4 IWifiStaIface mock objects to simulate - * the 1.4 HAL running on the device. - */ - private class WifiVendorHalSpyV1_4 extends WifiVendorHalSpyV1_3 { - WifiVendorHalSpyV1_4(Context context, HalDeviceManager halDeviceManager, Handler handler, - WifiGlobals wifiGlobals) { - super(context, halDeviceManager, handler, wifiGlobals); - } - - @Override - protected android.hardware.wifi.V1_4.IWifiChip getWifiChipForV1_4Mockable() { - return mIWifiChipV14; - } - } - - /** - * Spy used to return the V1_5 IWifiChip and V1_5 IWifiStaIface mock objects to simulate - * the 1.5 HAL running on the device. - */ - private class WifiVendorHalSpyV1_5 extends WifiVendorHalSpyV1_4 { - WifiVendorHalSpyV1_5(Context context, HalDeviceManager halDeviceManager, Handler handler, - WifiGlobals wifiGlobals) { - super(context, halDeviceManager, handler, wifiGlobals); - } - - @Override - protected android.hardware.wifi.V1_5.IWifiChip getWifiChipForV1_5Mockable() { - return mIWifiChipV15; - } - - @Override - protected android.hardware.wifi.V1_5.IWifiStaIface getWifiStaIfaceForV1_5Mockable( - String ifaceName) { - return mIWifiStaIfaceV15; - } - } - - /** - * Identity function to supply a type to its argument, which is a lambda - */ - static Answer<WifiStatus> answerWifiStatus(Answer<WifiStatus> statusLambda) { - return (statusLambda); - } + private ArgumentCaptor<List> mListCaptor = ArgumentCaptor.forClass(List.class); /** * Sets up for unit test @@ -361,15 +144,7 @@ public class WifiVendorHalTest extends WifiBaseTest { mWifiLog = new FakeWifiLog(); mLooper = new TestLooper(); mHandler = new Handler(mLooper.getLooper()); - mWifiStatusSuccess = new WifiStatus(); - mWifiStatusSuccess.code = WifiStatusCode.SUCCESS; - mWifiStatusFailure = new WifiStatus(); - mWifiStatusFailure.code = WifiStatusCode.ERROR_UNKNOWN; - mWifiStatusFailure.description = "I don't even know what a Mock Turtle is."; - mWifiStatusBusy = new WifiStatus(); - mWifiStatusBusy.code = WifiStatusCode.ERROR_BUSY; - mWifiStatusBusy.description = "Don't bother me, kid"; - when(mIWifiStaIface.enableLinkLayerStatsCollection(false)).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.enableLinkLayerStatsCollection(false)).thenReturn(true); // Setup the HalDeviceManager mock's start/stop behaviour. This can be overridden in // individual tests, if needed. @@ -392,59 +167,32 @@ public class WifiVendorHalTest extends WifiBaseTest { } }).when(mHalDeviceManager).stop(); when(mHalDeviceManager.createStaIface(any(), any(), any())) - .thenReturn(mIWifiStaIface); + .thenReturn(mWifiStaIface); when(mHalDeviceManager.createApIface(anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager))) - .thenReturn(mIWifiApIface); + .thenReturn(mWifiApIface); when(mHalDeviceManager.removeIface(any())).thenReturn(true); - when(mHalDeviceManager.getChip(any(IWifiIface.class))) - .thenReturn(mIWifiChip); + when(mHalDeviceManager.getChip(any(WifiHal.WifiInterface.class))) + .thenReturn(mWifiChip); when(mHalDeviceManager.isSupported()).thenReturn(true); - when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class))) - .thenReturn(mWifiStatusSuccess); - mIWifiStaIfaceEventCallback = null; - when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiStaIfaceEventCallback = (IWifiStaIfaceEventCallback) args[0]; - return (mWifiStatusSuccess); - })); - when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiChipEventCallback = (IWifiChipEventCallback) args[0]; - return (mWifiStatusSuccess); - })); - when(mIWifiChipV12.registerEventCallback_1_2( - any(android.hardware.wifi.V1_2.IWifiChipEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiChipEventCallbackV12 = - (android.hardware.wifi.V1_2.IWifiChipEventCallback) args[0]; - return (mWifiStatusSuccess); - })); - - when(mIWifiChipV14.registerEventCallback_1_4( - any(android.hardware.wifi.V1_4.IWifiChipEventCallback.class))) - .thenAnswer(answerWifiStatus((invocation) -> { - Object[] args = invocation.getArguments(); - mIWifiChipEventCallbackV14 = - (android.hardware.wifi.V1_4.IWifiChipEventCallback) args[0]; - return (mWifiStatusSuccess); - })); + when(mWifiChip.registerCallback(any(WifiChip.Callback.class))) + .thenReturn(true); + mWifiStaIfaceEventCallback = null; doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, TEST_IFACE_NAME); + public boolean answer(WifiStaIface.Callback callback) { + mWifiStaIfaceEventCallback = callback; + return true; } - }).when(mIWifiStaIface).getName(any(IWifiIface.getNameCallback.class)); + }).when(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class)); doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, TEST_IFACE_NAME); + public boolean answer(WifiChip.Callback callback) { + mWifiChipEventCallback = callback; + return true; } - }).when(mIWifiApIface).getName(any(IWifiIface.getNameCallback.class)); + }).when(mWifiChip).registerCallback(any(WifiChip.Callback.class)); + when(mWifiStaIface.getName()).thenReturn(TEST_IFACE_NAME); + when(mWifiApIface.getName()).thenReturn(TEST_IFACE_NAME); when(mContext.getResources()).thenReturn(mResources); when(mResources.getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled)) @@ -493,11 +241,11 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).start(); verify(mHalDeviceManager).createStaIface(any(), any(), any()); - verify(mHalDeviceManager).getChip(eq(mIWifiStaIface)); + verify(mHalDeviceManager).getChip(eq(mWifiStaIface)); verify(mHalDeviceManager).isReady(); verify(mHalDeviceManager).isStarted(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); + verify(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class)); + verify(mWifiChip).registerCallback(any(WifiChip.Callback.class)); verify(mHalDeviceManager, never()).createApIface( anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager)); @@ -524,9 +272,9 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager, never()).createStaIface(any(), any(), any()); verify(mHalDeviceManager, never()).createApIface( anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager)); - verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class)); - verify(mIWifiStaIface, never()) - .registerEventCallback(any(IWifiStaIfaceEventCallback.class)); + verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class)); + verify(mWifiStaIface, never()) + .registerFrameworkCallback(any(WifiStaIface.Callback.class)); } /** @@ -545,9 +293,9 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager, never()).createApIface( anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager)); - verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class)); - verify(mIWifiStaIface, never()) - .registerEventCallback(any(IWifiStaIfaceEventCallback.class)); + verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class)); + verify(mWifiStaIface, never()) + .registerFrameworkCallback(any(WifiStaIface.Callback.class)); } /** @@ -556,15 +304,15 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testStartHalFailureInChipGetInStaMode() throws Exception { - when(mHalDeviceManager.getChip(any(IWifiIface.class))).thenReturn(null); + when(mHalDeviceManager.getChip(any(WifiHal.WifiInterface.class))).thenReturn(null); assertFalse(mWifiVendorHal.startVendorHalSta()); assertFalse(mWifiVendorHal.isHalStarted()); verify(mHalDeviceManager).start(); verify(mHalDeviceManager).createStaIface(any(), any(), any()); - verify(mHalDeviceManager).getChip(any(IWifiIface.class)); + verify(mHalDeviceManager).getChip(any(WifiHal.WifiInterface.class)); verify(mHalDeviceManager).stop(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); + verify(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class)); verify(mHalDeviceManager, never()).createApIface( anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager)); @@ -576,17 +324,17 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testStartHalFailureInStaIfaceCallbackRegistration() throws Exception { - when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class))) - .thenReturn(mWifiStatusFailure); + when(mWifiStaIface.registerFrameworkCallback(any(WifiStaIface.Callback.class))) + .thenReturn(false); assertFalse(mWifiVendorHal.startVendorHalSta()); assertFalse(mWifiVendorHal.isHalStarted()); verify(mHalDeviceManager).start(); verify(mHalDeviceManager).createStaIface(any(), any(), any()); verify(mHalDeviceManager).stop(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); + verify(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class)); - verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class)); + verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class)); verify(mHalDeviceManager, never()).createApIface( anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager)); } @@ -597,17 +345,17 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testStartHalFailureInChipCallbackRegistration() throws Exception { - when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class))) - .thenReturn(mWifiStatusFailure); + when(mWifiChip.registerCallback(any(WifiChip.Callback.class))) + .thenReturn(false); assertFalse(mWifiVendorHal.startVendorHalSta()); assertFalse(mWifiVendorHal.isHalStarted()); verify(mHalDeviceManager).start(); verify(mHalDeviceManager).createStaIface(any(), any(), any()); - verify(mHalDeviceManager).getChip(any(IWifiIface.class)); + verify(mHalDeviceManager).getChip(any(WifiHal.WifiInterface.class)); verify(mHalDeviceManager).stop(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); + verify(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class)); + verify(mWifiChip).registerCallback(any(WifiChip.Callback.class)); verify(mHalDeviceManager, never()).createApIface( anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager)); @@ -628,7 +376,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).start(); verify(mHalDeviceManager).stop(); verify(mHalDeviceManager).createStaIface(any(), any(), any()); - verify(mHalDeviceManager).getChip(eq(mIWifiStaIface)); + verify(mHalDeviceManager).getChip(eq(mWifiStaIface)); verify(mHalDeviceManager, times(2)).isReady(); verify(mHalDeviceManager, times(2)).isStarted(); @@ -655,7 +403,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).stop(); verify(mHalDeviceManager).createApIface( anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager)); - verify(mHalDeviceManager).getChip(eq(mIWifiApIface)); + verify(mHalDeviceManager).getChip(eq(mWifiApIface)); verify(mHalDeviceManager, times(2)).isReady(); verify(mHalDeviceManager, times(2)).isStarted(); @@ -678,11 +426,11 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).start(); verify(mHalDeviceManager).createStaIface(internalListenerCaptor.capture(), any(), eq(TEST_WORKSOURCE)); - verify(mHalDeviceManager).getChip(eq(mIWifiStaIface)); + verify(mHalDeviceManager).getChip(eq(mWifiStaIface)); verify(mHalDeviceManager).isReady(); verify(mHalDeviceManager).isStarted(); - verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class)); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); + verify(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class)); + verify(mWifiChip).registerCallback(any(WifiChip.Callback.class)); // Now trigger the interface destroyed callback from HalDeviceManager and ensure the // external listener is invoked and iface removed from internal database. @@ -713,10 +461,10 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).createApIface(anyLong(), internalListenerCaptor.capture(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager)); - verify(mHalDeviceManager).getChip(eq(mIWifiApIface)); + verify(mHalDeviceManager).getChip(eq(mWifiApIface)); verify(mHalDeviceManager).isReady(); verify(mHalDeviceManager).isStarted(); - verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class)); + verify(mWifiChip).registerCallback(any(WifiChip.Callback.class)); // Now trigger the interface destroyed callback from HalDeviceManager and ensure the // external listener is invoked and iface removed from internal database. @@ -753,19 +501,6 @@ public class WifiVendorHalTest extends WifiBaseTest { } /** - * Test that boolResult logs a false result - */ - @Test - public void testBoolResultFalse() { - mWifiLog = spy(mWifiLog); - mWifiVendorHal.mLog = mWifiLog; - mWifiVendorHal.mVerboseLog = mWifiLog; - assertFalse(mWifiVendorHal.getBgScanCapabilities( - TEST_IFACE_NAME, new WifiNative.ScanCapabilities())); - verify(mWifiLog).err("% returns %"); - } - - /** * Test that getBgScanCapabilities is hooked up to the HAL correctly * * A call before the vendor HAL is started should return a non-null result with version 0 @@ -774,19 +509,12 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testGetBgScanCapabilities() throws Exception { - StaBackgroundScanCapabilities capabilities = new StaBackgroundScanCapabilities(); - capabilities.maxCacheSize = 12; - capabilities.maxBuckets = 34; - capabilities.maxApCachePerScan = 56; - capabilities.maxReportingThreshold = 78; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getBackgroundScanCapabilitiesCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, capabilities); - } - }).when(mIWifiStaIface).getBackgroundScanCapabilities(any( - IWifiStaIface.getBackgroundScanCapabilitiesCallback.class)); + WifiNative.ScanCapabilities capabilities = new WifiNative.ScanCapabilities(); + capabilities.max_scan_cache_size = 12; + capabilities.max_scan_buckets = 34; + capabilities.max_ap_cache_per_scan = 56; + capabilities.max_scan_reporting_threshold = 78; + when(mWifiStaIface.getBackgroundScanCapabilities()).thenReturn(capabilities); WifiNative.ScanCapabilities result = new WifiNative.ScanCapabilities(); @@ -804,96 +532,29 @@ public class WifiVendorHalTest extends WifiBaseTest { } /** - * Test translation to WifiManager.WIFI_FEATURE_* - * - * Just do a spot-check with a few feature bits here; since the code is table- - * driven we don't have to work hard to exercise all of it. - */ - @Test - public void testStaIfaceFeatureMaskTranslation() { - int caps = ( - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN - | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - ); - long expected = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); - assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps)); - } - - /** - * Test translation to WifiManager.WIFI_FEATURE_* - * - * Just do a spot-check with a few feature bits here; since the code is table- - * driven we don't have to work hard to exercise all of it. - */ - @Test - public void testChipFeatureMaskTranslation() { - int caps = ( - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT - | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT - | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT - ); - long expected = ( - WifiManager.WIFI_FEATURE_TX_POWER_LIMIT - | WifiManager.WIFI_FEATURE_D2D_RTT - | WifiManager.WIFI_FEATURE_D2AP_RTT - ); - assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromChipCapabilities(caps)); - } - - /** - * Test translation to WifiManager.WIFI_FEATURE_* for V1.3 - * - * Test the added features in V1.3 + * Test get supported features. Tests whether we coalesce information from different sources + * (IWifiStaIface, IWifiChip and HalDeviceManager) into the bitmask of supported features + * correctly. */ @Test - public void testChipFeatureMaskTranslation_1_3() { - int caps = ( - android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE - | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT - ); - long expected = ( - WifiManager.WIFI_FEATURE_LOW_LATENCY - | WifiManager.WIFI_FEATURE_D2D_RTT - ); - assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromChipCapabilities_1_3(caps)); - } - - private void testGetSupportedFeaturesCommon( - int staIfaceHidlCaps, int chipHidlCaps, long expectedFeatureSet) throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); + 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); + chipCapsResponse.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); + when(mWifiStaIface.getCapabilities()).thenReturn(staIfaceCaps); + when(mWifiChip.getCapabilitiesAfterIfacesExist()).thenReturn(chipCapsResponse); Set<Integer> halDeviceManagerSupportedIfaces = new HashSet<Integer>() {{ - add(IfaceType.STA); - add(IfaceType.P2P); + add(WifiChip.IFACE_TYPE_STA); + add(WifiChip.IFACE_TYPE_P2P); }}; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getCapabilitiesCallback cb) throws RemoteException { - cb.onValues(mWifiStatusSuccess, staIfaceHidlCaps); - } - }).when(mIWifiStaIface).getCapabilities(any(IWifiStaIface.getCapabilitiesCallback.class)); - when(mHalDeviceManager.getSupportedIfaceTypes()) .thenReturn(halDeviceManagerSupportedIfaces); - - assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)); - } - /** - * Test get supported features. Tests whether we coalesce information from different sources - * (IWifiStaIface, IWifiChip and HalDeviceManager) into the bitmask of supported features - * correctly. - */ - @Test - public void testGetSupportedFeatures() throws Exception { - int staIfaceHidlCaps = ( - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN - | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - ); - int chipHidlCaps = - android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT; when(mWifiGlobals.isWpa3SaeH2eSupported()).thenReturn(true); + when(mHalDeviceManager.is24g5gDbsSupported(any())).thenReturn(true); + long expectedFeatureSet = ( WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS @@ -901,92 +562,10 @@ public class WifiVendorHalTest extends WifiBaseTest { | WifiManager.WIFI_FEATURE_INFRA | WifiManager.WIFI_FEATURE_P2P | WifiManager.WIFI_FEATURE_SAE_H2E + | WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS ); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getCapabilitiesCallback cb) throws RemoteException { - cb.onValues(mWifiStatusSuccess, chipHidlCaps); - } - }).when(mIWifiChip).getCapabilities(any(IWifiChip.getCapabilitiesCallback.class)); - - mWifiVendorHal = new WifiVendorHalSpyV1_1(mContext, mHalDeviceManager, mHandler, - mWifiGlobals, mSsidTranslator); - testGetSupportedFeaturesCommon(staIfaceHidlCaps, chipHidlCaps, expectedFeatureSet); - } - - /** - * Test get supported features. Tests whether we coalesce information from different sources - * (IWifiStaIface, IWifiChip and HalDeviceManager) into the bitmask of supported features - * correctly. - */ - @Test - public void testGetSupportedFeaturesForHalV1_3() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - - int staIfaceHidlCaps = ( - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN - | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - ); - int chipHidlCaps = - android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE - | android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.P2P_RAND_MAC; - long expectedFeatureSet = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS - | WifiManager.WIFI_FEATURE_LOW_LATENCY - | WifiManager.WIFI_FEATURE_P2P_RAND_MAC - | WifiManager.WIFI_FEATURE_INFRA - | WifiManager.WIFI_FEATURE_P2P - ); - - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_3.IWifiChip.getCapabilities_1_3Callback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, chipHidlCaps); - } - }).when(mIWifiChipV13).getCapabilities_1_3( - any(android.hardware.wifi.V1_3.IWifiChip.getCapabilities_1_3Callback.class)); - - mWifiVendorHal = new WifiVendorHalSpyV1_3(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - testGetSupportedFeaturesCommon(staIfaceHidlCaps, chipHidlCaps, expectedFeatureSet); - } - - /** - * Test get supported features. Tests whether we coalesce information from different sources - * (IWifiStaIface, IWifiChip and HalDeviceManager) into the bitmask of supported features - * correctly. - */ - @Test - public void testGetSupportedFeaturesForHalV1_5() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - - int staIfaceHidlCaps = ( - IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN - | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS - ); - int chipHidlCaps = android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG; - long expectedFeatureSet = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS - | WifiManager.WIFI_FEATURE_INFRA_60G - | WifiManager.WIFI_FEATURE_INFRA - | WifiManager.WIFI_FEATURE_P2P - ); - - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_5.IWifiChip.getCapabilities_1_5Callback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, chipHidlCaps); - } - }).when(mIWifiChipV15).getCapabilities_1_5( - any(android.hardware.wifi.V1_5.IWifiChip.getCapabilities_1_5Callback.class)); - - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - testGetSupportedFeaturesCommon(staIfaceHidlCaps, chipHidlCaps, expectedFeatureSet); + assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)); } /** @@ -1016,56 +595,10 @@ public class WifiVendorHalTest extends WifiBaseTest { | WifiManager.WIFI_FEATURE_P2P | WifiManager.WIFI_FEATURE_AWARE ); - - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)); } /** - * Test |getFactoryMacAddress| gets called when the hal version is V1_3 - * @throws Exception - */ - @Test - public void testGetStaFactoryMacWithHalV1_3() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_3.IWifiStaIface.getFactoryMacAddressCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, MacAddress.BROADCAST_ADDRESS.toByteArray()); - } - }).when(mIWifiStaIfaceV13).getFactoryMacAddress(any( - android.hardware.wifi.V1_3.IWifiStaIface.getFactoryMacAddressCallback.class)); - mWifiVendorHal = new WifiVendorHalSpyV1_3(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - assertEquals(MacAddress.BROADCAST_ADDRESS.toString(), - mWifiVendorHal.getStaFactoryMacAddress(TEST_IFACE_NAME).toString()); - verify(mIWifiStaIfaceV13).getFactoryMacAddress(any()); - } - - /** - * Test getLinkLayerStats_1_3 gets called when the hal version is V1_3. - */ - @Test - public void testLinkLayerStatsCorrectVersionWithHalV1_3() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_3(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - mWifiVendorHal.getWifiLinkLayerStats(TEST_IFACE_NAME); - verify(mIWifiStaIfaceV13).getLinkLayerStats_1_3(any()); - } - - /** - * Test getLinkLayerStats_1_5 gets called when the hal version is V1_5. - */ - @Test - public void testLinkLayerStatsCorrectVersionWithHalV1_5() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - mWifiVendorHal.getWifiLinkLayerStats(TEST_IFACE_NAME); - verify(mIWifiStaIfaceV15).getLinkLayerStats_1_5(any()); - } - - /** * Test that link layer stats are not enabled and harmless in AP mode * * Start the HAL in AP mode @@ -1075,7 +608,7 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testLinkLayerStatsNotEnabledAndHarmlessInApMode() throws Exception { - doNothing().when(mIWifiStaIface).getLinkLayerStats(any()); + when(mWifiStaIface.getLinkLayerStats()).thenReturn(null); assertTrue(mWifiVendorHal.startVendorHal()); assertNotNull(mWifiVendorHal.createApIface(null, null, @@ -1085,548 +618,8 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).start(); - verify(mIWifiStaIface, never()).enableLinkLayerStatsCollection(false); - verify(mIWifiStaIface, never()).getLinkLayerStats(any()); - } - - /** - * Test that the link layer stats fields are populated correctly. - * - * This is done by filling Hal LinkLayerStats (V1_0) with random values, converting it to - * WifiLinkLayerStats and then asserting the values in the original structure are equal to the - * values in the converted structure. - */ - @Test - public void testLinkLayerStatsAssignment() throws Exception { - Random r = new Random(1775968256); - StaLinkLayerStats stats = new StaLinkLayerStats(); - randomizePacketStats(r, stats.iface.wmeBePktStats); - randomizePacketStats(r, stats.iface.wmeBkPktStats); - randomizePacketStats(r, stats.iface.wmeViPktStats); - randomizePacketStats(r, stats.iface.wmeVoPktStats); - randomizeRadioStats(r, stats.radios); - stats.timeStampInMs = r.nextLong() & 0xFFFFFFFFFFL; - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats(stats); - - verifyIFaceStats(stats.iface, converted); - verifyRadioStats(stats.radios, converted); - assertEquals(stats.timeStampInMs, converted.timeStampInMs); - assertEquals(WifiLinkLayerStats.V1_0, converted.version); - } - - /** - * Test that the link layer stats V1_3 fields are populated correctly. - * - * This is done by filling Hal LinkLayerStats (V1_3) with random values, converting it to - * WifiLinkLayerStats and then asserting the values in the original structure are equal to the - * values in the converted structure. - */ - @Test - public void testLinkLayerStatsAssignment_1_3() throws Exception { - Random r = new Random(1775968256); - android.hardware.wifi.V1_3.StaLinkLayerStats stats = - new android.hardware.wifi.V1_3.StaLinkLayerStats(); - randomizePacketStats(r, stats.iface.wmeBePktStats); - randomizePacketStats(r, stats.iface.wmeBkPktStats); - randomizePacketStats(r, stats.iface.wmeViPktStats); - randomizePacketStats(r, stats.iface.wmeVoPktStats); - android.hardware.wifi.V1_3.StaLinkLayerRadioStats rstat = - new android.hardware.wifi.V1_3.StaLinkLayerRadioStats(); - randomizeRadioStats_1_3(r, rstat); - stats.radios.add(rstat); - stats.timeStampInMs = r.nextLong() & 0xFFFFFFFFFFL; - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats_1_3(stats); - - verifyIFaceStats(stats.iface, converted); - verifyRadioStats_1_3(stats.radios.get(0), converted); - assertEquals(stats.timeStampInMs, converted.timeStampInMs); - assertEquals(WifiLinkLayerStats.V1_3, converted.version); - assertEquals(1, converted.numRadios); - } - - /** - * Test that the link layer stats V1_5 fields are populated correctly. - * - * This is done by filling Hal LinkLayerStats (V1_5) with random values, converting it to - * WifiLinkLayerStats and then asserting the values in the original structure are equal to the - * values in the converted structure. - */ - @Test - public void testLinkLayerStatsAssignment_1_5() throws Exception { - Random r = new Random(1775968256); - android.hardware.wifi.V1_5.StaLinkLayerStats stats = - new android.hardware.wifi.V1_5.StaLinkLayerStats(); - randomizePacketStats(r, stats.iface.V1_0.wmeBePktStats); - randomizePacketStats(r, stats.iface.V1_0.wmeBkPktStats); - randomizePacketStats(r, stats.iface.V1_0.wmeViPktStats); - randomizePacketStats(r, stats.iface.V1_0.wmeVoPktStats); - android.hardware.wifi.V1_5.StaLinkLayerRadioStats rstat = - new android.hardware.wifi.V1_5.StaLinkLayerRadioStats(); - randomizeRadioStats_1_5(r, rstat); - stats.radios.add(rstat); - stats.timeStampInMs = r.nextLong() & 0xFFFFFFFFFFL; - randomizeContentionTimeStats(r, stats.iface.wmeBeContentionTimeStats); - randomizeContentionTimeStats(r, stats.iface.wmeBkContentionTimeStats); - randomizeContentionTimeStats(r, stats.iface.wmeViContentionTimeStats); - randomizeContentionTimeStats(r, stats.iface.wmeVoContentionTimeStats); - randomizePeerInfoStats(r, stats.iface.peers); - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats_1_5(stats); - - verifyIFaceStats(stats.iface.V1_0, converted); - verifyIFaceStats_1_5(stats.iface, converted); - verifyPerRadioStats(stats.radios, converted); - verifyRadioStats_1_5(stats.radios.get(0), converted); - assertEquals(stats.timeStampInMs, converted.timeStampInMs); - assertEquals(WifiLinkLayerStats.V1_5, converted.version); - assertEquals(1, converted.numRadios); - } - - /** - * Test that the link layer stats V1_3 fields are aggregated correctly for two radios. - * - * This is done by filling multiple Hal LinkLayerStats (V1_3) with random values, - * converting it to WifiLinkLayerStats and then asserting the sum of values from HAL structure - * are equal to the values in the converted structure. - */ - @Test - public void testTwoRadioStatsAggregation_1_3() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled)) - .thenReturn(true); - Random r = new Random(245786856); - android.hardware.wifi.V1_3.StaLinkLayerStats stats = - new android.hardware.wifi.V1_3.StaLinkLayerStats(); - // Fill stats in two radios - for (int i = 0; i < 2; i++) { - android.hardware.wifi.V1_3.StaLinkLayerRadioStats rstat = - new android.hardware.wifi.V1_3.StaLinkLayerRadioStats(); - randomizeRadioStats_1_3(r, rstat); - stats.radios.add(rstat); - } - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats_1_3(stats); - verifyTwoRadioStatsAggregation_1_3(stats.radios, converted); - assertEquals(2, converted.numRadios); - } - - /** - * Test that the link layer stats V1_3 fields are not aggregated on setting - * config_wifiLinkLayerAllRadiosStatsAggregationEnabled to false(Default value). - * - * This is done by filling multiple Hal LinkLayerStats (V1_3) with random values, - * converting it to WifiLinkLayerStats and then asserting the values from radio 0 - * are equal to the values in the converted structure. - */ - @Test - public void testRadioStatsAggregationDisabled_1_3() throws Exception { - Random r = new Random(245786856); - android.hardware.wifi.V1_3.StaLinkLayerStats stats = - new android.hardware.wifi.V1_3.StaLinkLayerStats(); - // Fill stats in two radios - for (int i = 0; i < 2; i++) { - android.hardware.wifi.V1_3.StaLinkLayerRadioStats rstat = - new android.hardware.wifi.V1_3.StaLinkLayerRadioStats(); - randomizeRadioStats_1_3(r, rstat); - stats.radios.add(rstat); - } - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats_1_3(stats); - verifyRadioStats_1_3(stats.radios.get(0), converted); - assertEquals(1, converted.numRadios); - } - - /** - * Test that the link layer stats V1_5 fields are aggregated correctly for two radios. - * - * This is done by filling multiple Hal LinkLayerStats (V1_5) with random values, - * converting it to WifiLinkLayerStats and then asserting the sum of values from HAL structure - * are equal to the values in the converted structure. - */ - @Test - public void testTwoRadioStatsAggregation_1_5() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled)) - .thenReturn(true); - Random r = new Random(245786856); - android.hardware.wifi.V1_5.StaLinkLayerStats stats = - new android.hardware.wifi.V1_5.StaLinkLayerStats(); - // Fill stats in two radios - for (int i = 0; i < 2; i++) { - android.hardware.wifi.V1_5.StaLinkLayerRadioStats rstat = - new android.hardware.wifi.V1_5.StaLinkLayerRadioStats(); - randomizeRadioStats_1_5(r, rstat); - stats.radios.add(rstat); - } - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats_1_5(stats); - verifyPerRadioStats(stats.radios, converted); - verifyTwoRadioStatsAggregation_1_5(stats.radios, converted); - assertEquals(2, converted.numRadios); - } - - /** - * Test that the link layer stats V1_5 fields are not aggregated on setting - * config_wifiLinkLayerAllRadiosStatsAggregationEnabled to false(Default value). - * - * This is done by filling multiple Hal LinkLayerStats (V1_5) with random values, - * converting it to WifiLinkLayerStats and then asserting the values from radio 0 - * are equal to the values in the converted structure. - */ - @Test - public void testRadioStatsAggregationDisabled_1_5() throws Exception { - Random r = new Random(245786856); - android.hardware.wifi.V1_5.StaLinkLayerStats stats = - new android.hardware.wifi.V1_5.StaLinkLayerStats(); - // Fill stats in two radios - for (int i = 0; i < 2; i++) { - android.hardware.wifi.V1_5.StaLinkLayerRadioStats rstat = - new android.hardware.wifi.V1_5.StaLinkLayerRadioStats(); - randomizeRadioStats_1_5(r, rstat); - stats.radios.add(rstat); - } - - WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats_1_5(stats); - verifyPerRadioStats(stats.radios, converted); - verifyRadioStats_1_5(stats.radios.get(0), converted); - assertEquals(1, converted.numRadios); - } - - private void verifyIFaceStats(StaLinkLayerIfaceStats iface, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(iface.beaconRx, wifiLinkLayerStats.beacon_rx); - assertEquals(iface.avgRssiMgmt, wifiLinkLayerStats.rssi_mgmt); - - assertEquals(iface.wmeBePktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_be); - assertEquals(iface.wmeBePktStats.txMpdu, wifiLinkLayerStats.txmpdu_be); - assertEquals(iface.wmeBePktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_be); - assertEquals(iface.wmeBePktStats.retries, wifiLinkLayerStats.retries_be); - - assertEquals(iface.wmeBkPktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_bk); - assertEquals(iface.wmeBkPktStats.txMpdu, wifiLinkLayerStats.txmpdu_bk); - assertEquals(iface.wmeBkPktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_bk); - assertEquals(iface.wmeBkPktStats.retries, wifiLinkLayerStats.retries_bk); - - assertEquals(iface.wmeViPktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_vi); - assertEquals(iface.wmeViPktStats.txMpdu, wifiLinkLayerStats.txmpdu_vi); - assertEquals(iface.wmeViPktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_vi); - assertEquals(iface.wmeViPktStats.retries, wifiLinkLayerStats.retries_vi); - - assertEquals(iface.wmeVoPktStats.rxMpdu, wifiLinkLayerStats.rxmpdu_vo); - assertEquals(iface.wmeVoPktStats.txMpdu, wifiLinkLayerStats.txmpdu_vo); - assertEquals(iface.wmeVoPktStats.lostMpdu, wifiLinkLayerStats.lostmpdu_vo); - assertEquals(iface.wmeVoPktStats.retries, wifiLinkLayerStats.retries_vo); - } - - private void verifyIFaceStats_1_5(android.hardware.wifi.V1_5.StaLinkLayerIfaceStats iface, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(iface.wmeBeContentionTimeStats.contentionTimeMinInUsec, - wifiLinkLayerStats.contentionTimeMinBeInUsec); - assertEquals(iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec, - wifiLinkLayerStats.contentionTimeMaxBeInUsec); - assertEquals(iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec, - wifiLinkLayerStats.contentionTimeAvgBeInUsec); - assertEquals(iface.wmeBeContentionTimeStats.contentionNumSamples, - wifiLinkLayerStats.contentionNumSamplesBe); - - assertEquals(iface.wmeBkContentionTimeStats.contentionTimeMinInUsec, - wifiLinkLayerStats.contentionTimeMinBkInUsec); - assertEquals(iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec, - wifiLinkLayerStats.contentionTimeMaxBkInUsec); - assertEquals(iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec, - wifiLinkLayerStats.contentionTimeAvgBkInUsec); - assertEquals(iface.wmeBkContentionTimeStats.contentionNumSamples, - wifiLinkLayerStats.contentionNumSamplesBk); - - assertEquals(iface.wmeViContentionTimeStats.contentionTimeMinInUsec, - wifiLinkLayerStats.contentionTimeMinViInUsec); - assertEquals(iface.wmeViContentionTimeStats.contentionTimeMaxInUsec, - wifiLinkLayerStats.contentionTimeMaxViInUsec); - assertEquals(iface.wmeViContentionTimeStats.contentionTimeAvgInUsec, - wifiLinkLayerStats.contentionTimeAvgViInUsec); - assertEquals(iface.wmeViContentionTimeStats.contentionNumSamples, - wifiLinkLayerStats.contentionNumSamplesVi); - - assertEquals(iface.wmeVoContentionTimeStats.contentionTimeMinInUsec, - wifiLinkLayerStats.contentionTimeMinVoInUsec); - assertEquals(iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec, - wifiLinkLayerStats.contentionTimeMaxVoInUsec); - assertEquals(iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec, - wifiLinkLayerStats.contentionTimeAvgVoInUsec); - assertEquals(iface.wmeVoContentionTimeStats.contentionNumSamples, - wifiLinkLayerStats.contentionNumSamplesVo); - - for (int i = 0; i < iface.peers.size(); i++) { - assertEquals(iface.peers.get(i).staCount, wifiLinkLayerStats.peerInfo[i].staCount); - assertEquals(iface.peers.get(i).chanUtil, wifiLinkLayerStats.peerInfo[i].chanUtil); - for (int j = 0; j < iface.peers.get(i).rateStats.size(); j++) { - assertEquals(iface.peers.get(i).rateStats.get(j).rateInfo.preamble, - wifiLinkLayerStats.peerInfo[i].rateStats[j].preamble); - assertEquals(iface.peers.get(i).rateStats.get(j).rateInfo.nss, - wifiLinkLayerStats.peerInfo[i].rateStats[j].nss); - assertEquals(iface.peers.get(i).rateStats.get(j).rateInfo.bw, - wifiLinkLayerStats.peerInfo[i].rateStats[j].bw); - assertEquals(iface.peers.get(i).rateStats.get(j).rateInfo.rateMcsIdx, - wifiLinkLayerStats.peerInfo[i].rateStats[j].rateMcsIdx); - assertEquals(iface.peers.get(i).rateStats.get(j).rateInfo.bitRateInKbps, - wifiLinkLayerStats.peerInfo[i].rateStats[j].bitRateInKbps); - assertEquals(iface.peers.get(i).rateStats.get(j).txMpdu, - wifiLinkLayerStats.peerInfo[i].rateStats[j].txMpdu); - assertEquals(iface.peers.get(i).rateStats.get(j).rxMpdu, - wifiLinkLayerStats.peerInfo[i].rateStats[j].rxMpdu); - assertEquals(iface.peers.get(i).rateStats.get(j).mpduLost, - wifiLinkLayerStats.peerInfo[i].rateStats[j].mpduLost); - assertEquals(iface.peers.get(i).rateStats.get(j).retries, - wifiLinkLayerStats.peerInfo[i].rateStats[j].retries); - } - } - } - - private void verifyRadioStats(List<StaLinkLayerRadioStats> radios, - WifiLinkLayerStats wifiLinkLayerStats) { - StaLinkLayerRadioStats radio = radios.get(0); - assertEquals(radio.onTimeInMs, wifiLinkLayerStats.on_time); - assertEquals(radio.txTimeInMs, wifiLinkLayerStats.tx_time); - assertEquals(radio.rxTimeInMs, wifiLinkLayerStats.rx_time); - assertEquals(radio.onTimeInMsForScan, wifiLinkLayerStats.on_time_scan); - assertEquals(radio.txTimeInMsPerLevel.size(), - wifiLinkLayerStats.tx_time_per_level.length); - for (int i = 0; i < radio.txTimeInMsPerLevel.size(); i++) { - assertEquals((int) radio.txTimeInMsPerLevel.get(i), - wifiLinkLayerStats.tx_time_per_level[i]); - } - } - - private void verifyRadioStats_1_3( - android.hardware.wifi.V1_3.StaLinkLayerRadioStats radio, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(radio.V1_0.onTimeInMs, wifiLinkLayerStats.on_time); - assertEquals(radio.V1_0.txTimeInMs, wifiLinkLayerStats.tx_time); - assertEquals(radio.V1_0.rxTimeInMs, wifiLinkLayerStats.rx_time); - assertEquals(radio.V1_0.onTimeInMsForScan, wifiLinkLayerStats.on_time_scan); - assertEquals(radio.V1_0.txTimeInMsPerLevel.size(), - wifiLinkLayerStats.tx_time_per_level.length); - for (int i = 0; i < radio.V1_0.txTimeInMsPerLevel.size(); i++) { - assertEquals((int) radio.V1_0.txTimeInMsPerLevel.get(i), - wifiLinkLayerStats.tx_time_per_level[i]); - } - assertEquals(radio.onTimeInMsForNanScan, wifiLinkLayerStats.on_time_nan_scan); - assertEquals(radio.onTimeInMsForBgScan, wifiLinkLayerStats.on_time_background_scan); - assertEquals(radio.onTimeInMsForRoamScan, wifiLinkLayerStats.on_time_roam_scan); - assertEquals(radio.onTimeInMsForPnoScan, wifiLinkLayerStats.on_time_pno_scan); - assertEquals(radio.onTimeInMsForHs20Scan, wifiLinkLayerStats.on_time_hs20_scan); - assertEquals(radio.channelStats.size(), - wifiLinkLayerStats.channelStatsMap.size()); - for (int j = 0; j < radio.channelStats.size(); j++) { - WifiChannelStats channelStats = radio.channelStats.get(j); - ChannelStats retrievedChannelStats = - wifiLinkLayerStats.channelStatsMap.get(channelStats.channel.centerFreq); - assertNotNull(retrievedChannelStats); - assertEquals(channelStats.channel.centerFreq, retrievedChannelStats.frequency); - assertEquals(channelStats.onTimeInMs, retrievedChannelStats.radioOnTimeMs); - assertEquals(channelStats.ccaBusyTimeInMs, retrievedChannelStats.ccaBusyTimeMs); - } - } - - private void verifyPerRadioStats(List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(radios.size(), - wifiLinkLayerStats.radioStats.length); - for (int i = 0; i < radios.size(); i++) { - android.hardware.wifi.V1_5.StaLinkLayerRadioStats radio = radios.get(i); - RadioStat radioStat = wifiLinkLayerStats.radioStats[i]; - assertEquals(radio.radioId, radioStat.radio_id); - assertEquals(radio.V1_3.V1_0.onTimeInMs, radioStat.on_time); - assertEquals(radio.V1_3.V1_0.txTimeInMs, radioStat.tx_time); - assertEquals(radio.V1_3.V1_0.rxTimeInMs, radioStat.rx_time); - assertEquals(radio.V1_3.V1_0.onTimeInMsForScan, radioStat.on_time_scan); - assertEquals(radio.V1_3.onTimeInMsForNanScan, radioStat.on_time_nan_scan); - assertEquals(radio.V1_3.onTimeInMsForBgScan, radioStat.on_time_background_scan); - assertEquals(radio.V1_3.onTimeInMsForRoamScan, radioStat.on_time_roam_scan); - assertEquals(radio.V1_3.onTimeInMsForPnoScan, radioStat.on_time_pno_scan); - assertEquals(radio.V1_3.onTimeInMsForHs20Scan, radioStat.on_time_hs20_scan); - - assertEquals(radio.V1_3.channelStats.size(), - radioStat.channelStatsMap.size()); - for (int j = 0; j < radio.V1_3.channelStats.size(); j++) { - WifiChannelStats channelStats = radio.V1_3.channelStats.get(j); - ChannelStats retrievedChannelStats = - radioStat.channelStatsMap.get(channelStats.channel.centerFreq); - assertNotNull(retrievedChannelStats); - assertEquals(channelStats.channel.centerFreq, retrievedChannelStats.frequency); - assertEquals(channelStats.onTimeInMs, retrievedChannelStats.radioOnTimeMs); - assertEquals(channelStats.ccaBusyTimeInMs, retrievedChannelStats.ccaBusyTimeMs); - } - } - - } - - private void verifyRadioStats_1_5( - android.hardware.wifi.V1_5.StaLinkLayerRadioStats radio, - WifiLinkLayerStats wifiLinkLayerStats) { - verifyRadioStats_1_3(radio.V1_3, wifiLinkLayerStats); - } - - private void verifyTwoRadioStatsAggregation( - android.hardware.wifi.V1_3.StaLinkLayerRadioStats radio0, - android.hardware.wifi.V1_3.StaLinkLayerRadioStats radio1, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(radio0.V1_0.onTimeInMs + radio1.V1_0.onTimeInMs, - wifiLinkLayerStats.on_time); - assertEquals(radio0.V1_0.txTimeInMs + radio1.V1_0.txTimeInMs, - wifiLinkLayerStats.tx_time); - assertEquals(radio0.V1_0.rxTimeInMs + radio1.V1_0.rxTimeInMs, - wifiLinkLayerStats.rx_time); - assertEquals(radio0.V1_0.onTimeInMsForScan + radio1.V1_0.onTimeInMsForScan, - wifiLinkLayerStats.on_time_scan); - assertEquals(radio0.V1_0.txTimeInMsPerLevel.size(), - radio1.V1_0.txTimeInMsPerLevel.size()); - assertEquals(radio0.V1_0.txTimeInMsPerLevel.size(), - wifiLinkLayerStats.tx_time_per_level.length); - for (int i = 0; i < radio0.V1_0.txTimeInMsPerLevel.size(); i++) { - assertEquals((int) radio0.V1_0.txTimeInMsPerLevel.get(i) - + (int) radio1.V1_0.txTimeInMsPerLevel.get(i), - wifiLinkLayerStats.tx_time_per_level[i]); - } - assertEquals(radio0.onTimeInMsForNanScan + radio1.onTimeInMsForNanScan, - wifiLinkLayerStats.on_time_nan_scan); - assertEquals(radio0.onTimeInMsForBgScan + radio1.onTimeInMsForBgScan, - wifiLinkLayerStats.on_time_background_scan); - assertEquals(radio0.onTimeInMsForRoamScan + radio1.onTimeInMsForRoamScan, - wifiLinkLayerStats.on_time_roam_scan); - assertEquals(radio0.onTimeInMsForPnoScan + radio1.onTimeInMsForPnoScan, - wifiLinkLayerStats.on_time_pno_scan); - assertEquals(radio0.onTimeInMsForHs20Scan + radio1.onTimeInMsForHs20Scan, - wifiLinkLayerStats.on_time_hs20_scan); - assertEquals(radio0.channelStats.size(), radio1.channelStats.size()); - assertEquals(radio0.channelStats.size(), - wifiLinkLayerStats.channelStatsMap.size()); - for (int j = 0; j < radio0.channelStats.size(); j++) { - WifiChannelStats radio0ChannelStats = radio0.channelStats.get(j); - WifiChannelStats radio1ChannelStats = radio1.channelStats.get(j); - ChannelStats retrievedChannelStats = - wifiLinkLayerStats.channelStatsMap.get(radio0ChannelStats.channel.centerFreq); - assertNotNull(retrievedChannelStats); - assertEquals(radio0ChannelStats.channel.centerFreq, retrievedChannelStats.frequency); - assertEquals(radio1ChannelStats.channel.centerFreq, retrievedChannelStats.frequency); - assertEquals(radio0ChannelStats.onTimeInMs + radio1ChannelStats.onTimeInMs, - retrievedChannelStats.radioOnTimeMs); - assertEquals(radio0ChannelStats.ccaBusyTimeInMs - + radio1ChannelStats.ccaBusyTimeInMs, retrievedChannelStats.ccaBusyTimeMs); - } - } - - private void verifyTwoRadioStatsAggregation_1_3( - List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(2, radios.size()); - android.hardware.wifi.V1_3.StaLinkLayerRadioStats radio0 = radios.get(0); - android.hardware.wifi.V1_3.StaLinkLayerRadioStats radio1 = radios.get(1); - verifyTwoRadioStatsAggregation(radio0, radio1, wifiLinkLayerStats); - } - - private void verifyTwoRadioStatsAggregation_1_5( - List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios, - WifiLinkLayerStats wifiLinkLayerStats) { - assertEquals(2, radios.size()); - android.hardware.wifi.V1_5.StaLinkLayerRadioStats radio0 = radios.get(0); - android.hardware.wifi.V1_5.StaLinkLayerRadioStats radio1 = radios.get(1); - verifyTwoRadioStatsAggregation(radio0.V1_3, radio1.V1_3, wifiLinkLayerStats); - } - - /** - * Populate packet stats with non-negative random values - */ - private static void randomizePacketStats(Random r, StaLinkLayerIfacePacketStats pstats) { - pstats.rxMpdu = r.nextLong() & 0xFFFFFFFFFFL; // more than 32 bits - pstats.txMpdu = r.nextLong() & 0xFFFFFFFFFFL; - pstats.lostMpdu = r.nextLong() & 0xFFFFFFFFFFL; - pstats.retries = r.nextLong() & 0xFFFFFFFFFFL; - } - - /** - * Populate contention time stats with non-negative random values - */ - private static void randomizeContentionTimeStats(Random r, - StaLinkLayerIfaceContentionTimeStats cstats) { - cstats.contentionTimeMinInUsec = r.nextInt() & 0x7FFFFFFF; - cstats.contentionTimeMaxInUsec = r.nextInt() & 0x7FFFFFFF; - cstats.contentionTimeAvgInUsec = r.nextInt() & 0x7FFFFFFF; - cstats.contentionNumSamples = r.nextInt() & 0x7FFFFFFF; - } - - /** - * Populate peer info stats with non-negative random values - */ - private static void randomizePeerInfoStats(Random r, ArrayList<StaPeerInfo> pstats) { - StaPeerInfo pstat = new StaPeerInfo(); - pstat.staCount = 2; - pstat.chanUtil = 90; - pstat.rateStats = new ArrayList<StaRateStat>(); - StaRateStat rateStat = new StaRateStat(); - rateStat.rateInfo.preamble = r.nextInt() & 0x7FFFFFFF; - rateStat.rateInfo.nss = r.nextInt() & 0x7FFFFFFF; - rateStat.rateInfo.bw = r.nextInt() & 0x7FFFFFFF; - rateStat.rateInfo.rateMcsIdx = 9; - rateStat.rateInfo.bitRateInKbps = 101; - rateStat.txMpdu = r.nextInt() & 0x7FFFFFFF; - rateStat.rxMpdu = r.nextInt() & 0x7FFFFFFF; - rateStat.mpduLost = r.nextInt() & 0x7FFFFFFF; - rateStat.retries = r.nextInt() & 0x7FFFFFFF; - pstat.rateStats.add(rateStat); - pstats.add(pstat); - } - - /** - * Populate radio stats with non-negative random values - */ - private static void randomizeRadioStats(Random r, ArrayList<StaLinkLayerRadioStats> rstats) { - StaLinkLayerRadioStats rstat = new StaLinkLayerRadioStats(); - rstat.onTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.txTimeInMs = r.nextInt() & 0xFFFFFF; - for (int i = 0; i < 4; i++) { - Integer v = r.nextInt() & 0xFFFFFF; - rstat.txTimeInMsPerLevel.add(v); - } - rstat.rxTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForScan = r.nextInt() & 0xFFFFFF; - rstats.add(rstat); - } - - /** - * Populate radio stats V1_3 with non-negative random values - */ - private static void randomizeRadioStats_1_3(Random r, - android.hardware.wifi.V1_3.StaLinkLayerRadioStats rstat) { - rstat.V1_0.onTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.V1_0.txTimeInMs = r.nextInt() & 0xFFFFFF; - for (int j = 0; j < 4; j++) { - Integer v = r.nextInt() & 0xFFFFFF; - rstat.V1_0.txTimeInMsPerLevel.add(v); - } - rstat.V1_0.rxTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.V1_0.onTimeInMsForScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForNanScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForBgScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForRoamScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForPnoScan = r.nextInt() & 0xFFFFFF; - rstat.onTimeInMsForHs20Scan = r.nextInt() & 0xFFFFFF; - for (int k = 0; k < TEST_FREQUENCIES.length; k++) { - WifiChannelStats channelStats = new WifiChannelStats(); - channelStats.channel.centerFreq = TEST_FREQUENCIES[k]; - channelStats.onTimeInMs = r.nextInt() & 0xFFFFFF; - channelStats.ccaBusyTimeInMs = r.nextInt() & 0xFFFFFF; - rstat.channelStats.add(channelStats); - } - } - - /** - * Populate radio stats V1_5 with non-negative random values - */ - private static void randomizeRadioStats_1_5(Random r, - android.hardware.wifi.V1_5.StaLinkLayerRadioStats rstat) { - rstat.radioId = r.nextInt() & 0xFFFFFF; - randomizeRadioStats_1_3(r, rstat.V1_3); + verify(mWifiStaIface, never()).enableLinkLayerStatsCollection(false); + verify(mWifiStaIface, never()).getLinkLayerStats(); } /** @@ -1638,15 +631,9 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testVersionGetters() throws Exception { String firmwareVersion = "fuzzy"; String driverVersion = "dizzy"; - IWifiChip.ChipDebugInfo chipDebugInfo = new IWifiChip.ChipDebugInfo(); - chipDebugInfo.firmwareDescription = firmwareVersion; - chipDebugInfo.driverDescription = driverVersion; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.requestChipDebugInfoCallback cb) throws RemoteException { - cb.onValues(mWifiStatusSuccess, chipDebugInfo); - } - }).when(mIWifiChip).requestChipDebugInfo(any(IWifiChip.requestChipDebugInfoCallback.class)); + WifiChip.ChipDebugInfo chipDebugInfo = + new WifiChip.ChipDebugInfo(driverVersion, firmwareVersion); + when(mWifiChip.requestChipDebugInfo()).thenReturn(chipDebugInfo); assertNull(mWifiVendorHal.getFirmwareVersion()); assertNull(mWifiVendorHal.getDriverVersion()); @@ -1657,41 +644,6 @@ public class WifiVendorHalTest extends WifiBaseTest { assertEquals(driverVersion, mWifiVendorHal.getDriverVersion()); } - /** - * For checkRoundTripIntTranslation lambdas - */ - interface IntForInt { - int translate(int value); - } - - /** - * Checks that translation from x to y and back again is the identity function - * - * @param xFromY reverse translator - * @param yFromX forward translator - * @param xLimit non-inclusive upper bound on x (lower bound is zero) - */ - private void checkRoundTripIntTranslation( - IntForInt xFromY, IntForInt yFromX, int xFirst, int xLimit) throws Exception { - int ex = 0; - for (int i = xFirst; i < xLimit; i++) { - assertEquals(i, xFromY.translate(yFromX.translate(i))); - } - try { - yFromX.translate(xLimit); - assertTrue("expected an exception here", false); - } catch (IllegalArgumentException e) { - ex++; - } - try { - xFromY.translate(yFromX.translate(xLimit - 1) + 1); - assertTrue("expected an exception here", false); - } catch (IllegalArgumentException e) { - ex++; - } - assertEquals(2, ex); - } - @Test public void testStartSendingOffloadedPacket() throws Exception { byte[] srcMac = NativeUtil.macAddressToByteArray("4007b2088c81"); @@ -1704,30 +656,30 @@ public class WifiVendorHalTest extends WifiBaseTest { KeepalivePacketData kap = NattKeepalivePacketData.nattKeepalivePacket(src, 63000, dst, 4500); - when(mIWifiStaIface.startSendingKeepAlivePackets( - anyInt(), any(), anyShort(), any(), any(), anyInt() - )).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.startSendingKeepAlivePackets( + anyInt(), any(), anyInt(), any(), any(), anyInt() + )).thenReturn(true); assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(0 == mWifiVendorHal.startSendingOffloadedPacket( + assertEquals(0, mWifiVendorHal.startSendingOffloadedPacket( TEST_IFACE_NAME, slot, srcMac, dstMac, kap.getPacket(), OsConstants.ETH_P_IPV6, millis)); - verify(mIWifiStaIface).startSendingKeepAlivePackets( - eq(slot), any(), anyShort(), any(), any(), eq(millis)); + verify(mWifiStaIface).startSendingKeepAlivePackets( + eq(slot), any(), anyInt(), any(), any(), eq(millis)); } @Test public void testStopSendingOffloadedPacket() throws Exception { int slot = 13; - when(mIWifiStaIface.stopSendingKeepAlivePackets(anyInt())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.stopSendingKeepAlivePackets(anyInt())).thenReturn(true); assertTrue(mWifiVendorHal.startVendorHalSta()); assertTrue(0 == mWifiVendorHal.stopSendingOffloadedPacket( TEST_IFACE_NAME, slot)); - verify(mIWifiStaIface).stopSendingKeepAlivePackets(eq(slot)); + verify(mWifiStaIface).stopSendingKeepAlivePackets(eq(slot)); } /** @@ -1736,10 +688,10 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testRssiMonitoring() throws Exception { - when(mIWifiStaIface.startRssiMonitoring(anyInt(), anyInt(), anyInt())) - .thenReturn(mWifiStatusSuccess); - when(mIWifiStaIface.stopRssiMonitoring(anyInt())) - .thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.startRssiMonitoring(anyInt(), anyInt(), anyInt())) + .thenReturn(true); + when(mWifiStaIface.stopRssiMonitoring(anyInt())) + .thenReturn(true); ArrayList<Byte> breach = new ArrayList<>(10); byte hi = -21; @@ -1758,7 +710,7 @@ public class WifiVendorHalTest extends WifiBaseTest { assertEquals(0, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, hi, lo, handler)); int theCmdId = mWifiVendorHal.sRssiMonCmdId; breach.clear(); - mIWifiStaIfaceEventCallback.onRssiThresholdBreached(theCmdId, new byte[6], lower); + mWifiStaIfaceEventCallback.onRssiThresholdBreached(theCmdId, new byte[6], lower); assertEquals(breach.get(0), lower); assertEquals(0, mWifiVendorHal.stopRssiMonitoring(TEST_IFACE_NAME)); assertEquals(0, mWifiVendorHal.startRssiMonitoring(TEST_IFACE_NAME, hi, lo, handler)); @@ -1784,18 +736,9 @@ public class WifiVendorHalTest extends WifiBaseTest { int myVersion = 33; int myMaxSize = 1234; - StaApfPacketFilterCapabilities capabilities = new StaApfPacketFilterCapabilities(); - capabilities.version = myVersion; - capabilities.maxLength = myMaxSize; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getApfPacketFilterCapabilitiesCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, capabilities); - } - }).when(mIWifiStaIface).getApfPacketFilterCapabilities(any( - IWifiStaIface.getApfPacketFilterCapabilitiesCallback.class)); - + ApfCapabilities capabilities = + new ApfCapabilities(myVersion, myMaxSize, android.system.OsConstants.ARPHRD_ETHER); + when(mWifiStaIface.getApfPacketFilterCapabilities()).thenReturn(capabilities); assertEquals(0, mWifiVendorHal.getApfCapabilities(TEST_IFACE_NAME) .apfVersionSupported); @@ -1816,17 +759,11 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testInstallApf() throws Exception { byte[] filter = new byte[] {19, 53, 10}; - - ArrayList<Byte> expected = new ArrayList<>(3); - for (byte b : filter) expected.add(b); - - when(mIWifiStaIface.installApfPacketFilter(anyInt(), any(ArrayList.class))) - .thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.installApfPacketFilter(any(byte[].class))).thenReturn(true); assertTrue(mWifiVendorHal.startVendorHalSta()); assertTrue(mWifiVendorHal.installPacketFilter(TEST_IFACE_NAME, filter)); - - verify(mIWifiStaIface).installApfPacketFilter(eq(0), eq(expected)); + verify(mWifiStaIface).installApfPacketFilter(eq(filter)); } /** @@ -1834,69 +771,14 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testReadApf() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - byte[] program = new byte[] {65, 66, 67}; - ArrayList<Byte> expected = new ArrayList<>(3); - for (byte b : program) expected.add(b); - - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_2.IWifiStaIface.readApfPacketFilterDataCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, expected); - } - }).when(mIWifiStaIfaceV12).readApfPacketFilterData(any( - android.hardware.wifi.V1_2.IWifiStaIface.readApfPacketFilterDataCallback.class)); + when(mWifiStaIface.readApfPacketFilterData()).thenReturn(program); assertTrue(mWifiVendorHal.startVendorHalSta()); assertArrayEquals(program, mWifiVendorHal.readPacketFilter(TEST_IFACE_NAME)); } /** - * Test that the country code is set in AP mode (when it should be). - */ - @Test - public void testSetApCountryCode() throws Exception { - byte[] expected = new byte[]{(byte) 'C', (byte) 'A'}; - - when(mIWifiApIface.setCountryCode(any())) - .thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHal()); - assertNotNull(mWifiVendorHal.createApIface(null, null, - SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - - assertFalse(mWifiVendorHal.setApCountryCode(TEST_IFACE_NAME, null)); - assertFalse(mWifiVendorHal.setApCountryCode(TEST_IFACE_NAME, "")); - assertFalse(mWifiVendorHal.setApCountryCode(TEST_IFACE_NAME, "A")); - // Only one expected to succeed - assertTrue(mWifiVendorHal.setApCountryCode(TEST_IFACE_NAME, "CA")); - assertFalse(mWifiVendorHal.setApCountryCode(TEST_IFACE_NAME, "ZZZ")); - - verify(mIWifiApIface).setCountryCode(eq(expected)); - } - - /** - * Test that RemoteException is caught and logged. - */ - @Test - public void testRemoteExceptionIsHandled() throws Exception { - mWifiLog = spy(mWifiLog); - mWifiVendorHal.mVerboseLog = mWifiLog; - when(mIWifiApIface.setCountryCode(any())) - .thenThrow(new RemoteException("oops")); - assertTrue(mWifiVendorHal.startVendorHal()); - assertNotNull(mWifiVendorHal.createApIface(null, null, - SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); - assertFalse(mWifiVendorHal.setApCountryCode(TEST_IFACE_NAME, "CA")); - assertTrue(mWifiVendorHal.isHalStarted()); - verify(mWifiLog).err("% RemoteException in HIDL call %"); - } - - /** * Test that startLoggingToDebugRingBuffer is plumbed to chip * * A call before the vendor hal is started should just return false. @@ -1904,15 +786,15 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testStartLoggingRingBuffer() throws Exception { - when(mIWifiChip.startLoggingToDebugRingBuffer( + when(mWifiChip.startLoggingToDebugRingBuffer( any(String.class), anyInt(), anyInt(), anyInt() - )).thenReturn(mWifiStatusSuccess); + )).thenReturn(true); assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One")); assertTrue(mWifiVendorHal.startVendorHalSta()); assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One")); - verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000); + verify(mWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000); } /** @@ -1920,9 +802,9 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testStartLoggingRingBufferOnAp() throws Exception { - when(mIWifiChip.startLoggingToDebugRingBuffer( + when(mWifiChip.startLoggingToDebugRingBuffer( any(String.class), anyInt(), anyInt(), anyInt() - )).thenReturn(mWifiStatusSuccess); + )).thenReturn(true); assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One")); assertTrue(mWifiVendorHal.startVendorHal()); @@ -1930,53 +812,7 @@ public class WifiVendorHalTest extends WifiBaseTest { SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One")); - verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000); - } - - /** - * Test that getRingBufferStatus gets and translates its stuff correctly - */ - @Test - public void testRingBufferStatus() throws Exception { - WifiDebugRingBufferStatus one = new WifiDebugRingBufferStatus(); - one.ringName = "One"; - one.flags = WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES; - one.ringId = 5607371; - one.sizeInBytes = 54321; - one.freeSizeInBytes = 42; - one.verboseLevel = WifiDebugRingBufferVerboseLevel.VERBOSE; - String oneExpect = "name: One flag: 1 ringBufferId: 5607371 ringBufferByteSize: 54321" - + " verboseLevel: 2 writtenBytes: 0 readBytes: 0 writtenRecords: 0"; - - WifiDebugRingBufferStatus two = new WifiDebugRingBufferStatus(); - two.ringName = "Two"; - two.flags = WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES - | WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES; - two.ringId = 4512470; - two.sizeInBytes = 300; - two.freeSizeInBytes = 42; - two.verboseLevel = WifiDebugRingBufferVerboseLevel.DEFAULT; - - ArrayList<WifiDebugRingBufferStatus> halBufferStatus = new ArrayList<>(2); - halBufferStatus.add(one); - halBufferStatus.add(two); - - WifiNative.RingBufferStatus[] actual; - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getDebugRingBuffersStatusCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, halBufferStatus); - } - }).when(mIWifiChip).getDebugRingBuffersStatus(any( - IWifiChip.getDebugRingBuffersStatusCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - actual = mWifiVendorHal.getRingBufferStatus(); - - assertEquals(halBufferStatus.size(), actual.length); - assertEquals(oneExpect, actual[0].toString()); - assertEquals(two.ringId, actual[1].ringBufferId); + verify(mWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000); } /** @@ -1986,8 +822,8 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testForceRingBufferDump() throws Exception { - when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Gunk"))).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Glop"))).thenReturn(mWifiStatusFailure); + when(mWifiChip.forceDumpToDebugRingBuffer(eq("Gunk"))).thenReturn(true); + when(mWifiChip.forceDumpToDebugRingBuffer(eq("Glop"))).thenReturn(false); assertFalse(mWifiVendorHal.getRingBufferData("Gunk")); // hal not started @@ -1996,8 +832,8 @@ public class WifiVendorHalTest extends WifiBaseTest { assertTrue(mWifiVendorHal.getRingBufferData("Gunk")); // mocked call succeeds assertFalse(mWifiVendorHal.getRingBufferData("Glop")); // mocked call fails - verify(mIWifiChip).forceDumpToDebugRingBuffer("Gunk"); - verify(mIWifiChip).forceDumpToDebugRingBuffer("Glop"); + verify(mWifiChip).forceDumpToDebugRingBuffer("Gunk"); + verify(mWifiChip).forceDumpToDebugRingBuffer("Glop"); } /** @@ -2007,15 +843,13 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testFlushRingBufferToFile() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_3(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV13.flushRingBufferToFile()).thenReturn(mWifiStatusSuccess); + when(mWifiChip.flushRingBufferToFile()).thenReturn(true); assertFalse(mWifiVendorHal.flushRingBufferData()); assertTrue(mWifiVendorHal.startVendorHalSta()); assertTrue(mWifiVendorHal.flushRingBufferData()); - verify(mIWifiChipV13).flushRingBufferToFile(); + verify(mWifiChip).flushRingBufferToFile(); } /** @@ -2025,14 +859,14 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testStartPktFateMonitoring() throws Exception { - when(mIWifiStaIface.startDebugPacketFateMonitoring()).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.startDebugPacketFateMonitoring()).thenReturn(true); assertFalse(mWifiVendorHal.startPktFateMonitoring(TEST_IFACE_NAME)); - verify(mIWifiStaIface, never()).startDebugPacketFateMonitoring(); + verify(mWifiStaIface, never()).startDebugPacketFateMonitoring(); assertTrue(mWifiVendorHal.startVendorHalSta()); assertTrue(mWifiVendorHal.startPktFateMonitoring(TEST_IFACE_NAME)); - verify(mIWifiStaIface).startDebugPacketFateMonitoring(); + verify(mWifiStaIface).startDebugPacketFateMonitoring(); } /** @@ -2044,78 +878,26 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testGetTxPktFates() throws Exception { byte[] frameContentBytes = new byte[30]; new Random().nextBytes(frameContentBytes); - WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport(); - fateReport.fate = WifiDebugTxPacketFate.DRV_QUEUED; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, new ArrayList<>(Arrays.asList(fateReport))); - } - }).when(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); + byte fate = WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; + long driverTimestampUsec = new Random().nextLong(); + byte frameType = WifiLoggerHal.FRAME_TYPE_ETHERNET_II; + WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport( + fate, driverTimestampUsec, frameType, frameContentBytes); + when(mWifiStaIface.getDebugTxPacketFates()).thenReturn(Arrays.asList(fateReport)); assertEquals(0, mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME).size()); - verify(mIWifiStaIface, never()) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); + verify(mWifiStaIface, never()).getDebugTxPacketFates(); assertTrue(mWifiVendorHal.startVendorHalSta()); - List<TxFateReport> retrievedFates = mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME); + List<WifiNative.TxFateReport> retrievedFates = + mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME); assertEquals(1, retrievedFates.size()); - TxFateReport retrievedFate = retrievedFates.get(0); - verify(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - assertEquals(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, retrievedFate.mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, retrievedFate.mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFate.mFrameType); - assertArrayEquals(frameContentBytes, retrievedFate.mFrameBytes); - } - - /** - * Tests the retrieval of tx packet fates when the number of fates retrieved exceeds the - * maximum number of packet fates fetched ({@link WifiLoggerHal#MAX_FATE_LOG_LEN}). - * - * Try once before hal start, and once after. - */ - @Test - public void testGetTxPktFatesExceedsInputArrayLength() throws Exception { - byte[] frameContentBytes = new byte[30]; - new Random().nextBytes(frameContentBytes); - WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport(); - fateReport.fate = WifiDebugTxPacketFate.FW_DROP_OTHER; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, new ArrayList<>( - // create twice as many as the max size - Collections.nCopies(WifiLoggerHal.MAX_FATE_LOG_LEN * 2, fateReport))); - } - }).when(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - - assertEquals(0, mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME).size()); - verify(mIWifiStaIface, never()) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - List<TxFateReport> retrievedFates = mWifiVendorHal.getTxPktFates(TEST_IFACE_NAME); - // assert that at most WifiLoggerHal.MAX_FATE_LOG_LEN is retrieved - assertEquals(WifiLoggerHal.MAX_FATE_LOG_LEN, retrievedFates.size()); - TxFateReport retrievedFate = retrievedFates.get(0); - verify(mIWifiStaIface) - .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class)); - assertEquals(WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, retrievedFate.mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, retrievedFate.mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFate.mFrameType); + WifiNative.TxFateReport retrievedFate = retrievedFates.get(0); + verify(mWifiStaIface).getDebugTxPacketFates(); + assertEquals(fate, retrievedFate.mFate); + assertEquals(driverTimestampUsec, retrievedFate.mDriverTimestampUSec); + assertEquals(frameType, retrievedFate.mFrameType); assertArrayEquals(frameContentBytes, retrievedFate.mFrameBytes); } @@ -2128,77 +910,26 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testGetRxPktFates() throws Exception { byte[] frameContentBytes = new byte[30]; new Random().nextBytes(frameContentBytes); - WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport(); - fateReport.fate = WifiDebugRxPacketFate.SUCCESS; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, new ArrayList<>(Arrays.asList(fateReport))); - } - }).when(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); + byte fate = WifiLoggerHal.RX_PKT_FATE_SUCCESS; + long driverTimestampUsec = new Random().nextLong(); + byte frameType = WifiLoggerHal.FRAME_TYPE_ETHERNET_II; + WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport( + fate, driverTimestampUsec, frameType, frameContentBytes); + when(mWifiStaIface.getDebugRxPacketFates()).thenReturn(Arrays.asList(fateReport)); assertEquals(0, mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME).size()); - verify(mIWifiStaIface, never()) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); + verify(mWifiStaIface, never()).getDebugRxPacketFates(); assertTrue(mWifiVendorHal.startVendorHalSta()); - List<RxFateReport> retrievedFates = mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME); + List<WifiNative.RxFateReport> retrievedFates = + mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME); assertEquals(1, retrievedFates.size()); - RxFateReport retrievedFate = retrievedFates.get(0); - verify(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - assertEquals(WifiLoggerHal.RX_PKT_FATE_SUCCESS, retrievedFate.mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, retrievedFate.mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFate.mFrameType); - assertArrayEquals(frameContentBytes, retrievedFate.mFrameBytes); - } - - /** - * Tests the retrieval of rx packet fates when the number of fates retrieved exceeds the - * input array. - * - * Try once before hal start, and once after. - */ - @Test - public void testGetRxPktFatesExceedsInputArrayLength() throws Exception { - byte[] frameContentBytes = new byte[30]; - new Random().nextBytes(frameContentBytes); - WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport(); - fateReport.fate = WifiDebugRxPacketFate.FW_DROP_FILTER; - fateReport.frameInfo.driverTimestampUsec = new Random().nextLong(); - fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211; - fateReport.frameInfo.frameContent.addAll( - NativeUtil.byteArrayToArrayList(frameContentBytes)); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) { - cb.onValues(mWifiStatusSuccess, new ArrayList<>( - // create twice as many as the max size - Collections.nCopies(WifiLoggerHal.MAX_FATE_LOG_LEN * 2, fateReport))); - } - }).when(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - - assertEquals(0, mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME).size()); - verify(mIWifiStaIface, never()) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - List<RxFateReport> retrievedFates = mWifiVendorHal.getRxPktFates(TEST_IFACE_NAME); - assertEquals(WifiLoggerHal.MAX_FATE_LOG_LEN, retrievedFates.size()); - verify(mIWifiStaIface) - .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class)); - RxFateReport retrievedFate = retrievedFates.get(0); - assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, retrievedFate.mFate); - assertEquals(fateReport.frameInfo.driverTimestampUsec, retrievedFate.mDriverTimestampUSec); - assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFate.mFrameType); + WifiNative.RxFateReport retrievedFate = retrievedFates.get(0); + verify(mWifiStaIface).getDebugRxPacketFates(); + assertEquals(fate, retrievedFate.mFate); + assertEquals(driverTimestampUsec, retrievedFate.mDriverTimestampUSec); + assertEquals(frameType, retrievedFate.mFrameType); assertArrayEquals(frameContentBytes, retrievedFate.mFrameBytes); } @@ -2207,17 +938,17 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testEnableDisableNdOffload() throws Exception { - when(mIWifiStaIface.enableNdOffload(anyBoolean())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.enableNdOffload(anyBoolean())).thenReturn(true); assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, true)); - verify(mIWifiStaIface, never()).enableNdOffload(anyBoolean()); + verify(mWifiStaIface, never()).enableNdOffload(anyBoolean()); assertTrue(mWifiVendorHal.startVendorHalSta()); assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, true)); - verify(mIWifiStaIface).enableNdOffload(eq(true)); + verify(mWifiStaIface).enableNdOffload(eq(true)); assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, false)); - verify(mIWifiStaIface).enableNdOffload(eq(false)); + verify(mWifiStaIface).enableNdOffload(eq(false)); } /** @@ -2225,80 +956,12 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testEnableNdOffloadFailure() throws Exception { - when(mIWifiStaIface.enableNdOffload(eq(true))).thenReturn(mWifiStatusFailure); + when(mWifiStaIface.enableNdOffload(eq(true))).thenReturn(false); assertTrue(mWifiVendorHal.startVendorHalSta()); assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(TEST_IFACE_NAME, true)); - verify(mIWifiStaIface).enableNdOffload(eq(true)); - } - - /** - * Helper class for mocking getRoamingCapabilities callback - */ - private class GetRoamingCapabilitiesAnswer extends AnswerWithArguments { - private final WifiStatus mStatus; - private final StaRoamingCapabilities mCaps; - - GetRoamingCapabilitiesAnswer(WifiStatus status, StaRoamingCapabilities caps) { - mStatus = status; - mCaps = caps; - } - - public void answer(IWifiStaIface.getRoamingCapabilitiesCallback cb) { - cb.onValues(mStatus, mCaps); - } - } - - /** - * Tests retrieval of firmware roaming capabilities - */ - @Test - public void testFirmwareRoamingCapabilityRetrieval() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - for (int i = 0; i < 4; i++) { - int blocklistSize = i + 10; - int allowlistSize = i * 3; - StaRoamingCapabilities caps = new StaRoamingCapabilities(); - caps.maxBlacklistSize = blocklistSize; - caps.maxWhitelistSize = allowlistSize; - doAnswer(new GetRoamingCapabilitiesAnswer(mWifiStatusSuccess, caps)) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - RoamingCapabilities roamCap = mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME); - assertNotNull(roamCap); - assertEquals(blocklistSize, roamCap.maxBlocklistSize); - assertEquals(allowlistSize, roamCap.maxAllowlistSize); - } - } - - /** - * Tests unsuccessful retrieval of firmware roaming capabilities - */ - @Test - public void testUnsuccessfulFirmwareRoamingCapabilityRetrieval() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - StaRoamingCapabilities caps = new StaRoamingCapabilities(); - caps.maxBlacklistSize = 43; - caps.maxWhitelistSize = 18; - - // hal returns a failure status - doAnswer(new GetRoamingCapabilitiesAnswer(mWifiStatusFailure, null)) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - assertNull(mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME)); - - // hal returns failure status, but supplies caps anyway - doAnswer(new GetRoamingCapabilitiesAnswer(mWifiStatusFailure, caps)) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - assertNull(mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME)); - - // lost connection - doThrow(new RemoteException()) - .when(mIWifiStaIface).getRoamingCapabilities( - any(IWifiStaIface.getRoamingCapabilitiesCallback.class)); - assertNull(mWifiVendorHal.getRoamingCapabilities(TEST_IFACE_NAME)); + verify(mWifiStaIface).enableNdOffload(eq(true)); } /** @@ -2307,8 +970,8 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testEnableFirmwareRoamingSuccess() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(eq(StaRoamingState.ENABLED))) - .thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.setRoamingState(eq(WifiNative.ENABLE_FIRMWARE_ROAMING))) + .thenReturn(WifiNative.SET_FIRMWARE_ROAMING_SUCCESS); assertEquals(WifiNative.SET_FIRMWARE_ROAMING_SUCCESS, mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, WifiNative.ENABLE_FIRMWARE_ROAMING)); @@ -2320,34 +983,21 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testDisbleFirmwareRoamingSuccess() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(eq(StaRoamingState.DISABLED))) - .thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.setRoamingState(eq(WifiNative.DISABLE_FIRMWARE_ROAMING))) + .thenReturn(WifiNative.SET_FIRMWARE_ROAMING_SUCCESS); assertEquals(WifiNative.SET_FIRMWARE_ROAMING_SUCCESS, mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, WifiNative.DISABLE_FIRMWARE_ROAMING)); } /** - * Tests enableFirmwareRoaming failure case - invalid argument - */ - @Test - public void testEnableFirmwareRoamingFailureInvalidArgument() throws Exception { - final int badState = WifiNative.DISABLE_FIRMWARE_ROAMING - + WifiNative.ENABLE_FIRMWARE_ROAMING + 1; - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_FAILURE, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, badState)); - verify(mIWifiStaIface, never()).setRoamingState(anyByte()); - } - - /** * Tests enableFirmwareRoaming failure case - busy */ @Test public void testEnableFirmwareRoamingFailureBusy() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(anyByte())) - .thenReturn(mWifiStatusBusy); + when(mWifiStaIface.setRoamingState(anyInt())) + .thenReturn(WifiNative.SET_FIRMWARE_ROAMING_BUSY); assertEquals(WifiNative.SET_FIRMWARE_ROAMING_BUSY, mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, WifiNative.ENABLE_FIRMWARE_ROAMING)); @@ -2359,20 +1009,8 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testEnableFirmwareRoamingFailure() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - when(mIWifiStaIface.setRoamingState(anyByte())) - .thenReturn(mWifiStatusFailure); - assertEquals(WifiNative.SET_FIRMWARE_ROAMING_FAILURE, - mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, - WifiNative.ENABLE_FIRMWARE_ROAMING)); - } - - /** - * Tests enableFirmwareRoaming remote exception failure case - */ - @Test - public void testEnableFirmwareRoamingException() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - doThrow(new RemoteException()).when(mIWifiStaIface).setRoamingState(anyByte()); + when(mWifiStaIface.setRoamingState(anyInt())) + .thenReturn(WifiNative.SET_FIRMWARE_ROAMING_FAILURE); assertEquals(WifiNative.SET_FIRMWARE_ROAMING_FAILURE, mWifiVendorHal.enableFirmwareRoaming(TEST_IFACE_NAME, WifiNative.ENABLE_FIRMWARE_ROAMING)); @@ -2390,9 +1028,9 @@ public class WifiVendorHalTest extends WifiBaseTest { roamingConfig.allowlistSsids = new ArrayList(); roamingConfig.allowlistSsids.add("\"xyzzy\""); roamingConfig.allowlistSsids.add("\"\u0F00 \u05D0\""); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.configureRoaming(any(), any())).thenReturn(true); assertTrue(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); + verify(mWifiStaIface).configureRoaming(any(), any()); } /** @@ -2404,22 +1042,18 @@ public class WifiVendorHalTest extends WifiBaseTest { WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); roamingConfig.allowlistSsids = new ArrayList(); roamingConfig.allowlistSsids.add("\"xyzzy\""); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.configureRoaming(any(), any())).thenReturn(true); assertTrue(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - ArgumentCaptor<StaRoamingConfig> staRoamingConfigCaptor = ArgumentCaptor.forClass( - StaRoamingConfig.class); - verify(mIWifiStaIface).configureRoaming(staRoamingConfigCaptor.capture()); + verify(mWifiStaIface).configureRoaming(any(), mListCaptor.capture()); byte[] allowlistSsidsPadded = new byte[32]; allowlistSsidsPadded[0] = (byte) 0x78; allowlistSsidsPadded[1] = (byte) 0x79; allowlistSsidsPadded[2] = (byte) 0x7a; allowlistSsidsPadded[3] = (byte) 0x7a; allowlistSsidsPadded[4] = (byte) 0x79; - assertArrayEquals(staRoamingConfigCaptor.getValue().ssidWhitelist.get(0), - allowlistSsidsPadded); + assertArrayEquals((byte[]) mListCaptor.getValue().get(0), allowlistSsidsPadded); allowlistSsidsPadded[5] = (byte) 0x79; - assertFalse(Arrays.equals(staRoamingConfigCaptor.getValue().ssidWhitelist.get(0), - allowlistSsidsPadded)); + assertFalse(Arrays.equals((byte[]) mListCaptor.getValue().get(0), allowlistSsidsPadded)); } /** @@ -2429,9 +1063,9 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testConfigureRoamingResetSuccess() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.configureRoaming(any(), any())).thenReturn(true); assertTrue(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); + verify(mWifiStaIface).configureRoaming(any(), any()); } /** @@ -2441,21 +1075,9 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testConfigureRoamingFailure() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusFailure); - assertFalse(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); - } - - /** - * Tests configureRoaming failure due to remote exception - */ - @Test - public void testConfigureRoamingRemoteException() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); - doThrow(new RemoteException()).when(mIWifiStaIface).configureRoaming(any()); + when(mWifiStaIface.configureRoaming(any(), any())).thenReturn(false); assertFalse(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface).configureRoaming(any()); + verify(mWifiStaIface).configureRoaming(any(), any()); } /** @@ -2467,9 +1089,9 @@ public class WifiVendorHalTest extends WifiBaseTest { WifiNative.RoamingConfig roamingConfig = new WifiNative.RoamingConfig(); roamingConfig.blocklistBssids = new ArrayList(); roamingConfig.blocklistBssids.add("12:34:56:78:zz:zz"); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.configureRoaming(any(), any())).thenReturn(true); assertFalse(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - verify(mIWifiStaIface, never()).configureRoaming(any()); + verify(mWifiStaIface, never()).configureRoaming(any(), any()); } /** @@ -2482,61 +1104,11 @@ public class WifiVendorHalTest extends WifiBaseTest { roamingConfig.allowlistSsids = new ArrayList(); // Add an SSID that is too long (> 32 bytes) due to the multi-byte utf-8 characters roamingConfig.allowlistSsids.add("\"123456789012345678901234567890\u0F00\u05D0\""); - when(mIWifiStaIface.configureRoaming(any())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.configureRoaming(any(), any())).thenReturn(true); assertTrue(mWifiVendorHal.configureRoaming(TEST_IFACE_NAME, roamingConfig)); - ArgumentCaptor<StaRoamingConfig> staRoamingConfigCaptor = ArgumentCaptor.forClass( - StaRoamingConfig.class); - verify(mIWifiStaIface).configureRoaming(staRoamingConfigCaptor.capture()); + verify(mWifiStaIface).configureRoaming(any(), mListCaptor.capture()); verify(mSsidTranslator).getAllPossibleOriginalSsids(any()); - assertTrue(staRoamingConfigCaptor.getValue().ssidWhitelist.isEmpty()); - } - - /** - * Tests the retrieval of wlan wake reason stats. - */ - @Test - public void testGetWlanWakeReasonCount() throws Exception { - WifiDebugHostWakeReasonStats stats = new WifiDebugHostWakeReasonStats(); - Random rand = new Random(); - stats.totalCmdEventWakeCnt = rand.nextInt(); - stats.totalDriverFwLocalWakeCnt = rand.nextInt(); - stats.totalRxPacketWakeCnt = rand.nextInt(); - stats.rxPktWakeDetails.rxUnicastCnt = rand.nextInt(); - stats.rxPktWakeDetails.rxMulticastCnt = rand.nextInt(); - stats.rxIcmpPkWakeDetails.icmpPkt = rand.nextInt(); - stats.rxIcmpPkWakeDetails.icmp6Pkt = rand.nextInt(); - stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt = rand.nextInt(); - stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt = rand.nextInt(); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) { - cb.onValues(mWifiStatusSuccess, stats); - } - }).when(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - - assertNull(mWifiVendorHal.getWlanWakeReasonCount()); - verify(mIWifiChip, never()) - .getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - WlanWakeReasonAndCounts retrievedStats = mWifiVendorHal.getWlanWakeReasonCount(); - verify(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); - assertNotNull(retrievedStats); - assertEquals(stats.totalCmdEventWakeCnt, retrievedStats.totalCmdEventWake); - assertEquals(stats.totalDriverFwLocalWakeCnt, retrievedStats.totalDriverFwLocalWake); - assertEquals(stats.totalRxPacketWakeCnt, retrievedStats.totalRxDataWake); - assertEquals(stats.rxPktWakeDetails.rxUnicastCnt, retrievedStats.rxUnicast); - assertEquals(stats.rxPktWakeDetails.rxMulticastCnt, retrievedStats.rxMulticast); - assertEquals(stats.rxIcmpPkWakeDetails.icmpPkt, retrievedStats.icmp); - assertEquals(stats.rxIcmpPkWakeDetails.icmp6Pkt, retrievedStats.icmp6); - assertEquals(stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt, - retrievedStats.ipv4RxMulticast); - assertEquals(stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt, - retrievedStats.ipv6Multicast); + assertTrue(mListCaptor.getValue().isEmpty()); } /** @@ -2544,12 +1116,7 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testGetWlanWakeReasonCountFailure() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) { - cb.onValues(mWifiStatusFailure, new WifiDebugHostWakeReasonStats()); - } - }).when(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); + when(mWifiChip.getDebugHostWakeReasonStats()).thenReturn(null); // This should work in both AP & STA mode. assertTrue(mWifiVendorHal.startVendorHal()); @@ -2557,8 +1124,7 @@ public class WifiVendorHalTest extends WifiBaseTest { SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); assertNull(mWifiVendorHal.getWlanWakeReasonCount()); - verify(mIWifiChip).getDebugHostWakeReasonStats( - any(IWifiChip.getDebugHostWakeReasonStatsCallback.class)); + verify(mWifiChip).getDebugHostWakeReasonStats(); } /** @@ -2567,15 +1133,7 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testGetFwMemoryDump() throws Exception { byte [] sample = NativeUtil.hexStringToByteArray("268c7a3fbfa4661c0bdd6a36"); - ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.requestFirmwareDebugDumpCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, halBlob); - } - }).when(mIWifiChip).requestFirmwareDebugDump(any( - IWifiChip.requestFirmwareDebugDumpCallback.class)); + when(mWifiChip.requestFirmwareDebugDump()).thenReturn(sample); assertTrue(mWifiVendorHal.startVendorHalSta()); assertArrayEquals(sample, mWifiVendorHal.getFwMemoryDump()); @@ -2589,15 +1147,7 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testGetDriverStateDump() throws Exception { byte [] sample = NativeUtil.hexStringToByteArray("e83ff543cf80083e6459d20f"); - ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample); - - doAnswer(new AnswerWithArguments() { - public void answer(IWifiChip.requestDriverDebugDumpCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, halBlob); - } - }).when(mIWifiChip).requestDriverDebugDump(any( - IWifiChip.requestDriverDebugDumpCallback.class)); + when(mWifiChip.requestDriverDebugDump()).thenReturn(sample); assertTrue(mWifiVendorHal.startVendorHal()); assertNotNull(mWifiVendorHal.createApIface(null, null, @@ -2611,12 +1161,12 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testBgScanFailureCallback() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); + assertNotNull(mWifiStaIfaceEventCallback); WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); startBgScan(eventHandler); - mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId); + mWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId); verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); } @@ -2626,12 +1176,12 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testBgScanFailureCallbackWithInvalidCmdId() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); + assertNotNull(mWifiStaIfaceEventCallback); WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); startBgScan(eventHandler); - mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId + 1); + mWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId + 1); verify(eventHandler, never()).onScanStatus(WifiNative.WIFI_SCAN_FAILED); } @@ -2641,21 +1191,21 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testBgScanFullScanResults() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); + assertNotNull(mWifiStaIfaceEventCallback); WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); startBgScan(eventHandler); WifiSsid ssid = WifiSsid.fromUtf8Text("This is an SSID"); MacAddress bssid = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); - Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult(ssid, bssid); - mIWifiStaIfaceEventCallback.onBackgroundFullScanResult( - mWifiVendorHal.mScan.cmdId, 5, result.first); + ScanResult result = createFrameworkBgScanResult(ssid, bssid); + mWifiStaIfaceEventCallback.onBackgroundFullScanResult( + mWifiVendorHal.mScan.cmdId, 5, result); ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClass(ScanResult.class); verify(eventHandler).onFullScanResult(scanResultCaptor.capture(), eq(5)); - assertScanResultEqual(result.second, scanResultCaptor.getValue()); + assertScanResultEqual(result, scanResultCaptor.getValue()); } /** @@ -2664,19 +1214,18 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testBgScanScanResults() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); + assertNotNull(mWifiStaIfaceEventCallback); WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); startBgScan(eventHandler); - Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>> data = - createHidlAndFrameworkBgScanDatas(); - mIWifiStaIfaceEventCallback.onBackgroundScanResults( - mWifiVendorHal.mScan.cmdId, data.first); + WifiScanner.ScanData[] data = createFrameworkBgScanDatas(); + mWifiStaIfaceEventCallback.onBackgroundScanResults( + mWifiVendorHal.mScan.cmdId, data); verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); assertScanDatasEqual( - data.second, Arrays.asList(mWifiVendorHal.mScan.latestScanResults)); + Arrays.asList(data), Arrays.asList(mWifiVendorHal.mScan.latestScanResults)); } /** @@ -2684,16 +1233,16 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testBgScanReplacement() throws Exception { - when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(true); assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); + assertNotNull(mWifiStaIfaceEventCallback); WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); startBgScan(eventHandler); int cmdId1 = mWifiVendorHal.mScan.cmdId; startBgScan(eventHandler); assertNotEquals(mWifiVendorHal.mScan.cmdId, cmdId1); - verify(mIWifiStaIface, times(2)).startBackgroundScan(anyInt(), any()); - verify(mIWifiStaIface).stopBackgroundScan(cmdId1); + verify(mWifiStaIface, times(2)).startBackgroundScan(anyInt(), any()); + verify(mWifiStaIface).stopBackgroundScan(cmdId1); } /** @@ -2701,9 +1250,9 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testBgScanStop() throws Exception { - when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(true); assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); + assertNotNull(mWifiStaIfaceEventCallback); WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); startBgScan(eventHandler); @@ -2711,7 +1260,7 @@ public class WifiVendorHalTest extends WifiBaseTest { mWifiVendorHal.stopBgScan(TEST_IFACE_NAME); mWifiVendorHal.stopBgScan(TEST_IFACE_NAME); // second call should not do anything - verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once + verify(mWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once } /** @@ -2719,9 +1268,9 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testBgScanPauseAndRestart() throws Exception { - when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(true); assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiStaIfaceEventCallback); + assertNotNull(mWifiStaIfaceEventCallback); WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); startBgScan(eventHandler); @@ -2729,8 +1278,8 @@ public class WifiVendorHalTest extends WifiBaseTest { mWifiVendorHal.pauseBgScan(TEST_IFACE_NAME); mWifiVendorHal.restartBgScan(TEST_IFACE_NAME); - verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once - verify(mIWifiStaIface, times(2)).startBackgroundScan(eq(cmdId), any()); + verify(mWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once + verify(mWifiStaIface, times(2)).startBackgroundScan(eq(cmdId), any()); } /** @@ -2738,23 +1287,23 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testSetLogHandler() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); + when(mWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(true); WifiNative.WifiLoggerEventHandler eventHandler = mock(WifiNative.WifiLoggerEventHandler.class); assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); + verify(mWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); assertTrue(mWifiVendorHal.startVendorHalSta()); assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); - reset(mIWifiChip); + verify(mWifiChip).enableDebugErrorAlerts(eq(true)); + reset(mWifiChip); // Second call should fail. assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); + verify(mWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); } /** @@ -2762,12 +1311,12 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testResetLogHandler() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); + when(mWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(true); + when(mWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(true); assertFalse(mWifiVendorHal.resetLogHandler()); - verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); - verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer(); + verify(mWifiChip, never()).enableDebugErrorAlerts(anyBoolean()); + verify(mWifiChip, never()).stopLoggingToDebugRingBuffer(); assertTrue(mWifiVendorHal.startVendorHalSta()); @@ -2775,9 +1324,9 @@ public class WifiVendorHalTest extends WifiBaseTest { assertTrue(mWifiVendorHal.setLoggingEventHandler( mock(WifiNative.WifiLoggerEventHandler.class))); assertTrue(mWifiVendorHal.resetLogHandler()); - verify(mIWifiChip).enableDebugErrorAlerts(eq(false)); - verify(mIWifiChip).stopLoggingToDebugRingBuffer(); - reset(mIWifiChip); + verify(mWifiChip).enableDebugErrorAlerts(eq(false)); + verify(mWifiChip).stopLoggingToDebugRingBuffer(); + reset(mWifiChip); } /** @@ -2785,8 +1334,8 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testResetLogHandlerAfterHalStop() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); + when(mWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(true); + when(mWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(true); // Start in STA mode. assertTrue(mWifiVendorHal.startVendorHalSta()); @@ -2794,15 +1343,15 @@ public class WifiVendorHalTest extends WifiBaseTest { // Now set the log handler, succeeds. assertTrue(mWifiVendorHal.setLoggingEventHandler( mock(WifiNative.WifiLoggerEventHandler.class))); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); + verify(mWifiChip).enableDebugErrorAlerts(eq(true)); // Stop mWifiVendorHal.stopVendorHal(); // Reset the log handler after stop, not HAL methods invoked. assertFalse(mWifiVendorHal.resetLogHandler()); - verify(mIWifiChip, never()).enableDebugErrorAlerts(eq(false)); - verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer(); + verify(mWifiChip, never()).enableDebugErrorAlerts(eq(false)); + verify(mWifiChip, never()).stopLoggingToDebugRingBuffer(); // Start in STA mode again. assertTrue(mWifiVendorHal.startVendorHalSta()); @@ -2810,7 +1359,7 @@ public class WifiVendorHalTest extends WifiBaseTest { // Now set the log handler again, should succeed. assertTrue(mWifiVendorHal.setLoggingEventHandler( mock(WifiNative.WifiLoggerEventHandler.class))); - verify(mIWifiChip, times(2)).enableDebugErrorAlerts(eq(true)); + verify(mWifiChip, times(2)).enableDebugErrorAlerts(eq(true)); } /** @@ -2819,9 +1368,8 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testAlertCallback() throws Exception { assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallback); - - testAlertCallbackUsingProvidedCallback(mIWifiChipEventCallback); + assertNotNull(mWifiChipEventCallback); + testAlertCallbackUsingProvidedCallback(mWifiChipEventCallback); } /** @@ -2829,29 +1377,29 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testRingBufferDataCallback() throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); + when(mWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(true); + when(mWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(true); assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallback); + assertNotNull(mWifiChipEventCallback); byte[] errorData = new byte[45]; new Random().nextBytes(errorData); - // Randomly raise the HIDL callback before we register for the log callback. + // Randomly raise the callback before we register for the log callback. // This should be safely ignored. (Not trigger NPE.) - mIWifiChipEventCallback.onDebugRingBufferDataAvailable( - new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); + mWifiChipEventCallback.onDebugRingBufferDataAvailable( + new WifiNative.RingBufferStatus(), errorData); mLooper.dispatchAll(); WifiNative.WifiLoggerEventHandler eventHandler = mock(WifiNative.WifiLoggerEventHandler.class); assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); + verify(mWifiChip).enableDebugErrorAlerts(eq(true)); - // Now raise the HIDL callback, this should be properly handled. - mIWifiChipEventCallback.onDebugRingBufferDataAvailable( - new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); + // Now raise the callback, this should be properly handled. + mWifiChipEventCallback.onDebugRingBufferDataAvailable( + new WifiNative.RingBufferStatus(), errorData); mLooper.dispatchAll(); verify(eventHandler).onRingBufferData( any(WifiNative.RingBufferStatus.class), eq(errorData)); @@ -2859,8 +1407,8 @@ public class WifiVendorHalTest extends WifiBaseTest { // Now stop the logging and invoke the callback. This should be ignored. reset(eventHandler); assertTrue(mWifiVendorHal.resetLogHandler()); - mIWifiChipEventCallback.onDebugRingBufferDataAvailable( - new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData)); + mWifiChipEventCallback.onDebugRingBufferDataAvailable( + new WifiNative.RingBufferStatus(), errorData); mLooper.dispatchAll(); verify(eventHandler, never()).onRingBufferData(anyObject(), anyObject()); } @@ -2880,436 +1428,11 @@ public class WifiVendorHalTest extends WifiBaseTest { } /** - * Test the selectTxPowerScenario HIDL method invocation for 1.0 interface. - * This should return failure since SAR is not supported for this interface version. - */ - @Test - public void testSelectTxPowerScenario_1_0() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.isVoiceCall = true; - - assertTrue(mWifiVendorHal.startVendorHalSta()); - // Should fail because we exposed the 1.0 IWifiChip. - assertFalse(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation for 1.1 interface. - * This should return success. - */ - @Test - public void testSelectTxPowerScenario_1_1() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - sarInfo.isVoiceCall = true; - - // Now expose the 1.1 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_1(mContext, mHalDeviceManager, mHandler, - mWifiGlobals, mSsidTranslator); - when(mIWifiChipV11.selectTxPowerScenario(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11).selectTxPowerScenario( - eq(android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL)); - verify(mIWifiChipV11, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation for 1.2 interface. - * This should return success. - */ - @Test - public void testSelectTxPowerScenario_1_2() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - sarInfo.isVoiceCall = true; - - // Now expose the 1.2 IWifiChip - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.VOICE_CALL)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the resetTxPowerScenario HIDL method invocation for 1.0 interface. - * This should return failure since it does not supprt SAR. - */ - @Test - public void testResetTxPowerScenario_1_0() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - // Should fail because we exposed the 1.0 IWifiChip. - assertFalse(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the resetTxPowerScenario HIDL method invocation for 1.1 interface. - * This should return success. - */ - @Test - public void testResetTxPowerScenario_1_1() throws RemoteException { - // Create a SAR info record - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.1 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_1(mContext, mHalDeviceManager, mHandler, - mWifiGlobals, mSsidTranslator); - when(mIWifiChipV11.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV11).resetTxPowerScenario(); - verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test resetting SAR scenario when not needed, should return true without invoking - * the HAL method. - * This is using HAL 1.1 interface. - */ - @Test - public void testResetTxPowerScenario_not_needed_1_1() throws RemoteException { - InOrder inOrder = inOrder(mIWifiChipV11); - - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.1 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_1(mContext, mHalDeviceManager, mHandler, - mWifiGlobals, mSsidTranslator); - when(mIWifiChipV11.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - /* Calling reset once */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV11).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - sarInfo.reportingSuccessful(); - - /* Calling reset second time */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV11, never()).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt()); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the new resetTxPowerScenario HIDL method invocation for 1.2 interface. - * This should return success. - */ - @Test - public void testResetTxPowerScenario_1_2() throws RemoteException { - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).resetTxPowerScenario(); - verify(mIWifiChipV12, never()).selectTxPowerScenario_1_2(anyInt()); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test resetting SAR scenario when not needed, should return true without invoking - * the HAL method. - * This is using HAL 1.2 interface. - */ - @Test - public void testResetTxPowerScenario_not_needed_1_2() throws RemoteException { - InOrder inOrder = inOrder(mIWifiChipV12); - - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = false; - - // Now expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - /* Calling reset once */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt()); - sarInfo.reportingSuccessful(); - - /* Calling reset second time */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12, never()).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt()); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with SAP and voice call support. - * When SAP is enabled, should result in SAP with near body scenario - * Using IWifiChip 1.2 interface - */ - @Test - public void testSapScenarios_SelectTxPowerV1_2() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - sarInfo.isWifiSapEnabled = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - // ON_BODY_CELL_ON - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_BODY_CELL_ON)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with SAP and voice call support. - * When a voice call is ongoing, should result in cell with near head scenario - * Using IWifiChip 1.2 interface - */ - @Test - public void testVoiceCallScenarios_SelectTxPowerV1_2() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isVoiceCall = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - // ON_HEAD_CELL_ON - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with SAP and voice call support. - * When earpiece is active, should result in cell with near head scenario - * Using IWifiChip 1.2 interface - */ - @Test - public void testEarPieceScenarios_SelectTxPowerV1_2() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isEarPieceActive = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - // ON_HEAD_CELL_ON - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON)); - verify(mIWifiChipV12, never()).resetTxPowerScenario(); - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test setting SAR scenario when not needed, should return true without invoking - * the HAL method. - * This is using HAL 1.2 interface. - */ - @Test - public void testSetTxPowerScenario_not_needed_1_2() throws RemoteException { - InOrder inOrder = inOrder(mIWifiChipV12); - - // Create a SAR info record (no SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - // Now expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - - /* Calling set once */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12).resetTxPowerScenario(); - sarInfo.reportingSuccessful(); - - /* Calling set second time */ - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - inOrder.verify(mIWifiChipV12, never()).resetTxPowerScenario(); - inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt()); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface. - * The following inputs: - * - SAP is enabled - * - No voice call - */ - @Test - public void testSelectTxPowerScenario_1_2_sap() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isWifiSapEnabled = true; - sarInfo.isVoiceCall = false; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_BODY_CELL_ON)); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface. - * The following inputs: - * - SAP is enabled - * - voice call is enabled - */ - @Test - public void testSelectTxPowerScenario_1_2_head_sap_call() throws RemoteException { - // Create a SAR info record (with SAP support) - SarInfo sarInfo = new SarInfo(); - sarInfo.sarVoiceCallSupported = true; - sarInfo.sarSapSupported = true; - - sarInfo.isWifiSapEnabled = true; - sarInfo.isVoiceCall = true; - - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo)); - verify(mIWifiChipV12).selectTxPowerScenario_1_2( - eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON)); - - mWifiVendorHal.stopVendorHal(); - } - - /** - * Test the setLowLatencyMode HIDL method invocation with IWifiChip 1.2 interface. - * Function should return false - */ - @Test - public void testSetLowLatencyMode_1_2() throws RemoteException { - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - assertFalse(mWifiVendorHal.setLowLatencyMode(true)); - assertFalse(mWifiVendorHal.setLowLatencyMode(false)); - } - - /** - * Test the setLowLatencyMode HIDL method invocation with IWifiChip 1.3 interface - */ - @Test - public void testSetLowLatencyMode_1_3_enabled() throws RemoteException { - int mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.LOW; - - // Expose the 1.3 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_3(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV13.setLatencyMode(anyInt())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.setLowLatencyMode(true)); - verify(mIWifiChipV13).setLatencyMode(eq(mode)); - } - - /** - * Test the setLowLatencyMode HIDL method invocation with IWifiChip 1.3 interface - */ - @Test - public void testSetLowLatencyMode_1_3_disabled() throws RemoteException { - int mode = android.hardware.wifi.V1_3.IWifiChip.LatencyMode.NORMAL; - - // Expose the 1.3 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_3(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV13.setLatencyMode(anyInt())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.setLowLatencyMode(false)); - verify(mIWifiChipV13).setLatencyMode(eq(mode)); - } - - /** * Test the STA Iface creation failure due to iface name retrieval failure. */ @Test public void testCreateStaIfaceFailureInIfaceName() throws RemoteException { - doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusFailure, "wlan0"); - } - }).when(mIWifiStaIface).getName(any(IWifiIface.getNameCallback.class)); - + when(mWifiStaIface.getName()).thenReturn(null); assertTrue(mWifiVendorHal.startVendorHal()); assertNull(mWifiVendorHal.createStaIface(null, TEST_WORKSOURCE)); verify(mHalDeviceManager).createStaIface(any(), any(), eq(TEST_WORKSOURCE)); @@ -3320,13 +1443,7 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testCreateApIfaceFailureInIfaceName() throws RemoteException { - doAnswer(new AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusFailure, "wlan0"); - } - }).when(mIWifiApIface).getName(any(IWifiIface.getNameCallback.class)); - + when(mWifiApIface.getName()).thenReturn(null); assertTrue(mWifiVendorHal.startVendorHal()); assertNull(mWifiVendorHal.createApIface( null, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager)); @@ -3344,7 +1461,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).createStaIface(any(), any(), eq(TEST_WORKSOURCE)); assertEquals(TEST_IFACE_NAME, ifaceName); assertTrue(mWifiVendorHal.removeStaIface(ifaceName)); - verify(mHalDeviceManager).removeIface(eq(mIWifiStaIface)); + verify(mHalDeviceManager).removeIface(eq(mWifiStaIface)); } /** @@ -3359,297 +1476,7 @@ public class WifiVendorHalTest extends WifiBaseTest { anyLong(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager)); assertEquals(TEST_IFACE_NAME, ifaceName); assertTrue(mWifiVendorHal.removeApIface(ifaceName)); - verify(mHalDeviceManager).removeIface(eq(mIWifiApIface)); - } - - /** - * Test removeIfaceInstanceFromBridgedApIface - */ - @Test - public void testRemoveIfaceInstanceFromBridgedApIface() throws RemoteException { - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV15.removeIfaceInstanceFromBridgedApIface(any(), any())) - .thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.removeIfaceInstanceFromBridgedApIface(any(), any())); - } - - /** - * Test setCoexUnsafeChannels - */ - @Test - public void testSetCoexUnsafeChannels() throws RemoteException { - assumeTrue(SdkLevel.isAtLeastS()); - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV15.setCoexUnsafeChannels(any(), anyInt())) - .thenReturn(mWifiStatusSuccess); - final List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>(); - unsafeChannels.add(new CoexUnsafeChannel(WifiScanner.WIFI_BAND_24_GHZ, 6)); - unsafeChannels.add(new CoexUnsafeChannel(WifiScanner.WIFI_BAND_5_GHZ, 36)); - final int restrictions = WifiManager.COEX_RESTRICTION_WIFI_DIRECT - | WifiManager.COEX_RESTRICTION_WIFI_AWARE | WifiManager.COEX_RESTRICTION_SOFTAP; - assertTrue(mWifiVendorHal.setCoexUnsafeChannels(unsafeChannels, restrictions)); - } - - /** - * Test the callback handling for the 1.2 HAL. - */ - @Test - public void testAlertCallbackUsing_1_2_EventCallback() throws Exception { - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallbackV12); - - testAlertCallbackUsingProvidedCallback(mIWifiChipEventCallbackV12); - } - - /** - * Verifies setMacAddress() success. - */ - @Test - public void testSetStaMacAddressSuccess() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiStaIfaceV12.setMacAddress(macByteArray)).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.setStaMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - verify(mIWifiStaIfaceV12).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle failure status. - */ - @Test - public void testSetStaMacAddressFailDueToStatusFailure() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiStaIfaceV12.setMacAddress(macByteArray)).thenReturn(mWifiStatusFailure); - - assertFalse(mWifiVendorHal.setStaMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - verify(mIWifiStaIfaceV12).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle RemoteException. - */ - @Test - public void testSetStaMacAddressFailDueToRemoteException() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - doThrow(new RemoteException()).when(mIWifiStaIfaceV12).setMacAddress(macByteArray); - - assertFalse(mWifiVendorHal.setStaMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - verify(mIWifiStaIfaceV12).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() success. - */ - @Test - public void testSetApMacAddressSuccess() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiApIfaceV14.setMacAddress(macByteArray)).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.setApMacAddress(TEST_IFACE_NAME_1, TEST_MAC_ADDRESS)); - verify(mIWifiApIfaceV14).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle failure status. - */ - @Test - public void testSetApMacAddressFailDueToStatusFailure() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - when(mIWifiApIfaceV14.setMacAddress(macByteArray)).thenReturn(mWifiStatusFailure); - - assertFalse(mWifiVendorHal.setApMacAddress(TEST_IFACE_NAME_1, TEST_MAC_ADDRESS)); - verify(mIWifiApIfaceV14).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() can handle RemoteException. - */ - @Test - public void testSetApMacAddressFailDueToRemoteException() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - doThrow(new RemoteException()).when(mIWifiApIfaceV14).setMacAddress(macByteArray); - - assertFalse(mWifiVendorHal.setApMacAddress(TEST_IFACE_NAME_1, TEST_MAC_ADDRESS)); - verify(mIWifiApIfaceV14).setMacAddress(macByteArray); - } - - /** - * Verifies setMacAddress() does not crash with older HALs. - */ - @Test - public void testSetMacAddressDoesNotCrashOnOlderHal() throws Exception { - byte[] macByteArray = TEST_MAC_ADDRESS.toByteArray(); - assertFalse(mWifiVendorHal.setStaMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - assertFalse(mWifiVendorHal.setApMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); - } - - /** - * Verifies resetApMacToFactoryMacAddress resetToFactoryMacAddress() success. - */ - @Test - public void testResetApMacToFactoryMacAddressSuccess() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_5Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV15); - when(mIWifiApIfaceV15.resetToFactoryMacAddress()).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.resetApMacToFactoryMacAddress(TEST_IFACE_NAME_1)); - verify(mIWifiApIfaceV15).resetToFactoryMacAddress(); - } - - /** - * Verifies resetApMacToFactoryMacAddress() can handle failure status. - */ - @Test - public void testResetApMacToFactoryMacAddressFailDueToStatusFailure() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_5Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV15); - when(mIWifiApIfaceV15.resetToFactoryMacAddress()).thenReturn(mWifiStatusFailure); - - assertFalse(mWifiVendorHal.resetApMacToFactoryMacAddress(TEST_IFACE_NAME_1)); - verify(mIWifiApIfaceV15).resetToFactoryMacAddress(); - } - - /** - * Verifies resetApMacToFactoryMacAddress() can handle RemoteException. - */ - @Test - public void testResetApMacToFactoryMacAddressFailDueToRemoteException() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_5Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV15); - doThrow(new RemoteException()).when(mIWifiApIfaceV15).resetToFactoryMacAddress(); - assertFalse(mWifiVendorHal.resetApMacToFactoryMacAddress(TEST_IFACE_NAME_1)); - verify(mIWifiApIfaceV15).resetToFactoryMacAddress(); - } - - /** - * Verifies resetApMacToFactoryMacAddress() does not crash with older HALs. - */ - @Test - public void testResetApMacToFactoryMacAddressDoesNotCrashOnOlderHal() throws Exception { - assertFalse(mWifiVendorHal.resetApMacToFactoryMacAddress(TEST_IFACE_NAME)); - } - - /** - * Verifies getBridgedApInstances() success. - */ - @Test - public void testGetBridgedApInstancesSuccess() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_5.IWifiApIface.getBridgedInstancesCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, - new ArrayList<String>() {{ add(TEST_IFACE_NAME_1); }}); - } - }).when(mIWifiApIfaceV15).getBridgedInstances(any( - android.hardware.wifi.V1_5.IWifiApIface.getBridgedInstancesCallback.class)); - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_5Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV15); - - assertNotNull(mWifiVendorHal.getBridgedApInstances(TEST_IFACE_NAME_1)); - verify(mIWifiApIfaceV15).getBridgedInstances(any()); - } - - /** - * Verifies getBridgedApInstances() can handle failure status. - */ - @Test - public void testGetBridgedApInstancesFailDueToStatusFailure() throws Exception { - doAnswer(new AnswerWithArguments() { - public void answer( - android.hardware.wifi.V1_5.IWifiApIface.getBridgedInstancesCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusFailure, null); - } - }).when(mIWifiApIfaceV15).getBridgedInstances(any( - android.hardware.wifi.V1_5.IWifiApIface.getBridgedInstancesCallback.class)); - - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_5Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV15); - assertNull(mWifiVendorHal.getBridgedApInstances(TEST_IFACE_NAME_1)); - verify(mIWifiApIfaceV15).getBridgedInstances(any()); - } - - /** - * Verifies getBridgedApInstances() can handle RemoteException. - */ - @Test - public void testGetBridgedApInstancesFailDueToRemoteException() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_5Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV15); - doThrow(new RemoteException()).when(mIWifiApIfaceV15).getBridgedInstances(any()); - assertNull(mWifiVendorHal.getBridgedApInstances(TEST_IFACE_NAME_1)); - verify(mIWifiApIfaceV15).getBridgedInstances(any()); - } - - /** - * Verifies getBridgedApInstances() does not crash with older HALs. - */ - @Test - public void testGetBridgedApInstancesNotCrashOnOlderHal() throws Exception { - assertNull(mWifiVendorHal.getBridgedApInstances(TEST_IFACE_NAME)); - } - - /** - * Verifies isSetMacAddressSupported(). - */ - @Test - public void testIsApSetMacAddressSupportedWhenV1_4Support() throws Exception { - mWifiVendorHal = spy(mWifiVendorHal); - when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) - .thenReturn(mIWifiApIfaceV14); - - assertTrue(mWifiVendorHal.isApSetMacAddressSupported(TEST_IFACE_NAME_1)); - } - - /** - * Verifies isSetMacAddressSupported(). - */ - @Test - public void testIsStaSetMacAddressSupportedWhenV1_2Support() throws Exception { - // Expose the 1.2 IWifiStaIface. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - assertTrue(mWifiVendorHal.isStaSetMacAddressSupported(TEST_IFACE_NAME)); - } - - /** - * Verifies isSetMacAddressSupported() does not crash with older HALs. - */ - @Test - public void testIsSetMacAddressSupportedOnOlderHal() throws Exception { - assertFalse(mWifiVendorHal.isStaSetMacAddressSupported(TEST_IFACE_NAME)); - assertFalse(mWifiVendorHal.isApSetMacAddressSupported(TEST_IFACE_NAME)); + verify(mHalDeviceManager).removeIface(eq(mWifiApIface)); } /** @@ -3659,62 +1486,19 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testRadioModeChangeCallbackToDbsMode() throws Exception { startHalInStaModeAndRegisterRadioModeChangeCallback(); - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - RadioModeInfo radioModeInfo1 = new RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_24_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 1; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo1); + WifiChip.IfaceInfo ifaceInfo0 = new WifiChip.IfaceInfo(TEST_IFACE_NAME, 34); + WifiChip.IfaceInfo ifaceInfo1 = new WifiChip.IfaceInfo(TEST_IFACE_NAME_1, 1); - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); - radioModeInfos.add(radioModeInfo0); - radioModeInfos.add(radioModeInfo1); + WifiChip.RadioModeInfo radioModeInfo0 = new WifiChip.RadioModeInfo( + 0, WifiScanner.WIFI_BAND_5_GHZ, Arrays.asList(ifaceInfo0)); + WifiChip.RadioModeInfo radioModeInfo1 = new WifiChip.RadioModeInfo( + 1, WifiScanner.WIFI_BAND_24_GHZ, Arrays.asList(ifaceInfo1)); - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); - mLooper.dispatchAll(); - verify(mVendorHalRadioModeChangeHandler).onDbs(); - - verifyNoMoreInteractions(mVendorHalRadioModeChangeHandler); - } - - /** - * Verifies radio mode change callback to indicate DBS mode using V1.4 callback. - */ - @Test - public void testRadioModeChangeCallbackToDbsModeV14() throws Exception { - startHalInStaModeAndRegisterRadioModeChangeCallback14(); - - android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo radioModeInfo0 = - new android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_6_GHZ; - android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo radioModeInfo1 = - new android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_24_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 1; - - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo1); - - ArrayList<android.hardware.wifi.V1_4.IWifiChipEventCallback.RadioModeInfo> radioModeInfos = - new ArrayList<>(); + ArrayList<WifiChip.RadioModeInfo> radioModeInfos = new ArrayList<>(); radioModeInfos.add(radioModeInfo0); radioModeInfos.add(radioModeInfo1); - mIWifiChipEventCallbackV14.onRadioModeChange_1_4(radioModeInfos); + mWifiChipEventCallback.onRadioModeChange(radioModeInfos); mLooper.dispatchAll(); verify(mVendorHalRadioModeChangeHandler).onDbs(); @@ -3728,26 +1512,19 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testRadioModeChangeCallbackToSbsMode() throws Exception { startHalInStaModeAndRegisterRadioModeChangeCallback(); - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - RadioModeInfo radioModeInfo1 = new RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 36; + WifiChip.IfaceInfo ifaceInfo0 = new WifiChip.IfaceInfo(TEST_IFACE_NAME, 34); + WifiChip.IfaceInfo ifaceInfo1 = new WifiChip.IfaceInfo(TEST_IFACE_NAME_1, 36); - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo1); + WifiChip.RadioModeInfo radioModeInfo0 = new WifiChip.RadioModeInfo( + 0, WifiScanner.WIFI_BAND_5_GHZ, Arrays.asList(ifaceInfo0)); + WifiChip.RadioModeInfo radioModeInfo1 = new WifiChip.RadioModeInfo( + 1, WifiScanner.WIFI_BAND_5_GHZ, Arrays.asList(ifaceInfo1)); - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); + ArrayList<WifiChip.RadioModeInfo> radioModeInfos = new ArrayList<>(); radioModeInfos.add(radioModeInfo0); radioModeInfos.add(radioModeInfo1); - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); + mWifiChipEventCallback.onRadioModeChange(radioModeInfos); mLooper.dispatchAll(); verify(mVendorHalRadioModeChangeHandler).onSbs(WifiScanner.WIFI_BAND_5_GHZ); @@ -3761,23 +1538,15 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testRadioModeChangeCallbackToSccMode() throws Exception { startHalInStaModeAndRegisterRadioModeChangeCallback(); - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 34; + WifiChip.IfaceInfo ifaceInfo0 = new WifiChip.IfaceInfo(TEST_IFACE_NAME, 34); + WifiChip.IfaceInfo ifaceInfo1 = new WifiChip.IfaceInfo(TEST_IFACE_NAME_1, 34); + WifiChip.RadioModeInfo radioModeInfo0 = new WifiChip.RadioModeInfo( + 0, WifiScanner.WIFI_BAND_5_GHZ, Arrays.asList(ifaceInfo0, ifaceInfo1)); - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo0.ifaceInfos.add(ifaceInfo1); - - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); + ArrayList<WifiChip.RadioModeInfo> radioModeInfos = new ArrayList<>(); radioModeInfos.add(radioModeInfo0); - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); + mWifiChipEventCallback.onRadioModeChange(radioModeInfos); mLooper.dispatchAll(); verify(mVendorHalRadioModeChangeHandler).onScc(WifiScanner.WIFI_BAND_5_GHZ); @@ -3791,23 +1560,16 @@ public class WifiVendorHalTest extends WifiBaseTest { public void testRadioModeChangeCallbackToMccMode() throws Exception { startHalInStaModeAndRegisterRadioModeChangeCallback(); - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_BOTH; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 1; - IfaceInfo ifaceInfo1 = new IfaceInfo(); - ifaceInfo1.name = TEST_IFACE_NAME_1; - ifaceInfo1.channel = 36; + WifiChip.IfaceInfo ifaceInfo0 = new WifiChip.IfaceInfo(TEST_IFACE_NAME, 1); + WifiChip.IfaceInfo ifaceInfo1 = new WifiChip.IfaceInfo(TEST_IFACE_NAME_1, 36); - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo0.ifaceInfos.add(ifaceInfo1); + WifiChip.RadioModeInfo radioModeInfo0 = new WifiChip.RadioModeInfo( + 0, WifiScanner.WIFI_BAND_BOTH, Arrays.asList(ifaceInfo0, ifaceInfo1)); - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); + ArrayList<WifiChip.RadioModeInfo> radioModeInfos = new ArrayList<>(); radioModeInfos.add(radioModeInfo0); - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); + mWifiChipEventCallback.onRadioModeChange(radioModeInfos); mLooper.dispatchAll(); verify(mVendorHalRadioModeChangeHandler).onMcc(WifiScanner.WIFI_BAND_BOTH); @@ -3822,23 +1584,18 @@ public class WifiVendorHalTest extends WifiBaseTest { throws Exception { startHalInStaModeAndRegisterRadioModeChangeCallback(); - RadioModeInfo radioModeInfo0 = new RadioModeInfo(); - radioModeInfo0.bandInfo = WifiScanner.WIFI_BAND_24_GHZ; - RadioModeInfo radioModeInfo1 = new RadioModeInfo(); - radioModeInfo1.bandInfo = WifiScanner.WIFI_BAND_5_GHZ; - - IfaceInfo ifaceInfo0 = new IfaceInfo(); - ifaceInfo0.name = TEST_IFACE_NAME; - ifaceInfo0.channel = 34; + WifiChip.IfaceInfo ifaceInfo0 = new WifiChip.IfaceInfo(TEST_IFACE_NAME, 34); - radioModeInfo0.ifaceInfos.add(ifaceInfo0); - radioModeInfo1.ifaceInfos.add(ifaceInfo0); + WifiChip.RadioModeInfo radioModeInfo0 = new WifiChip.RadioModeInfo( + 0, WifiScanner.WIFI_BAND_24_GHZ, Arrays.asList(ifaceInfo0)); + WifiChip.RadioModeInfo radioModeInfo1 = new WifiChip.RadioModeInfo( + 1, WifiScanner.WIFI_BAND_5_GHZ, Arrays.asList(ifaceInfo0)); - ArrayList<RadioModeInfo> radioModeInfos = new ArrayList<>(); + ArrayList<WifiChip.RadioModeInfo> radioModeInfos = new ArrayList<>(); radioModeInfos.add(radioModeInfo0); radioModeInfos.add(radioModeInfo1); - mIWifiChipEventCallbackV12.onRadioModeChange(radioModeInfos); + mWifiChipEventCallback.onRadioModeChange(radioModeInfos); mLooper.dispatchAll(); // Ignored.... @@ -3859,111 +1616,60 @@ public class WifiVendorHalTest extends WifiBaseTest { @Test public void testIsStaApConcurrencySupported() { when(mHalDeviceManager.canDeviceSupportCreateTypeCombo( - argThat(ifaceCombo -> ifaceCombo.get(IfaceType.STA) == 1 - && ifaceCombo.get(IfaceType.AP) == 1))).thenReturn(true); + argThat(ifaceCombo -> ifaceCombo.get(WifiChip.IFACE_TYPE_STA) == 1 + && ifaceCombo.get(WifiChip.IFACE_TYPE_AP) == 1))).thenReturn(true); assertTrue(mWifiVendorHal.isStaApConcurrencySupported()); } @Test public void testIsStaStaConcurrencySupported() { when(mHalDeviceManager.canDeviceSupportCreateTypeCombo( - argThat(ifaceCombo -> ifaceCombo.get(IfaceType.STA) == 2))).thenReturn(true); + argThat(ifaceCombo -> ifaceCombo.get(WifiChip.IFACE_TYPE_STA) == 2))) + .thenReturn(true); assertTrue(mWifiVendorHal.isStaStaConcurrencySupported()); } - @Test - public void testSetMultiStaPrimaryConnection() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV15.setMultiStaPrimaryConnection(any())).thenReturn(mWifiStatusSuccess); - assertTrue(mWifiVendorHal.setMultiStaPrimaryConnection(TEST_IFACE_NAME)); - verify(mIWifiChipV15).setMultiStaPrimaryConnection(TEST_IFACE_NAME); - } - - @Test - public void testSetMultiStaUseCase() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV15.setMultiStaUseCase(MultiStaUseCase.DUAL_STA_TRANSIENT_PREFER_PRIMARY)) - .thenReturn(mWifiStatusSuccess); - when(mIWifiChipV15.setMultiStaUseCase(MultiStaUseCase.DUAL_STA_NON_TRANSIENT_UNBIASED)) - .thenReturn(mWifiStatusFailure); - - assertTrue(mWifiVendorHal.setMultiStaUseCase(WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY)); - verify(mIWifiChipV15).setMultiStaUseCase(MultiStaUseCase.DUAL_STA_TRANSIENT_PREFER_PRIMARY); - - assertFalse(mWifiVendorHal.setMultiStaUseCase(WifiNative.DUAL_STA_NON_TRANSIENT_UNBIASED)); - verify(mIWifiChipV15).setMultiStaUseCase(MultiStaUseCase.DUAL_STA_NON_TRANSIENT_UNBIASED); - - // illegal value. - assertFalse(mWifiVendorHal.setMultiStaUseCase(5)); - } - private void startHalInStaModeAndRegisterRadioModeChangeCallback() { - // Expose the 1.2 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_2(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); mWifiVendorHal.registerRadioModeChangeHandler(mVendorHalRadioModeChangeHandler); assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallbackV12); + assertNotNull(mWifiChipEventCallback); } - private void startHalInStaModeAndRegisterRadioModeChangeCallback14() { - // Expose the 1.4 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_4(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - mWifiVendorHal.registerRadioModeChangeHandler(mVendorHalRadioModeChangeHandler); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallbackV14); - } - - private void startHalInStaModeAndRegisterRadioModeChangeCallback15() { - // Expose the 1.5 IWifiChip. - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - mWifiVendorHal.registerRadioModeChangeHandler(mVendorHalRadioModeChangeHandler); - assertTrue(mWifiVendorHal.startVendorHalSta()); - assertNotNull(mIWifiChipEventCallbackV14); - } - - private void testAlertCallbackUsingProvidedCallback(IWifiChipEventCallback chipCallback) + private void testAlertCallbackUsingProvidedCallback(WifiChip.Callback chipCallback) throws Exception { - when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess); - when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess); + when(mWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(true); + when(mWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(true); int errorCode = 5; byte[] errorData = new byte[45]; new Random().nextBytes(errorData); - // Randomly raise the HIDL callback before we register for the log callback. + // Randomly raise the callback before we register for the log callback. // This should be safely ignored. (Not trigger NPE.) - chipCallback.onDebugErrorAlert( - errorCode, NativeUtil.byteArrayToArrayList(errorData)); + chipCallback.onDebugErrorAlert(errorCode, errorData); mLooper.dispatchAll(); WifiNative.WifiLoggerEventHandler eventHandler = mock(WifiNative.WifiLoggerEventHandler.class); assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler)); - verify(mIWifiChip).enableDebugErrorAlerts(eq(true)); + verify(mWifiChip).enableDebugErrorAlerts(eq(true)); - // Now raise the HIDL callback, this should be properly handled. - chipCallback.onDebugErrorAlert( - errorCode, NativeUtil.byteArrayToArrayList(errorData)); + // Now raise the callback, this should be properly handled. + chipCallback.onDebugErrorAlert(errorCode, errorData); mLooper.dispatchAll(); verify(eventHandler).onWifiAlert(eq(errorCode), eq(errorData)); // Now stop the logging and invoke the callback. This should be ignored. reset(eventHandler); assertTrue(mWifiVendorHal.resetLogHandler()); - chipCallback.onDebugErrorAlert( - errorCode, NativeUtil.byteArrayToArrayList(errorData)); + chipCallback.onDebugErrorAlert(errorCode, errorData); mLooper.dispatchAll(); verify(eventHandler, never()).onWifiAlert(anyInt(), anyObject()); } private void startBgScan(WifiNative.ScanEventHandler eventHandler) throws Exception { - when(mIWifiStaIface.startBackgroundScan( - anyInt(), any(StaBackgroundScanParameters.class))).thenReturn(mWifiStatusSuccess); + when(mWifiStaIface.startBackgroundScan( + anyInt(), any(WifiStaIface.StaBackgroundScanParameters.class))).thenReturn(true); WifiNative.ScanSettings settings = new WifiNative.ScanSettings(); settings.num_buckets = 1; WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings(); @@ -3974,61 +1680,34 @@ public class WifiVendorHalTest extends WifiBaseTest { assertTrue(mWifiVendorHal.startBgScan(TEST_IFACE_NAME, settings, eventHandler)); } - // Create a pair of HIDL scan result and its corresponding framework scan result for - // comparison. - private Pair<StaScanResult, ScanResult> createHidlAndFrameworkBgScanResult( + private ScanResult createFrameworkBgScanResult( @NonNull WifiSsid ssid, @NonNull MacAddress bssid) { - StaScanResult staScanResult = new StaScanResult(); - staScanResult.ssid.addAll(NativeUtil.byteArrayToArrayList(ssid.getBytes())); - staScanResult.bssid = bssid.toByteArray(); - staScanResult.frequency = 2432; - staScanResult.rssi = -45; - staScanResult.timeStampInUs = 5; - WifiInformationElement ie1 = new WifiInformationElement(); - byte[] ie1_data = new byte[56]; - new Random().nextBytes(ie1_data); - ie1.id = 1; - ie1.data.addAll(NativeUtil.byteArrayToArrayList(ie1_data)); - staScanResult.informationElements.add(ie1); - - // Now create the corresponding Scan result structure. ScanResult scanResult = new ScanResult(); scanResult.setWifiSsid(getTranslatedSsid(ssid)); scanResult.BSSID = bssid.toString(); - scanResult.frequency = staScanResult.frequency; - scanResult.level = staScanResult.rssi; - scanResult.timestamp = staScanResult.timeStampInUs; - - return Pair.create(staScanResult, scanResult); + scanResult.frequency = 2432; + scanResult.level = -45; + scanResult.timestamp = 5; + return scanResult; } - // Create a pair of HIDL scan datas and its corresponding framework scan datas for - // comparison. - private Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>> - createHidlAndFrameworkBgScanDatas() { - ArrayList<StaScanData> staScanDatas = new ArrayList<>(); - StaScanData staScanData = new StaScanData(); - + private WifiScanner.ScanData[] createFrameworkBgScanDatas() { byte[] ssidBytes = new byte[8]; byte[] bssidBytes = new byte[6]; Random random = new Random(); random.nextBytes(ssidBytes); random.nextBytes(bssidBytes); - Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult( + ScanResult result = createFrameworkBgScanResult( WifiSsid.fromBytes(ssidBytes), MacAddress.fromBytes(bssidBytes)); - staScanData.results.add(result.first); - staScanData.bucketsScanned = 5; - staScanData.flags = StaScanDataFlagMask.INTERRUPTED; - staScanDatas.add(staScanData); - ArrayList<WifiScanner.ScanData> scanDatas = new ArrayList<>(); + WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1]; ScanResult[] scanResults = new ScanResult[1]; - scanResults[0] = result.second; + scanResults[0] = result; WifiScanner.ScanData scanData = new WifiScanner.ScanData(mWifiVendorHal.mScan.cmdId, 1, - staScanData.bucketsScanned, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults); - scanDatas.add(scanData); - return Pair.create(staScanDatas, scanDatas); + 5, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults); + scanDatas[0] = scanData; + return scanDatas; } private void assertScanResultEqual(ScanResult expected, ScanResult actual) { @@ -4061,60 +1740,4 @@ public class WifiVendorHalTest extends WifiBaseTest { assertScanDataEqual(expected.get(i), actual.get(i)); } } - - /** - * Test setCountryCode gets called when the hal version is V1_5. - */ - @Test - public void testSetCountryCodeWithHalV1_5() throws Exception { - byte[] expected = new byte[]{(byte) 'U', (byte) 'S'}; - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiChipV15.setCountryCode(any())).thenReturn(mWifiStatusSuccess); - - // Invalid cases - assertFalse(mWifiVendorHal.setChipCountryCode(null)); - assertFalse(mWifiVendorHal.setChipCountryCode("")); - assertFalse(mWifiVendorHal.setChipCountryCode("A")); - verify(mIWifiChipV15, never()).setCountryCode(any()); - - //valid country code - assertTrue(mWifiVendorHal.setChipCountryCode("US")); - verify(mIWifiChipV15).setCountryCode(eq(expected)); - } - - @Test - public void testSetScanMode() throws Exception { - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - when(mIWifiStaIfaceV15.setScanMode(anyBoolean())).thenReturn(mWifiStatusSuccess); - - assertTrue(mWifiVendorHal.setScanMode(TEST_IFACE_NAME, true)); - verify(mIWifiStaIfaceV15).setScanMode(true); - - assertTrue(mWifiVendorHal.setScanMode(TEST_IFACE_NAME, false)); - verify(mIWifiStaIfaceV15).setScanMode(false); - } - - @Test - public void testGetUsableChannels() throws Exception { - assertTrue(mWifiVendorHal.startVendorHalSta()); - mWifiVendorHal = new WifiVendorHalSpyV1_5(mContext, mHalDeviceManager, mHandler, - mWifiGlobals); - ArrayList<WifiUsableChannel> channels = new ArrayList<>(); - doAnswer(new AnswerWithArguments() { - public void answer(int band, int mode, int filter, - android.hardware.wifi.V1_5.IWifiChip.getUsableChannelsCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, channels); - } - }).when(mIWifiChipV15).getUsableChannels(anyInt(), anyInt(), anyInt(), - any(android.hardware.wifi.V1_5.IWifiChip.getUsableChannelsCallback.class)); - mWifiVendorHal.getUsableChannels( - WifiScanner.WIFI_BAND_24_GHZ, - WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI, - WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE); - verify(mIWifiChipV15).getUsableChannels(anyInt(), anyInt(), anyInt(), - any(android.hardware.wifi.V1_5.IWifiChip.getUsableChannelsCallback.class)); - } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java index 24be263fcb..e9488c628e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java @@ -16,7 +16,6 @@ package com.android.server.wifi.aware; -import static android.hardware.wifi.V1_0.NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED; import static android.net.wifi.ScanResult.CHANNEL_WIDTH_80MHZ; import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; @@ -46,7 +45,6 @@ import android.app.test.TestAlarmManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.NanStatusType; import android.net.ConnectivityManager; import android.net.MacAddress; import android.net.NetworkCapabilities; @@ -95,6 +93,8 @@ import com.android.server.wifi.MockResources; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiInjector; import com.android.server.wifi.aware.WifiAwareDataPathStateManager.WifiAwareNetworkAgent; +import com.android.server.wifi.hal.WifiNanIface.NanDataPathChannelCfg; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.server.wifi.util.WifiPermissionsWrapper; @@ -550,7 +550,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB); inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(requestorId + i), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), + eq(NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), eq(interfaceName), eq(false), any(), any(), any()); @@ -573,7 +573,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { } inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); agentBinders[i] = agentCaptor.getValue(); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(false), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -669,7 +669,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { // (3) verify the start NDP HAL request inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(0), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), + eq(NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), eq(sAwareInterfacePrefix + "0"), eq(true), any(), any(), any()); @@ -707,7 +707,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(true), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -823,8 +823,8 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { if (i < numNdis) { inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(0), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), - ifNameCaptor.capture(), eq(true), any(), any(), + eq(NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED), anyInt(), + eq(peerDiscoveryMac), ifNameCaptor.capture(), eq(true), any(), any(), any()); interfaces.add(ifNameCaptor.getValue()); @@ -840,7 +840,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(true), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -914,7 +914,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB); inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(0), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), + eq(NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), ifNameCaptor.capture(), eq(true), any(), any(), any()); interfaces.add(ifNameCaptor.getValue()); @@ -934,7 +934,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { first = false; } inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(true), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -1009,8 +1009,9 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { if (i < numNdis) { inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(0), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), - ifNameCaptor.capture(), eq(true), any(), any(), any()); + eq(NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED), anyInt(), + eq(peerDiscoveryMac), ifNameCaptor.capture(), eq(true), any(), any(), + any()); interfaces.add(ifNameCaptor.getValue()); mDut.onInitiateDataPathResponseSuccess(transactionId.getValue(), ndpId + i); @@ -1025,7 +1026,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(true), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -1106,7 +1107,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB); inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(0), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), + eq(NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), ifNameCaptor.capture(), eq(true), any(), any(), any()); interfaces.add(ifNameCaptor.getValue()); @@ -1125,7 +1126,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { first = false; } inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(true), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -1732,13 +1733,13 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrderM.verify(mAwareMetricsMock).recordNdpRequestType(anyInt()); inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), eq(useDirect ? 0 : requestorId), - eq(CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), + eq(NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED), anyInt(), eq(peerDiscoveryMac), eq(sAwareInterfacePrefix + "0"), eq(useDirect), any(), any(), any()); if (immediateHalFailure) { // short-circuit the rest of this test - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.INTERNAL_FAILURE), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.INTERNAL_FAILURE), eq(useDirect), anyLong()); verifyRequestDeclaredUnfullfillable(nr); verifyNoMoreInteractions(mMockNative, mAwareMetricsMock); @@ -1809,7 +1810,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { } else { inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); networkAgent = agentCaptor.getValue(); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(useDirect), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -1835,7 +1836,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); mMockLooper.dispatchAll(); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.INTERNAL_FAILURE), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.INTERNAL_FAILURE), eq(useDirect), anyLong()); } @@ -1936,7 +1937,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNetdWrapper).setInterfaceUp(anyString()); inOrder.verify(mMockNetdWrapper).enableIpv6(anyString()); inOrder.verify(mMockNetworkInterface).setConnected(agentCaptor.capture()); - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(useDirect), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); WifiAwareNetworkInfo netInfo = @@ -1961,7 +1962,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); mMockLooper.dispatchAll(); inOrderM.verify(mAwareMetricsMock).recordNdpStatus( - eq(NanStatusType.INTERNAL_FAILURE), eq(useDirect), anyLong()); + eq(NanStatusCode.INTERNAL_FAILURE), eq(useDirect), anyLong()); } // (4) end data-path (unless didn't get confirmation) @@ -2167,7 +2168,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { inOrder.verify(mMockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(Process.myUid()), any()); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(Process.myUid(), - NanStatusType.SUCCESS, doPublish); + NanStatusCode.SUCCESS, doPublish); mDut.onMessageReceivedNotification(pubSubId, requestorId, peerDiscoveryMac, someMsg.getBytes()); @@ -2448,7 +2449,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { assertEquals(-1, netInfo.getTransportProtocol()); assertEquals(1, mDut.mDataPathMgr.getNumOfNdps()); } - inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusType.SUCCESS), + inOrderM.verify(mAwareMetricsMock).recordNdpStatus(eq(NanStatusCode.SUCCESS), eq(false), anyLong()); inOrderM.verify(mAwareMetricsMock).recordNdpCreation(anyInt(), any(), any()); assertEquals(successNdpIds.size(), mDut.mDataPathMgr.getNumOfNdps()); @@ -2460,7 +2461,7 @@ public class WifiAwareDataPathStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); inOrderM.verify(mAwareMetricsMock).recordNdpStatus( - eq(NanStatusType.INTERNAL_FAILURE), eq(false), anyLong()); + eq(NanStatusCode.INTERNAL_FAILURE), eq(false), anyLong()); mDut.onDataPathEndNotification(ndpId); mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); verify(mMockCm, never()).declareNetworkRequestUnfulfillable(any()); diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java index 38bacade31..62c11dceb1 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java @@ -27,7 +27,6 @@ import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.content.Context; -import android.hardware.wifi.V1_0.NanStatusType; import android.net.wifi.aware.WifiAwareNetworkSpecifier; import android.util.LocalLog; import android.util.Log; @@ -38,6 +37,7 @@ import androidx.test.filters.SmallTest; import com.android.server.wifi.Clock; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.util.MetricsUtils; import com.android.server.wifi.util.WifiPermissionsUtil; @@ -283,8 +283,8 @@ public class WifiAwareMetricsTest extends WifiBaseTest { mDut.recordAttachSession(uid2, false, clients); // a few failures - mDut.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); - mDut.recordAttachStatus(NanStatusType.INTERNAL_FAILURE); + mDut.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE); + mDut.recordAttachStatus(NanStatusCode.INTERNAL_FAILURE); mDut.recordAttachStatus(-5); // invalid // verify @@ -335,49 +335,49 @@ public class WifiAwareMetricsTest extends WifiBaseTest { client1.addSession(new WifiAwareDiscoverySessionState(null, 100, (byte) 0, null, true, false, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySession(uid1, clients); - mDut.recordDiscoveryStatus(uid1, NanStatusType.SUCCESS, true); + mDut.recordDiscoveryStatus(uid1, NanStatusCode.SUCCESS, true); // uid1: publish session 2 client1.addSession(new WifiAwareDiscoverySessionState(null, 101, (byte) 0, null, true, false, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySession(uid1, clients); - mDut.recordDiscoveryStatus(uid1, NanStatusType.SUCCESS, true); + mDut.recordDiscoveryStatus(uid1, NanStatusCode.SUCCESS, true); // uid3: publish session 3 with ranging client3.addSession(new WifiAwareDiscoverySessionState(null, 111, (byte) 0, null, true, true, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySessionWithRanging(uid3, false, -1, -1, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, true); + mDut.recordDiscoveryStatus(uid3, NanStatusCode.SUCCESS, true); // uid2: subscribe session 1 client2.addSession(new WifiAwareDiscoverySessionState(null, 102, (byte) 0, null, false, false, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySession(uid2, clients); - mDut.recordDiscoveryStatus(uid2, NanStatusType.SUCCESS, false); + mDut.recordDiscoveryStatus(uid2, NanStatusCode.SUCCESS, false); // uid2: publish session 2 client2.addSession(new WifiAwareDiscoverySessionState(null, 103, (byte) 0, null, true, false, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySession(uid2, clients); - mDut.recordDiscoveryStatus(uid2, NanStatusType.SUCCESS, false); + mDut.recordDiscoveryStatus(uid2, NanStatusCode.SUCCESS, false); // uid3: subscribe session 3 with ranging: min client3.addSession(new WifiAwareDiscoverySessionState(null, 112, (byte) 0, null, false, true, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySessionWithRanging(uid3, true, 10, -1, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); + mDut.recordDiscoveryStatus(uid3, NanStatusCode.SUCCESS, false); // uid3: subscribe session 3 with ranging: max client3.addSession(new WifiAwareDiscoverySessionState(null, 113, (byte) 0, null, false, true, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySessionWithRanging(uid3, true, -1, 50, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); + mDut.recordDiscoveryStatus(uid3, NanStatusCode.SUCCESS, false); // uid3: subscribe session 3 with ranging: minmax client3.addSession(new WifiAwareDiscoverySessionState(null, 114, (byte) 0, null, false, true, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); mDut.recordDiscoverySessionWithRanging(uid3, true, 0, 110, clients); - mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); + mDut.recordDiscoveryStatus(uid3, NanStatusCode.SUCCESS, false); // uid1: delete session 1 setTime(10); @@ -397,9 +397,9 @@ public class WifiAwareMetricsTest extends WifiBaseTest { false, mClock.getElapsedSinceBootMillis(), false, 0, mLocalLog)); // a few failures - mDut.recordDiscoveryStatus(uid1, NanStatusType.INTERNAL_FAILURE, true); - mDut.recordDiscoveryStatus(uid2, NanStatusType.INTERNAL_FAILURE, false); - mDut.recordDiscoveryStatus(uid2, NanStatusType.NO_RESOURCES_AVAILABLE, false); + mDut.recordDiscoveryStatus(uid1, NanStatusCode.INTERNAL_FAILURE, true); + mDut.recordDiscoveryStatus(uid2, NanStatusCode.INTERNAL_FAILURE, false); + mDut.recordDiscoveryStatus(uid2, NanStatusCode.NO_RESOURCES_AVAILABLE, false); mDut.recordAttachStatus(-5); // invalid // verify @@ -486,28 +486,28 @@ public class WifiAwareMetricsTest extends WifiBaseTest { addNetworkInfoToCache(networkRequestCache, 10, uid1, package1, ndi0, null); mDut.recordNdpCreation(uid1, package1, networkRequestCache); setTime(7); // 2ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, false, 5); + mDut.recordNdpStatus(NanStatusCode.SUCCESS, false, 5); // uid2: ndp (non-secure) on ndi0 WifiAwareNetworkSpecifier ns = addNetworkInfoToCache(networkRequestCache, 11, uid2, package2, ndi0, null); mDut.recordNdpCreation(uid2, package2, networkRequestCache); setTime(10); // 3 ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, false, 7); + mDut.recordNdpStatus(NanStatusCode.SUCCESS, false, 7); // uid2: ndp (secure) on ndi1 (OOB) addNetworkInfoToCache(networkRequestCache, 12, uid2, package2, ndi1, "passphrase of some kind"); mDut.recordNdpCreation(uid2, package2, networkRequestCache); setTime(25); // 15 ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, true, 10); + mDut.recordNdpStatus(NanStatusCode.SUCCESS, true, 10); // uid2: ndp (secure) on ndi0 (OOB) addNetworkInfoToCache(networkRequestCache, 13, uid2, package2, ndi0, "super secret password"); mDut.recordNdpCreation(uid2, package2, networkRequestCache); setTime(36); // 11 ms creation time - mDut.recordNdpStatus(NanStatusType.SUCCESS, true, 25); + mDut.recordNdpStatus(NanStatusCode.SUCCESS, true, 25); // uid2: delete the first NDP networkRequestCache.remove(ns); @@ -516,12 +516,12 @@ public class WifiAwareMetricsTest extends WifiBaseTest { addNetworkInfoToCache(networkRequestCache, 14, uid2, package2, ndi0, null); mDut.recordNdpCreation(uid2, package2, networkRequestCache); setTime(37); // 1 ms creation time! - mDut.recordNdpStatus(NanStatusType.SUCCESS, false, 36); + mDut.recordNdpStatus(NanStatusCode.SUCCESS, false, 36); // a few error codes - mDut.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, false, 0); - mDut.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, false, 0); - mDut.recordNdpStatus(NanStatusType.NO_RESOURCES_AVAILABLE, false, 0); + mDut.recordNdpStatus(NanStatusCode.INTERNAL_FAILURE, false, 0); + mDut.recordNdpStatus(NanStatusCode.INTERNAL_FAILURE, false, 0); + mDut.recordNdpStatus(NanStatusCode.NO_RESOURCES_AVAILABLE, false, 0); // and some durations setTime(150); @@ -611,13 +611,13 @@ public class WifiAwareMetricsTest extends WifiBaseTest { public void testNanStatusTypeHistogram() { SparseIntArray statusHistogram = new SparseIntArray(); - addNanHalStatusToHistogram(NanStatusType.SUCCESS, statusHistogram); + addNanHalStatusToHistogram(NanStatusCode.SUCCESS, statusHistogram); addNanHalStatusToHistogram(-1, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.ALREADY_ENABLED, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.SUCCESS, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.INTERNAL_FAILURE, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.SUCCESS, statusHistogram); - addNanHalStatusToHistogram(NanStatusType.INTERNAL_FAILURE, statusHistogram); + addNanHalStatusToHistogram(NanStatusCode.ALREADY_ENABLED, statusHistogram); + addNanHalStatusToHistogram(NanStatusCode.SUCCESS, statusHistogram); + addNanHalStatusToHistogram(NanStatusCode.INTERNAL_FAILURE, statusHistogram); + addNanHalStatusToHistogram(NanStatusCode.SUCCESS, statusHistogram); + addNanHalStatusToHistogram(NanStatusCode.INTERNAL_FAILURE, statusHistogram); addNanHalStatusToHistogram(55, statusHistogram); addNanHalStatusToHistogram(65, statusHistogram); diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java index c4263a48c9..7d7ea7be41 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java @@ -16,43 +16,24 @@ package com.android.server.wifi.aware; -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_SK_128; -import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; - import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyShort; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.hardware.wifi.V1_0.IWifiNanIface; -import android.hardware.wifi.V1_0.NanBandIndex; -import android.hardware.wifi.V1_0.NanConfigRequest; -import android.hardware.wifi.V1_0.NanDataPathSecurityType; -import android.hardware.wifi.V1_0.NanEnableRequest; -import android.hardware.wifi.V1_0.NanPublishRequest; -import android.hardware.wifi.V1_0.NanRangingIndication; -import android.hardware.wifi.V1_0.NanSubscribeRequest; -import android.hardware.wifi.V1_0.WifiStatus; -import android.hardware.wifi.V1_0.WifiStatusCode; -import android.hardware.wifi.V1_2.NanConfigRequestSupplemental; -import android.net.MacAddress; -import android.net.wifi.aware.ConfigRequest; -import android.net.wifi.aware.PublishConfig; -import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.aware.WifiAwareDataPathSecurityConfig; -import android.os.RemoteException; -import android.util.Pair; - import androidx.test.filters.SmallTest; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.hal.WifiNanIface; import org.junit.Before; import org.junit.Rule; @@ -63,7 +44,6 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.PrintWriter; -import java.util.ArrayList; /** @@ -72,8 +52,7 @@ import java.util.ArrayList; @SmallTest public class WifiAwareNativeApiTest extends WifiBaseTest { @Mock WifiAwareNativeManager mWifiAwareNativeManagerMock; - @Mock IWifiNanIface mIWifiNanIfaceMock; - @Mock android.hardware.wifi.V1_2.IWifiNanIface mIWifiNanIface12Mock; + @Mock WifiNanIface mWifiNanIfaceMock; @Rule public ErrorCollector collector = new ErrorCollector(); @@ -81,16 +60,9 @@ public class WifiAwareNativeApiTest extends WifiBaseTest { MockableWifiAwareNativeApi(WifiAwareNativeManager wifiAwareNativeManager) { super(wifiAwareNativeManager); } - - @Override - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return mIsInterface12 ? mIWifiNanIface12Mock : null; - } } private MockableWifiAwareNativeApi mDut; - private boolean mIsInterface12; - private static final Capabilities CAP = new Capabilities(); /** * Initializes mocks. @@ -98,28 +70,8 @@ public class WifiAwareNativeApiTest extends WifiBaseTest { @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); - - when(mWifiAwareNativeManagerMock.getWifiNanIface()).thenReturn(mIWifiNanIfaceMock); - - WifiStatus status = new WifiStatus(); - status.code = WifiStatusCode.SUCCESS; - when(mIWifiNanIfaceMock.enableRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.configRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.startPublishRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.startSubscribeRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.initiateDataPathRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIfaceMock.respondToDataPathIndicationRequest(anyShort(), any())).thenReturn( - status); - when(mIWifiNanIface12Mock.enableRequest_1_2(anyShort(), any(), any())).thenReturn(status); - when(mIWifiNanIface12Mock.configRequest_1_2(anyShort(), any(), any())).thenReturn(status); - when(mIWifiNanIface12Mock.startPublishRequest(anyShort(), any())).thenReturn(status); - when(mIWifiNanIface12Mock.startSubscribeRequest(anyShort(), any())).thenReturn(status); - - mIsInterface12 = false; - + when(mWifiAwareNativeManagerMock.getWifiNanIface()).thenReturn(mWifiNanIfaceMock); mDut = new MockableWifiAwareNativeApi(mWifiAwareNativeManagerMock); - CAP.supportedCipherSuites = WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 - | WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; } /** @@ -149,444 +101,76 @@ public class WifiAwareNativeApiTest extends WifiBaseTest { } /** - * Validate that the configuration parameters used to manage power state behavior is - * using default values at the default power state. + * Validate disable Aware will pass to the NAN interface, and trigger releaseAware. + * @throws Exception */ @Test - public void testEnableAndConfigPowerSettingsDefaults() throws RemoteException { - byte default5 = 1; - byte default24 = 1; - - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), true, - true, true, false, false); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", default5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", default24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); + public void testDisableConfigRequest() throws Exception { + when(mWifiNanIfaceMock.disable(anyShort())).thenReturn(true); + assertTrue(mDut.disable((short) 10)); + verify(mWifiNanIfaceMock).disable((short) 10); } /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified non-interactive values when in that power state. + * Validate that power configuration params set in the DUT are properly converted to + * {@link WifiNanIface.PowerParameters}. */ @Test - public void testEnableAndConfigPowerSettingsNoneInteractive() throws RemoteException { - byte interactive5 = 2; - byte interactive24 = 3; + public void testConversionToPowerParams() { + ArgumentCaptor<WifiNanIface.PowerParameters> powerParamsCaptor = ArgumentCaptor.forClass( + WifiNanIface.PowerParameters.class); + when(mWifiNanIfaceMock.enableAndConfigure(anyShort(), any(), anyBoolean(), + anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), anyInt(), any())) + .thenReturn(true); - setPowerConfigurationParams(interactive5, interactive24, (byte) -1, (byte) -1); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - false, false, false, false); + // Call enableAndConfigure without changing the config. + mDut.enableAndConfigure((short) 1, null, true, true, + false, true /* isIdle */, true, true, 1); + verify(mWifiNanIfaceMock).enableAndConfigure(anyShort(), any(), anyBoolean(), + anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), + eq(1800), // PARAM_MAC_RANDOM_INTERVAL_SEC_DEFAULT + powerParamsCaptor.capture()); - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", interactive5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", interactive24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); - } + // Expect the default power parameters. + WifiNanIface.PowerParameters powerParams = powerParamsCaptor.getValue(); + assertEquals(powerParams.discoveryWindow24Ghz, 4); // PARAM_DW_24GHZ_IDLE + assertEquals(powerParams.discoveryWindow5Ghz, 0); // PARAM_DW_5GHZ_IDLE + assertEquals(powerParams.discoveryWindow6Ghz, 0); // PARAM_DW_6GHZ_IDLE + assertEquals(powerParams.discoveryBeaconIntervalMs, + 0); // PARAM_DISCOVERY_BEACON_INTERVAL_MS_IDLE + assertEquals(powerParams.numberOfSpatialStreamsInDiscovery, + 0); // PARAM_NUM_SS_IN_DISCOVERY_IDLE + assertFalse(powerParams.enableDiscoveryWindowEarlyTermination); - /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified idle (doze) values when in that power state. - */ - @Test - public void testEnableAndConfigPowerSettingsIdle() throws RemoteException { + // Set custom power configuration params. byte idle5 = 2; byte idle24 = -1; - - setPowerConfigurationParams((byte) -1, (byte) -1, idle5, idle24); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - true, false, true, false); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", idle5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", false, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using default values at the default power state. - * - * Using HAL 1.2: additional power configurations. - */ - @Test - public void testEnableAndConfigPowerSettingsDefaults_1_2() throws RemoteException { - byte default5 = 1; - byte default24 = 1; - - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), true, - true, true, false, true); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", default5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", default24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); - - collector.checkThat("discoveryBeaconIntervalMs", 0, - equalTo(configs.second.discoveryBeaconIntervalMs)); - collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, - equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); - collector.checkThat("enableDiscoveryWindowEarlyTermination", false, - equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified non-interactive values when in that power state. - * - * Using HAL 1.2: additional power configurations. - */ - @Test - public void testEnableAndConfigPowerSettingsNoneInteractive_1_2() throws RemoteException { - byte interactive5 = 2; - byte interactive24 = 3; - - setPowerConfigurationParams(interactive5, interactive24, (byte) -1, (byte) -1); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - false, false, false, true); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", interactive5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-24", interactive24, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .discoveryWindowIntervalVal)); - - // Note: still defaults (i.e. disabled) - will be tweaked for low power - collector.checkThat("discoveryBeaconIntervalMs", 0, - equalTo(configs.second.discoveryBeaconIntervalMs)); - collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, - equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); - collector.checkThat("enableDiscoveryWindowEarlyTermination", false, - equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); - } - - /** - * Validate that the configuration parameters used to manage power state behavior is - * using the specified idle (doze) values when in that power state. - * - * Using HAL 1.2: additional power configurations. - */ - @Test - public void testEnableAndConfigPowerSettingsIdle_1_2() throws RemoteException { - byte idle5 = 2; - byte idle24 = -1; - - setPowerConfigurationParams((byte) -1, (byte) -1, idle5, idle24); - Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = - validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, - true, false, true, true); - - collector.checkThat("validDiscoveryWindowIntervalVal-5", true, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .validDiscoveryWindowIntervalVal)); - collector.checkThat("discoveryWindowIntervalVal-5", idle5, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] - .discoveryWindowIntervalVal)); - collector.checkThat("validDiscoveryWindowIntervalVal-24", false, - equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] - .validDiscoveryWindowIntervalVal)); - - // Note: still defaults (i.e. disabled) - will be tweaked for low power - collector.checkThat("discoveryBeaconIntervalMs", 0, - equalTo(configs.second.discoveryBeaconIntervalMs)); - collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, - equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); - collector.checkThat("enableDiscoveryWindowEarlyTermination", false, - equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); - } - - @Test - public void testDiscoveryRangingSettings() throws RemoteException { - short tid = 666; - byte pid = 34; - int minDistanceMm = 100; - int maxDistanceMm = 555; - // TODO: b/69428593 remove once HAL is converted from CM to MM - short minDistanceCm = (short) (minDistanceMm / 10); - short maxDistanceCm = (short) (maxDistanceMm / 10); - - ArgumentCaptor<NanPublishRequest> pubCaptor = ArgumentCaptor.forClass( - NanPublishRequest.class); - ArgumentCaptor<NanSubscribeRequest> subCaptor = ArgumentCaptor.forClass( - NanSubscribeRequest.class); - - PublishConfig pubDefault = new PublishConfig.Builder().setServiceName("XXX").build(); - PublishConfig pubWithRanging = new PublishConfig.Builder().setServiceName( - "XXX").setRangingEnabled(true).build(); - SubscribeConfig subDefault = new SubscribeConfig.Builder().setServiceName("XXX").build(); - SubscribeConfig subWithMin = new SubscribeConfig.Builder().setServiceName( - "XXX").setMinDistanceMm(minDistanceMm).build(); - SubscribeConfig subWithMax = new SubscribeConfig.Builder().setServiceName( - "XXX").setMaxDistanceMm(maxDistanceMm).build(); - SubscribeConfig subWithMinMax = new SubscribeConfig.Builder().setServiceName( - "XXX").setMinDistanceMm(minDistanceMm).setMaxDistanceMm(maxDistanceMm).build(); - - mDut.publish(tid, pid, pubDefault); - mDut.publish(tid, pid, pubWithRanging); - mDut.subscribe(tid, pid, subDefault); - mDut.subscribe(tid, pid, subWithMin); - mDut.subscribe(tid, pid, subWithMax); - mDut.subscribe(tid, pid, subWithMinMax); - - verify(mIWifiNanIfaceMock, times(2)).startPublishRequest(eq(tid), pubCaptor.capture()); - verify(mIWifiNanIfaceMock, times(4)).startSubscribeRequest(eq(tid), subCaptor.capture()); - - NanPublishRequest halPubReq; - NanSubscribeRequest halSubReq; - - // pubDefault - halPubReq = pubCaptor.getAllValues().get(0); - collector.checkThat("pubDefault.baseConfigs.sessionId", pid, - equalTo(halPubReq.baseConfigs.sessionId)); - collector.checkThat("pubDefault.baseConfigs.rangingRequired", false, - equalTo(halPubReq.baseConfigs.rangingRequired)); - - // pubWithRanging - halPubReq = pubCaptor.getAllValues().get(1); - collector.checkThat("pubWithRanging.baseConfigs.sessionId", pid, - equalTo(halPubReq.baseConfigs.sessionId)); - collector.checkThat("pubWithRanging.baseConfigs.rangingRequired", true, - equalTo(halPubReq.baseConfigs.rangingRequired)); - - // subDefault - halSubReq = subCaptor.getAllValues().get(0); - collector.checkThat("subDefault.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subDefault.baseConfigs.rangingRequired", false, - equalTo(halSubReq.baseConfigs.rangingRequired)); - - // subWithMin - halSubReq = subCaptor.getAllValues().get(1); - collector.checkThat("subWithMin.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subWithMin.baseConfigs.rangingRequired", true, - equalTo(halSubReq.baseConfigs.rangingRequired)); - collector.checkThat("subWithMin.baseConfigs.configRangingIndications", - NanRangingIndication.EGRESS_MET_MASK, - equalTo(halSubReq.baseConfigs.configRangingIndications)); - collector.checkThat("subWithMin.baseConfigs.distanceEgressCm", minDistanceCm, - equalTo(halSubReq.baseConfigs.distanceEgressCm)); - - // subWithMax - halSubReq = subCaptor.getAllValues().get(2); - collector.checkThat("subWithMax.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subWithMax.baseConfigs.rangingRequired", true, - equalTo(halSubReq.baseConfigs.rangingRequired)); - collector.checkThat("subWithMax.baseConfigs.configRangingIndications", - NanRangingIndication.INGRESS_MET_MASK, - equalTo(halSubReq.baseConfigs.configRangingIndications)); - collector.checkThat("subWithMin.baseConfigs.distanceIngressCm", maxDistanceCm, - equalTo(halSubReq.baseConfigs.distanceIngressCm)); - - // subWithMinMax - halSubReq = subCaptor.getAllValues().get(3); - collector.checkThat("subWithMinMax.baseConfigs.sessionId", pid, - equalTo(halSubReq.baseConfigs.sessionId)); - collector.checkThat("subWithMinMax.baseConfigs.rangingRequired", true, - equalTo(halSubReq.baseConfigs.rangingRequired)); - collector.checkThat("subWithMinMax.baseConfigs.configRangingIndications", - NanRangingIndication.INGRESS_MET_MASK | NanRangingIndication.EGRESS_MET_MASK, - equalTo(halSubReq.baseConfigs.configRangingIndications)); - collector.checkThat("subWithMin.baseConfigs.distanceEgressCm", minDistanceCm, - equalTo(halSubReq.baseConfigs.distanceEgressCm)); - collector.checkThat("subWithMin.baseConfigs.distanceIngressCm", maxDistanceCm, - equalTo(halSubReq.baseConfigs.distanceIngressCm)); - } - - /** - * Validate the initiation of NDP for an open link. - */ - @Test - public void testInitiateDataPathOpen() throws Exception { - validateInitiateDataPath( - /* usePmk */ false, - /* usePassphrase */ false, - /* isOutOfBand */ false, - /* publicCipherSuites */ 0, - /* halCipherSuite */ 0); - } - - /** - * Validate the initiation of NDP for an PMK protected link with in-band discovery. - */ - @Test - public void testInitiateDataPathPmkInBand() throws Exception { - validateInitiateDataPath( - /* usePmk */ true, - /* usePassphrase */ false, - /* isOutOfBand */ false, - /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_256, - /* halCipherSuite */ SHARED_KEY_256_MASK); - - } - - /** - * Validate the initiation of NDP for an Passphrase protected link with in-band discovery. - */ - @Test - public void testInitiateDataPathPassphraseInBand() throws Exception { - validateInitiateDataPath( - /* usePmk */ false, - /* usePassphrase */ true, - /* isOutOfBand */ false, - /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, - /* halCipherSuite */ SHARED_KEY_128_MASK); - } - - /** - * Validate the initiation of NDP for an PMK protected link with out-of-band discovery. - */ - @Test - public void testInitiateDataPathPmkOutOfBand() throws Exception { - validateInitiateDataPath( - /* usePmk */ true, - /* usePassphrase */ false, - /* isOutOfBand */ true, - /* supportedCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, - /* expectedCipherSuite */ SHARED_KEY_128_MASK); - } - - /** - * Validate the response to an NDP request for an open link. - */ - @Test - public void testRespondToDataPathRequestOpenInBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ false, - /* usePassphrase */ false, - /* accept */ true, - /* isOutOfBand */ false, - /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_256, - /* halCipherSuite */ SHARED_KEY_256_MASK); - } - - /** - * Validate the response to an NDP request for a PMK-protected link with in-band discovery. - */ - @Test - public void testRespondToDataPathRequestPmkInBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ true, - /* usePassphrase */ false, - /* accept */ true, - /* isOutOfBand */ false, - /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, - /* halCipherSuite */ SHARED_KEY_128_MASK); - } - - /** - * Validate the response to an NDP request for a Passphrase-protected link with in-band - * discovery. - */ - @Test - public void testRespondToDataPathRequestPassphraseInBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ false, - /* usePassphrase */ true, - /* accept */ true, - /* isOutOfBand */ false, - /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_256, - /* halCipherSuite */ SHARED_KEY_256_MASK); - } - - /** - * Validate the response to an NDP request for a PMK-protected link with out-of-band discovery. - */ - @Test - public void testRespondToDataPathRequestPmkOutOfBand() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ true, - /* usePassphrase */ false, - /* accept */ true, - /* isOutOfBand */ true, - /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, - /* halCipherSuite */ SHARED_KEY_128_MASK); - } - - /** - * Validate the response to an NDP request - when request is rejected. - */ - @Test - public void testRespondToDataPathRequestReject() throws Exception { - validateRespondToDataPathRequest( - /* usePmk */ true, - /* usePassphrase */ false, - /* accept */ false, - /* isOutOfBand */ true, - /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, - /* halCipherSuite */ 0); - } - - /** - * Validate disable Aware will pass to the NAN interface, and trigger releaseAware. - * @throws Exception - */ - @Test - public void testDisableConfigRequest() throws Exception { - WifiStatus status = new WifiStatus(); - status.code = WifiStatusCode.SUCCESS; - when(mIWifiNanIfaceMock.disableRequest(anyShort())).thenReturn(status); - assertTrue(mDut.disable((short) 10)); - verify(mIWifiNanIfaceMock).disableRequest((short) 10); - } - - // utilities - - private void setPowerConfigurationParams(byte interactive5, byte interactive24, byte idle5, - byte idle24) { - setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_INACTIVE_KEY, - WifiAwareNativeApi.PARAM_DW_5GHZ, Integer.toString(interactive5), true); - setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_INACTIVE_KEY, - WifiAwareNativeApi.PARAM_DW_24GHZ, Integer.toString(interactive24), true); setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_IDLE_KEY, WifiAwareNativeApi.PARAM_DW_5GHZ, Integer.toString(idle5), true); setSettablePowerParam(WifiAwareNativeApi.POWER_PARAM_IDLE_KEY, WifiAwareNativeApi.PARAM_DW_24GHZ, Integer.toString(idle24), true); + + mDut.enableAndConfigure((short) 1, null, true, true, + false, true /* isIdle */, true, true, 1); + verify(mWifiNanIfaceMock, times(2)).enableAndConfigure(anyShort(), any(), anyBoolean(), + anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), + eq(1800), // PARAM_MAC_RANDOM_INTERVAL_SEC_DEFAULT + powerParamsCaptor.capture()); + + // Expect the updated power parameters. + powerParams = powerParamsCaptor.getValue(); + assertEquals(powerParams.discoveryWindow24Ghz, idle24); + assertEquals(powerParams.discoveryWindow5Ghz, idle5); + assertEquals(powerParams.discoveryWindow6Ghz, 0); // PARAM_DW_6GHZ_IDLE + assertEquals(powerParams.discoveryBeaconIntervalMs, + 0); // PARAM_DISCOVERY_BEACON_INTERVAL_MS_IDLE + assertEquals(powerParams.numberOfSpatialStreamsInDiscovery, + 0); // PARAM_NUM_SS_IN_DISCOVERY_IDLE + assertFalse(powerParams.enableDiscoveryWindowEarlyTermination); } + // utilities + private void setSettablePowerParam(String mode, String name, String value, boolean expectSuccess) { PrintWriter pwMock = mock(PrintWriter.class); @@ -607,217 +191,4 @@ public class WifiAwareNativeApiTest extends WifiBaseTest { collector.checkThat(mDut.onCommand(parentShellMock), equalTo(expectSuccess ? 0 : -1)); } - - private Pair<NanConfigRequest, NanConfigRequestSupplemental> validateEnableAndConfigure( - short transactionId, ConfigRequest configRequest, boolean notifyIdentityChange, - boolean initialConfiguration, boolean isInteractive, boolean isIdle, boolean isHal12) - throws RemoteException { - mIsInterface12 = isHal12; - - mDut.enableAndConfigure(transactionId, configRequest, notifyIdentityChange, - initialConfiguration, isInteractive, isIdle, false, false, 2437); - - ArgumentCaptor<NanEnableRequest> enableReqCaptor = ArgumentCaptor.forClass( - NanEnableRequest.class); - ArgumentCaptor<NanConfigRequest> configReqCaptor = ArgumentCaptor.forClass( - NanConfigRequest.class); - ArgumentCaptor<NanConfigRequestSupplemental> configSuppCaptor = ArgumentCaptor.forClass( - NanConfigRequestSupplemental.class); - NanConfigRequest config; - NanConfigRequestSupplemental configSupp = null; - - if (initialConfiguration) { - if (isHal12) { - verify(mIWifiNanIface12Mock).enableRequest_1_2(eq(transactionId), - enableReqCaptor.capture(), configSuppCaptor.capture()); - configSupp = configSuppCaptor.getValue(); - } else { - verify(mIWifiNanIfaceMock).enableRequest(eq(transactionId), - enableReqCaptor.capture()); - } - config = enableReqCaptor.getValue().configParams; - } else { - if (isHal12) { - verify(mIWifiNanIface12Mock).configRequest_1_2(eq(transactionId), - configReqCaptor.capture(), configSuppCaptor.capture()); - configSupp = configSuppCaptor.getValue(); - } else { - verify(mIWifiNanIfaceMock).configRequest(eq(transactionId), - configReqCaptor.capture()); - } - config = configReqCaptor.getValue(); - } - - collector.checkThat("disableDiscoveryAddressChangeIndication", !notifyIdentityChange, - equalTo(config.disableDiscoveryAddressChangeIndication)); - collector.checkThat("disableStartedClusterIndication", !notifyIdentityChange, - equalTo(config.disableStartedClusterIndication)); - collector.checkThat("disableJoinedClusterIndication", !notifyIdentityChange, - equalTo(config.disableJoinedClusterIndication)); - - return new Pair<>(config, configSupp); - } - - private void validateInitiateDataPath(boolean usePmk, boolean usePassphrase, - boolean isOutOfBand, int publicCipherSuites, int halCipherSuite) - throws Exception { - short tid = 44; - int peerId = 555; - int channelRequestType = - android.hardware.wifi.V1_0.NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED; - int channel = 2146; - byte[] peer = MacAddress.fromString("00:01:02:03:04:05").toByteArray(); - String interfaceName = "aware_data5"; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - String passphrase = "blahblah"; - final byte[] appInfo = "Out-of-band info".getBytes(); - - ArgumentCaptor<android.hardware.wifi.V1_0.NanInitiateDataPathRequest> captor = - ArgumentCaptor.forClass( - android.hardware.wifi.V1_0.NanInitiateDataPathRequest.class); - WifiAwareDataPathSecurityConfig securityConfig = null; - if (usePassphrase) { - securityConfig = new WifiAwareDataPathSecurityConfig - .Builder(publicCipherSuites) - .setPskPassphrase(passphrase) - .build(); - } else if (usePmk) { - securityConfig = new WifiAwareDataPathSecurityConfig - .Builder(publicCipherSuites) - .setPmk(pmk) - .build(); - } - - mDut.initiateDataPath(tid, peerId, channelRequestType, channel, peer, interfaceName, - isOutOfBand, appInfo, CAP, securityConfig); - - verify(mIWifiNanIfaceMock).initiateDataPathRequest(eq(tid), captor.capture()); - - android.hardware.wifi.V1_0.NanInitiateDataPathRequest nidpr = captor.getValue(); - collector.checkThat("peerId", peerId, equalTo(nidpr.peerId)); - collector.checkThat("peerDiscMacAddr", peer, equalTo(nidpr.peerDiscMacAddr)); - collector.checkThat("channelRequestType", channelRequestType, - equalTo(nidpr.channelRequestType)); - collector.checkThat("channel", channel, equalTo(nidpr.channel)); - collector.checkThat("ifaceName", interfaceName, equalTo(nidpr.ifaceName)); - - if (usePmk) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PMK, - equalTo(nidpr.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", halCipherSuite, - equalTo(nidpr.securityConfig.cipherType)); - collector.checkThat("securityConfig.pmk", pmk, equalTo(nidpr.securityConfig.pmk)); - collector.checkThat("securityConfig.passphrase.length", 0, - equalTo(nidpr.securityConfig.passphrase.size())); - } - - if (usePassphrase) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PASSPHRASE, - equalTo(nidpr.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", halCipherSuite, - equalTo(nidpr.securityConfig.cipherType)); - collector.checkThat("securityConfig.passphrase", passphrase.getBytes(), - equalTo(convertArrayListToNativeByteArray(nidpr.securityConfig.passphrase))); - } - - collector.checkThat("appInfo", appInfo, - equalTo(convertArrayListToNativeByteArray(nidpr.appInfo))); - - if ((usePmk || usePassphrase) && isOutOfBand) { - collector.checkThat("serviceNameOutOfBand", - WifiAwareNativeApi.SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(), - equalTo(convertArrayListToNativeByteArray(nidpr.serviceNameOutOfBand))); - } else { - collector.checkThat("serviceNameOutOfBand.length", 0, - equalTo(nidpr.serviceNameOutOfBand.size())); - } - } - - private void validateRespondToDataPathRequest(boolean usePmk, boolean usePassphrase, - boolean accept, boolean isOutOfBand, int publicCipherSuites, int halCipherSuite) - throws Exception { - short tid = 33; - int ndpId = 44; - String interfaceName = "aware_whatever22"; - final byte[] pmk = "01234567890123456789012345678901".getBytes(); - String passphrase = "blahblah"; - final byte[] appInfo = "Out-of-band info".getBytes(); - - ArgumentCaptor<android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest> captor = - ArgumentCaptor.forClass( - android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest.class); - WifiAwareDataPathSecurityConfig securityConfig = null; - if (usePassphrase) { - securityConfig = new WifiAwareDataPathSecurityConfig - .Builder(publicCipherSuites) - .setPskPassphrase(passphrase) - .build(); - } else if (usePmk) { - securityConfig = new WifiAwareDataPathSecurityConfig - .Builder(publicCipherSuites) - .setPmk(pmk) - .build(); - } - - mDut.respondToDataPathRequest(tid, accept, ndpId, interfaceName, - appInfo, isOutOfBand, CAP, securityConfig); - - verify(mIWifiNanIfaceMock).respondToDataPathIndicationRequest(eq(tid), captor.capture()); - - android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest nrtdpir = - captor.getValue(); - collector.checkThat("acceptRequest", accept, equalTo(nrtdpir.acceptRequest)); - collector.checkThat("ndpInstanceId", ndpId, equalTo(nrtdpir.ndpInstanceId)); - collector.checkThat("ifaceName", interfaceName, equalTo(nrtdpir.ifaceName)); - - if (accept) { - if (usePmk) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PMK, - equalTo(nrtdpir.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", halCipherSuite, - equalTo(nrtdpir.securityConfig.cipherType)); - collector.checkThat("securityConfig.pmk", pmk, equalTo(nrtdpir.securityConfig.pmk)); - collector.checkThat("securityConfig.passphrase.length", 0, - equalTo(nrtdpir.securityConfig.passphrase.size())); - } - - if (usePassphrase) { - collector.checkThat("securityConfig.securityType", - NanDataPathSecurityType.PASSPHRASE, - equalTo(nrtdpir.securityConfig.securityType)); - collector.checkThat("securityConfig.cipherType", halCipherSuite, - equalTo(nrtdpir.securityConfig.cipherType)); - collector.checkThat("securityConfig.passphrase", passphrase.getBytes(), - equalTo(convertArrayListToNativeByteArray( - nrtdpir.securityConfig.passphrase))); - } - - collector.checkThat("appInfo", appInfo, - equalTo(convertArrayListToNativeByteArray(nrtdpir.appInfo))); - - if ((usePmk || usePassphrase) && isOutOfBand) { - collector.checkThat("serviceNameOutOfBand", - WifiAwareNativeApi.SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(), - equalTo(convertArrayListToNativeByteArray(nrtdpir.serviceNameOutOfBand))); - } else { - collector.checkThat("serviceNameOutOfBand.length", 0, - equalTo(nrtdpir.serviceNameOutOfBand.size())); - } - } - } - - private byte[] convertArrayListToNativeByteArray(ArrayList<Byte> from) { - if (from == null) { - return null; - } - - byte[] to = new byte[from.size()]; - for (int i = 0; i < from.size(); ++i) { - to[i] = from.get(i); - } - return to; - } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java index 8c9fdf8b24..3aa410c0f2 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java @@ -19,13 +19,13 @@ package com.android.server.wifi.aware; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import android.hardware.wifi.V1_0.IWifiNanIface; import android.hardware.wifi.V1_0.WifiStatus; import android.hardware.wifi.V1_0.WifiStatusCode; import android.os.Handler; @@ -35,6 +35,7 @@ import androidx.test.filters.SmallTest; import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.hal.WifiNanIface; import org.junit.Before; import org.junit.Rule; @@ -56,10 +57,7 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { @Mock private WifiAwareStateManager mWifiAwareStateManagerMock; @Mock private HalDeviceManager mHalDeviceManager; @Mock private WifiAwareNativeCallback mWifiAwareNativeCallback; - @Mock private IWifiNanIface mWifiNanIfaceMock; - @Mock android.hardware.wifi.V1_2.IWifiNanIface mIWifiNanIface12Mock; - @Mock android.hardware.wifi.V1_5.IWifiNanIface mIWifiNanIface15Mock; - @Mock android.hardware.wifi.V1_6.IWifiNanIface mIWifiNanIface16Mock; + @Mock private WifiNanIface mWifiNanIfaceMock; @Mock private Handler mHandlerMock; private ArgumentCaptor<HalDeviceManager.ManagerStatusListener> mManagerStatusListenerCaptor = ArgumentCaptor.forClass(HalDeviceManager.ManagerStatusListener.class); @@ -77,21 +75,6 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { WifiAwareNativeCallback wifiAwareNativeCallback) { super(awareStateManager, halDeviceManager, wifiAwareNativeCallback); } - - @Override - public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { - return (iface == mIWifiNanIface12Mock) ? mIWifiNanIface12Mock : null; - } - - @Override - public android.hardware.wifi.V1_5.IWifiNanIface mockableCastTo_1_5(IWifiNanIface iface) { - return (iface == mIWifiNanIface15Mock) ? mIWifiNanIface15Mock : null; - } - - @Override - public android.hardware.wifi.V1_6.IWifiNanIface mockableCastTo_1_6(IWifiNanIface iface) { - return (iface == mIWifiNanIface16Mock) ? mIWifiNanIface16Mock : null; - } } @Before @@ -101,15 +84,13 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { mStatusOk = new WifiStatus(); mStatusOk.code = WifiStatusCode.SUCCESS; - when(mWifiNanIfaceMock.registerEventCallback(any())).thenReturn(mStatusOk); - when(mIWifiNanIface15Mock.registerEventCallback_1_5(any())).thenReturn(mStatusOk); + when(mWifiNanIfaceMock.registerFrameworkCallback(any())).thenReturn(true); mDut = new MockableWifiAwareNativeManager(mWifiAwareStateManagerMock, mHalDeviceManager, mWifiAwareNativeCallback); mDut.start(mHandlerMock); - mInOrder = inOrder(mWifiAwareStateManagerMock, mHalDeviceManager, mWifiNanIfaceMock, - mIWifiNanIface15Mock); + mInOrder = inOrder(mWifiAwareStateManagerMock, mHalDeviceManager, mWifiNanIfaceMock); // validate (and capture) that register manage status callback mInOrder.verify(mHalDeviceManager).initialize(); @@ -133,7 +114,8 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { // configure HalDeviceManager as ready/wifi started (and to return an interface if // requested) when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any(), any())).thenReturn(mWifiNanIfaceMock); + when(mHalDeviceManager.createNanIface(any(), any(), any())) + .thenReturn(mWifiNanIfaceMock); // 1. onStatusChange (ready/started) mManagerStatusListenerCaptor.getValue().onStatusChanged(); @@ -151,8 +133,7 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { mInOrder.verify(mWifiAwareStateManagerMock).tryToGetAwareCapability(); mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any(), any()); - verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, - mIWifiNanIface15Mock); + verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock); assertNull("Interface non-null!", mDut.getWifiNanIface()); } @@ -165,7 +146,8 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { // configure HalDeviceManager as ready/wifi started (and to return an interface if // requested) when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any(), any())).thenReturn(mWifiNanIfaceMock); + when(mHalDeviceManager.createNanIface(any(), any(), any())) + .thenReturn(mWifiNanIfaceMock); // 1. onStatusChange (ready/started) mManagerStatusListenerCaptor.getValue().onStatusChanged(); @@ -176,7 +158,8 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { mDut.tryToGetAware(TEST_WS); mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), any(), eq(TEST_WS)); - mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); + mInOrder.verify(mWifiNanIfaceMock).registerFrameworkCallback(any()); + mInOrder.verify(mWifiNanIfaceMock).enableVerboseLogging(anyBoolean()); assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); // 3. release (interface released) @@ -190,7 +173,8 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { mDut.tryToGetAware(TEST_WS); mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), any(), eq(TEST_WS)); - mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); + mInOrder.verify(mWifiNanIfaceMock).registerFrameworkCallback(any()); + mInOrder.verify(mWifiNanIfaceMock).enableVerboseLogging(anyBoolean()); assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); // 5. request (nop - already have interface) @@ -210,8 +194,7 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any(), any()); mInOrder.verify(mHalDeviceManager, never()).removeIface(any()); - verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, - mIWifiNanIface15Mock); + verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock); } /** @@ -222,7 +205,8 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { // configure HalDeviceManager as ready/wifi started (and to return an interface if // requested) when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any(), any())).thenReturn(mWifiNanIfaceMock); + when(mHalDeviceManager.createNanIface(any(), any(), any())) + .thenReturn(mWifiNanIfaceMock); // 1. onStatusChange (ready/started) mManagerStatusListenerCaptor.getValue().onStatusChanged(); @@ -233,7 +217,8 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { mDut.tryToGetAware(TEST_WS); mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), any(), eq(TEST_WS)); - mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); + mInOrder.verify(mWifiNanIfaceMock).registerFrameworkCallback(any()); + mInOrder.verify(mWifiNanIfaceMock).enableVerboseLogging(anyBoolean()); assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); // 3. interface gets destroyed @@ -247,32 +232,6 @@ public class WifiAwareNativeManagerTest extends WifiBaseTest { mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any(), any()); mInOrder.verify(mHalDeviceManager, never()).removeIface(any()); - verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, - mIWifiNanIface15Mock); - } - - /** - * Test the basic control flow for HAL 1.5 - validate that the correct event registration - * occurs. - */ - @Test - public void testBasicFlowHal15() throws Exception { - // configure HalDeviceManager as ready/wifi started (and to return an interface if - // requested) - when(mHalDeviceManager.isStarted()).thenReturn(true); - when(mHalDeviceManager.createNanIface(any(), any(), any())) - .thenReturn(mIWifiNanIface15Mock); - - // 1. onStatusChange (ready/started) - mManagerStatusListenerCaptor.getValue().onStatusChanged(); - mInOrder.verify(mWifiAwareStateManagerMock).tryToGetAwareCapability(); - assertNull("Interface non-null!", mDut.getWifiNanIface()); - - // 2. request (interface obtained) - mDut.tryToGetAware(TEST_WS); - mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), - any(), eq(TEST_WS)); - mInOrder.verify(mIWifiNanIface15Mock).registerEventCallback_1_5(any()); - assertEquals("Interface mismatch", mIWifiNanIface15Mock, mDut.getWifiNanIface()); + verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock); } } 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 4ddf8d78af..67759ce3c8 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 @@ -57,8 +57,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.hardware.wifi.V1_0.NanRangingIndication; -import android.hardware.wifi.V1_0.NanStatusType; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.wifi.WifiAvailableChannel; @@ -103,6 +101,8 @@ import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiInjector; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiThreadRunner; +import com.android.server.wifi.hal.WifiNanIface.NanRangingIndication; +import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.WaitingState; import com.android.server.wifi.util.WifiPermissionsUtil; @@ -473,7 +473,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mMockAwareDataPathStatemanager).deleteAllInterfaces(); inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); assertFalse(mDut.isDeviceAttached()); @@ -509,7 +509,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); validateCorrectAwareStatusChangeBroadcast(inOrder); inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); // (3) try connecting and validate that get failure callback (though app should be aware of // non-availability through state change broadcast and/or query API) @@ -574,7 +574,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrderM.verify(mAwareMetricsMock).recordDisableAware(); inOrderM.verify(mAwareMetricsMock).recordDisableUsage(); validateInternalClientInfoCleanedUp(clientId); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); inOrderM.verify(mAwareMetricsMock).recordDisableAware(); assertFalse(mDut.isDeviceAttached()); @@ -584,7 +584,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { configRequest, false, mExtras); mMockLooper.dispatchAll(); inOrder.verify(mockCallback).onConnectFail(anyInt()); - inOrderM.verify(mAwareMetricsMock).recordAttachStatus(NanStatusType.INTERNAL_FAILURE); + inOrderM.verify(mAwareMetricsMock).recordAttachStatus(NanStatusCode.INTERNAL_FAILURE); assertFalse(mDut.isDeviceAttached()); // (5) disable usage again and validate that not much happens @@ -648,8 +648,9 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { 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()); + inOrder.verify(mMockNativeManager).releaseAware(); - inOrder.verify(mockCallback).onConnectFail(NanStatusType.INTERNAL_FAILURE); + inOrder.verify(mockCallback).onConnectFail(NanStatusCode.INTERNAL_FAILURE); validateInternalClientInfoCleanedUp(clientId); verifyNoMoreInteractions(mMockNative, mockCallback); @@ -670,7 +671,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final int pid = 2000; final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; - final int reason = NanStatusType.INTERNAL_FAILURE; + final int reason = NanStatusCode.INTERNAL_FAILURE; final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); final byte[] someMac2 = HexEncoding.decode("060708090A0B".toCharArray(), false); @@ -795,9 +796,9 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNative).publish(anyShort(), eq((byte) 0), eq(publishConfig)); assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_COMMAND_TIMEOUT_TAG)); mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, - NanStatusType.INTERNAL_FAILURE, true); + NanStatusCode.INTERNAL_FAILURE, true); validateInternalNoSessions(clientId); // (3) publish + success @@ -809,7 +810,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, true); verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback, mAwareMetricsMock); } @@ -825,7 +826,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final int pid = 2000; final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; + final int reasonFail = NanStatusCode.INTERNAL_FAILURE; ConfigRequest configRequest = new ConfigRequest.Builder().build(); PublishConfig publishConfig = new PublishConfig.Builder().build(); @@ -896,7 +897,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final int pid = 2000; final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; - final int reasonTerminate = NanStatusType.SUCCESS; + final int reasonTerminate = NanStatusCode.SUCCESS; final byte publishId = 15; ConfigRequest configRequest = new ConfigRequest.Builder().build(); @@ -939,7 +940,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, true); validateCorrectAwareResourcesChangeBroadcast(inOrder); assertEquals(1, mDut.getAvailableAwareResources().getAvailablePublishSessionsCount()); assertEquals(2, mDut.getAvailableAwareResources().getAvailableSubscribeSessionsCount()); @@ -981,7 +982,6 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final int pid = 2000; final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; - final int reasonTerminate = NanStatusType.SUCCESS; final byte publishId = 15; ConfigRequest configRequest = new ConfigRequest.Builder().build(); @@ -1025,7 +1025,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, true); validateCorrectAwareResourcesChangeBroadcast(inOrder); assertEquals(1, mDut.getAvailableAwareResources().getAvailablePublishSessionsCount()); assertEquals(2, mDut.getAvailableAwareResources().getAvailableSubscribeSessionsCount()); @@ -1067,7 +1067,6 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final int pid = 2000; final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; - final int reasonTerminate = NanStatusType.SUCCESS; final byte subscribeId = 15; ConfigRequest configRequest = new ConfigRequest.Builder().build(); @@ -1111,7 +1110,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, false); validateCorrectAwareResourcesChangeBroadcast(inOrder); assertEquals(2, mDut.getAvailableAwareResources().getAvailablePublishSessionsCount()); assertEquals(1, mDut.getAvailableAwareResources().getAvailableSubscribeSessionsCount()); @@ -1156,7 +1155,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; final byte publishId = 15; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; + final int reasonFail = NanStatusCode.INTERNAL_FAILURE; ConfigRequest configRequest = new ConfigRequest.Builder().build(); PublishConfig publishConfig = new PublishConfig.Builder().setRangingEnabled(true).build(); @@ -1198,7 +1197,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(false), eq(-1), eq(-1), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, true); mMockLooper.dispatchAll(); // Verify reconfigure aware to enable ranging. inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), @@ -1228,7 +1227,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionConfigSuccess(); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, true); // (7) another update + immediate failure when(mMockNative.publish(anyShort(), anyByte(), any())).thenReturn(false); @@ -1248,11 +1247,11 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), eq(publishConfig)); mDut.onSessionConfigFailResponse(transactionId.getValue(), true, - NanStatusType.INVALID_SESSION_ID); + NanStatusCode.INVALID_SESSION_ID); mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INVALID_SESSION_ID); + inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusCode.INVALID_SESSION_ID); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, - NanStatusType.INVALID_SESSION_ID, true); + NanStatusCode.INVALID_SESSION_ID, true); // Verify reconfigure aware to disable ranging. mMockLooper.dispatchAll(); inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), @@ -1330,10 +1329,10 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNative).disable(transactionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, true); inOrderM.verify(mAwareMetricsMock).recordAttachSessionDuration(anyLong()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionDuration(anyLong(), eq(true)); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); inOrderM.verify(mAwareMetricsMock).recordDisableAware(); verify(mMockNativeManager, times(2)).releaseAware(); @@ -1355,7 +1354,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final int pid = 2000; final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; + final int reasonFail = NanStatusCode.INTERNAL_FAILURE; ConfigRequest configRequest = new ConfigRequest.Builder().build(); SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); @@ -1426,7 +1425,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final int pid = 2000; final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; - final int reasonTerminate = NanStatusType.SUCCESS; + final int reasonTerminate = NanStatusCode.SUCCESS; final byte subscribeId = 15; ConfigRequest configRequest = new ConfigRequest.Builder().build(); @@ -1468,7 +1467,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, false); validateCorrectAwareResourcesChangeBroadcast(inOrder); assertEquals(2, mDut.getAvailableAwareResources().getAvailablePublishSessionsCount()); assertEquals(1, mDut.getAvailableAwareResources().getAvailableSubscribeSessionsCount()); @@ -1512,7 +1511,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; final byte subscribeId = 15; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; + final int reasonFail = NanStatusCode.INTERNAL_FAILURE; final int rangeMax = 10; ConfigRequest configRequest = new ConfigRequest.Builder().build(); @@ -1556,7 +1555,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true), eq(-1), eq(rangeMax), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, false); // Verify reconfigure aware to enable ranging. mMockLooper.dispatchAll(); inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), @@ -1586,7 +1585,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionConfigSuccess(); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, false); // (7) another update + immediate failure when(mMockNative.subscribe(anyShort(), anyByte(), any())) @@ -1678,7 +1677,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String callingFeature = "com.google.someFeature"; final String serviceName = "some-service-name"; final String ssi = "some much longer and more arbitrary data"; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; + final int reasonFail = NanStatusCode.INTERNAL_FAILURE; final byte subscribeId = 15; final int requestorId = 22; final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); @@ -1736,7 +1735,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true), eq(rangeMin), eq(rangeMax), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, false); // Verify reconfigure aware to enable ranging. mMockLooper.dispatchAll(); inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), @@ -1829,7 +1828,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String msgToPeer2 = "hey there 0506..."; final int msgToPeerId1 = 546; final int msgToPeerId2 = 9654; - final int reason = NanStatusType.INTERNAL_FAILURE; + final int reason = NanStatusCode.INTERNAL_FAILURE; ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); @@ -2070,7 +2069,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { ssi.getBytes(), messageId, 0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, - NanStatusType.INTERNAL_FAILURE); + NanStatusCode.INTERNAL_FAILURE); validateInternalSendMessageQueuesCleanedUp(messageId); verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); @@ -2160,10 +2159,10 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 2)); short transactionId3 = transactionId.getValue(); - mDut.onMessageSendQueuedFailResponse(transactionId3, NanStatusType.INTERNAL_FAILURE); + mDut.onMessageSendQueuedFailResponse(transactionId3, NanStatusCode.INTERNAL_FAILURE); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 2, - NanStatusType.INTERNAL_FAILURE); + NanStatusCode.INTERNAL_FAILURE); validateInternalSendMessageQueuesCleanedUp(messageId + 2); // (5) send a message and get an immediate failure (configure first) @@ -2177,14 +2176,14 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 3)); short transactionId4 = transactionId.getValue(); inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 3, - NanStatusType.INTERNAL_FAILURE); + NanStatusCode.INTERNAL_FAILURE); validateInternalSendMessageQueuesCleanedUp(messageId + 3); // (6) message send timeout assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_SEND_MESSAGE_TIMEOUT_TAG)); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, - NanStatusType.INTERNAL_FAILURE); + NanStatusCode.INTERNAL_FAILURE); validateInternalSendMessageQueuesCleanedUp(messageId); // (7) firmware response (unlikely - but good to check) @@ -2193,7 +2192,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { // bogus: these didn't even go to firmware or weren't queued mDut.onMessageSendSuccessNotification(transactionId3); - mDut.onMessageSendFailNotification(transactionId4, NanStatusType.INTERNAL_FAILURE); + mDut.onMessageSendFailNotification(transactionId4, NanStatusCode.INTERNAL_FAILURE); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId + 1); @@ -2271,7 +2270,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { // (4) loop and fail until reach retryCount for (int i = 0; i < retryCount; ++i) { - mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); + mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusCode.NO_OTA_ACK); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); @@ -2358,7 +2357,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { // (4) loop and fail until reach retryCount+1 for (int i = 0; i < retryCount + 1; ++i) { - mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); + mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusCode.NO_OTA_ACK); mMockLooper.dispatchAll(); if (i != retryCount) { @@ -2370,7 +2369,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { } inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, - NanStatusType.NO_OTA_ACK); + NanStatusCode.NO_OTA_ACK); validateInternalSendMessageQueuesCleanedUp(messageId); verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); @@ -2596,7 +2595,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback, times(numOfReject * 2)) .onMessageSendFail(messageIdCaptorFail.capture(), - eq(NanStatusType.INTERNAL_FAILURE)); + eq(NanStatusCode.INTERNAL_FAILURE)); // (4) Transmit messages int successNum = 0; @@ -2761,9 +2760,9 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { verify(mockSessionCallback, times(numOfSuccesses)).onMessageSendSuccess(anyInt()); verify(mockSessionCallback, times(numOfFailuresInternalFailure)).onMessageSendFail(anyInt(), - eq(NanStatusType.INTERNAL_FAILURE)); + eq(NanStatusCode.INTERNAL_FAILURE)); verify(mockSessionCallback, times(numOfFailuresNoOta)).onMessageSendFail(anyInt(), - eq(NanStatusType.NO_OTA_ACK)); + eq(NanStatusCode.NO_OTA_ACK)); verifyNoMoreInteractions(mockCallback, mockSessionCallback); } @@ -2924,7 +2923,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { } if (mFailQueueCommandLater != null && mFailQueueCommandLater.contains(messageId)) { - mDut.onMessageSendQueuedFailResponse(transactionId, NanStatusType.INTERNAL_FAILURE); + mDut.onMessageSendQueuedFailResponse(transactionId, NanStatusCode.INTERNAL_FAILURE); } else { if (mQueue.size() <= mMaxQueueDepth) { mQueue.addLast(transactionId); @@ -2932,7 +2931,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mDut.onMessageSendQueuedSuccessResponse(transactionId); } else { mDut.onMessageSendQueuedFailResponse(transactionId, - NanStatusType.FOLLOWUP_TX_QUEUE_FULL); + NanStatusCode.FOLLOWUP_TX_QUEUE_FULL); } } @@ -2953,7 +2952,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { if (mRetryLimit != null && mRetryLimit.containsKey(mid)) { int numRetries = mRetryLimit.get(mid); if (numRetries == -1) { - mDut.onMessageSendFailNotification(tid, NanStatusType.INTERNAL_FAILURE); + mDut.onMessageSendFailNotification(tid, NanStatusCode.INTERNAL_FAILURE); } else { int currentRetries = mTriesUsedByMid.get(mid); if (currentRetries > numRetries) { @@ -2961,7 +2960,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { } else if (currentRetries == numRetries) { mDut.onMessageSendSuccessNotification(tid); } else { - mDut.onMessageSendFailNotification(tid, NanStatusType.NO_OTA_ACK); + mDut.onMessageSendFailNotification(tid, NanStatusCode.NO_OTA_ACK); } mTriesUsedByMid.put(mid, currentRetries + 1); } @@ -3055,7 +3054,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mDut.connect(clientId2, uid, pid, callingPackage, callingFeature, mockCallback2, configRequest2, false, mExtras); mMockLooper.dispatchAll(); - inOrder.verify(mockCallback2).onConnectFail(NanStatusType.INTERNAL_FAILURE); + inOrder.verify(mockCallback2).onConnectFail(NanStatusCode.INTERNAL_FAILURE); validateInternalClientInfoCleanedUp(clientId2); // (3) config3 (compatible with config1) @@ -3249,14 +3248,14 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNative).disable(transactionId.capture()); validateInternalClientInfoCleanedUp(clientId); assertFalse(mDut.isDeviceAttached()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); verify(mMockNativeManager, times(2)).releaseAware(); // (5) trying to publish on the same client: NOP mDut.publish(clientId, publishConfig, mockSessionCallback); mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); // (6) got some callback on original publishId - should be ignored mDut.onSessionTerminatedNotification(publishId, 0, true); @@ -3433,10 +3432,10 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false), eq(false), anyInt()); short transactionIdConfig = transactionId.getValue(); - mDut.onConfigFailedResponse(transactionIdConfig, NanStatusType.INTERNAL_FAILURE); + mDut.onConfigFailedResponse(transactionIdConfig, NanStatusCode.INTERNAL_FAILURE); mMockLooper.dispatchAll(); inOrder.verify(mMockNativeManager).releaseAware(); - inOrder.verify(mockCallback).onConnectFail(NanStatusType.INTERNAL_FAILURE); + inOrder.verify(mockCallback).onConnectFail(NanStatusCode.INTERNAL_FAILURE); verifyNoMoreInteractions(mMockNative, mockCallback); @@ -3491,7 +3490,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { // (3) update-subscribe -> failure mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); } @@ -3547,7 +3546,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { // (3) update-publish -> error mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); + inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusCode.INTERNAL_FAILURE); verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); } @@ -3722,7 +3721,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { validateCorrectAwareStatusChangeBroadcast(inOrder); inOrder.verify(mMockNative).disable(transactionId.capture()); assertFalse(mDut.isDeviceAttached()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); inOrder.verify(mMockNativeManager).releaseAware(); @@ -3795,7 +3794,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockCallback).onAttachTerminate(); validateCorrectAwareStatusChangeBroadcast(inOrder); inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); assertFalse(mDut.isDeviceAttached()); collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); @@ -3930,7 +3929,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockCallback).onAttachTerminate(); validateCorrectAwareStatusChangeBroadcast(inOrder); inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); inOrder.verify(mMockNativeManager).releaseAware(); assertFalse(mDut.isDeviceAttached()); @@ -3991,7 +3990,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockCallback).onConnectSuccess(clientId); // (2) Aware down notification from native - mDut.onAwareDownNotification(NanStatusType.UNSUPPORTED_CONCURRENCY_NAN_DISABLED); + mDut.onAwareDownNotification(NanStatusCode.UNSUPPORTED_CONCURRENCY_NAN_DISABLED); mMockLooper.dispatchAll(); inOrder.verify(mockCallback).onAttachTerminate(); collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); @@ -4026,7 +4025,6 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String callingFeature = "com.google.someFeature"; final String serviceName = "some-service-name"; final String ssi = "some much longer and more arbitrary data"; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; final byte subscribeId = 15; final int requestorId = 22; final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); @@ -4084,7 +4082,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true), eq(rangeMin), eq(rangeMax), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, false); // Verify reconfigure aware to enable ranging. mMockLooper.dispatchAll(); inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), @@ -4227,7 +4225,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mMockAwareDataPathStatemanager).deleteAllInterfaces(); inOrder.verify(mMockNative).disable(transactionId.capture()); assertFalse(mDut.isDeviceAttached()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); inOrderM.verify(mAwareMetricsMock).recordAttachSessionDuration(anyLong()); inOrderM.verify(mAwareMetricsMock).recordDisableAware(); @@ -4304,7 +4302,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrderM.verify(mAwareMetricsMock).recordDisableAware(); inOrderM.verify(mAwareMetricsMock).recordDisableUsage(); validateInternalClientInfoCleanedUp(clientId); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); inOrderM.verify(mAwareMetricsMock).recordDisableAware(); @@ -4332,7 +4330,6 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String callingPackage = "com.google.somePackage"; final String callingFeature = "com.google.someFeature"; final byte publishId = 15; - final int reasonFail = NanStatusType.INTERNAL_FAILURE; ConfigRequest configRequest = new ConfigRequest.Builder().build(); PublishConfig publishConfig = new PublishConfig.Builder().setRangingEnabled(true).build(); @@ -4374,7 +4371,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(false), eq(-1), eq(-1), any()); - inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusCode.SUCCESS, true); mMockLooper.dispatchAll(); // Verify reconfigure aware to enable ranging. inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), @@ -4384,11 +4381,11 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { mDut.disconnect(clientId); mMockLooper.dispatchAll(); - inOrder.verify(mockSessionCallback).onSessionTerminated(NanStatusType.SUCCESS); + inOrder.verify(mockSessionCallback).onSessionTerminated(NanStatusCode.SUCCESS); inOrder.verify(mMockNative).stopPublish(anyShort(), eq(publishId)); inOrder.verify(mockCallback).onAttachTerminate(); inOrder.verify(mMockNative).disable(transactionId.capture()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusType.SUCCESS); + mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); mMockLooper.dispatchAll(); inOrderM.verify(mAwareMetricsMock).recordAttachSessionDuration(anyLong()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionDuration(anyLong(), eq(true)); @@ -4460,7 +4457,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { verify(mMockNative).enableAndConfigure(anyShort(), eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false), eq(false), anyInt()); } else { - verify(mockCallback).onConnectFail(NanStatusType.NO_RESOURCES_AVAILABLE); + verify(mockCallback).onConnectFail(NanStatusCode.NO_RESOURCES_AVAILABLE); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/HalTestUtils.java b/service/tests/wifitests/src/com/android/server/wifi/hal/HalTestUtils.java new file mode 100644 index 0000000000..abd1b1cc40 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/HalTestUtils.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertEquals; + +import static org.mockito.Mockito.when; + +import java.util.function.Supplier; + +public class HalTestUtils { + /** + * Check that we get the expected return value when the specified method is called. + * + * @param calledMethod Method to call on mDut. + * @param mockedMethod Method called by mDut to retrieve the value. + * @param value Value that the mockedMethod should return. + */ + public static <T> void verifyReturnValue(Supplier<T> calledMethod, T mockedMethod, T value) { + when(mockedMethod).thenReturn(value); + T retrievedValue = calledMethod.get(); + assertEquals(value, retrievedValue); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiApIfaceTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiApIfaceTest.java new file mode 100644 index 0000000000..d4f9c3aec4 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiApIfaceTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNull; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.net.MacAddress; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class WifiApIfaceTest { + // HAL mocks + @Mock android.hardware.wifi.V1_0.IWifiApIface mIWifiApIfaceHidlMock; + @Mock android.hardware.wifi.IWifiApIface mIWifiApIfaceAidlMock; + + // Framework HIDL/AIDL implementation mocks + @Mock WifiApIfaceHidlImpl mWifiApIfaceHidlImplMock; + @Mock WifiApIfaceAidlImpl mWifiApIfaceAidlImplMock; + + private WifiApIface mDut; + + private class WifiApIfaceSpy extends WifiApIface { + WifiApIfaceSpy(android.hardware.wifi.V1_0.IWifiApIface apIface) { + super(apIface); + } + + WifiApIfaceSpy(android.hardware.wifi.IWifiApIface apIface) { + super(apIface); + } + + @Override + protected WifiApIfaceHidlImpl createWifiApIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiApIface apIface) { + return mWifiApIfaceHidlImplMock; + } + + @Override + protected WifiApIfaceAidlImpl createWifiApIfaceAidlImplMockable( + android.hardware.wifi.IWifiApIface apIface) { + return mWifiApIfaceAidlImplMock; + } + } + + private class NullWifiApIfaceSpy extends WifiApIface { + NullWifiApIfaceSpy() { + super(mIWifiApIfaceAidlMock); + } + + @Override + protected WifiApIfaceAidlImpl createWifiApIfaceAidlImplMockable( + android.hardware.wifi.IWifiApIface apIface) { + return null; + } + } + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + mDut = new WifiApIfaceSpy(mIWifiApIfaceAidlMock); + } + + /** + * Test that we can initialize using the HIDL implementation. + */ + @Test + public void testInitWithHidlImpl() { + mDut = new WifiApIfaceSpy(mIWifiApIfaceHidlMock); + mDut.getName(); + verify(mWifiApIfaceHidlImplMock).getName(); + verify(mWifiApIfaceAidlImplMock, never()).getName(); + } + + /** + * Test the case where the creation of the xIDL implementation + * fails, so mWifiApIface is null. + */ + @Test + public void testInitFailureCase() { + mDut = new NullWifiApIfaceSpy(); + assertNull(mDut.getName()); + verify(mWifiApIfaceHidlImplMock, never()).getName(); + verify(mWifiApIfaceAidlImplMock, never()).getName(); + } + + @Test + public void testGetName() { + HalTestUtils.verifyReturnValue( + () -> mDut.getName(), + mWifiApIfaceAidlImplMock.getName(), + "wlan0"); + verify(mWifiApIfaceAidlImplMock).getName(); + } + + @Test + public void testSetCountryCode() { + HalTestUtils.verifyReturnValue( + () -> mDut.setCountryCode("MX"), + mWifiApIfaceAidlImplMock.setCountryCode(any()), + true); + verify(mWifiApIfaceAidlImplMock).setCountryCode(any()); + } + + /** + * Test that setCountryCode rejects invalid country codes. + */ + @Test + public void testSetCountryCodeInvalidInput() { + when(mWifiApIfaceAidlImplMock.setCountryCode(any())).thenReturn(true); + assertFalse(mDut.setCountryCode(null)); + assertFalse(mDut.setCountryCode("")); + assertFalse(mDut.setCountryCode("A")); + assertFalse(mDut.setCountryCode("ABC")); + verify(mWifiApIfaceAidlImplMock, never()).setCountryCode(any()); + } + + @Test + public void testSetMacAddress() { + HalTestUtils.verifyReturnValue( + () -> mDut.setMacAddress(mock(MacAddress.class)), + mWifiApIfaceAidlImplMock.setMacAddress(any()), + true); + verify(mWifiApIfaceAidlImplMock).setMacAddress(any()); + } + + /** + * Test that setMacAddress rejects a null MacAddress. + */ + @Test + public void testSetMacAddressInvalidInput() { + when(mWifiApIfaceAidlImplMock.setMacAddress(any())).thenReturn(true); + assertFalse(mDut.setMacAddress(null)); + verify(mWifiApIfaceAidlImplMock, never()).setMacAddress(any()); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipTest.java new file mode 100644 index 0000000000..7d9eb3e943 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertFalse; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.annotation.NonNull; +import android.content.Context; + +import com.android.server.wifi.SsidTranslator; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class WifiChipTest { + // HAL mocks + @Mock android.hardware.wifi.V1_0.IWifiChip mIWifiChipHidlMock; + @Mock android.hardware.wifi.IWifiChip mIWifiChipAidlMock; + + // Framework HIDL/AIDL implementation mocks + @Mock WifiChipHidlImpl mWifiChipHidlImplMock; + @Mock WifiChipAidlImpl mWifiChipAidlImplMock; + + @Mock Context mContextMock; + @Mock SsidTranslator mSsidTranslatorMock; + + private WifiChip mDut; + + private class WifiChipSpy extends WifiChip { + WifiChipSpy(android.hardware.wifi.V1_0.IWifiChip chip) { + super(chip, mContextMock, mSsidTranslatorMock); + } + + WifiChipSpy(android.hardware.wifi.IWifiChip chip) { + super(chip, mContextMock, mSsidTranslatorMock); + } + + @Override + protected WifiChipHidlImpl createWifiChipHidlImplMockable( + @NonNull android.hardware.wifi.V1_0.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return mWifiChipHidlImplMock; + } + + @Override + protected WifiChipAidlImpl createWifiChipAidlImplMockable( + @NonNull android.hardware.wifi.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return mWifiChipAidlImplMock; + } + } + + private class NullWifiChipSpy extends WifiChip { + NullWifiChipSpy() { + super(mIWifiChipAidlMock, mContextMock, mSsidTranslatorMock); + } + + @Override + protected WifiChipAidlImpl createWifiChipAidlImplMockable( + @NonNull android.hardware.wifi.IWifiChip chip, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return null; + } + } + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + mDut = new WifiChipSpy(mIWifiChipAidlMock); + } + + /** + * Test that we can initialize using the HIDL implementation. + */ + @Test + public void testInitWithHidlImpl() { + mDut = new WifiChipSpy(mIWifiChipHidlMock); + mDut.configureChip(1); + verify(mWifiChipHidlImplMock).configureChip(eq(1)); + verify(mWifiChipAidlImplMock, never()).configureChip(anyInt()); + } + + /** + * Test the case where the creation of the xIDL implementation + * fails, so mWifiChip is null. + */ + @Test + public void testInitFailureCase() { + mDut = new NullWifiChipSpy(); + assertFalse(mDut.configureChip(1)); + verify(mWifiChipHidlImplMock, never()).configureChip(anyInt()); + verify(mWifiChipAidlImplMock, never()).configureChip(anyInt()); + } + + @Test + public void testConfigureChip() { + HalTestUtils.verifyReturnValue( + () -> mDut.configureChip(1), + mWifiChipAidlImplMock.configureChip(anyInt()), + true); + verify(mWifiChipAidlImplMock).configureChip(eq(1)); + } + + @Test + public void testSetCountryCode() { + HalTestUtils.verifyReturnValue( + () -> mDut.setCountryCode("MX"), + mWifiChipAidlImplMock.setCountryCode(any()), + true); + verify(mWifiChipAidlImplMock).setCountryCode(any()); + } + + /** + * Test that setCountryCode rejects invalid country codes. + */ + @Test + public void testSetCountryCodeInvalidInput() { + when(mWifiChipAidlImplMock.setCountryCode(any())).thenReturn(true); + assertFalse(mDut.setCountryCode(null)); + assertFalse(mDut.setCountryCode("")); + assertFalse(mDut.setCountryCode("A")); + assertFalse(mDut.setCountryCode("ABC")); + verify(mWifiChipAidlImplMock, never()).setCountryCode(any()); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiHalTest.java new file mode 100644 index 0000000000..71ef5f3b7f --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiHalTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertNull; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.annotation.NonNull; +import android.content.Context; + +import com.android.server.wifi.SsidTranslator; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class WifiHalTest { + // Framework HIDL/AIDL implementation mocks + @Mock WifiHalHidlImpl mWifiHalHidlImplMock; + @Mock WifiHalAidlImpl mWifiHalAidlImplMock; + + @Mock Context mContextMock; + @Mock SsidTranslator mSsidTranslatorMock; + + private WifiHal mDut; + + private class WifiHalAidlSpy extends WifiHal { + WifiHalAidlSpy() { + super(mContextMock, mSsidTranslatorMock); + } + + @Override + protected IWifiHal createWifiHalMockable(@NonNull Context context, + @NonNull SsidTranslator ssidTranslator) { + return mWifiHalAidlImplMock; + } + } + + private class WifiHalHidlSpy extends WifiHal { + WifiHalHidlSpy() { + super(mContextMock, mSsidTranslatorMock); + } + + @Override + protected IWifiHal createWifiHalMockable(@NonNull Context context, + @NonNull SsidTranslator ssidTranslator) { + return mWifiHalHidlImplMock; + } + } + + private class WifiHalNullSpy extends WifiHal { + WifiHalNullSpy() { + super(mContextMock, mSsidTranslatorMock); + } + + @Override + protected IWifiHal createWifiHalMockable(@NonNull Context context, + @NonNull SsidTranslator ssidTranslator) { + return null; + } + } + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + } + + /** + * Test that we can initialize using the HIDL implementation. + */ + @Test + public void testInitWithHidlImpl() { + mDut = new WifiHalHidlSpy(); + mDut.getChip(1); + verify(mWifiHalHidlImplMock).getChip(eq(1)); + verify(mWifiHalAidlImplMock, never()).getChip(anyInt()); + } + + /** + * Test the case where the creation of the xIDL implementation + * fails, so mWifi is null. + */ + @Test + public void testInitFailureCase() { + mDut = new WifiHalNullSpy(); + assertNull(mDut.getChip(1)); + verify(mWifiHalHidlImplMock, never()).getChip(anyInt()); + verify(mWifiHalAidlImplMock, never()).getChip(anyInt()); + } + + @Test + public void testGetChip() { + mDut = new WifiHalAidlSpy(); + HalTestUtils.verifyReturnValue( + () -> mDut.getChip(1), + mWifiHalAidlImplMock.getChip(anyInt()), + mock(WifiChip.class)); + verify(mWifiHalAidlImplMock).getChip(eq(1)); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceHidlImplTest.java new file mode 100644 index 0000000000..5757cdfcb9 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceHidlImplTest.java @@ -0,0 +1,756 @@ +/* + * Copyright (C) 2022 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.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_SK_128; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyShort; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.hardware.wifi.V1_0.IWifiNanIface; +import android.hardware.wifi.V1_0.NanBandIndex; +import android.hardware.wifi.V1_0.NanConfigRequest; +import android.hardware.wifi.V1_0.NanDataPathSecurityType; +import android.hardware.wifi.V1_0.NanEnableRequest; +import android.hardware.wifi.V1_0.NanPublishRequest; +import android.hardware.wifi.V1_0.NanRangingIndication; +import android.hardware.wifi.V1_0.NanSubscribeRequest; +import android.hardware.wifi.V1_0.WifiStatus; +import android.hardware.wifi.V1_0.WifiStatusCode; +import android.hardware.wifi.V1_2.NanConfigRequestSupplemental; +import android.net.MacAddress; +import android.net.wifi.aware.ConfigRequest; +import android.net.wifi.aware.PublishConfig; +import android.net.wifi.aware.SubscribeConfig; +import android.net.wifi.aware.WifiAwareDataPathSecurityConfig; +import android.os.RemoteException; +import android.util.Pair; + +import com.android.server.wifi.aware.Capabilities; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ErrorCollector; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +public class WifiNanIfaceHidlImplTest { + @Mock IWifiNanIface mIWifiNanIface; + @Mock android.hardware.wifi.V1_2.IWifiNanIface mIWifiNanIface12Mock; + + @Rule public ErrorCollector collector = new ErrorCollector(); + + private class MockableWifiNanIface extends WifiNanIfaceHidlImpl { + MockableWifiNanIface(IWifiNanIface wifiNanIface) { + super(wifiNanIface); + } + + @Override + public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2() { + return mIsInterface12 ? mIWifiNanIface12Mock : null; + } + } + + private boolean mIsInterface12; + private MockableWifiNanIface mDut; + private static final Capabilities CAP = new Capabilities(); + + /** + * Initializes mocks. + */ + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + + WifiStatus status = new WifiStatus(); + status.code = WifiStatusCode.SUCCESS; + when(mIWifiNanIface.enableRequest(anyShort(), any())).thenReturn(status); + when(mIWifiNanIface.configRequest(anyShort(), any())).thenReturn(status); + when(mIWifiNanIface.startPublishRequest(anyShort(), any())).thenReturn(status); + when(mIWifiNanIface.startSubscribeRequest(anyShort(), any())).thenReturn(status); + when(mIWifiNanIface.initiateDataPathRequest(anyShort(), any())).thenReturn(status); + when(mIWifiNanIface.respondToDataPathIndicationRequest(anyShort(), any())).thenReturn( + status); + when(mIWifiNanIface12Mock.enableRequest_1_2(anyShort(), any(), any())).thenReturn(status); + when(mIWifiNanIface12Mock.configRequest_1_2(anyShort(), any(), any())).thenReturn(status); + when(mIWifiNanIface12Mock.startPublishRequest(anyShort(), any())).thenReturn(status); + when(mIWifiNanIface12Mock.startSubscribeRequest(anyShort(), any())).thenReturn(status); + + mIsInterface12 = false; + + mDut = new MockableWifiNanIface(mIWifiNanIface); + CAP.supportedCipherSuites = WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 + | WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; + } + + @Test + public void testDiscoveryRangingSettings() throws RemoteException { + short tid = 250; + byte pid = 34; + int minDistanceMm = 100; + int maxDistanceMm = 555; + short minDistanceCm = (short) (minDistanceMm / 10); + short maxDistanceCm = (short) (maxDistanceMm / 10); + + ArgumentCaptor<NanPublishRequest> pubCaptor = ArgumentCaptor.forClass( + NanPublishRequest.class); + ArgumentCaptor<NanSubscribeRequest> subCaptor = ArgumentCaptor.forClass( + NanSubscribeRequest.class); + + PublishConfig pubDefault = new PublishConfig.Builder().setServiceName("XXX").build(); + PublishConfig pubWithRanging = new PublishConfig.Builder().setServiceName( + "XXX").setRangingEnabled(true).build(); + SubscribeConfig subDefault = new SubscribeConfig.Builder().setServiceName("XXX").build(); + SubscribeConfig subWithMin = new SubscribeConfig.Builder().setServiceName( + "XXX").setMinDistanceMm(minDistanceMm).build(); + SubscribeConfig subWithMax = new SubscribeConfig.Builder().setServiceName( + "XXX").setMaxDistanceMm(maxDistanceMm).build(); + SubscribeConfig subWithMinMax = new SubscribeConfig.Builder().setServiceName( + "XXX").setMinDistanceMm(minDistanceMm).setMaxDistanceMm(maxDistanceMm).build(); + + mDut.publish(tid, pid, pubDefault); + mDut.publish(tid, pid, pubWithRanging); + mDut.subscribe(tid, pid, subDefault); + mDut.subscribe(tid, pid, subWithMin); + mDut.subscribe(tid, pid, subWithMax); + mDut.subscribe(tid, pid, subWithMinMax); + + verify(mIWifiNanIface, times(2)).startPublishRequest(eq(tid), pubCaptor.capture()); + verify(mIWifiNanIface, times(4)).startSubscribeRequest(eq(tid), subCaptor.capture()); + + NanPublishRequest halPubReq; + NanSubscribeRequest halSubReq; + + // pubDefault + halPubReq = pubCaptor.getAllValues().get(0); + collector.checkThat("pubDefault.baseConfigs.sessionId", pid, + equalTo(halPubReq.baseConfigs.sessionId)); + collector.checkThat("pubDefault.baseConfigs.rangingRequired", false, + equalTo(halPubReq.baseConfigs.rangingRequired)); + + // pubWithRanging + halPubReq = pubCaptor.getAllValues().get(1); + collector.checkThat("pubWithRanging.baseConfigs.sessionId", pid, + equalTo(halPubReq.baseConfigs.sessionId)); + collector.checkThat("pubWithRanging.baseConfigs.rangingRequired", true, + equalTo(halPubReq.baseConfigs.rangingRequired)); + + // subDefault + halSubReq = subCaptor.getAllValues().get(0); + collector.checkThat("subDefault.baseConfigs.sessionId", pid, + equalTo(halSubReq.baseConfigs.sessionId)); + collector.checkThat("subDefault.baseConfigs.rangingRequired", false, + equalTo(halSubReq.baseConfigs.rangingRequired)); + + // subWithMin + halSubReq = subCaptor.getAllValues().get(1); + collector.checkThat("subWithMin.baseConfigs.sessionId", pid, + equalTo(halSubReq.baseConfigs.sessionId)); + collector.checkThat("subWithMin.baseConfigs.rangingRequired", true, + equalTo(halSubReq.baseConfigs.rangingRequired)); + collector.checkThat("subWithMin.baseConfigs.configRangingIndications", + NanRangingIndication.EGRESS_MET_MASK, + equalTo(halSubReq.baseConfigs.configRangingIndications)); + collector.checkThat("subWithMin.baseConfigs.distanceEgressCm", minDistanceCm, + equalTo(halSubReq.baseConfigs.distanceEgressCm)); + + // subWithMax + halSubReq = subCaptor.getAllValues().get(2); + collector.checkThat("subWithMax.baseConfigs.sessionId", pid, + equalTo(halSubReq.baseConfigs.sessionId)); + collector.checkThat("subWithMax.baseConfigs.rangingRequired", true, + equalTo(halSubReq.baseConfigs.rangingRequired)); + collector.checkThat("subWithMax.baseConfigs.configRangingIndications", + NanRangingIndication.INGRESS_MET_MASK, + equalTo(halSubReq.baseConfigs.configRangingIndications)); + collector.checkThat("subWithMin.baseConfigs.distanceIngressCm", maxDistanceCm, + equalTo(halSubReq.baseConfigs.distanceIngressCm)); + + // subWithMinMax + halSubReq = subCaptor.getAllValues().get(3); + collector.checkThat("subWithMinMax.baseConfigs.sessionId", pid, + equalTo(halSubReq.baseConfigs.sessionId)); + collector.checkThat("subWithMinMax.baseConfigs.rangingRequired", true, + equalTo(halSubReq.baseConfigs.rangingRequired)); + collector.checkThat("subWithMinMax.baseConfigs.configRangingIndications", + NanRangingIndication.INGRESS_MET_MASK | NanRangingIndication.EGRESS_MET_MASK, + equalTo(halSubReq.baseConfigs.configRangingIndications)); + collector.checkThat("subWithMin.baseConfigs.distanceEgressCm", minDistanceCm, + equalTo(halSubReq.baseConfigs.distanceEgressCm)); + collector.checkThat("subWithMin.baseConfigs.distanceIngressCm", maxDistanceCm, + equalTo(halSubReq.baseConfigs.distanceIngressCm)); + } + + /** + * Validate that the configuration parameters used to manage power state behavior are + * using default values at the default power state. + */ + @Test + public void testEnableAndConfigPowerSettingsDefaults() throws RemoteException { + byte default24 = 1; + byte default5 = 1; + + Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = + validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), true, + true, true, false, default24, default5, false); + + collector.checkThat("validDiscoveryWindowIntervalVal-5", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("validDiscoveryWindowIntervalVal-24", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-5", default5, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .discoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-24", default24, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .discoveryWindowIntervalVal)); + } + + /** + * Validate that the configuration parameters used to manage power state behavior are + * using the specified non-interactive values when in that power state. + */ + @Test + public void testEnableAndConfigPowerSettingsNoneInteractive() throws RemoteException { + byte interactive24 = 3; + byte interactive5 = 2; + + Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = + validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, + false, false, false, interactive24, interactive5, false); + + collector.checkThat("validDiscoveryWindowIntervalVal-5", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-5", interactive5, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .discoveryWindowIntervalVal)); + collector.checkThat("validDiscoveryWindowIntervalVal-24", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-24", interactive24, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .discoveryWindowIntervalVal)); + } + + /** + * Validate that the configuration parameters used to manage power state behavior are + * using the specified idle (doze) values when in that power state. + */ + @Test + public void testEnableAndConfigPowerSettingsIdle() throws RemoteException { + byte idle24 = -1; + byte idle5 = 2; + + Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = + validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, + true, false, true, idle24, idle5, false); + + collector.checkThat("validDiscoveryWindowIntervalVal-5", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-5", idle5, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .discoveryWindowIntervalVal)); + collector.checkThat("validDiscoveryWindowIntervalVal-24", false, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal)); + } + + /** + * Validate that the configuration parameters used to manage power state behavior are + * using default values at the default power state. + * + * Using HAL 1.2: additional power configurations. + */ + @Test + public void testEnableAndConfigPowerSettingsDefaults_1_2() throws RemoteException { + byte default24 = 1; + byte default5 = 1; + + Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = + validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), true, + true, true, false, default24, default5, true); + + collector.checkThat("validDiscoveryWindowIntervalVal-5", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("validDiscoveryWindowIntervalVal-24", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-5", default5, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .discoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-24", default24, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .discoveryWindowIntervalVal)); + + collector.checkThat("discoveryBeaconIntervalMs", 0, + equalTo(configs.second.discoveryBeaconIntervalMs)); + collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, + equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); + collector.checkThat("enableDiscoveryWindowEarlyTermination", false, + equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); + } + + /** + * Validate that the configuration parameters used to manage power state behavior are + * using the specified non-interactive values when in that power state. + * + * Using HAL 1.2: additional power configurations. + */ + @Test + public void testEnableAndConfigPowerSettingsNoneInteractive_1_2() throws RemoteException { + byte interactive24 = 3; + byte interactive5 = 2; + + Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = + validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, + false, false, false, interactive24, interactive5, true); + + collector.checkThat("validDiscoveryWindowIntervalVal-5", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-5", interactive5, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .discoveryWindowIntervalVal)); + collector.checkThat("validDiscoveryWindowIntervalVal-24", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-24", interactive24, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .discoveryWindowIntervalVal)); + + // Note: still defaults (i.e. disabled) - will be tweaked for low power + collector.checkThat("discoveryBeaconIntervalMs", 0, + equalTo(configs.second.discoveryBeaconIntervalMs)); + collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, + equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); + collector.checkThat("enableDiscoveryWindowEarlyTermination", false, + equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); + } + + /** + * Validate that the configuration parameters used to manage power state behavior are + * using the specified idle (doze) values when in that power state. + * + * Using HAL 1.2: additional power configurations. + */ + @Test + public void testEnableAndConfigPowerSettingsIdle_1_2() throws RemoteException { + byte idle24 = -1; + byte idle5 = 2; + + Pair<NanConfigRequest, NanConfigRequestSupplemental> configs = + validateEnableAndConfigure((short) 10, new ConfigRequest.Builder().build(), false, + true, false, true, idle24, idle5, true); + + collector.checkThat("validDiscoveryWindowIntervalVal-5", true, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal)); + collector.checkThat("discoveryWindowIntervalVal-5", idle5, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] + .discoveryWindowIntervalVal)); + collector.checkThat("validDiscoveryWindowIntervalVal-24", false, + equalTo(configs.first.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal)); + + // Note: still defaults (i.e. disabled) - will be tweaked for low power + collector.checkThat("discoveryBeaconIntervalMs", 0, + equalTo(configs.second.discoveryBeaconIntervalMs)); + collector.checkThat("numberOfSpatialStreamsInDiscovery", 0, + equalTo(configs.second.numberOfSpatialStreamsInDiscovery)); + collector.checkThat("enableDiscoveryWindowEarlyTermination", false, + equalTo(configs.second.enableDiscoveryWindowEarlyTermination)); + } + + /** + * Validate the initiation of NDP for an open link. + */ + @Test + public void testInitiateDataPathOpen() throws Exception { + validateInitiateDataPath( + /* usePmk */ false, + /* usePassphrase */ false, + /* isOutOfBand */ false, + /* publicCipherSuites */ 0, + /* halCipherSuite */ 0); + } + + /** + * Validate the initiation of NDP for an PMK protected link with in-band discovery. + */ + @Test + public void testInitiateDataPathPmkInBand() throws Exception { + validateInitiateDataPath( + /* usePmk */ true, + /* usePassphrase */ false, + /* isOutOfBand */ false, + /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_256, + /* halCipherSuite */ SHARED_KEY_256_MASK); + + } + + /** + * Validate the initiation of NDP for an Passphrase protected link with in-band discovery. + */ + @Test + public void testInitiateDataPathPassphraseInBand() throws Exception { + validateInitiateDataPath( + /* usePmk */ false, + /* usePassphrase */ true, + /* isOutOfBand */ false, + /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, + /* halCipherSuite */ SHARED_KEY_128_MASK); + } + + /** + * Validate the initiation of NDP for an PMK protected link with out-of-band discovery. + */ + @Test + public void testInitiateDataPathPmkOutOfBand() throws Exception { + validateInitiateDataPath( + /* usePmk */ true, + /* usePassphrase */ false, + /* isOutOfBand */ true, + /* supportedCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, + /* expectedCipherSuite */ SHARED_KEY_128_MASK); + } + + /** + * Validate the response to an NDP request for an open link. + */ + @Test + public void testRespondToDataPathRequestOpenInBand() throws Exception { + validateRespondToDataPathRequest( + /* usePmk */ false, + /* usePassphrase */ false, + /* accept */ true, + /* isOutOfBand */ false, + /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_256, + /* halCipherSuite */ SHARED_KEY_256_MASK); + } + + /** + * Validate the response to an NDP request for a PMK-protected link with in-band discovery. + */ + @Test + public void testRespondToDataPathRequestPmkInBand() throws Exception { + validateRespondToDataPathRequest( + /* usePmk */ true, + /* usePassphrase */ false, + /* accept */ true, + /* isOutOfBand */ false, + /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, + /* halCipherSuite */ SHARED_KEY_128_MASK); + } + + /** + * Validate the response to an NDP request for a Passphrase-protected link with in-band + * discovery. + */ + @Test + public void testRespondToDataPathRequestPassphraseInBand() throws Exception { + validateRespondToDataPathRequest( + /* usePmk */ false, + /* usePassphrase */ true, + /* accept */ true, + /* isOutOfBand */ false, + /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_256, + /* halCipherSuite */ SHARED_KEY_256_MASK); + } + + /** + * Validate the response to an NDP request for a PMK-protected link with out-of-band discovery. + */ + @Test + public void testRespondToDataPathRequestPmkOutOfBand() throws Exception { + validateRespondToDataPathRequest( + /* usePmk */ true, + /* usePassphrase */ false, + /* accept */ true, + /* isOutOfBand */ true, + /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, + /* halCipherSuite */ SHARED_KEY_128_MASK); + } + + /** + * Validate the response to an NDP request - when request is rejected. + */ + @Test + public void testRespondToDataPathRequestReject() throws Exception { + validateRespondToDataPathRequest( + /* usePmk */ true, + /* usePassphrase */ false, + /* accept */ false, + /* isOutOfBand */ true, + /* publicCipherSuites */ WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, + /* halCipherSuite */ 0); + } + + + // utilities + + private Pair<NanConfigRequest, NanConfigRequestSupplemental> validateEnableAndConfigure( + short transactionId, ConfigRequest configRequest, boolean notifyIdentityChange, + boolean initialConfiguration, boolean isInteractive, boolean isIdle, + int discoveryWindow24Ghz, int discoveryWindow5Ghz, boolean isHal12) + throws RemoteException { + mIsInterface12 = isHal12; + + mDut.enableAndConfigure(transactionId, configRequest, notifyIdentityChange, + initialConfiguration, false, false, 2437, + 1800 /* PARAM_MAC_RANDOM_INTERVAL_SEC_DEFAULT */, + getPowerParams(isInteractive, isIdle, discoveryWindow24Ghz, discoveryWindow5Ghz)); + + ArgumentCaptor<NanEnableRequest> enableReqCaptor = ArgumentCaptor.forClass( + NanEnableRequest.class); + ArgumentCaptor<NanConfigRequest> configReqCaptor = ArgumentCaptor.forClass( + NanConfigRequest.class); + ArgumentCaptor<NanConfigRequestSupplemental> configSuppCaptor = ArgumentCaptor.forClass( + NanConfigRequestSupplemental.class); + NanConfigRequest config; + NanConfigRequestSupplemental configSupp = null; + + if (initialConfiguration) { + if (isHal12) { + verify(mIWifiNanIface12Mock).enableRequest_1_2(eq(transactionId), + enableReqCaptor.capture(), configSuppCaptor.capture()); + configSupp = configSuppCaptor.getValue(); + } else { + verify(mIWifiNanIface).enableRequest(eq(transactionId), + enableReqCaptor.capture()); + } + config = enableReqCaptor.getValue().configParams; + } else { + if (isHal12) { + verify(mIWifiNanIface12Mock).configRequest_1_2(eq(transactionId), + configReqCaptor.capture(), configSuppCaptor.capture()); + configSupp = configSuppCaptor.getValue(); + } else { + verify(mIWifiNanIface).configRequest(eq(transactionId), + configReqCaptor.capture()); + } + config = configReqCaptor.getValue(); + } + + collector.checkThat("disableDiscoveryAddressChangeIndication", !notifyIdentityChange, + equalTo(config.disableDiscoveryAddressChangeIndication)); + collector.checkThat("disableStartedClusterIndication", !notifyIdentityChange, + equalTo(config.disableStartedClusterIndication)); + collector.checkThat("disableJoinedClusterIndication", !notifyIdentityChange, + equalTo(config.disableJoinedClusterIndication)); + + return new Pair<>(config, configSupp); + } + + private WifiNanIface.PowerParameters getPowerParams(boolean isInteractive, boolean isIdle, + int discoveryWindow24Ghz, int discoveryWindow5Ghz) { + WifiNanIface.PowerParameters params = new WifiNanIface.PowerParameters(); + params.discoveryBeaconIntervalMs = 0; // PARAM_DISCOVERY_BEACON_INTERVAL_MS_DEFAULT + params.enableDiscoveryWindowEarlyTermination = false; // PARAM_ENABLE_DW_EARLY_TERM_DEFAULT + params.numberOfSpatialStreamsInDiscovery = 0; // PARAM_NUM_SS_IN_DISCOVERY_DEFAULT + if (isInteractive && !isIdle) { + params.discoveryWindow24Ghz = 1; // PARAM_DW_24GHZ_DEFAULT + params.discoveryWindow5Ghz = 1; // PARAM_DW_5GHZ_DEFAULT + params.discoveryWindow6Ghz = 1; // PARAM_DW_6GHZ_DEFAULT + } else { + params.discoveryWindow24Ghz = discoveryWindow24Ghz; + params.discoveryWindow5Ghz = discoveryWindow5Ghz; + params.discoveryWindow6Ghz = 0; + } + return params; + } + + private void validateInitiateDataPath(boolean usePmk, boolean usePassphrase, + boolean isOutOfBand, int publicCipherSuites, int halCipherSuite) + throws Exception { + short tid = 44; + int peerId = 555; + int channelRequestType = + android.hardware.wifi.V1_0.NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED; + int channel = 2146; + MacAddress peer = MacAddress.fromString("00:01:02:03:04:05"); + String interfaceName = "aware_data5"; + final byte[] pmk = "01234567890123456789012345678901".getBytes(); + String passphrase = "blahblah"; + final byte[] appInfo = "Out-of-band info".getBytes(); + + ArgumentCaptor<android.hardware.wifi.V1_0.NanInitiateDataPathRequest> captor = + ArgumentCaptor.forClass( + android.hardware.wifi.V1_0.NanInitiateDataPathRequest.class); + WifiAwareDataPathSecurityConfig securityConfig = null; + if (usePassphrase) { + securityConfig = new WifiAwareDataPathSecurityConfig + .Builder(publicCipherSuites) + .setPskPassphrase(passphrase) + .build(); + } else if (usePmk) { + securityConfig = new WifiAwareDataPathSecurityConfig + .Builder(publicCipherSuites) + .setPmk(pmk) + .build(); + } + + mDut.initiateDataPath(tid, peerId, channelRequestType, channel, peer, interfaceName, + isOutOfBand, appInfo, CAP, securityConfig); + + verify(mIWifiNanIface).initiateDataPathRequest(eq(tid), captor.capture()); + + android.hardware.wifi.V1_0.NanInitiateDataPathRequest nidpr = captor.getValue(); + collector.checkThat("peerId", peerId, equalTo(nidpr.peerId)); + collector.checkThat("peerDiscMacAddr", peer.toByteArray(), + equalTo(nidpr.peerDiscMacAddr)); + collector.checkThat("channelRequestType", channelRequestType, + equalTo(nidpr.channelRequestType)); + collector.checkThat("channel", channel, equalTo(nidpr.channel)); + collector.checkThat("ifaceName", interfaceName, equalTo(nidpr.ifaceName)); + + if (usePmk) { + collector.checkThat("securityConfig.securityType", + NanDataPathSecurityType.PMK, + equalTo(nidpr.securityConfig.securityType)); + collector.checkThat("securityConfig.cipherType", halCipherSuite, + equalTo(nidpr.securityConfig.cipherType)); + collector.checkThat("securityConfig.pmk", pmk, equalTo(nidpr.securityConfig.pmk)); + collector.checkThat("securityConfig.passphrase.length", 0, + equalTo(nidpr.securityConfig.passphrase.size())); + } + + if (usePassphrase) { + collector.checkThat("securityConfig.securityType", + NanDataPathSecurityType.PASSPHRASE, + equalTo(nidpr.securityConfig.securityType)); + collector.checkThat("securityConfig.cipherType", halCipherSuite, + equalTo(nidpr.securityConfig.cipherType)); + collector.checkThat("securityConfig.passphrase", passphrase.getBytes(), + equalTo(convertArrayListToNativeByteArray(nidpr.securityConfig.passphrase))); + } + + collector.checkThat("appInfo", appInfo, + equalTo(convertArrayListToNativeByteArray(nidpr.appInfo))); + + if ((usePmk || usePassphrase) && isOutOfBand) { + collector.checkThat("serviceNameOutOfBand", + WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(), + equalTo(convertArrayListToNativeByteArray(nidpr.serviceNameOutOfBand))); + } else { + collector.checkThat("serviceNameOutOfBand.length", 0, + equalTo(nidpr.serviceNameOutOfBand.size())); + } + } + + private void validateRespondToDataPathRequest(boolean usePmk, boolean usePassphrase, + boolean accept, boolean isOutOfBand, int publicCipherSuites, int halCipherSuite) + throws Exception { + short tid = 33; + int ndpId = 44; + String interfaceName = "aware_whatever22"; + final byte[] pmk = "01234567890123456789012345678901".getBytes(); + String passphrase = "blahblah"; + final byte[] appInfo = "Out-of-band info".getBytes(); + + ArgumentCaptor<android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest> captor = + ArgumentCaptor.forClass( + android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest.class); + WifiAwareDataPathSecurityConfig securityConfig = null; + if (usePassphrase) { + securityConfig = new WifiAwareDataPathSecurityConfig + .Builder(publicCipherSuites) + .setPskPassphrase(passphrase) + .build(); + } else if (usePmk) { + securityConfig = new WifiAwareDataPathSecurityConfig + .Builder(publicCipherSuites) + .setPmk(pmk) + .build(); + } + + mDut.respondToDataPathRequest(tid, accept, ndpId, interfaceName, + appInfo, isOutOfBand, CAP, securityConfig); + + verify(mIWifiNanIface).respondToDataPathIndicationRequest(eq(tid), captor.capture()); + + android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest nrtdpir = + captor.getValue(); + collector.checkThat("acceptRequest", accept, equalTo(nrtdpir.acceptRequest)); + collector.checkThat("ndpInstanceId", ndpId, equalTo(nrtdpir.ndpInstanceId)); + collector.checkThat("ifaceName", interfaceName, equalTo(nrtdpir.ifaceName)); + + if (accept) { + if (usePmk) { + collector.checkThat("securityConfig.securityType", + NanDataPathSecurityType.PMK, + equalTo(nrtdpir.securityConfig.securityType)); + collector.checkThat("securityConfig.cipherType", halCipherSuite, + equalTo(nrtdpir.securityConfig.cipherType)); + collector.checkThat("securityConfig.pmk", pmk, equalTo(nrtdpir.securityConfig.pmk)); + collector.checkThat("securityConfig.passphrase.length", 0, + equalTo(nrtdpir.securityConfig.passphrase.size())); + } + + if (usePassphrase) { + collector.checkThat("securityConfig.securityType", + NanDataPathSecurityType.PASSPHRASE, + equalTo(nrtdpir.securityConfig.securityType)); + collector.checkThat("securityConfig.cipherType", halCipherSuite, + equalTo(nrtdpir.securityConfig.cipherType)); + collector.checkThat("securityConfig.passphrase", passphrase.getBytes(), + equalTo(convertArrayListToNativeByteArray( + nrtdpir.securityConfig.passphrase))); + } + + collector.checkThat("appInfo", appInfo, + equalTo(convertArrayListToNativeByteArray(nrtdpir.appInfo))); + + if ((usePmk || usePassphrase) && isOutOfBand) { + collector.checkThat("serviceNameOutOfBand", + WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(), + equalTo(convertArrayListToNativeByteArray(nrtdpir.serviceNameOutOfBand))); + } else { + collector.checkThat("serviceNameOutOfBand.length", 0, + equalTo(nrtdpir.serviceNameOutOfBand.size())); + } + } + } + + private byte[] convertArrayListToNativeByteArray(ArrayList<Byte> from) { + if (from == null) { + return null; + } + + byte[] to = new byte[from.size()]; + for (int i = 0; i < from.size(); ++i) { + to[i] = from.get(i); + } + return to; + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceTest.java new file mode 100644 index 0000000000..9a315d74ce --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertNull; + +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class WifiNanIfaceTest { + // HAL mocks + @Mock android.hardware.wifi.V1_0.IWifiNanIface mIWifiNanIfaceHidlMock; + @Mock android.hardware.wifi.IWifiNanIface mIWifiNanIfaceAidlMock; + + // Framework HIDL/AIDL implementation mocks + @Mock WifiNanIfaceHidlImpl mWifiNanIfaceHidlImplMock; + @Mock WifiNanIfaceAidlImpl mWifiNanIfaceAidlImplMock; + + private WifiNanIface mDut; + + private class WifiNanIfaceSpy extends WifiNanIface { + WifiNanIfaceSpy(android.hardware.wifi.V1_0.IWifiNanIface nanIface) { + super(nanIface); + } + + WifiNanIfaceSpy(android.hardware.wifi.IWifiNanIface nanIface) { + super(nanIface); + } + + @Override + protected WifiNanIfaceHidlImpl createWifiNanIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiNanIface nanIface) { + return mWifiNanIfaceHidlImplMock; + } + + @Override + protected WifiNanIfaceAidlImpl createWifiNanIfaceAidlImplMockable( + android.hardware.wifi.IWifiNanIface nanIface) { + return mWifiNanIfaceAidlImplMock; + } + } + + private class NullWifiNanIfaceSpy extends WifiNanIface { + NullWifiNanIfaceSpy() { + super(mIWifiNanIfaceAidlMock); + } + + @Override + protected WifiNanIfaceAidlImpl createWifiNanIfaceAidlImplMockable( + android.hardware.wifi.IWifiNanIface nanIface) { + return null; + } + } + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + mDut = new WifiNanIfaceSpy(mIWifiNanIfaceAidlMock); + } + + /** + * Test that we can initialize using the HIDL implementation. + */ + @Test + public void testInitWithHidlImpl() { + mDut = new WifiNanIfaceSpy(mIWifiNanIfaceHidlMock); + mDut.getName(); + verify(mWifiNanIfaceHidlImplMock).getName(); + verify(mWifiNanIfaceAidlImplMock, never()).getName(); + } + + /** + * Test the case where the creation of the xIDL implementation + * fails, so mWifiNanIface is null. + */ + @Test + public void testInitFailureCase() { + mDut = new NullWifiNanIfaceSpy(); + assertNull(mDut.getName()); + verify(mWifiNanIfaceHidlImplMock, never()).getName(); + verify(mWifiNanIfaceAidlImplMock, never()).getName(); + } + + @Test + public void testGetName() { + HalTestUtils.verifyReturnValue( + () -> mDut.getName(), + mWifiNanIfaceAidlImplMock.getName(), + "wlan0"); + verify(mWifiNanIfaceAidlImplMock).getName(); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiP2pIfaceTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiP2pIfaceTest.java new file mode 100644 index 0000000000..76b7606d88 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiP2pIfaceTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertNull; + +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class WifiP2pIfaceTest { + // HAL mocks + @Mock android.hardware.wifi.V1_0.IWifiP2pIface mIWifiP2pIfaceHidlMock; + @Mock android.hardware.wifi.IWifiP2pIface mIWifiP2pIfaceAidlMock; + + // Framework HIDL/AIDL implementation mocks + @Mock WifiP2pIfaceHidlImpl mWifiP2pIfaceHidlImplMock; + @Mock WifiP2pIfaceAidlImpl mWifiP2pIfaceAidlImplMock; + + private WifiP2pIface mDut; + + private class WifiP2pIfaceSpy extends WifiP2pIface { + WifiP2pIfaceSpy(android.hardware.wifi.V1_0.IWifiP2pIface p2pIface) { + super(p2pIface); + } + + WifiP2pIfaceSpy(android.hardware.wifi.IWifiP2pIface p2pIface) { + super(p2pIface); + } + + @Override + protected WifiP2pIfaceHidlImpl createWifiP2pIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiP2pIface p2pIface) { + return mWifiP2pIfaceHidlImplMock; + } + + @Override + protected WifiP2pIfaceAidlImpl createWifiP2pIfaceAidlImplMockable( + android.hardware.wifi.IWifiP2pIface p2pIface) { + return mWifiP2pIfaceAidlImplMock; + } + } + + private class NullWifiP2pIfaceSpy extends WifiP2pIface { + NullWifiP2pIfaceSpy() { + super(mIWifiP2pIfaceAidlMock); + } + + @Override + protected WifiP2pIfaceAidlImpl createWifiP2pIfaceAidlImplMockable( + android.hardware.wifi.IWifiP2pIface p2pIface) { + return null; + } + } + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + mDut = new WifiP2pIfaceSpy(mIWifiP2pIfaceAidlMock); + } + + /** + * Test that we can initialize using the HIDL implementation. + */ + @Test + public void testInitWithHidlImpl() { + mDut = new WifiP2pIfaceSpy(mIWifiP2pIfaceHidlMock); + mDut.getName(); + verify(mWifiP2pIfaceHidlImplMock).getName(); + verify(mWifiP2pIfaceAidlImplMock, never()).getName(); + } + + /** + * Test the case where the creation of the xIDL implementation + * fails, so mWifiP2pIface is null. + */ + @Test + public void testInitFailureCase() { + mDut = new NullWifiP2pIfaceSpy(); + assertNull(mDut.getName()); + verify(mWifiP2pIfaceHidlImplMock, never()).getName(); + verify(mWifiP2pIfaceAidlImplMock, never()).getName(); + } + + @Test + public void testGetName() { + HalTestUtils.verifyReturnValue( + () -> mDut.getName(), + mWifiP2pIfaceAidlImplMock.getName(), + "wlan0"); + verify(mWifiP2pIfaceAidlImplMock).getName(); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerHidlImplTest.java index 8c6a4eec50..a33b4b072f 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerHidlImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2022 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. @@ -14,13 +14,11 @@ * limitations under the License. */ - -package com.android.server.wifi.rtt; +package com.android.server.wifi.hal; import static org.hamcrest.core.IsEqual.equalTo; +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.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; @@ -47,10 +45,7 @@ import android.net.wifi.rtt.RangingRequest; import android.net.wifi.rtt.RangingResult; import android.net.wifi.rtt.ResponderConfig; -import androidx.test.filters.SmallTest; - -import com.android.server.wifi.HalDeviceManager; -import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.rtt.RttTestUtils; import org.hamcrest.core.IsNull; import org.junit.Before; @@ -64,46 +59,33 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; -/** - * Unit test harness for the RttNative class. - */ -@SmallTest -public class RttNativeTest extends WifiBaseTest { - private RttNative mDut; +public class WifiRttControllerHidlImplTest { + private WifiRttController mDut; private WifiStatus mStatusSuccess; private ArgumentCaptor<ArrayList> mRttConfigCaptor = ArgumentCaptor.forClass(ArrayList.class); - private ArgumentCaptor<List> mRttResultCaptor = ArgumentCaptor.forClass(List.class); - private ArgumentCaptor<HalDeviceManager.ManagerStatusListener> mHdmStatusListener = - ArgumentCaptor.forClass(HalDeviceManager.ManagerStatusListener.class); - private ArgumentCaptor<HalDeviceManager.InterfaceRttControllerLifecycleCallback> - mRttLifecycleCbCaptor = ArgumentCaptor.forClass( - HalDeviceManager.InterfaceRttControllerLifecycleCallback.class); + private ArgumentCaptor<ArrayList> mRttResultCaptor = ArgumentCaptor.forClass(ArrayList.class); private ArgumentCaptor<IWifiRttController.getCapabilitiesCallback> mGetCapCbCatpr = ArgumentCaptor.forClass(IWifiRttController.getCapabilitiesCallback.class); private ArgumentCaptor<IWifiRttControllerEventCallback.Stub> mEventCallbackArgumentCaptor = ArgumentCaptor.forClass(IWifiRttControllerEventCallback.Stub.class); + private ArgumentCaptor<ArrayList> mArrayListCaptor = ArgumentCaptor.forClass(ArrayList.class); @Rule public ErrorCollector collector = new ErrorCollector(); @Mock - public RttServiceImpl mockRttServiceImpl; - - @Mock - public HalDeviceManager mockHalDeviceManager; + public IWifiRttController mockRttController; @Mock - public IWifiRttController mockRttController; + public WifiRttController.RttControllerRangingResultsCallback mockRangingResultsCallback; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - - when(mockHalDeviceManager.isStarted()).thenReturn(true); - mStatusSuccess = new WifiStatus(); mStatusSuccess.code = WifiStatusCode.SUCCESS; + when(mockRttController.registerEventCallback(mEventCallbackArgumentCaptor.capture())) .thenReturn(mStatusSuccess); when(mockRttController.rangeRequest(anyInt(), any(ArrayList.class))).thenReturn( @@ -111,20 +93,15 @@ public class RttNativeTest extends WifiBaseTest { when(mockRttController.rangeCancel(anyInt(), any(ArrayList.class))).thenReturn( mStatusSuccess); - mDut = new RttNative(mockRttServiceImpl, mockHalDeviceManager); - mDut.start(null); - verify(mockHalDeviceManager).initialize(); - verify(mockHalDeviceManager).registerRttControllerLifecycleCallback( - mRttLifecycleCbCaptor.capture(), any()); - mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttController); - verify(mockRttController).registerEventCallback(any()); - verify(mockRttServiceImpl).enableIfPossible(); + mDut = new WifiRttController(mockRttController); + mDut.setup(); + mDut.registerRangingResultsCallback(mockRangingResultsCallback); verify(mockRttController).getCapabilities(mGetCapCbCatpr.capture()); + verify(mockRttController).registerEventCallback(any()); // will override capabilities (just call cb again) for specific tests mGetCapCbCatpr.getValue().onValues(mStatusSuccess, getFullRttCapabilities()); // This is for the castFrom() call verify(mockRttController, times(2)).asBinder(); - assertTrue(mDut.isReady()); } /** @@ -136,7 +113,7 @@ public class RttNativeTest extends WifiBaseTest { RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); // (1) issue range request - mDut.rangeRequest(cmdId, request, true); + mDut.rangeRequest(cmdId, request); // (2) verify HAL call and parameters verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); @@ -155,7 +132,7 @@ public class RttNativeTest extends WifiBaseTest { 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())); + equalTo(RangingRequest.getMaxRttBurstSize())); rttConfig = halRequest.get(1); collector.checkThat("entry 1: MAC", rttConfig.addr, @@ -177,8 +154,7 @@ public class RttNativeTest extends WifiBaseTest { collector.checkThat("entry 2: rtt burst size", rttConfig.numFramesPerBurst, equalTo(RangingRequest.getMaxRttBurstSize())); - - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); + verifyNoMoreInteractions(mockRttController); } /** @@ -205,7 +181,7 @@ public class RttNativeTest extends WifiBaseTest { // Note: request 1: BW = 40MHz --> 10MHz, Preamble = HT (since 40MHz) -> Legacy // (1) issue range request - mDut.rangeRequest(cmdId, request, true); + mDut.rangeRequest(cmdId, request); // (2) verify HAL call and parameters verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); @@ -235,7 +211,7 @@ public class RttNativeTest extends WifiBaseTest { collector.checkThat("entry 1: lci", rttConfig.mustRequestLci, equalTo(false)); collector.checkThat("entry 1: lcr", rttConfig.mustRequestLcr, equalTo(false)); - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); + verifyNoMoreInteractions(mockRttController); } /** @@ -259,7 +235,7 @@ public class RttNativeTest extends WifiBaseTest { // dropped // (1) issue range request - mDut.rangeRequest(cmdId, request, true); + mDut.rangeRequest(cmdId, request); // (2) verify HAL call and parameters verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); @@ -277,58 +253,7 @@ public class RttNativeTest extends WifiBaseTest { collector.checkThat("entry 0: lci", rttConfig.mustRequestLci, equalTo(false)); collector.checkThat("entry 0: lcr", rttConfig.mustRequestLcr, equalTo(false)); - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); - } - - /** - * Validate no range request when Wi-Fi is down - */ - @Test - public void testWifiDown() throws Exception { - int cmdId = 55; - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); - - // (1) simulate Wi-Fi down and send a status change indication - mRttLifecycleCbCaptor.getValue().onRttControllerDestroyed(); - verify(mockRttServiceImpl).disable(); - assertFalse(mDut.isReady()); - - // (2) issue range request - mDut.rangeRequest(cmdId, request, true); - - verifyNoMoreInteractions(mockRttServiceImpl, mockRttController); - } - - /** - * Validate that we react correctly (i.e. enable/disable global RTT availability) when - * notified that the RTT controller has disappear and appeared. - */ - @Test - public void testRttControllerLifecycle() throws Exception { - // RTT controller disappears - mRttLifecycleCbCaptor.getValue().onRttControllerDestroyed(); - verify(mockRttServiceImpl).disable(); - assertFalse(mDut.isReady()); - - // RTT controller re-appears (verification is x2 since 1st time is in setup()) - mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttController); - verify(mockRttController, times(2)).registerEventCallback(any()); - verify(mockRttServiceImpl, times(2)).enableIfPossible(); - verify(mockRttController, times(2)).getCapabilities(mGetCapCbCatpr.capture()); - // This is for the castFrom() calls - verify(mockRttController, times(4)).asBinder(); - assertTrue(mDut.isReady()); - - // RTT controller switch - previous is invalid and new one is created. Should not try to - // enable - mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttController); - verify(mockRttController, times(3)).registerEventCallback(any()); - // This is for the castFrom() calls - verify(mockRttController, times(6)).asBinder(); - verify(mockRttController, times(3)).getCapabilities(mGetCapCbCatpr.capture()); - assertTrue(mDut.isReady()); - - verifyNoMoreInteractions(mockRttServiceImpl, mockRttController); + verifyNoMoreInteractions(mockRttController); } /** @@ -337,9 +262,9 @@ public class RttNativeTest extends WifiBaseTest { @Test public void testRangeCancel() throws Exception { int cmdId = 66; - ArrayList<byte[]> macAddresses = new ArrayList<>(); - byte[] mac1 = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; - byte[] mac2 = {0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; + ArrayList<MacAddress> macAddresses = new ArrayList<>(); + MacAddress mac1 = MacAddress.fromString("00:01:02:03:04:05"); + MacAddress mac2 = MacAddress.fromString("0A:0B:0C:0D:0E:0F"); macAddresses.add(mac1); macAddresses.add(mac2); @@ -347,7 +272,9 @@ public class RttNativeTest extends WifiBaseTest { mDut.rangeCancel(cmdId, macAddresses); // (2) verify HAL call and parameters - verify(mockRttController).rangeCancel(cmdId, macAddresses); + verify(mockRttController).rangeCancel(eq(cmdId), mArrayListCaptor.capture()); + assertArrayEquals(mac1.toByteArray(), (byte[]) mArrayListCaptor.getValue().get(0)); + assertArrayEquals(mac2.toByteArray(), (byte[]) mArrayListCaptor.getValue().get(1)); verifyNoMoreInteractions(mockRttController); } @@ -371,11 +298,11 @@ public class RttNativeTest extends WifiBaseTest { res.timeStampInUs = 6000; results.add(res); - // (1) have HAL call native with results + // (1) have the HAL call us with results mEventCallbackArgumentCaptor.getValue().onResults(cmdId, results); // (2) verify call to framework - verify(mockRttServiceImpl).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); + verify(mockRangingResultsCallback).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); // verify contents of the framework results List<RangingResult> rttR = mRttResultCaptor.getValue(); @@ -384,13 +311,13 @@ public class RttNativeTest extends WifiBaseTest { RangingResult rttResult = rttR.get(0); collector.checkThat("status", rttResult.getStatus(), - equalTo(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS)); + equalTo(WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS)); collector.checkThat("mac", rttResult.getMacAddress().toByteArray(), equalTo(MacAddress.fromString("05:06:07:08:09:0A").toByteArray())); collector.checkThat("distanceCm", rttResult.getDistanceMm(), equalTo(1500)); collector.checkThat("timestamp", rttResult.getRangingTimestampMillis(), equalTo(6L)); - verifyNoMoreInteractions(mockRttController, mockRttServiceImpl); + verifyNoMoreInteractions(mockRttController); } /** @@ -401,7 +328,7 @@ public class RttNativeTest extends WifiBaseTest { int cmdId = 66; mEventCallbackArgumentCaptor.getValue().onResults(cmdId, null); - verify(mockRttServiceImpl).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); + verify(mockRangingResultsCallback).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); collector.checkThat("number of entries", mRttResultCaptor.getValue().size(), equalTo(0)); } @@ -422,7 +349,7 @@ public class RttNativeTest extends WifiBaseTest { results.add(null); mEventCallbackArgumentCaptor.getValue().onResults(cmdId, results); - verify(mockRttServiceImpl).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); + verify(mockRangingResultsCallback).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); List<RttResult> rttR = mRttResultCaptor.getValue(); collector.checkThat("number of entries", rttR.size(), equalTo(2)); @@ -448,11 +375,12 @@ public class RttNativeTest extends WifiBaseTest { // Add a ResponderConfig with invalid parameter, should be ignored. request.mRttPeers.add(invalidConfig); request.mRttPeers.add(config); - mDut.rangeRequest(cmdId, request, true); + mDut.rangeRequest(cmdId, request); verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); assertEquals(request.mRttPeers.size() - 1, mRttConfigCaptor.getValue().size()); } + // Utilities /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerTest.java new file mode 100644 index 0000000000..00f688b302 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertNull; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class WifiRttControllerTest { + // HAL mocks + @Mock android.hardware.wifi.V1_0.IWifiRttController mIWifiRttControllerHidlMock; + @Mock android.hardware.wifi.IWifiRttController mIWifiRttControllerAidlMock; + + // Framework HIDL/AIDL implementation mocks + @Mock WifiRttControllerHidlImpl mWifiRttControllerHidlImplMock; + @Mock WifiRttControllerAidlImpl mWifiRttControllerAidlImplMock; + + private WifiRttController mDut; + + private class WifiRttControllerSpy extends WifiRttController { + WifiRttControllerSpy(android.hardware.wifi.V1_0.IWifiRttController rttController) { + super(rttController); + } + + WifiRttControllerSpy(android.hardware.wifi.IWifiRttController rttController) { + super(rttController); + } + + @Override + protected WifiRttControllerHidlImpl createWifiRttControllerHidlImplMockable( + android.hardware.wifi.V1_0.IWifiRttController rttController) { + return mWifiRttControllerHidlImplMock; + } + + @Override + protected WifiRttControllerAidlImpl createWifiRttControllerAidlImplMockable( + android.hardware.wifi.IWifiRttController rttController) { + return mWifiRttControllerAidlImplMock; + } + } + + private class NullWifiRttControllerSpy extends WifiRttController { + NullWifiRttControllerSpy() { + super(mIWifiRttControllerAidlMock); + } + + @Override + protected WifiRttControllerAidlImpl createWifiRttControllerAidlImplMockable( + android.hardware.wifi.IWifiRttController rttController) { + return null; + } + } + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + mDut = new WifiRttControllerSpy(mIWifiRttControllerAidlMock); + } + + /** + * Test that we can initialize using the HIDL implementation. + */ + @Test + public void testInitWithHidlImpl() { + mDut = new WifiRttControllerSpy(mIWifiRttControllerHidlMock); + mDut.getRttCapabilities(); + verify(mWifiRttControllerHidlImplMock).getRttCapabilities(); + verify(mWifiRttControllerAidlImplMock, never()).getRttCapabilities(); + } + + /** + * Test the case where the creation of the xIDL implementation + * fails, so mWifiRttController is null. + */ + @Test + public void testInitFailureCase() { + mDut = new NullWifiRttControllerSpy(); + assertNull(mDut.getRttCapabilities()); + verify(mWifiRttControllerHidlImplMock, never()).getRttCapabilities(); + verify(mWifiRttControllerAidlImplMock, never()).getRttCapabilities(); + } + + @Test + public void testGetRttCapabilities() { + HalTestUtils.verifyReturnValue( + () -> mDut.getRttCapabilities(), + mWifiRttControllerAidlImplMock.getRttCapabilities(), + mock(WifiRttController.Capabilities.class)); + verify(mWifiRttControllerAidlImplMock).getRttCapabilities(); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceTest.java new file mode 100644 index 0000000000..8e83433a01 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2022 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.hal; + +import static junit.framework.Assert.assertNull; + +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.annotation.NonNull; +import android.content.Context; + +import com.android.server.wifi.SsidTranslator; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class WifiStaIfaceTest { + // HAL mocks + @Mock android.hardware.wifi.V1_0.IWifiStaIface mIWifiStaIfaceHidlMock; + @Mock android.hardware.wifi.IWifiStaIface mIWifiStaIfaceAidlMock; + + // Framework HIDL/AIDL implementation mocks + @Mock WifiStaIfaceHidlImpl mWifiStaIfaceHidlImplMock; + @Mock WifiStaIfaceAidlImpl mWifiStaIfaceAidlImplMock; + + @Mock Context mContextMock; + @Mock SsidTranslator mSsidTranslatorMock; + + private WifiStaIface mDut; + + private class WifiStaIfaceSpy extends WifiStaIface { + WifiStaIfaceSpy(android.hardware.wifi.V1_0.IWifiStaIface staIface) { + super(staIface, mContextMock, mSsidTranslatorMock); + } + + WifiStaIfaceSpy(android.hardware.wifi.IWifiStaIface staIface) { + super(staIface, mContextMock, mSsidTranslatorMock); + } + + @Override + protected WifiStaIfaceHidlImpl createWifiStaIfaceHidlImplMockable( + android.hardware.wifi.V1_0.IWifiStaIface staIface, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return mWifiStaIfaceHidlImplMock; + } + + @Override + protected WifiStaIfaceAidlImpl createWifiStaIfaceAidlImplMockable( + android.hardware.wifi.IWifiStaIface staIface, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return mWifiStaIfaceAidlImplMock; + } + } + + private class NullWifiStaIfaceSpy extends WifiStaIface { + NullWifiStaIfaceSpy() { + super(mIWifiStaIfaceAidlMock, mContextMock, mSsidTranslatorMock); + } + + @Override + protected WifiStaIfaceAidlImpl createWifiStaIfaceAidlImplMockable( + android.hardware.wifi.IWifiStaIface staIface, + @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { + return null; + } + } + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + mDut = new WifiStaIfaceSpy(mIWifiStaIfaceAidlMock); + } + + /** + * Test that we can initialize using the HIDL implementation. + */ + @Test + public void testInitWithHidlImpl() { + mDut = new WifiStaIfaceSpy(mIWifiStaIfaceHidlMock); + mDut.getName(); + verify(mWifiStaIfaceHidlImplMock).getName(); + verify(mWifiStaIfaceAidlImplMock, never()).getName(); + } + + /** + * Test the case where the creation of the xIDL implementation + * fails, so mWifiStaIface is null. + */ + @Test + public void testInitFailureCase() { + mDut = new NullWifiStaIfaceSpy(); + assertNull(mDut.getName()); + verify(mWifiStaIfaceHidlImplMock, never()).getName(); + verify(mWifiStaIfaceAidlImplMock, never()).getName(); + } + + @Test + public void testGetName() { + HalTestUtils.verifyReturnValue( + () -> mDut.getName(), + mWifiStaIfaceAidlImplMock.getName(), + "wlan0"); + verify(mWifiStaIfaceAidlImplMock).getName(); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java index 4036c974dc..a3083ef40a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java @@ -68,7 +68,6 @@ import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.pps.Credential; import android.net.wifi.hotspot2.pps.HomeSp; -import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.os.test.TestLooper; @@ -76,6 +75,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Base64; +import android.util.LocalLog; import android.util.Pair; import androidx.test.filters.SmallTest; @@ -85,6 +85,7 @@ import com.android.server.wifi.FakeKeys; import com.android.server.wifi.FrameworkFacade; import com.android.server.wifi.MacAddressUtil; import com.android.server.wifi.NetworkUpdateResult; +import com.android.server.wifi.RunnerHandler; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiCarrierInfoManager; import com.android.server.wifi.WifiConfigManager; @@ -220,7 +221,7 @@ public class PasspointManagerTest extends WifiBaseTest { @Mock MacAddressUtil mMacAddressUtil; @Mock WifiPermissionsUtil mWifiPermissionsUtil; - Handler mHandler; + RunnerHandler mHandler; TestLooper mLooper; PasspointManager mManager; boolean mConfigSettingsPasspointEnabled = true; @@ -271,7 +272,7 @@ public class PasspointManagerTest extends WifiBaseTest { when(mWifiSettingsStore.isWifiPasspointEnabled()) .thenReturn(mConfigSettingsPasspointEnabled); mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); + mHandler = new RunnerHandler(mLooper.getLooper(), 100, new LocalLog(128)); mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager, mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class), mock(WifiContext.class), mWifiConfigStore, mHandler, mWifiMetrics, mClock); diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java index 7a95a41f8e..0c881f6c3e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.test.MockAnswerUtil.AnswerWithArguments; +import android.hardware.wifi.supplicant.P2pGroupStartedEventParams; import android.hardware.wifi.supplicant.P2pProvDiscStatusCode; import android.hardware.wifi.supplicant.P2pStatusCode; import android.hardware.wifi.supplicant.WpsConfigMethods; @@ -52,7 +53,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.MockitoAnnotations; import java.util.ArrayList; -import java.util.Arrays;; +import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -401,6 +402,107 @@ public class SupplicantP2pIfaceCallbackAidlImplTest extends WifiBaseTest { } /** + * Success scenario for onGroupStartedWithParams call. + */ + @Test + public void testOnGroupStartedWithParams_success() throws Exception { + String fakeName = "group name"; + String fakePassphrase = "secret"; + byte[] fakeSsidBytesList = new byte[] {0x30, 0x31, 0x32, 0x33}; + String fakeSsidString = "0123"; + HashSet<String> passwords = new HashSet<>(); + byte[] fakeMacAddress = new byte[] {0x40, 0x41, 0x42, 0x43, 0x44, 0x45}; + + doAnswer(new AnswerWithArguments() { + public void answer(String iface, WifiP2pGroup group) { + assertEquals(iface, mIface); + assertNotNull(group.getOwner()); + assertEquals(group.getOwner().deviceAddress, mDeviceAddress1String); + assertEquals(group.getNetworkId(), WifiP2pGroup.NETWORK_ID_PERSISTENT); + passwords.add(group.getPassphrase()); + assertEquals(group.getInterface(), fakeName); + assertEquals(group.getNetworkName(), fakeSsidString); + assertEquals(group.interfaceAddress, fakeMacAddress); + } + }).when(mMonitor).broadcastP2pGroupStarted( + anyString(), any(WifiP2pGroup.class)); + + P2pGroupStartedEventParams params1 = new P2pGroupStartedEventParams(); + params1.groupInterfaceName = fakeName; + params1.isGroupOwner = true; + params1.ssid = fakeSsidBytesList; + params1.frequencyMHz = 1; + params1.passphrase = fakePassphrase; + params1.goDeviceAddress = mDeviceAddress1Bytes; + params1.goInterfaceAddress = fakeMacAddress; + params1.isPersistent = true; + mDut.onGroupStartedWithParams(params1); + assertTrue(passwords.contains(fakePassphrase)); + + P2pGroupStartedEventParams params2 = new P2pGroupStartedEventParams(); + params2.groupInterfaceName = fakeName; + params2.isGroupOwner = true; + params2.ssid = fakeSsidBytesList; + params2.frequencyMHz = 1; + params2.goDeviceAddress = mDeviceAddress1Bytes; + params2.goInterfaceAddress = fakeMacAddress; + params2.isPersistent = true; + mDut.onGroupStartedWithParams(params2); + assertTrue(passwords.contains(null)); + + verify(mMonitor, times(2)).broadcastP2pGroupStarted( + anyString(), any(WifiP2pGroup.class)); + } + + /** + * Failing scenarios for onGroupStartedWithParams call. + */ + @Test + public void testOnGroupStartedWithParams_invalidArguments() + throws Exception { + String fakeName = "group name"; + String fakePassphrase = "secret"; + byte[] fakeSsidBytesList = new byte[] {0x30, 0x31, 0x32, 0x33}; + byte[] fakeMacAddress = new byte[] {0x40, 0x41, 0x42, 0x43, 0x44, 0x45}; + + P2pGroupStartedEventParams params1 = new P2pGroupStartedEventParams(); + params1.isGroupOwner = true; + params1.ssid = fakeSsidBytesList; + params1.frequencyMHz = 1; + params1.passphrase = fakePassphrase; + params1.goDeviceAddress = mDeviceAddress1Bytes; + params1.goInterfaceAddress = fakeMacAddress; + params1.isPersistent = true; + mDut.onGroupStartedWithParams(params1); + verify(mMonitor, never()).broadcastP2pGroupStarted( + anyString(), any(WifiP2pGroup.class)); + + P2pGroupStartedEventParams params2 = new P2pGroupStartedEventParams(); + params2.groupInterfaceName = fakeName; + params2.isGroupOwner = true; + params2.frequencyMHz = 1; + params1.passphrase = fakePassphrase; + params2.goDeviceAddress = mDeviceAddress1Bytes; + params2.goInterfaceAddress = fakeMacAddress; + params2.isPersistent = true; + mDut.onGroupStartedWithParams(params2); + verify(mMonitor, never()).broadcastP2pGroupStarted( + anyString(), any(WifiP2pGroup.class)); + + P2pGroupStartedEventParams params3 = new P2pGroupStartedEventParams(); + params3.groupInterfaceName = fakeName; + params3.isGroupOwner = true; + params3.ssid = fakeSsidBytesList; + params3.frequencyMHz = 1; + params3.passphrase = fakePassphrase; + params3.goInterfaceAddress = fakeMacAddress; + params3.isPersistent = true; + mDut.onGroupStartedWithParams(params3); + verify(mMonitor, never()).broadcastP2pGroupStarted( + anyString(), any(WifiP2pGroup.class)); + } + + /** * Test provision discovery callback. */ @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlImplTest.java index 2d65645a70..dca52eb615 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackHidlImplTest.java @@ -345,12 +345,11 @@ public class SupplicantP2pIfaceCallbackHidlImplTest extends WifiBaseTest { public void testOnGroupStarted_success() throws Exception { String fakeName = "group name"; String fakePassphrase = "secret"; - ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{ - add((byte) 0x30); - add((byte) 0x31); - add((byte) 0x32); - add((byte) 0x33); - }}; + ArrayList<Byte> fakeSsidBytesList = new ArrayList<>(); + fakeSsidBytesList.add((byte) 0x30); + fakeSsidBytesList.add((byte) 0x31); + fakeSsidBytesList.add((byte) 0x32); + fakeSsidBytesList.add((byte) 0x33); String fakeSsidString = "0123"; HashSet<String> passwords = new HashSet<String>(); @@ -388,12 +387,12 @@ public class SupplicantP2pIfaceCallbackHidlImplTest extends WifiBaseTest { public void testOnGroupStarted_invalidArguments() throws Exception { String fakeName = "group name"; String fakePassphrase = "secret"; - ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{ - add((byte) 0x30); - add((byte) 0x31); - add((byte) 0x32); - add((byte) 0x33); - }}; + ArrayList<Byte> fakeSsidBytesList = new ArrayList<>(); + fakeSsidBytesList.add((byte) 0x30); + fakeSsidBytesList.add((byte) 0x31); + fakeSsidBytesList.add((byte) 0x32); + fakeSsidBytesList.add((byte) 0x33); + String fakeSsidString = "0123"; mDut.onGroupStarted( diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java index e49c856f42..32379be019 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java @@ -2357,10 +2357,9 @@ public class SupplicantP2pIfaceHalAidlImplTest extends WifiBaseTest { // Convert these to long to help with comparisons. MacAddress[] clients = capturedClients.getValue(); - ArrayList<Long> expectedClients = new ArrayList<Long>() {{ - add(NativeUtil.macAddressToLong(mGroupOwnerMacAddressBytes)); - add(NativeUtil.macAddressToLong(mPeerMacAddressBytes)); - }}; + List<Long> expectedClients = List.of( + NativeUtil.macAddressToLong(mGroupOwnerMacAddressBytes), + NativeUtil.macAddressToLong(mPeerMacAddressBytes)); ArrayList<Long> receivedClients = new ArrayList<Long>(); for (MacAddress client : clients) { receivedClients.add(NativeUtil.macAddressToLong(client.data)); diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java index 16ddd06378..734255abbc 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java @@ -105,9 +105,15 @@ public class SupplicantP2pIfaceHalHidlImplTest extends WifiBaseTest { final String mIfaceName = "virtual_interface_name"; final String mSsid = "\"SSID\""; - final ArrayList<Byte> mSsidBytes = new ArrayList<Byte>() {{ - add((byte) 'S'); add((byte) 'S'); add((byte) 'I'); add((byte) 'D'); - }}; + private static ArrayList<Byte> createSsidBytes() { + ArrayList<Byte> result = new ArrayList<Byte>(); + result.add((byte) 'S'); + result.add((byte) 'S'); + result.add((byte) 'I'); + result.add((byte) 'D'); + return result; + } + final ArrayList<Byte> mSsidBytes = createSsidBytes(); final String mPeerMacAddress = "00:11:22:33:44:55"; final byte[] mPeerMacAddressBytes = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; final String mGroupOwnerMacAddress = "01:12:23:34:45:56"; @@ -142,12 +148,24 @@ public class SupplicantP2pIfaceHalHidlImplTest extends WifiBaseTest { final int mValidUpnpServiceVersion = 16; final String mValidUpnpServiceName = "serviceName"; final String mValidBonjourService = "bonjour 30313233 34353637"; - final ArrayList<Byte> mValidBonjourServiceRequest = new ArrayList<Byte>() {{ - add((byte) '0'); add((byte) '1'); add((byte) '2'); add((byte) '3'); - }}; - final ArrayList<Byte> mValidBonjourServiceResponse = new ArrayList<Byte>() {{ - add((byte) '4'); add((byte) '5'); add((byte) '6'); add((byte) '7'); - }}; + private static ArrayList<Byte> createValidBonjourServiceRequest() { + ArrayList<Byte> result = new ArrayList<Byte>(); + result.add((byte) '0'); + result.add((byte) '1'); + result.add((byte) '2'); + result.add((byte) '3'); + return result; + } + final ArrayList<Byte> mValidBonjourServiceRequest = createValidBonjourServiceRequest(); + private static ArrayList<Byte> createValidBonjourServiceResponse() { + ArrayList<Byte> result = new ArrayList<Byte>(); + result.add((byte) '4'); + result.add((byte) '5'); + result.add((byte) '6'); + result.add((byte) '7'); + return result; + } + final ArrayList<Byte> mValidBonjourServiceResponse = createValidBonjourServiceResponse(); // variables for groupAdd with config final String mNetworkName = "DIRECT-xy-Hello"; @@ -2614,10 +2632,9 @@ public class SupplicantP2pIfaceHalHidlImplTest extends WifiBaseTest { // Convert these to long to help with comparisons. ArrayList<byte[]> clients = capturedClients.getValue(); - ArrayList<Long> expectedClients = new ArrayList<Long>() {{ - add(NativeUtil.macAddressToLong(mGroupOwnerMacAddressBytes)); - add(NativeUtil.macAddressToLong(mPeerMacAddressBytes)); - }}; + List<Long> expectedClients = List.of( + NativeUtil.macAddressToLong(mGroupOwnerMacAddressBytes), + NativeUtil.macAddressToLong(mPeerMacAddressBytes)); ArrayList<Long> receivedClients = new ArrayList<Long>(); for (byte[] client : clients) { receivedClients.add(NativeUtil.macAddressToLong(client)); @@ -2675,10 +2692,9 @@ public class SupplicantP2pIfaceHalHidlImplTest extends WifiBaseTest { .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); doAnswer(new AnswerWithArguments() { public void answer(ISupplicantP2pNetwork.getClientListCallback cb) { - ArrayList<byte[]> clients = new ArrayList<byte[]>() {{ - add(mGroupOwnerMacAddressBytes); - add(mPeerMacAddressBytes); - }}; + ArrayList<byte[]> clients = new ArrayList<>(); + clients.add(mGroupOwnerMacAddressBytes); + clients.add(mPeerMacAddressBytes); cb.onValues(mStatusSuccess, clients); return; } @@ -2712,10 +2728,9 @@ public class SupplicantP2pIfaceHalHidlImplTest extends WifiBaseTest { .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class)); doAnswer(new AnswerWithArguments() { public void answer(ISupplicantP2pNetwork.getClientListCallback cb) { - ArrayList<byte[]> clients = new ArrayList<byte[]>() {{ - add(mGroupOwnerMacAddressBytes); - add(mPeerMacAddressBytes); - }}; + ArrayList<byte[]> clients = new ArrayList<>(); + clients.add(mGroupOwnerMacAddressBytes); + clients.add(mPeerMacAddressBytes); cb.onValues(mStatusSuccess, clients); return; } diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java index 8b8f95e2ff..cc2456f238 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java @@ -18,20 +18,18 @@ package com.android.server.wifi.p2p; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.test.MockAnswerUtil; import android.hardware.wifi.V1_0.IWifiIface; import android.hardware.wifi.V1_0.IWifiP2pIface; import android.hardware.wifi.V1_0.WifiStatus; import android.hardware.wifi.V1_0.WifiStatusCode; import android.net.wifi.nl80211.WifiNl80211Manager; import android.os.Handler; -import android.os.RemoteException; import android.os.WorkSource; import androidx.test.filters.SmallTest; @@ -44,6 +42,7 @@ import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiVendorHal; +import com.android.server.wifi.hal.WifiHal; import org.junit.Before; import org.junit.Test; @@ -86,14 +85,7 @@ public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { when(mHalDeviceManager.isSupported()).thenReturn(true); when(mHalDeviceManager.createP2pIface(any(InterfaceDestroyedListener.class), - any(Handler.class), any(WorkSource.class))).thenReturn(mIWifiP2pIface); - doAnswer(new MockAnswerUtil.AnswerWithArguments() { - public void answer(IWifiIface.getNameCallback cb) - throws RemoteException { - cb.onValues(mWifiStatusSuccess, P2P_IFACE_NAME); - } - }).when(mIWifiP2pIface).getName(any(IWifiIface.getNameCallback.class)); - + any(Handler.class), any(WorkSource.class))).thenReturn(P2P_IFACE_NAME); when(mSupplicantP2pIfaceHal.isInitializationStarted()).thenReturn(true); when(mSupplicantP2pIfaceHal.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHal.isInitializationComplete()).thenReturn(true); @@ -146,7 +138,7 @@ public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { mWifiP2pNative.teardownInterface(); - verify(mHalDeviceManager).removeIface(any(IWifiIface.class)); + verify(mHalDeviceManager).removeP2pIface(anyString()); verify(mSupplicantP2pIfaceHal).teardownIface(eq(P2P_IFACE_NAME)); } @@ -162,7 +154,7 @@ public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { mWifiP2pNative.teardownInterface(); - verify(mHalDeviceManager, never()).removeIface(any(IWifiIface.class)); + verify(mHalDeviceManager, never()).removeIface(any(WifiHal.WifiInterface.class)); verify(mSupplicantP2pIfaceHal).teardownIface(eq(P2P_IFACE_NAME)); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java index c9dc95e80c..4a7e183f0b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java @@ -30,7 +30,6 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; import android.app.test.MockAnswerUtil.AnswerWithArguments; -import android.hardware.wifi.V1_0.IWifiIface; import android.hardware.wifi.V1_0.IWifiP2pIface; import android.net.wifi.WifiManager; import android.net.wifi.nl80211.WifiNl80211Manager; @@ -53,6 +52,7 @@ import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiVendorHal; +import com.android.server.wifi.hal.WifiHal; import org.junit.After; import org.junit.Before; @@ -129,9 +129,6 @@ public class WifiP2pNativeTest extends WifiBaseTest { .mockStatic(HalDeviceManager.class, withSettings().lenient()) .strictness(Strictness.LENIENT) .startMocking(); - - when(HalDeviceManager.getName(any())).thenReturn(TEST_IFACE); - mWifiClientInterfaceNames.add("wlan0"); mWifiClientInterfaceNames.add("wlan1"); @@ -187,8 +184,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testSetupInterfaceSuccessInCreatingP2pIface() { when(mHalDeviceManagerMock.createP2pIface( any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(mIWifiP2pIfaceMock); - when(HalDeviceManager.getName(any(IWifiIface.class))).thenReturn(TEST_IFACE); + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(true); @@ -234,22 +230,6 @@ public class WifiP2pNativeTest extends WifiBaseTest { } /** - * Verifies that setupInterface returns correct values when failing in getting P2P Iface name. - */ - @Test - public void testSetupInterfaceFailureInGettingP2pIfaceName() { - when(mHalDeviceManagerMock.createP2pIface( - any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(mIWifiP2pIfaceMock); - when(HalDeviceManager.getName(any(IWifiIface.class))).thenReturn(null); - - assertEquals( - mWifiP2pNative.setupInterface( - mDestroyedListenerMock, mHandlerMock, mWorkSourceMock), - null); - } - - /** * Verifies that setupInterface returns correct values when supplicant connection * initialization fails. */ @@ -257,8 +237,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testSetupInterfaceFailureInSupplicantConnectionInitialization() { when(mHalDeviceManagerMock.createP2pIface( any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(mIWifiP2pIfaceMock); - when(HalDeviceManager.getName(any(IWifiIface.class))).thenReturn(TEST_IFACE); + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); when(mSupplicantP2pIfaceHalMock.isInitializationStarted()).thenReturn(false); when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(false); @@ -278,8 +257,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testSetupInterfaceFailureInSupplicantConnectionInitNotCompleted() { when(mHalDeviceManagerMock.createP2pIface( any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(mIWifiP2pIfaceMock); - when(HalDeviceManager.getName(any(IWifiIface.class))).thenReturn(TEST_IFACE); + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(true); when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(false); @@ -300,8 +278,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testSetupInterfaceFailureInSettingUpP2pIfaceInSupplicant() { when(mHalDeviceManagerMock.createP2pIface( any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(mIWifiP2pIfaceMock); - when(HalDeviceManager.getName(any(IWifiIface.class))).thenReturn(TEST_IFACE); + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(false); @@ -321,9 +298,6 @@ public class WifiP2pNativeTest extends WifiBaseTest { @Test public void testSetupInterfaceSuccessWhenHalDeviceMgrDoesSupport() throws Exception { prepareDbsMock(true); - - when(HalDeviceManager.getName(any(IWifiIface.class))).thenReturn(TEST_IFACE); - assertEquals( mWifiP2pNative.setupInterface( mDestroyedListenerMock, mHandlerMock, mWorkSourceMock), @@ -406,7 +380,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testReplaceRequestorWsSuccessWhenHalDeviceMgrSucceedInReplace() throws Exception { prepareDbsMock(true); - when(mHalDeviceManagerMock.replaceRequestorWs(any(IWifiIface.class), + when(mHalDeviceManagerMock.replaceRequestorWsForP2pIface(anyString(), any(WorkSource.class))).thenReturn(true); assertTrue(mWifiP2pNative.replaceRequestorWs(mWorkSourceMock)); } @@ -419,7 +393,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testReplaceRequestorWsSuccessWhenHalDeviceMgrFailInReplace() throws Exception { prepareDbsMock(true); - when(mHalDeviceManagerMock.replaceRequestorWs(any(IWifiIface.class), + when(mHalDeviceManagerMock.replaceRequestorWs(any(WifiHal.WifiInterface.class), any(WorkSource.class))).thenReturn(false); assertFalse(mWifiP2pNative.replaceRequestorWs(mWorkSourceMock)); } @@ -1028,7 +1002,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { when(mHalDeviceManagerMock.isSupported()).thenReturn(isHalDeviceManagerSupported); when(mHalDeviceManagerMock.createP2pIface( any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(mIWifiP2pIfaceMock); + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); when(mSupplicantP2pIfaceHalMock.isInitializationStarted()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); @@ -1043,9 +1017,9 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testDbsSupport() throws Exception { prepareDbsMock(true); - when(mHalDeviceManagerMock.is5g6gDbsSupported(any())).thenReturn(true); + when(mHalDeviceManagerMock.is5g6gDbsSupportedOnP2pIface(any())).thenReturn(true); assertTrue(mWifiP2pNative.is5g6gDbsSupported()); - when(mHalDeviceManagerMock.is5g6gDbsSupported(any())).thenReturn(false); + when(mHalDeviceManagerMock.is5g6gDbsSupportedOnP2pIface(any())).thenReturn(false); assertFalse(mWifiP2pNative.is5g6gDbsSupported()); } @@ -1056,9 +1030,9 @@ public class WifiP2pNativeTest extends WifiBaseTest { public void testDbsSupportWhenHalDeviceManagerNotSupported() throws Exception { prepareDbsMock(false); - when(mHalDeviceManagerMock.is5g6gDbsSupported(any())).thenReturn(true); + when(mHalDeviceManagerMock.is5g6gDbsSupportedOnP2pIface(any())).thenReturn(true); assertFalse(mWifiP2pNative.is5g6gDbsSupported()); - when(mHalDeviceManagerMock.is5g6gDbsSupported(any())).thenReturn(false); + when(mHalDeviceManagerMock.is5g6gDbsSupportedOnP2pIface(any())).thenReturn(false); assertFalse(mWifiP2pNative.is5g6gDbsSupported()); } } 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 e0fb8ec40b..9e6fcdf3e5 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 @@ -137,6 +137,7 @@ import com.android.server.wifi.WifiSettingsConfigStore; import com.android.server.wifi.coex.CoexManager; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent; +import com.android.server.wifi.util.LastCallerInfoManager; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.StringUtil; import com.android.server.wifi.util.WaitingState; @@ -256,6 +257,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { @Mock AlertDialog.Builder mAlertDialogBuilder; @Mock AlertDialog mAlertDialog; @Mock AsyncChannel mAsyncChannel; + @Mock LastCallerInfoManager mLastCallerInfoManager; CoexManager.CoexListener mCoexListener; @Mock DeviceConfigFacade mDeviceConfigFacade; @@ -1241,6 +1243,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mWifiInjector.makeBroadcastOptions()).thenReturn(mBroadcastOptions); when(mWifiInjector.getWifiDialogManager()).thenReturn(mWifiDialogManager); + when(mWifiInjector.getLastCallerInfoManager()).thenReturn(mLastCallerInfoManager); when(mWifiDialogManager.createP2pInvitationReceivedDialog(any(), anyBoolean(), any(), anyInt(), any(), any())).thenReturn(mDialogHandle); when(mWifiDialogManager.createP2pInvitationSentDialog(any(), any(), anyInt())) @@ -1987,6 +1990,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { eq("testFeature"), anyInt(), eq(true)); } assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_SUCCEEDED)); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_DISCOVER_PEERS), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -2579,6 +2584,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq(TEST_PACKAGE_NAME), eq("testFeature"), anyInt(), eq(true)); } + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_START_LISTENING), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -2605,6 +2612,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { verify(mWifiNative).p2pStopFind(); verify(mWifiNative).p2pExtListen(eq(false), anyInt(), anyInt()); assertTrue(mClientHandler.hasMessages(WifiP2pManager.STOP_LISTEN_SUCCEEDED)); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_STOP_LISTENING), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** Verify the p2p randomized MAC feature is enabled if OEM supports it. */ @@ -2851,6 +2860,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { eq(WifiMetricsProto.GroupEvent.GROUP_UNKNOWN), eq(mClient1.getCallingUid())); assertEquals(mTestWifiP2pPeerConfig.toString(), configCaptor.getValue().toString()); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_CONNECT), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -2917,6 +2928,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { eq(null), eq(WifiMetricsProto.GroupEvent.GROUP_OWNER), eq(mClient1.getCallingUid())); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_CREATE_GROUP), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -3037,6 +3050,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { eq(mClient1.getCallingUid())); assertEquals(mTestWifiP2pFastConnectionConfig.toString(), configCaptor.getValue().toString()); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_CREATE_GROUP_P2P_CONFIG), + anyInt(), anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -3134,6 +3149,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { reset(mAsyncChannel); sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); verify(mAsyncChannel).sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST, 0); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_CANCEL_CONNECT), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -3703,6 +3720,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { verify(mClientHandler).sendMessage(mMessageCaptor.capture()); Message message = mMessageCaptor.getValue(); assertEquals(WifiP2pManager.STOP_DISCOVERY_SUCCEEDED, message.what); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_STOP_PEER_DISCOVERY), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -3826,6 +3845,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { verify(mClientHandler).sendMessage(mMessageCaptor.capture()); Message message = mMessageCaptor.getValue(); assertEquals(WifiP2pManager.REMOVE_GROUP_SUCCEEDED, message.what); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_REMOVE_GROUP), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -3918,6 +3939,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { verify(mClientHandler).sendMessage(mMessageCaptor.capture()); Message message = mMessageCaptor.getValue(); assertEquals(WifiP2pManager.SET_CHANNEL_SUCCEEDED, message.what); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_SET_CHANNELS), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttMetricsTest.java b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttMetricsTest.java index 2c2f892bd1..7cb196d20f 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttMetricsTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttMetricsTest.java @@ -30,6 +30,7 @@ import androidx.test.filters.SmallTest; import com.android.server.wifi.Clock; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.hal.WifiRttController; import com.android.server.wifi.proto.nano.WifiMetricsProto; import org.junit.Before; @@ -216,13 +217,17 @@ public class RttMetricsTest extends WifiBaseTest { RangingRequest requestAp6 = getDummyRangingRequest(6, 0); mDut.clear(); - mDut.recordResult(requestAp1, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, + mDut.recordResult(requestAp1, getDummyRangingResults( + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, requestAp1, 5, 0), 500); - mDut.recordResult(requestAp2, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, + mDut.recordResult(requestAp2, getDummyRangingResults( + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, requestAp2, 10, 30), 1500); - mDut.recordResult(requestAp5, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, + mDut.recordResult(requestAp5, getDummyRangingResults( + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, requestAp5, 0.3, -0.2), 700); - mDut.recordResult(requestAp6, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, + mDut.recordResult(requestAp6, getDummyRangingResults( + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, requestAp6, 40, 30), 1800); log = mDut.consolidateProto(); @@ -261,13 +266,17 @@ public class RttMetricsTest extends WifiBaseTest { mDut.clear(); mDut.recordResult(requestMixed03, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed03, 5, 0), 6400); + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, + requestMixed03, 5, 0), 6400); mDut.recordResult(requestMixed25, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30), 7800); + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, + requestMixed25, 10, 30), 7800); mDut.recordResult(requestMixed50, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed50, 0.3, -0.2), 3100); + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, + requestMixed50, 0.3, -0.2), 3100); mDut.recordResult(requestMixed08, getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed08, 40, 30), 9500); + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, + requestMixed08, 40, 30), 9500); log = mDut.consolidateProto(); checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 1, 2); @@ -321,7 +330,7 @@ public class RttMetricsTest extends WifiBaseTest { mDut.clear(); RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); List<RangingResult> resultMixed25 = getDummyRangingResults( - RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30); + WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30); // remove some results resultMixed25.remove(3); // Second Aware result: distance = 100 resultMixed25.remove(0); // First AP result: distance = 10 @@ -401,22 +410,22 @@ public class RttMetricsTest extends WifiBaseTest { mDut.clear(); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 5); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAILURE, 6); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, 7); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_REJECTED, 8); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, 9); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, 10); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, 11); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, 12); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_ABORTED, 13); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, 14); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, 15); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, 16); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, 17); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_INVALID_REQ, 18); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_NO_WIFI, 19); - recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE, 20); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS, 5); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE, 6); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, 7); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED, 8); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, 9); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, 10); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, 11); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, 12); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED, 13); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, 14); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, 15); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, 16); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, 17); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ, 18); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI, 19); + recordResultNTimes(WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE, 20); log = mDut.consolidateProto(); diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java index a5b16f6d6f..33e8407045 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java @@ -17,10 +17,13 @@ package com.android.server.wifi.rtt; +import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_LCI; +import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_LCR; +import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT; + import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; import static com.android.server.wifi.rtt.RttTestUtils.compareListContentsNoOrdering; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -31,7 +34,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; @@ -79,9 +81,11 @@ import androidx.test.filters.SmallTest; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.Clock; +import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.MockResources; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiSettingsConfigStore; +import com.android.server.wifi.hal.WifiRttController; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.util.WifiPermissionsUtil; import com.android.wifi.resources.R; @@ -128,6 +132,12 @@ public class RttServiceImplTest extends WifiBaseTest { private ArgumentCaptor<RangingRequest> mRequestCaptor = ArgumentCaptor.forClass( RangingRequest.class); private ArgumentCaptor<List> mListCaptor = ArgumentCaptor.forClass(List.class); + private ArgumentCaptor<HalDeviceManager.InterfaceRttControllerLifecycleCallback> + mRttLifecycleCbCaptor = ArgumentCaptor.forClass( + HalDeviceManager.InterfaceRttControllerLifecycleCallback.class); + private ArgumentCaptor<WifiRttController.RttControllerRangingResultsCallback> + mRangingResultsCbCaptor = ArgumentCaptor.forClass( + WifiRttController.RttControllerRangingResultsCallback.class); private BinderLinkToDeathAnswer mBinderLinkToDeathCounter = new BinderLinkToDeathAnswer(); private BinderUnlinkToDeathAnswer mBinderUnlinkToDeathCounter = new BinderUnlinkToDeathAnswer(); @@ -145,7 +155,10 @@ public class RttServiceImplTest extends WifiBaseTest { public Clock mockClock; @Mock - public RttNative mockNative; + public WifiRttController mockRttControllerHal; + + @Mock + public HalDeviceManager mockHalDeviceManager; @Mock public RttMetrics mockMetrics; @@ -218,9 +231,9 @@ public class RttServiceImplTest extends WifiBaseTest { when(mockPermissionUtil.checkCallersLocationPermission(eq(mPackageName), eq(mFeatureId), anyInt(), anyBoolean(), nullable(String.class))).thenReturn(true); when(mockPermissionUtil.isLocationModeEnabled()).thenReturn(true); - when(mockNative.isReady()).thenReturn(true); - when(mockNative.rangeRequest(anyInt(), any(RangingRequest.class), anyBoolean())).thenReturn( + when(mockRttControllerHal.rangeRequest(anyInt(), any(RangingRequest.class))).thenReturn( true); + when(mockHalDeviceManager.isStarted()).thenReturn(true); when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true); mMockPowerManager = new PowerManager(mockContext, mock(IPowerManager.class), @@ -233,17 +246,23 @@ public class RttServiceImplTest extends WifiBaseTest { doAnswer(mBinderLinkToDeathCounter).when(mockIbinder).linkToDeath(any(), anyInt()); doAnswer(mBinderUnlinkToDeathCounter).when(mockIbinder).unlinkToDeath(any(), anyInt()); - mDut.start(mMockLooper.getLooper(), mockClock, mockAwareManager, mockNative, - mockMetrics, mockPermissionUtil, mWifiSettingsConfigStore); + mDut.start(mMockLooper.getLooper(), mockClock, mockAwareManager, mockMetrics, + mockPermissionUtil, mWifiSettingsConfigStore, mockHalDeviceManager); mMockLooper.dispatchAll(); ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mockContext, times(2)).registerReceiver(bcastRxCaptor.capture(), any(IntentFilter.class)); - verify(mockNative).start(any()); mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(0); mLocationModeReceiver = bcastRxCaptor.getAllValues().get(1); + verify(mockHalDeviceManager).registerRttControllerLifecycleCallback( + mRttLifecycleCbCaptor.capture(), any()); + mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttControllerHal); + verify(mockRttControllerHal).registerRangingResultsCallback( + mRangingResultsCbCaptor.capture()); + + validateCorrectRttStatusChangeBroadcast(); assertTrue(mDut.isAvailable()); } @@ -257,6 +276,34 @@ public class RttServiceImplTest extends WifiBaseTest { } /** + * Validate that we react correctly (i.e. enable/disable RTT availability) when + * notified that the RTT controller has disappeared and appeared. + */ + @Test + public void testRttControllerLifecycle() throws Exception { + // RTT controller disappears + mRttLifecycleCbCaptor.getValue().onRttControllerDestroyed(); + assertFalse(mDut.isAvailable()); + validateCorrectRttStatusChangeBroadcast(); + + // RTT controller re-appears + mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttControllerHal); + verify(mockRttControllerHal, times(2)).registerRangingResultsCallback(any()); + assertTrue(mDut.isAvailable()); + verify(mockMetrics).enableVerboseLogging(anyBoolean()); + verifyNoMoreInteractions(mockRttControllerHal); + validateCorrectRttStatusChangeBroadcast(); + + + // RTT controller switch - previous is invalid and new one is created. Should not send the + // broadcast + mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttControllerHal); + verify(mockRttControllerHal, times(3)).registerRangingResultsCallback(any()); + mInOrder.verify(mockContext, never()) + .sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL)); + } + + /** * Validate successful ranging flow. */ @Test @@ -286,12 +333,13 @@ public class RttServiceImplTest extends WifiBaseTest { for (int i = 0; i < numIter; ++i) { clock.time += MEASUREMENT_DURATION; - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(requests[i])); verifyWakeupSet(i % 2 != 0, 0); - // (3) native calls back with result - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); + // (3) HAL calls back with result + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.get(i).second); mMockLooper.dispatchAll(); // (4) verify that results dispatched @@ -299,7 +347,8 @@ public class RttServiceImplTest extends WifiBaseTest { verifyWakeupCancelled(); // (5) replicate results - shouldn't dispatch another callback - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.get(i).second); mMockLooper.dispatchAll(); } @@ -311,10 +360,8 @@ public class RttServiceImplTest extends WifiBaseTest { } verify(mockMetrics, times(numIter)).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -357,12 +404,12 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - // verify that requested with MAC address translated from the PeerHandle issued to Native - verify(mockNative).rangeRequest(mIntCaptor.capture(), mRequestCaptor.capture(), eq(true)); + // verify that the request is translated from the PeerHandle issued to WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), mRequestCaptor.capture()); verifyWakeupSet(true, 0); RangingRequest finalRequest = mRequestCaptor.getValue(); - assertNotEquals("Request to native is not null", null, finalRequest); + assertNotEquals("Request to WifiRttController is not null", null, finalRequest); assertEquals("Size of request", request.mRttPeers.size() - 1, finalRequest.mRttPeers.size()); assertEquals("Aware peer 1 MAC", MacAddress.fromBytes(peerMapping1.macAddress), @@ -379,7 +426,8 @@ public class RttServiceImplTest extends WifiBaseTest { new RangingResult(RangingResult.STATUS_FAIL, removed.getPeerHandle(), 0, 0, 0, 0, 0, null, null, null, 0)); clock.time += MEASUREMENT_DURATION; - mDut.onRangingResults(mIntCaptor.getValue(), results.first); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.first); mMockLooper.dispatchAll(); // verify that results with MAC addresses filtered out and replaced by PeerHandles issued @@ -395,11 +443,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordResult(eq(finalRequest), eq(results.first), eq(MEASUREMENT_DURATION)); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); if (SdkLevel.isAtLeastT()) { // Nearby permission should never be checked here since the request contains APs others @@ -410,7 +455,7 @@ public class RttServiceImplTest extends WifiBaseTest { } /** - * Verifity that for ranging request to only aware APs, nearby devices permission can be used + * Verify that for ranging request to only aware APs, nearby devices' permission can be used * to bypass location check. * @throws Exception */ @@ -432,15 +477,16 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - // verify that requested with MAC address translated from the PeerHandle issued to Native - verify(mockNative).rangeRequest(mIntCaptor.capture(), mRequestCaptor.capture(), eq(true)); + // verify that the request is translated from the PeerHandle issued to WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), mRequestCaptor.capture()); verifyWakeupSet(true, 0); // issue results Pair<List<RangingResult>, List<RangingResult>> results = RttTestUtils.getDummyRangingResults(mRequestCaptor.getValue()); clock.time += MEASUREMENT_DURATION; - mDut.onRangingResults(mIntCaptor.getValue(), results.first); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.first); mMockLooper.dispatchAll(); // Verify permission checks. Post T Aware ranging can be done with nearby permission. @@ -450,10 +496,10 @@ public class RttServiceImplTest extends WifiBaseTest { } /** - * Validate failed ranging flow (native failure). + * Validate failed ranging flow (WifiRttController failure). */ @Test - public void testRangingFlowNativeFailure() throws Exception { + public void testRangingFlowHalFailure() throws Exception { int numIter = 10; RangingRequest[] requests = new RangingRequest[numIter]; List<Pair<List<RangingResult>, List<RangingResult>>> results = new ArrayList<>(); @@ -464,13 +510,13 @@ public class RttServiceImplTest extends WifiBaseTest { } // (1) request 10 ranging operations: fail the first one - when(mockNative.rangeRequest(anyInt(), any(RangingRequest.class), anyBoolean())).thenReturn( + when(mockRttControllerHal.rangeRequest(anyInt(), any(RangingRequest.class))).thenReturn( false); mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, requests[0], mockCallback, mExtras); mMockLooper.dispatchAll(); - when(mockNative.rangeRequest(anyInt(), any(RangingRequest.class), anyBoolean())).thenReturn( + when(mockRttControllerHal.rangeRequest(anyInt(), any(RangingRequest.class))).thenReturn( true); for (int i = 1; i < numIter; ++i) { mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, requests[i], @@ -479,19 +525,20 @@ public class RttServiceImplTest extends WifiBaseTest { mMockLooper.dispatchAll(); for (int i = 0; i < numIter; ++i) { - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(requests[i])); - // (3) verify that failure callback dispatched (for the HAL failure) + // (3) verify that failure callback dispatched (for the WifiRttController failure) if (i == 0) { verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); } else { verifyWakeupSet(true, 0); } - // (4) on failed HAL: even if native calls back with result we shouldn't dispatch + // (4) on failed HAL: even if the HAL calls back with result we shouldn't dispatch // callback, otherwise expect result - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.get(i).second); mMockLooper.dispatchAll(); if (i != 0) { @@ -511,11 +558,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE); verify(mockMetrics, times(numIter - 1)).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -533,15 +577,16 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); - // (3) native calls back with result - should get a FAILED callback + // (3) HAL calls back with result - should get a FAILED callback when(mockPermissionUtil.checkCallersLocationPermission(eq(mPackageName), eq(mFeatureId), anyInt(), anyBoolean(), nullable(String.class))).thenReturn(false); - mDut.onRangingResults(mIntCaptor.getValue(), results.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.second); mMockLooper.dispatchAll(); verify(mockCallback).onRangingFailure(eq(RangingResultCallback.STATUS_CODE_FAIL)); @@ -551,11 +596,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); verify(mockMetrics).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -586,9 +628,9 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockIbinder, times(numIter)).linkToDeath(mDeathRecipientCaptor.capture(), anyInt()); for (int i = 0; i < numIter; ++i) { - // (3) verify first request and all odd requests issued to HAL + // (3) verify first request and all odd requests were issued to the WifiRttController if (i == 0 || i % 2 == 1) { - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(requests[i]), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(requests[i])); verifyWakeupSet(true, 0); } @@ -597,22 +639,23 @@ public class RttServiceImplTest extends WifiBaseTest { mDeathRecipientCaptor.getAllValues().get(0).binderDied(); mMockLooper.dispatchAll(); - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), + verify(mockRttControllerHal).rangeCancel(eq(mIntCaptor.getValue()), (ArrayList) mListCaptor.capture()); RangingRequest request0 = requests[0]; assertEquals(request0.mRttPeers.size(), mListCaptor.getValue().size()); - assertArrayEquals(MacAddress.fromString("00:01:02:03:04:00").toByteArray(), - (byte[]) mListCaptor.getValue().get(0)); - assertArrayEquals(MacAddress.fromString("0A:0B:0C:0D:0E:00").toByteArray(), - (byte[]) mListCaptor.getValue().get(1)); - assertArrayEquals(MacAddress.fromString("08:09:08:07:06:05").toByteArray(), - (byte[]) mListCaptor.getValue().get(2)); + assertTrue(MacAddress.fromString("00:01:02:03:04:00") + .equals(mListCaptor.getValue().get(0))); + assertTrue(MacAddress.fromString("0A:0B:0C:0D:0E:00") + .equals(mListCaptor.getValue().get(1))); + assertTrue(MacAddress.fromString("08:09:08:07:06:05") + .equals(mListCaptor.getValue().get(2))); } - // (5) native calls back with all results - should get requests for the odd attempts and + // (5) HAL calls back with all results - should get requests for the odd attempts and // should only get callbacks for the odd attempts (the non-dead UID), but this simulates // invalid results (or possibly the firmware not cancelling some requests) - mDut.onRangingResults(mIntCaptor.getValue(), results.get(i).second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.get(i).second); mMockLooper.dispatchAll(); if (i == 0) { verifyWakeupCancelled(); // as the first (dispatched) request is aborted @@ -635,11 +678,8 @@ public class RttServiceImplTest extends WifiBaseTest { } verify(mockMetrics, times(numIter / 2)).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -661,27 +701,25 @@ public class RttServiceImplTest extends WifiBaseTest { mMockLooper.dispatchAll(); verify(mockIbinder).linkToDeath(mDeathRecipientCaptor.capture(), anyInt()); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // (2) execute binder death mDeathRecipientCaptor.getValue().binderDied(); mMockLooper.dispatchAll(); - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); + verify(mockRttControllerHal).rangeCancel(eq(mIntCaptor.getValue()), any()); verifyWakeupCancelled(); // (3) provide results back - should be ignored - mDut.onRangingResults(mIntCaptor.getValue(), results.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.second); mMockLooper.dispatchAll(); // verify metrics verify(mockMetrics).recordRequest(eq(ws), eq(request)); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -716,25 +754,24 @@ public class RttServiceImplTest extends WifiBaseTest { // verify metrics verify(mockMetrics).recordRequest(eq(worksourceRequest), eq(request)); - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // (3) cancel the request mDut.cancelRanging(worksourceCancel); mMockLooper.dispatchAll(); - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); + verify(mockRttControllerHal).rangeCancel(eq(mIntCaptor.getValue()), any()); verifyWakeupCancelled(); - // (4) send results back from native - mDut.onRangingResults(mIntCaptor.getValue(), results.second); + // (4) send results back from the HAL + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.second); mMockLooper.dispatchAll(); - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -765,15 +802,16 @@ public class RttServiceImplTest extends WifiBaseTest { // verify metrics verify(mockMetrics).recordRequest(eq(worksourceRequest), eq(request)); - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // (3) cancel the request mDut.cancelRanging(worksourceCancel); - // (4) send results back from native - mDut.onRangingResults(mIntCaptor.getValue(), results.second); + // (4) send results back from the HAL + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.second); mMockLooper.dispatchAll(); verify(mockCallback).onRangingResults(results.second); @@ -782,16 +820,13 @@ public class RttServiceImplTest extends WifiBaseTest { // verify metrics verify(mockMetrics).recordResult(eq(request), eq(results.second), anyInt()); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } /** - * Validate that when an unexpected result is provided by the Native it is not propagated to + * Validate that when an unexpected result is provided by the HAL it is not propagated to * caller (unexpected = different command ID). */ @Test @@ -805,17 +840,19 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); - // (3) native calls back with result - but wrong ID - mDut.onRangingResults(mIntCaptor.getValue() + 1, + // (3) HAL calls back with result - but wrong ID + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue() + 1, RttTestUtils.getDummyRangingResults(null).second); mMockLooper.dispatchAll(); // (4) now send results with correct ID (different set of results to differentiate) - mDut.onRangingResults(mIntCaptor.getValue(), results.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.second); mMockLooper.dispatchAll(); // (5) verify that results dispatched @@ -826,11 +863,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); verify(mockMetrics).recordResult(eq(request), eq(results.second), anyInt()); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -859,12 +893,13 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // (3) return results with missing entries - mDut.onRangingResults(mIntCaptor.getValue(), results.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), results.second); mMockLooper.dispatchAll(); // (5) verify that (full) results dispatched @@ -876,11 +911,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); verify(mockMetrics).recordResult(eq(request), eq(results.second), anyInt()); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -905,12 +937,13 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - // (2) verify that request issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + // (2) verify that the request was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // (3) return results with ALL results missing - mDut.onRangingResults(mIntCaptor.getValue(), new ArrayList<>()); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), new ArrayList<>()); mMockLooper.dispatchAll(); // (5) verify that (full) results dispatched @@ -922,11 +955,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request)); verify(mockMetrics).recordResult(eq(request), eq(new ArrayList<>()), anyInt()); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -950,8 +980,8 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - // verify that request 1 issued to native - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); + // verify that request 1 was issued to the WifiRttController + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request1)); int cmdId1 = mIntCaptor.getValue(); verifyWakeupSet(true, 0); @@ -959,15 +989,17 @@ public class RttServiceImplTest extends WifiBaseTest { mAlarmManager.dispatch(RttServiceImpl.HAL_RANGING_TIMEOUT_TAG); mMockLooper.dispatchAll(); - // verify that: failure callback + request 2 issued to native - verify(mockNative).rangeCancel(eq(cmdId1), any()); + // verify that the failure callback + request 2 were issued to the WifiRttController + verify(mockRttControllerHal).rangeCancel(eq(cmdId1), any()); verify(mockCallback).onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request2), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request2)); verifyWakeupSet(true, 0); // (3) send both result 1 and result 2 - mDut.onRangingResults(cmdId1, result1.second); - mDut.onRangingResults(mIntCaptor.getValue(), result2.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(cmdId1, result1.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result2.second); mMockLooper.dispatchAll(); // verify that only result 2 is forwarded to client @@ -980,11 +1012,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordResult(eq(request2), eq(result2.second), anyInt()); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -1027,11 +1056,12 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request1)); verifyWakeupSet(true, clock.time); // (1.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result1.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result1.second); mMockLooper.dispatchAll(); cbInorder.verify(mockCallback).onRangingResults(result1.second); @@ -1051,11 +1081,12 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request3), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request3)); verifyWakeupSet(true, clock.time); // (3.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result3.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result3.second); mMockLooper.dispatchAll(); cbInorder.verify(mockCallback).onRangingResults(result3.second); @@ -1070,11 +1101,12 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request4), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request4)); verifyWakeupSet(true, clock.time); // (4.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result4.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result4.second); mMockLooper.dispatchAll(); cbInorder.verify(mockCallback).onRangingResults(result4.second); @@ -1103,11 +1135,12 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request6), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request6)); verifyWakeupSet(true, clock.time); // (6.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result6.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result6.second); mMockLooper.dispatchAll(); cbInorder.verify(mockCallback).onRangingResults(result6.second); @@ -1128,11 +1161,8 @@ public class RttServiceImplTest extends WifiBaseTest { WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE); verify(mockMetrics, times(4)).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -1189,11 +1219,12 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request1)); verifyWakeupSet(true, clock.time); // (1.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result1.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result1.second); mMockLooper.dispatchAll(); cbInorder.verify(mockCallback).onRangingResults(result1.second); @@ -1206,11 +1237,12 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request2), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request2)); verifyWakeupSet(true, clock.time); // (2.1) get result - mDut.onRangingResults(mIntCaptor.getValue(), result2.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result2.second); mMockLooper.dispatchAll(); cbInorder.verify(mockCallback).onRangingResults(result2.second); @@ -1233,11 +1265,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE); verify(mockMetrics, times(2)).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -1279,7 +1308,7 @@ public class RttServiceImplTest extends WifiBaseTest { mockCallback, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // 2. issue FLOOD LEVEL requests + 10 at various UIDs - no failure expected @@ -1296,7 +1325,7 @@ public class RttServiceImplTest extends WifiBaseTest { mMockLooper.dispatchAll(); verifyWakeupCancelled(); - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); + verify(mockRttControllerHal).rangeCancel(eq(mIntCaptor.getValue()), any()); verify(mockCallback, times(RttServiceImpl.MAX_QUEUED_PER_UID + 11)) .onRangingFailure(RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); @@ -1310,14 +1339,24 @@ public class RttServiceImplTest extends WifiBaseTest { } verify(mockMetrics, times(RttServiceImpl.MAX_QUEUED_PER_UID + 11)) .recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } + @Test + public void testGetRttCharacteristics() { + WifiRttController.Capabilities cap = new WifiRttController.Capabilities(); + cap.lcrSupported = true; + cap.oneSidedRttSupported = true; + cap.lciSupported = true; + when(mockRttControllerHal.getRttCapabilities()).thenReturn(cap); + Bundle characteristics = mDut.getRttCharacteristics(); + assertTrue(characteristics.getBoolean(CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT)); + assertTrue(characteristics.getBoolean(CHARACTERISTICS_KEY_BOOLEAN_LCI)); + assertTrue(characteristics.getBoolean(CHARACTERISTICS_KEY_BOOLEAN_LCR)); + } + /** * Utility to run configurable tests for flooding range requests. * - Execute a single request @@ -1342,14 +1381,15 @@ public class RttServiceImplTest extends WifiBaseTest { } InOrder cbInorder = inOrder(mockCallback); - InOrder nativeInorder = inOrder(mockNative); + InOrder controllerInorder = inOrder(mockRttControllerHal); // 1. issue a request mDut.startRanging(mockIbinder, mPackageName, mFeatureId, useUids ? null : ws, request, mockCallback, mExtras); mMockLooper.dispatchAll(); - nativeInorder.verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + controllerInorder.verify(mockRttControllerHal).rangeRequest( + mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // 2. issue FLOOD LEVEL requests + 10: should get 11 failures (10 extra + 1 original) @@ -1363,13 +1403,15 @@ public class RttServiceImplTest extends WifiBaseTest { RangingResultCallback.STATUS_CODE_FAIL); // 3. provide results - mDut.onRangingResults(mIntCaptor.getValue(), result.second); + mRangingResultsCbCaptor.getValue() + .onRangingResults(mIntCaptor.getValue(), result.second); mMockLooper.dispatchAll(); cbInorder.verify(mockCallback).onRangingResults(result.second); verifyWakeupCancelled(); - nativeInorder.verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request), eq(true)); + controllerInorder.verify(mockRttControllerHal).rangeRequest( + mIntCaptor.capture(), eq(request)); verifyWakeupSet(true, 0); // 4. issue a request: don't expect a failure @@ -1382,7 +1424,8 @@ public class RttServiceImplTest extends WifiBaseTest { mMockLooper.dispatchAll(); verifyWakeupCancelled(); - nativeInorder.verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); + controllerInorder.verify(mockRttControllerHal).rangeCancel( + eq(mIntCaptor.getValue()), any()); cbInorder.verify(mockCallback, times(RttServiceImpl.MAX_QUEUED_PER_UID)).onRangingFailure( RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); @@ -1395,11 +1438,8 @@ public class RttServiceImplTest extends WifiBaseTest { verify(mockMetrics, times(RttServiceImpl.MAX_QUEUED_PER_UID)).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); verify(mockMetrics).recordOverallStatus(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mAlarmManager.getAlarmManager()); } @@ -1447,20 +1487,19 @@ public class RttServiceImplTest extends WifiBaseTest { IRttCallback mockCallback2 = mock(IRttCallback.class); IRttCallback mockCallback3 = mock(IRttCallback.class); - // (1) request 2 ranging operations: request 1 should be sent to HAL + // (1) request 2 ranging operations: request 1 should be sent to the WifiRttController mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request1, mockCallback, mExtras); mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request2, mockCallback2, mExtras); mMockLooper.dispatchAll(); - verify(mockNative).rangeRequest(mIntCaptor.capture(), eq(request1), eq(true)); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), eq(request1)); verifyWakeupSet(true, 0); // (2) disable RTT: all requests should "fail" if (failureMode == FAILURE_MODE_DISABLE_WIFI) { - when(mockNative.isReady()).thenReturn(false); - mDut.disable(); + mRttLifecycleCbCaptor.getValue().onRttControllerDestroyed(); } else if (failureMode == FAILURE_MODE_ENABLE_DOZE) { simulatePowerStateChangeDoze(true); } else if (failureMode == FAILURE_MODE_DISABLE_LOCATIONING) { @@ -1470,8 +1509,10 @@ public class RttServiceImplTest extends WifiBaseTest { mMockLooper.dispatchAll(); assertFalse(mDut.isAvailable()); - validateCorrectRttStatusChangeBroadcast(false); - verify(mockNative).rangeCancel(eq(mIntCaptor.getValue()), any()); + validateCorrectRttStatusChangeBroadcast(); + if (failureMode != FAILURE_MODE_DISABLE_WIFI) { + verify(mockRttControllerHal).rangeCancel(eq(mIntCaptor.getValue()), any()); + } verify(mockCallback).onRangingFailure( RangingResultCallback.STATUS_CODE_FAIL_RTT_NOT_AVAILABLE); verify(mockCallback2).onRangingFailure( @@ -1488,8 +1529,8 @@ public class RttServiceImplTest extends WifiBaseTest { // (4) enable RTT: nothing should happen (no requests in queue!) if (failureMode == FAILURE_MODE_DISABLE_WIFI) { - when(mockNative.isReady()).thenReturn(true); - mDut.enableIfPossible(); + mRttLifecycleCbCaptor.getValue().onNewRttController(mockRttControllerHal); + verify(mockRttControllerHal, times(2)).registerRangingResultsCallback(any()); } else if (failureMode == FAILURE_MODE_ENABLE_DOZE) { simulatePowerStateChangeDoze(false); } else if (failureMode == FAILURE_MODE_DISABLE_LOCATIONING) { @@ -1499,18 +1540,15 @@ public class RttServiceImplTest extends WifiBaseTest { mMockLooper.dispatchAll(); assertTrue(mDut.isAvailable()); - validateCorrectRttStatusChangeBroadcast(true); + validateCorrectRttStatusChangeBroadcast(); // verify metrics verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request1)); verify(mockMetrics).recordRequest(eq(mDefaultWs), eq(request2)); verify(mockMetrics, times(3)).recordOverallStatus( WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE); - - verify(mockNative, atLeastOnce()).isReady(); verify(mockMetrics).enableVerboseLogging(anyBoolean()); - verify(mockNative).enableVerboseLogging(anyBoolean()); - verifyNoMoreInteractions(mockNative, mockMetrics, mockCallback, mockCallback2, + verifyNoMoreInteractions(mockRttControllerHal, mockMetrics, mockCallback, mockCallback2, mockCallback3, mAlarmManager.getAlarmManager()); } @@ -1556,10 +1594,8 @@ public class RttServiceImplTest extends WifiBaseTest { /** * Validates that the broadcast sent on RTT status change is correct. * - * @param expectedEnabled The expected change status - i.e. are we expected to announce that - * RTT is enabled (true) or disabled (false). */ - private void validateCorrectRttStatusChangeBroadcast(boolean expectedEnabled) { + private void validateCorrectRttStatusChangeBroadcast() { ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); mInOrder.verify(mockContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL)); 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 9d68fa81aa..32583e69f6 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 @@ -36,6 +36,7 @@ import static com.android.server.wifi.scanner.WifiScanningServiceImpl.WifiSingle import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.any; @@ -69,6 +70,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.os.BatteryStatsManager; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.WorkSource; @@ -86,6 +88,7 @@ import com.android.server.wifi.MockResources; import com.android.server.wifi.ScanResults; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiInjector; +import com.android.server.wifi.WifiLocalServices; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; import com.android.server.wifi.proto.nano.WifiMetricsProto; @@ -104,7 +107,6 @@ import org.mockito.Spy; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.StringWriter; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; @@ -147,6 +149,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { PresetKnownBandsChannelHelper mChannelHelper1; TestLooper mLooper; WifiScanningServiceImpl mWifiScanningServiceImpl; + private Bundle mExtras = new Bundle(); @Before public void setUp() throws Exception { @@ -195,6 +198,12 @@ public class WifiScanningServiceTest extends WifiBaseTest { anyInt(), eq(Binder.getCallingUid()))) .thenReturn(PERMISSION_GRANTED); when(mWifiInjector.getLastCallerInfoManager()).thenReturn(mLastCallerInfoManager); + // Defaulting apps to target SDK level that's prior to U. This is needed to test for + // backward compatibility of API changes. + when(mWifiPermissionsUtil.isTargetSdkLessThan(any(), + eq(Build.VERSION_CODES.UPSIDE_DOWN_CAKE), + anyInt())).thenReturn(true); + WifiLocalServices.removeServiceForTest(WifiScannerInternal.class); mWifiScanningServiceImpl = new WifiScanningServiceImpl(mContext, mLooper.getLooper(), mWifiScannerImplFactory, mBatteryStats, mWifiInjector); } @@ -593,6 +602,8 @@ public class WifiScanningServiceTest extends WifiBaseTest { 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), ScanResults.create(0, WifiScanner.WIFI_BAND_BOTH, new int[0])); + verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_SCANNER_START_SCAN), anyInt(), + anyInt(), anyInt(), anyString(), eq(true)); } /** @@ -1839,10 +1850,9 @@ public class WifiScanningServiceTest extends WifiBaseTest { scanResults.getRawScanResults()[1].timestamp = (currentTimeInMillis - 2) * 1000; scanResults.getRawScanResults()[2].timestamp = (currentTimeInMillis - CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS) * 1000; - List<ScanResult> expectedResults = new ArrayList<ScanResult>() {{ - add(scanResults.getRawScanResults()[0]); - add(scanResults.getRawScanResults()[1]); - }}; + List<ScanResult> expectedResults = List.of( + scanResults.getRawScanResults()[0], + scanResults.getRawScanResults()[1]); doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings), scanResults); @@ -3353,6 +3363,44 @@ public class WifiScanningServiceTest extends WifiBaseTest { mWifiScanningServiceImpl.isScanning()); } + @Test + public void getAvailableChannels_noPermission_throwsException_After_U() { + assumeTrue(SdkLevel.isAtLeastU()); + startServiceAndLoadDriver(); + + // verify app targeting prior to Android U can call API with location permission + when(mWifiPermissionsUtil.isTargetSdkLessThan(any(), + eq(Build.VERSION_CODES.UPSIDE_DOWN_CAKE), + anyInt())).thenReturn(true); + mWifiScanningServiceImpl.getAvailableChannels(WifiScanner.WIFI_BAND_24_GHZ, + TEST_PACKAGE_NAME, TEST_FEATURE_ID, mExtras); + + // Verify app targeting prior to Android U fails to call API without location permission + doThrow(new SecurityException()).when(mContext).enforcePermission( + eq(Manifest.permission.NETWORK_STACK), anyInt(), eq(Binder.getCallingUid()), any()); + doThrow(new SecurityException()) + .when(mWifiPermissionsUtil).enforceCanAccessScanResultsForWifiScanner( + TEST_PACKAGE_NAME, TEST_FEATURE_ID, Binder.getCallingUid(), false, false); + assertThrows(SecurityException.class, + () -> mWifiScanningServiceImpl.getAvailableChannels(WifiScanner.WIFI_BAND_24_GHZ, + TEST_PACKAGE_NAME, TEST_FEATURE_ID, mExtras)); + + // Verify app targeting Android U no longer need location. + when(mWifiPermissionsUtil.isTargetSdkLessThan(any(), + eq(Build.VERSION_CODES.UPSIDE_DOWN_CAKE), + anyInt())).thenReturn(false); + mWifiScanningServiceImpl.getAvailableChannels(WifiScanner.WIFI_BAND_24_GHZ, + TEST_PACKAGE_NAME, TEST_FEATURE_ID, mExtras); + + // Verify app targeting Android U will fail without nearby permission + doThrow(new SecurityException()) + .when(mWifiPermissionsUtil).enforceNearbyDevicesPermission( + any(), anyBoolean(), any()); + assertThrows(SecurityException.class, + () -> mWifiScanningServiceImpl.getAvailableChannels(WifiScanner.WIFI_BAND_24_GHZ, + TEST_PACKAGE_NAME, TEST_FEATURE_ID, mExtras)); + } + /** * Tests that {@link WifiScanningServiceImpl#getAvailableChannels(int, String)} throws a * {@link SecurityException} if the caller doesn't hold the required permissions. @@ -3371,7 +3419,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { TEST_PACKAGE_NAME, TEST_FEATURE_ID, Binder.getCallingUid(), false, false); mWifiScanningServiceImpl.getAvailableChannels(WifiScanner.WIFI_BAND_24_GHZ, - TEST_PACKAGE_NAME, TEST_FEATURE_ID); + TEST_PACKAGE_NAME, TEST_FEATURE_ID, mExtras); } /** @@ -3392,7 +3440,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { mLooper.startAutoDispatch(); Bundle bundle = mWifiScanningServiceImpl.getAvailableChannels( - WifiScanner.WIFI_BAND_24_GHZ, TEST_PACKAGE_NAME, TEST_FEATURE_ID); + WifiScanner.WIFI_BAND_24_GHZ, TEST_PACKAGE_NAME, TEST_FEATURE_ID, mExtras); mLooper.stopAutoDispatchAndIgnoreExceptions(); List<Integer> actual = bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA); @@ -3418,7 +3466,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { mLooper.startAutoDispatch(); Bundle bundle = mWifiScanningServiceImpl.getAvailableChannels( - WifiScanner.WIFI_BAND_24_GHZ, TEST_PACKAGE_NAME, TEST_FEATURE_ID); + WifiScanner.WIFI_BAND_24_GHZ, TEST_PACKAGE_NAME, TEST_FEATURE_ID, mExtras); mLooper.stopAutoDispatchAndIgnoreExceptions(); List<Integer> actual = bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA); @@ -3557,4 +3605,43 @@ public class WifiScanningServiceTest extends WifiBaseTest { mWifiScanningServiceImpl.stopPnoScan(client.listener, TEST_PACKAGE_NAME, null); mLooper.dispatchAll(); } + + /** + * Do a single scan and then stop. + * Expect scan canceled. + */ + @Test + public void sendSingleScanRequestAndThenStop() + throws Exception { + WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2412), 0, + 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); + ScanResults results = ScanResults.create(0, WifiScanner.WIFI_BAND_UNSPECIFIED, 2412); + + startServiceAndLoadDriver(); + + when(mWifiScannerImpl0.startSingleScan(any(WifiNative.ScanSettings.class), + any(WifiNative.ScanEventHandler.class))).thenReturn(true); + + TestClient client = new TestClient(); + InOrder order = inOrder(client.listener, mWifiScannerImpl0); + + // Run scan + client.sendSingleScanRequest(requestSettings, null); + mLooper.dispatchAll(); + client.verifySuccessfulResponse(); + WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, + computeSingleScanNativeSettings(requestSettings)); + //Stop scan + mWifiScanningServiceImpl.stopScan(client.listener, TEST_PACKAGE_NAME, TEST_FEATURE_ID); + mLooper.dispatchAll(); + // dispatch scan results + when(mWifiScannerImpl0.getLatestSingleScanResults()) + .thenReturn(results.getScanData()); + eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); + + // Stopped scan should not receive results + mLooper.dispatchAll(); + order.verify(client.listener, never()).onResults(any()); + order.verify(client.listener, never()).onSingleScanCompleted(); + } } 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 3f9cb51010..0ee9ea2484 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 @@ -941,9 +941,8 @@ public class ApConfigUtilTest extends WifiBaseTest { mockSoftApCapability)); // Reset client control testConfigBuilder.setClientControlByUserEnabled(false); - // - testConfigBuilder.setBlockedClientList(new ArrayList<>() {{ - add(MacAddress.fromString("aa:bb:cc:dd:ee:ff")); }}); + testConfigBuilder.setBlockedClientList(List.of( + MacAddress.fromString("aa:bb:cc:dd:ee:ff"))); assertFalse(ApConfigUtil.checkSupportAllConfiguration(testConfigBuilder.build(), mockSoftApCapability)); diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java index 566a94b45c..0ecf3b7d44 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/util/NativeUtilTest.java @@ -17,15 +17,24 @@ package com.android.server.wifi.util; import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.net.MacAddress; +import android.net.wifi.SecurityParams; +import android.net.wifi.WifiConfiguration; import androidx.test.filters.SmallTest; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.WifiConfigurationTestUtil; +import com.android.server.wifi.WifiGlobals; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; /** * Unit tests for {@link com.android.server.wifi.util.NativeUtil}. @@ -53,6 +62,19 @@ public class NativeUtilTest extends WifiBaseTest { } /** + * Test that converting a colon delimited MAC address to android.net.MacAddress works. Also test + * invalid input exception is handled by NativeUtil#getMacAddressOrNull() and returns 'null'. + */ + @Test + public void testGetMacAddressOrNull() throws Exception { + String macAddressStr = "11:22:33:44:55:66"; + assertEquals(MacAddress.fromString(macAddressStr), + NativeUtil.getMacAddressOrNull(macAddressStr)); + assertNull(NativeUtil.getMacAddressOrNull(":44:55:66")); + assertNull(NativeUtil.getMacAddressOrNull(null)); + } + + /** * Test that conversion of byte array of mac address to typical colon-delimited MAC address * works. */ @@ -227,4 +249,82 @@ public class NativeUtilTest extends WifiBaseTest { assertEquals("abcdefgh", NativeUtil.removeEnclosingQuotes("\"abcdefgh\"")); assertEquals("abcdefgh", NativeUtil.removeEnclosingQuotes("abcdefgh")); } + + /** + * Test PMF is disable when SAE is selected when SAE auto-upgrade offload is supported. + */ + @Test + public void testPmfIsDisableWhenPmfEnabledAndAutoUpgradeOffloadSupported() throws Exception { + WifiGlobals globals = mock(WifiGlobals.class); + when(globals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); + assertFalse(NativeUtil.getOptimalPmfSettingForConfig( + WifiConfigurationTestUtil.createPskSaeNetwork(), + true, globals)); + } + + /** + * Test pairwise & group cihpers are merged when SAE auto-upgrade offload is supported. + */ + @Test + public void testPairwiseCiphersMergedForSaeAutoUpgradeOffloadSupported() throws Exception { + WifiGlobals globals = mock(WifiGlobals.class); + when(globals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); + + SecurityParams saeParams = SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_SAE); + BitSet expectedPairwiseCiphers = new BitSet(); + expectedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); + expectedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + expectedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); + expectedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); + + BitSet optimalPairwiseCiphers = NativeUtil.getOptimalPairwiseCiphersForConfig( + WifiConfigurationTestUtil.createPskSaeNetwork(), + saeParams.getAllowedPairwiseCiphers(), globals); + assertEquals(expectedPairwiseCiphers, optimalPairwiseCiphers); + + BitSet expectedGroupCiphers = new BitSet(); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); + BitSet optimalGroupCiphers = NativeUtil.getOptimalGroupCiphersForConfig( + WifiConfigurationTestUtil.createPskSaeNetwork(), + saeParams.getAllowedGroupCiphers(), globals); + assertEquals(expectedGroupCiphers, optimalGroupCiphers); + } + + /** + * Test pairwise and group cihpers are not merged when SAE auto-upgrade offload + * is not supported. + */ + @Test + public void testPairwiseCiphersNotMergedForSaeAutoUpgradeOffloadNotSupported() + throws Exception { + WifiGlobals globals = mock(WifiGlobals.class); + when(globals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false); + + SecurityParams saeParams = SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_SAE); + BitSet expectedPairwiseCiphers = new BitSet(); + expectedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + expectedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); + expectedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); + + BitSet optimalPairwiseCiphers = NativeUtil.getOptimalPairwiseCiphersForConfig( + WifiConfigurationTestUtil.createPskSaeNetwork(), + saeParams.getAllowedPairwiseCiphers(), globals); + assertEquals(expectedPairwiseCiphers, optimalPairwiseCiphers); + + BitSet expectedGroupCiphers = new BitSet(); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); + expectedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); + BitSet optimalGroupCiphers = NativeUtil.getOptimalGroupCiphersForConfig( + WifiConfigurationTestUtil.createPskSaeNetwork(), + saeParams.getAllowedGroupCiphers(), globals); + assertEquals(expectedGroupCiphers, optimalGroupCiphers); + } } |