Snap for 11914274 from c4a85e50cd37a68db6908e9e3ef34a18a1e52025 to 24Q3-release Change-Id: I2b902694c125f3f87453cdf20875321599622a82
diff --git a/service/ServiceWifiResources/res/values/config.xml b/service/ServiceWifiResources/res/values/config.xml index 0e57ea8..19a7963 100644 --- a/service/ServiceWifiResources/res/values/config.xml +++ b/service/ServiceWifiResources/res/values/config.xml
@@ -1330,4 +1330,13 @@ <!-- Wi-Fi chip supports single link MLO SoftAp instances in the bridged mode --> <bool translatable="false" name="config_wifiSoftApSingleLinkMloInBridgedModeSupported">false</bool> + + <!-- Boolean indicating whether Target Wake Time (TWT) feature is supported or not. This flag + overrides the device's TWT capability if set to false. If the device supports TWT and this + overlay parameter is set to false, the application cannot set up a TWT session. Also, the + API WifiManager#getTwtCapabilities returns TWT unsupported even if the device is capable + of setting up TWT session. + --> + <bool translatable="false" name="config_wifiTwtSupported">true</bool> + </resources>
diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml index 421299d..eb540d1 100644 --- a/service/ServiceWifiResources/res/values/overlayable.xml +++ b/service/ServiceWifiResources/res/values/overlayable.xml
@@ -343,6 +343,7 @@ <item type="bool" name="config_wifiD2dAllowedControlSupportedWhenInfraStaDisabled" /> <item type="array" name="config_wifiTwtBlockedOuiList" /> <item type="bool" name="config_wifiSoftApSingleLinkMloInBridgedModeSupported" /> + <item type="bool" name="config_wifiTwtSupported" /> <!-- Params from config.xml that can be overlayed -->
diff --git a/service/java/com/android/server/wifi/TwtManager.java b/service/java/com/android/server/wifi/TwtManager.java index 077cd15..2d1333f 100644 --- a/service/java/com/android/server/wifi/TwtManager.java +++ b/service/java/com/android/server/wifi/TwtManager.java
@@ -97,12 +97,12 @@ private final AlarmManager mAlarmManager; private final Handler mHandler; ArraySet<Integer> mBlockedOuiSet = new ArraySet<>(); - private final WifiNative mWifiNative; private final WifiNativeTwtEvents mWifiNativeTwtEvents; private final AlarmManager.OnAlarmListener mTimeoutListener = () -> { startGarbageCollector(); }; + private final WifiInjector mWifiInjector; /** * Whenever primary clientModeManager identified by the interface name gets disconnected, reset @@ -121,6 +121,7 @@ TwtManager(@NonNull WifiInjector wifiInjector, @NonNull ClientModeImplMonitor cmiMonitor, @NonNull WifiNative wifiNative, @NonNull Handler handler, @NonNull Clock clock, int maxSessions, int startOffset) { + mWifiInjector = wifiInjector; mAlarmManager = wifiInjector.getAlarmManager(); mHandler = handler; mClock = clock; @@ -483,7 +484,7 @@ public void getTwtCapabilities(@Nullable String interfaceName, @NonNull ITwtCapabilitiesListener listener) { try { - if (interfaceName == null) { + if (interfaceName == null || !isTwtSupported()) { listener.onResult(getDefaultTwtCapabilities()); return; } @@ -506,6 +507,11 @@ */ public void setupTwtSession(@Nullable String interfaceName, @NonNull TwtRequest twtRequest, @NonNull ITwtCallback iTwtCallback, int callingUid, @NonNull String bssid) { + if (!isTwtSupported() || !isTwtCapable(interfaceName)) { + notifyFailure(iTwtCallback, CallbackType.SETUP, + TwtSessionCallback.TWT_ERROR_CODE_NOT_SUPPORTED); + return; + } if (isOuiBlockListed(bssid)) { notifyFailure(iTwtCallback, CallbackType.SETUP, TwtSessionCallback.TWT_ERROR_CODE_AP_OUI_BLOCKLISTED); @@ -527,6 +533,18 @@ } } + private boolean isTwtSupported() { + return mWifiInjector.getContext().getResources().getBoolean( + R.bool.config_wifiTwtSupported); + } + + private boolean isTwtCapable(String interfaceName) { + if (interfaceName == null) return false; + Bundle twtCapabilities = mWifiNative.getTwtCapabilities(interfaceName); + if (twtCapabilities == null) return false; + return twtCapabilities.getBoolean(WifiManager.TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER); + } + private boolean isOuiBlockListed(@NonNull String bssid) { if (mBlockedOuiSet.isEmpty()) return false; byte[] macBytes = MacAddress.fromString(bssid).toByteArray();
diff --git a/service/tests/wifitests/src/com/android/server/wifi/TwtManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/TwtManagerTest.java index 6bcc9c5..79db9d4 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/TwtManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/TwtManagerTest.java
@@ -118,11 +118,20 @@ {TEST_BLOCKED_OUI_4, TEST_BLOCKED_OUI_3, TEST_BLOCKED_OUI_2, TEST_BLOCKED_OUI_1}; when(mResources.getIntArray(R.array.config_wifiTwtBlockedOuiList)).thenReturn( blockedOuiList); + when(mResources.getBoolean(R.bool.config_wifiTwtSupported)).thenReturn(true); mTwtManager = new TwtManager(mWifiInjector, mCmiMonitor, mWifiNative, mHandler, mClock, WifiTwtSession.MAX_TWT_SESSIONS, TWT_CALLBACKS_ID_START_OFFSET); verify(mCmiMonitor).registerListener(mCmiListenerCaptor.capture()); mTwtManager.registerWifiNativeTwtEvents(); verify(mWifiNative).registerTwtCallbacks(mWifiNativeTwtEventsArgumentCaptor.capture()); + when(mWifiNative.getTwtCapabilities(eq(WIFI_IFACE_NAME))).thenReturn( + getMockTwtCapabilities()); + } + + private void disableTwtSupport() { + when(mResources.getBoolean(R.bool.config_wifiTwtSupported)).thenReturn(false); + mTwtManager = new TwtManager(mWifiInjector, mCmiMonitor, mWifiNative, mHandler, mClock, + WifiTwtSession.MAX_TWT_SESSIONS, TWT_CALLBACKS_ID_START_OFFSET); } private Bundle getDefaultTwtCapabilities() { @@ -199,6 +208,11 @@ mTwtManager.getTwtCapabilities(WIFI_IFACE_NAME, iTwtCapabilitiesListener); inorder.verify(iTwtCapabilitiesListener).onResult( argThat(argument -> isBundleContentEqual(mockTwtCapabilities, argument))); + // Disable overlay and test + disableTwtSupport(); + mTwtManager.getTwtCapabilities(WIFI_IFACE_NAME, iTwtCapabilitiesListener); + inorder.verify(iTwtCapabilitiesListener).onResult( + argThat(argument -> isBundleContentEqual(defaultTwtCapabilities, argument))); } @Test @@ -227,7 +241,7 @@ mTwtManager.setupTwtSession(null, twtRequest, iTwtCallback, Binder.getCallingUid(), TEST_BSSID); inOrderCallback.verify(iTwtCallback).onFailure( - TwtSessionCallback.TWT_ERROR_CODE_NOT_AVAILABLE); + TwtSessionCallback.TWT_ERROR_CODE_NOT_SUPPORTED); // Test when wifiNative.setupTwtSession return false when(mWifiNative.setupTwtSession(eq(1), eq(WIFI_IFACE_NAME), eq(twtRequest))).thenReturn( false); @@ -248,6 +262,28 @@ inOrderBinder.verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); inOrderAlarm.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyString(), any(AlarmManager.OnAlarmListener.class), eq(mHandler)); + // Enable overlay, disable TWT capability, and test + when(mWifiNative.getTwtCapabilities(eq(WIFI_IFACE_NAME))).thenReturn( + getDefaultTwtCapabilities()); + mTwtManager.setupTwtSession(WIFI_IFACE_NAME, twtRequest, iTwtCallback, + Binder.getCallingUid(), TEST_BSSID); + inOrderCallback.verify(iTwtCallback).onFailure( + TwtSessionCallback.TWT_ERROR_CODE_NOT_SUPPORTED); + // Disable overlay, enable TWT capability, and test + when(mWifiNative.getTwtCapabilities(eq(WIFI_IFACE_NAME))).thenReturn( + getMockTwtCapabilities()); + disableTwtSupport(); + mTwtManager.setupTwtSession(WIFI_IFACE_NAME, twtRequest, iTwtCallback, + Binder.getCallingUid(), TEST_BSSID); + inOrderCallback.verify(iTwtCallback).onFailure( + TwtSessionCallback.TWT_ERROR_CODE_NOT_SUPPORTED); + // Disable overlay, disable TWT capability, and test + when(mWifiNative.getTwtCapabilities(eq(WIFI_IFACE_NAME))).thenReturn( + getDefaultTwtCapabilities()); + mTwtManager.setupTwtSession(WIFI_IFACE_NAME, twtRequest, iTwtCallback, + Binder.getCallingUid(), TEST_BSSID); + inOrderCallback.verify(iTwtCallback).onFailure( + TwtSessionCallback.TWT_ERROR_CODE_NOT_SUPPORTED); } @Test