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