From 857b2f8fddb9b30f353b0543939df1bd12f9f641 Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 9 Jul 2020 01:08:16 +0800 Subject: wifi: bypass randomized Mac set failure when hal not support There are two use cases on SAP setMacaddress. 1. Mac randomization a. HAl not support - get pass b. Hal support - report error - generic error (Behavior changed in this commit) 2. Customized bssid - it should get failure since it is unsupported. a. Hal support - generic error b. Hal not support - unsupported configuration error indication. Bug: 160550985 Bug: 160550184 Test: atest FrameworksWifiTest Test: R-GSI + Q-vendor : Hotspot works normally. Merged-In: I530f41cd072ad0061e65fea9daf47c6b28113a77 Change-Id: I530f41cd072ad0061e65fea9daf47c6b28113a77 --- .../com/android/server/wifi/SoftApManager.java | 14 +++- .../java/com/android/server/wifi/WifiNative.java | 9 ++ .../com/android/server/wifi/WifiVendorHal.java | 22 +++++ .../com/android/server/wifi/SoftApManagerTest.java | 96 ++++++++++++++++++---- .../com/android/server/wifi/WifiNativeTest.java | 9 ++ .../com/android/server/wifi/WifiVendorHalTest.java | 30 +++++++ 6 files changed, 162 insertions(+), 18 deletions(-) diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java index ffbb388cc..9ef52e796 100644 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ b/service/java/com/android/server/wifi/SoftApManager.java @@ -348,10 +348,16 @@ public class SoftApManager implements ActiveModeManager { return SUCCESS; } - // We're configuring a random/custom MAC address. In this case, driver support is mandatory. - if (!mWifiNative.setMacAddress(mApInterfaceName, mac)) { - Log.e(TAG, "failed to set explicitly requested MAC address"); - return ERROR_GENERIC; + + if (mWifiNative.isSetMacAddressSupported(mApInterfaceName)) { + if (!mWifiNative.setMacAddress(mApInterfaceName, mac)) { + Log.e(TAG, "failed to set explicitly requested MAC address"); + return ERROR_GENERIC; + } + } else if (!mIsRandomizeBssid) { + // If hardware does not support MAC address setter, + // only report the error for non randomization. + return ERROR_UNSUPPORTED_CONFIGURATION; } return SUCCESS; } diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index 39d0fcc84..cf362d6a8 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -1787,6 +1787,15 @@ public class WifiNative { return mWifiVendorHal.setMacAddress(interfaceName, mac); } + /** + * Returns true if Hal version supports setMacAddress, otherwise false. + * + * @param interfaceName Name of the interface + */ + public boolean isSetMacAddressSupported(@NonNull String interfaceName) { + return mWifiVendorHal.isSetMacAddressSupported(interfaceName); + } + /** * Get the factory MAC address of the given interface * @param interfaceName Name of the interface. diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java index ed6ac7fdd..fd90c35df 100644 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ b/service/java/com/android/server/wifi/WifiVendorHal.java @@ -1331,6 +1331,28 @@ public class WifiVendorHal { return boolResult(false); } + /** + * Returns true if Hal version supports setMacAddress, otherwise false. + * + * @param ifaceName Name of the interface + */ + public boolean isSetMacAddressSupported(@NonNull String ifaceName) { + synchronized (sLock) { + android.hardware.wifi.V1_2.IWifiStaIface sta12 = + getWifiStaIfaceForV1_2Mockable(ifaceName); + if (sta12 != null) { + return true; + } + + android.hardware.wifi.V1_4.IWifiApIface ap14 = + getWifiApIfaceForV1_4Mockable(ifaceName); + if (ap14 != null) { + return true; + } + } + return false; + } + /** * Get factory MAC address of the given interface * diff --git a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java index ddd8fe515..c4c00939a 100644 --- a/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java @@ -146,6 +146,8 @@ public class SoftApManagerTest extends WifiBaseTest { MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); + when(mWifiNative.isSetMacAddressSupported(any())).thenReturn(true); + when(mWifiNative.setMacAddress(any(), any())).thenReturn(true); when(mWifiNative.startSoftAp(eq(TEST_INTERFACE_NAME), any(), any())).thenReturn(true); when(mFrameworkFacade.getIntegerSetting( @@ -1699,17 +1701,75 @@ public class SoftApManagerTest extends WifiBaseTest { } @Test - public void setMacFailureAllowedWhenRandomizationOff() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi_ap_mac_randomization_supported)) - .thenReturn(false); - SoftApModeConfiguration apConfig = - new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, - mTestSoftApCapability); + public void setsCustomMacWhenSetMacNotSupport() throws Exception { + when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); + when(mWifiNative.isSetMacAddressSupported(any())).thenReturn(false); + Builder configBuilder = new SoftApConfiguration.Builder(); + configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); + configBuilder.setSsid(TEST_SSID); + configBuilder.setBssid(MacAddress.fromString("23:34:45:56:67:78")); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + IFACE_IP_MODE_LOCAL_ONLY, configBuilder.build(), mTestSoftApCapability); + ArgumentCaptor mac = ArgumentCaptor.forClass(MacAddress.class); + + mSoftApManager = createSoftApManager(apConfig, TEST_COUNTRY_CODE); + mSoftApManager.start(); + mLooper.dispatchAll(); + verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); + verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, + WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION); + verify(mWifiNative, never()).setMacAddress(any(), any()); + } + + @Test + public void setMacFailureWhenCustomMac() throws Exception { + when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); + Builder configBuilder = new SoftApConfiguration.Builder(); + configBuilder.setBand(SoftApConfiguration.BAND_2GHZ); + configBuilder.setSsid(TEST_SSID); + configBuilder.setBssid(MacAddress.fromString("23:34:45:56:67:78")); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + IFACE_IP_MODE_LOCAL_ONLY, configBuilder.build(), mTestSoftApCapability); ArgumentCaptor mac = ArgumentCaptor.forClass(MacAddress.class); + when(mWifiNative.setMacAddress(eq(TEST_INTERFACE_NAME), mac.capture())).thenReturn(false); - when(mWifiNative.setMacAddress(any(), any())).thenReturn(false); + mSoftApManager = createSoftApManager(apConfig, TEST_COUNTRY_CODE); + mSoftApManager.start(); + mLooper.dispatchAll(); + verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); + verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, + WifiManager.SAP_START_FAILURE_GENERAL); + assertThat(mac.getValue()).isEqualTo(MacAddress.fromString("23:34:45:56:67:78")); + } + @Test + public void setMacFailureWhenRandomMac() throws Exception { + when(mWifiNative.setupInterfaceForSoftApMode(any())).thenReturn(TEST_INTERFACE_NAME); + when(mWifiApConfigStore.getApConfiguration()).thenReturn(mDefaultApConfig); + SoftApConfiguration randomizedBssidConfig = + new SoftApConfiguration.Builder(mDefaultApConfig) + .setBssid(TEST_MAC_ADDRESS).build(); + when(mWifiApConfigStore.randomizeBssidIfUnset(any(), any())).thenReturn( + randomizedBssidConfig); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + IFACE_IP_MODE_LOCAL_ONLY, null, mTestSoftApCapability); + ArgumentCaptor mac = ArgumentCaptor.forClass(MacAddress.class); + when(mWifiNative.setMacAddress(eq(TEST_INTERFACE_NAME), mac.capture())).thenReturn(false); + mSoftApManager = createSoftApManager(apConfig, TEST_COUNTRY_CODE); + mSoftApManager.start(); + mLooper.dispatchAll(); + verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); + verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, + WifiManager.SAP_START_FAILURE_GENERAL); + } + + @Test + public void setRandomMacWhenSetMacNotsupport() throws Exception { + when(mWifiNative.isSetMacAddressSupported(any())).thenReturn(false); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + IFACE_IP_MODE_LOCAL_ONLY, null, mTestSoftApCapability); startSoftApAndVerifyEnabled(apConfig); + verify(mWifiNative, never()).setMacAddress(any(), any()); } @Test @@ -1852,15 +1912,22 @@ public class SoftApManagerTest extends WifiBaseTest { /** Starts soft AP and verifies that it is enabled successfully. */ protected void startSoftApAndVerifyEnabled( SoftApModeConfiguration softApConfig, String countryCode) throws Exception { - SoftApConfiguration expectedConfig; + // The expected config to pass to Native + SoftApConfiguration expectedConfig = null; + // The config which base on mDefaultApConfig and generate ramdonized mac address + SoftApConfiguration randomizedBssidConfig = null; InOrder order = inOrder(mCallback, mWifiNative); - mSoftApManager = createSoftApManager(softApConfig, countryCode); - mSoftApManager.mSoftApNotifier = mFakeSoftApNotifier; SoftApConfiguration config = softApConfig.getSoftApConfiguration(); if (config == null) { + // Only generate randomized mac for default config since test case doesn't care it. when(mWifiApConfigStore.getApConfiguration()).thenReturn(mDefaultApConfig); - expectedConfig = new SoftApConfiguration.Builder(mDefaultApConfig) + randomizedBssidConfig = + new SoftApConfiguration.Builder(mDefaultApConfig) + .setBssid(TEST_MAC_ADDRESS).build(); + when(mWifiApConfigStore.randomizeBssidIfUnset(any(), any())).thenReturn( + randomizedBssidConfig); + expectedConfig = new SoftApConfiguration.Builder(randomizedBssidConfig) .setChannel(DEFAULT_AP_CHANNEL, SoftApConfiguration.BAND_2GHZ) .build(); } else { @@ -1868,7 +1935,8 @@ public class SoftApManagerTest extends WifiBaseTest { .setChannel(DEFAULT_AP_CHANNEL, SoftApConfiguration.BAND_2GHZ) .build(); } - + mSoftApManager = createSoftApManager(softApConfig, countryCode); + mSoftApManager.mSoftApNotifier = mFakeSoftApNotifier; ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); when(mWifiNative.setupInterfaceForSoftApMode(any())) @@ -1905,8 +1973,8 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mListener).onStarted(); verify(mWifiMetrics).addSoftApUpChangedEvent(true, softApConfig.getTargetMode(), TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLS); - verify(mWifiMetrics).updateSoftApConfiguration(config == null ? mDefaultApConfig : config, - softApConfig.getTargetMode()); + verify(mWifiMetrics).updateSoftApConfiguration(config == null + ? randomizedBssidConfig : config, softApConfig.getTargetMode()); verify(mWifiMetrics).updateSoftApCapability(softApConfig.getCapability(), softApConfig.getTargetMode()); } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java index ea4ebe5d0..46a3de86a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java @@ -865,6 +865,15 @@ public class WifiNativeTest extends WifiBaseTest { verify(mWifiVendorHal).setMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS); } + /** + * Verifies that isSetMacAddressSupported() calls underlying WifiVendorHal. + */ + @Test + public void testIsSetMacAddressSupported() throws Exception { + mWifiNative.isSetMacAddressSupported(WIFI_IFACE_NAME); + verify(mWifiVendorHal).isSetMacAddressSupported(WIFI_IFACE_NAME); + } + /** * Test that selectTxPowerScenario() calls into WifiVendorHal (success case) */ diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java index 363ae6923..9cf9ed4b1 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java @@ -2964,6 +2964,36 @@ public class WifiVendorHalTest extends WifiBaseTest { assertFalse(mWifiVendorHal.setMacAddress(TEST_IFACE_NAME, TEST_MAC_ADDRESS)); } + /** + * Verifies isSetMacAddressSupported(). + */ + @Test + public void testIsSetMacAddressSupportedWhenV1_4Support() throws Exception { + mWifiVendorHal = spy(mWifiVendorHal); + when(mWifiVendorHal.getWifiApIfaceForV1_4Mockable(TEST_IFACE_NAME_1)) + .thenReturn(mIWifiApIfaceV14); + + assertTrue(mWifiVendorHal.isSetMacAddressSupported(TEST_IFACE_NAME_1)); + } + + /** + * Verifies isSetMacAddressSupported(). + */ + @Test + public void testIsSetMacAddressSupportedWhenV1_2Support() throws Exception { + // Expose the 1.2 IWifiStaIface. + mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mHandler); + assertTrue(mWifiVendorHal.isSetMacAddressSupported(TEST_IFACE_NAME)); + } + + /** + * Verifies isSetMacAddressSupported() does not crash with older HALs. + */ + @Test + public void testIsSetMacAddressSupportedOnOlderHal() throws Exception { + assertFalse(mWifiVendorHal.isSetMacAddressSupported(TEST_IFACE_NAME)); + } + /** * Verifies radio mode change callback to indicate DBS mode. */ -- cgit v1.2.3