From 3990382e47de260883cd05e935bfdbde9d12c2fd Mon Sep 17 00:00:00 2001 From: maheshkkv Date: Tue, 28 Nov 2023 15:31:53 -0800 Subject: [PATCH] Add TWT support for vendor HAL Bug: 296108122 Test: m Change-Id: I897d405567a23e3c30ca46dce49c52dc939b508c --- .../android/hardware/wifi/IWifiStaIface.aidl | 7 + .../wifi/IWifiStaIfaceEventCallback.aidl | 27 +++ .../hardware/wifi/TwtCapabilities.aidl | 45 ++++ .../android/hardware/wifi/TwtRequest.aidl | 42 ++++ .../android/hardware/wifi/TwtSession.aidl | 54 +++++ .../hardware/wifi/TwtSessionStats.aidl | 43 ++++ .../android/hardware/wifi/IWifiStaIface.aidl | 111 +++++++++ .../wifi/IWifiStaIfaceEventCallback.aidl | 102 ++++++++ .../hardware/wifi/TwtCapabilities.aidl | 56 +++++ .../android/hardware/wifi/TwtRequest.aidl | 44 ++++ .../android/hardware/wifi/TwtSession.aidl | 92 +++++++ .../hardware/wifi/TwtSessionStats.aidl | 53 ++++ wifi/aidl/default/aidl_struct_util.cpp | 126 ++++++++++ wifi/aidl/default/aidl_struct_util.h | 12 + wifi/aidl/default/wifi_legacy_hal.cpp | 167 +++++++++++++ wifi/aidl/default/wifi_legacy_hal.h | 49 +++- wifi/aidl/default/wifi_legacy_hal_stubs.cpp | 7 + wifi/aidl/default/wifi_sta_iface.cpp | 226 ++++++++++++++++++ wifi/aidl/default/wifi_sta_iface.h | 16 ++ 19 files changed, 1273 insertions(+), 6 deletions(-) create mode 100644 wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtCapabilities.aidl create mode 100644 wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtRequest.aidl create mode 100644 wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSession.aidl create mode 100644 wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSessionStats.aidl create mode 100644 wifi/aidl/android/hardware/wifi/TwtCapabilities.aidl create mode 100644 wifi/aidl/android/hardware/wifi/TwtRequest.aidl create mode 100644 wifi/aidl/android/hardware/wifi/TwtSession.aidl create mode 100644 wifi/aidl/android/hardware/wifi/TwtSessionStats.aidl diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl index f8384130b2..e7c3444d84 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIface.aidl @@ -62,6 +62,13 @@ interface IWifiStaIface { void stopSendingKeepAlivePackets(in int cmdId); void setDtimMultiplier(in int multiplier); android.hardware.wifi.CachedScanData getCachedScanData(); + android.hardware.wifi.TwtCapabilities twtGetCapabilities(); + void twtSessionSetup(in int cmdId, in android.hardware.wifi.TwtRequest twtRequest); + void twtSessionUpdate(in int cmdId, in int sessionId, in android.hardware.wifi.TwtRequest twtRequest); + void twtSessionSuspend(in int cmdId, in int sessionId); + void twtSessionResume(in int cmdId, in int sessionId); + void twtSessionTeardown(in int cmdId, in int sessionId); + void twtSessionGetStats(in int cmdId, in int sessionId); @Backing(type="int") @VintfStability enum FeatureSetMask { APF = (1 << 0) /* 1 */, diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl index 48b85b0fcf..629ca3d922 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl @@ -38,4 +38,31 @@ interface IWifiStaIfaceEventCallback { oneway void onBackgroundScanFailure(in int cmdId); oneway void onBackgroundScanResults(in int cmdId, in android.hardware.wifi.StaScanData[] scanDatas); oneway void onRssiThresholdBreached(in int cmdId, in byte[6] currBssid, in int currRssi); + oneway void onTwtFailure(in int cmdId, in android.hardware.wifi.IWifiStaIfaceEventCallback.TwtErrorCode error); + oneway void onTwtSessionCreate(in int cmdId, in android.hardware.wifi.TwtSession twtSession); + oneway void onTwtSessionUpdate(in int cmdId, in android.hardware.wifi.TwtSession twtSession); + oneway void onTwtSessionTeardown(in int cmdId, in int twtSessionId, in android.hardware.wifi.IWifiStaIfaceEventCallback.TwtTeardownReasonCode reasonCode); + oneway void onTwtSessionStats(in int cmdId, in int twtSessionId, in android.hardware.wifi.TwtSessionStats twtSessionStats); + oneway void onTwtSessionSuspend(in int cmdId, in int twtSessionId); + oneway void onTwtSessionResume(in int cmdId, in int twtSessionId); + @Backing(type="byte") @VintfStability + enum TwtErrorCode { + FAILURE_UNKNOWN, + ALREADY_RESUMED, + ALREADY_SUSPENDED, + INVALID_PARAMS, + MAX_SESSION_REACHED, + NOT_AVAILABLE, + NOT_SUPPORTED, + PEER_NOT_SUPPORTED, + PEER_REJECTED, + TIMEOUT, + } + @Backing(type="byte") @VintfStability + enum TwtTeardownReasonCode { + UNKNOWN, + LOCALLY_REQUESTED, + INTERNALLY_INITIATED, + PEER_INITIATED, + } } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtCapabilities.aidl new file mode 100644 index 0000000000..d8e73fb4b7 --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtCapabilities.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable TwtCapabilities { + boolean isTwtRequesterSupported; + boolean isTwtResponderSupported; + boolean isBroadcastTwtSupported; + boolean isFlexibleTwtScheduleSupported; + int minWakeDurationMicros; + int maxWakeDurationMicros; + int minWakeIntervalMicros; + int maxWakeIntervalMicros; +} diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtRequest.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtRequest.aidl new file mode 100644 index 0000000000..3051b943a3 --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtRequest.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable TwtRequest { + int mloLinkId; + int minWakeDurationMicros; + int maxWakeDurationMicros; + int minWakeIntervalMicros; + int maxWakeIntervalMicros; +} diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSession.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSession.aidl new file mode 100644 index 0000000000..92c2533e2c --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSession.aidl @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable TwtSession { + int sessionId; + int mloLinkId; + int wakeDurationMicros; + int wakeIntervalMicros; + android.hardware.wifi.TwtSession.TwtNegotiationType negotiationType; + boolean isTriggerEnabled; + boolean isAnnounced; + boolean isImplicit; + boolean isProtected; + boolean isUpdatable; + boolean isSuspendable; + boolean isResponderPmModeEnabled; + @Backing(type="byte") @VintfStability + enum TwtNegotiationType { + INDIVIDUAL = 0, + BROADCAST = 1, + } +} diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSessionStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSessionStats.aidl new file mode 100644 index 0000000000..528444a84b --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/TwtSessionStats.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable TwtSessionStats { + int avgTxPktCount; + int avgRxPktCount; + int avgTxPktSize; + int avgRxPktSize; + int avgEospDurationMicros; + int eospCount; +} diff --git a/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl index 3c8b55fa03..2ec95c5540 100644 --- a/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl +++ b/wifi/aidl/android/hardware/wifi/IWifiStaIface.aidl @@ -25,6 +25,8 @@ import android.hardware.wifi.StaLinkLayerStats; import android.hardware.wifi.StaRoamingCapabilities; import android.hardware.wifi.StaRoamingConfig; import android.hardware.wifi.StaRoamingState; +import android.hardware.wifi.TwtCapabilities; +import android.hardware.wifi.TwtRequest; import android.hardware.wifi.WifiBand; import android.hardware.wifi.WifiDebugRxPacketFateReport; import android.hardware.wifi.WifiDebugTxPacketFateReport; @@ -569,4 +571,113 @@ interface IWifiStaIface { * |WifiStatusCode.ERROR_UNKNOWN| */ CachedScanData getCachedScanData(); + + /** + * Get Target Wake Time (TWT) local device capabilities for the station interface. + * + * @return Instance of |TwtCapabilities|. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_NOT_AVAILABLE|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + TwtCapabilities twtGetCapabilities(); + + /** + * Setup a Target Wake Time (TWT) session. + * + * Supported only if |TwtCapabilities.isTwtRequesterSupported| is set. Results in asynchronous + * callback |IWifiStaIfaceEventCallback.onTwtSessionCreate| on success or + * |IWifiStaIfaceEventCallback.onTwtFailure| on failure. + * + * @param cmdId Command Id to use for this invocation. The value 0 is reserved. + * @param twtRequest TWT Request parameters. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + void twtSessionSetup(in int cmdId, in TwtRequest twtRequest); + + /** + * Update a Target Wake Time (TWT) session. + * + * Supported only if the TWT session can be updated. See |TwtSession.isUpdatable|. Results in + * asynchronous callback |IWifiStaIfaceEventCallback.onTwtSessionUpdate| on success or + * |IWifiStaIfaceEventCallback.onTwtFailure| on failure. + * + * @param cmdId Command Id to use for this invocation. The value 0 is reserved. + * @param sessionId TWT session id. + * @param twtRequest TWT Request parameters. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + void twtSessionUpdate(in int cmdId, in int sessionId, in TwtRequest twtRequest); + + /** + * Suspend a Target Wake Time (TWT) session until a resume is called. + * + * Supported only if the TWT session supports suspend and resume. See + * |TwtSession.isSuspendable|. Results in asynchronous callback + * |IWifiStaIfaceEventCallback.onTwtSessionSuspend| on success or + * |IWifiStaIfaceEventCallback.onTwtFailure| on failure. + * + * @param cmdId Command Id to use for this invocation. The value 0 is reserved. + * @param sessionId TWT session id. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + void twtSessionSuspend(in int cmdId, in int sessionId); + + /** + * Resume a Target Wake Time (TWT) session which is suspended. + * + * Supported only if the TWT session supports suspend and resume. See + * |TwtSession.isSuspendable|. Results in asynchronous callback + * |IWifiStaIfaceEventCallback.onTwtSessionResume| on success or + * |IWifiStaIfaceEventCallback.onTwtFailure| on failure. + * + * @param cmdId Command Id to use for this invocation. The value 0 is reserved. + * @param sessionId TWT session id. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + void twtSessionResume(in int cmdId, in int sessionId); + + /** + * Teardown a Target Wake Time (TWT) session. + * + * Results in asynchronous callback |IWifiStaIfaceEventCallback.onTwtSessionTeardown| on + * success or |IWifiStaIfaceEventCallback.onTwtFailure| on failure. + * + * @param cmdId Command Id to use for this invocation. The value 0 is reserved. + * @param sessionId TWT session id. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + void twtSessionTeardown(in int cmdId, in int sessionId); + + /** + * Get stats for a Target Wake Time (TWT) session. + * + * Results in asynchronous callback |IWifiStaIfaceEventCallback.onTwtSessionStats| on success + * or |IWifiStaIfaceEventCallback.onTwtFailure| on failure. + * + * @param cmdId Command Id to use for this invocation. The value 0 is reserved. + * @param sessionId TWT session id. + * @throws ServiceSpecificException with one of the following values: + * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|, + * |WifiStatusCode.ERROR_NOT_SUPPORTED|, + * |WifiStatusCode.ERROR_UNKNOWN| + */ + void twtSessionGetStats(in int cmdId, in int sessionId); } diff --git a/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl b/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl index 93a255f9b4..dda7c771f5 100644 --- a/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl +++ b/wifi/aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.aidl @@ -18,6 +18,8 @@ package android.hardware.wifi; import android.hardware.wifi.StaScanData; import android.hardware.wifi.StaScanResult; +import android.hardware.wifi.TwtSession; +import android.hardware.wifi.TwtSessionStats; @VintfStability oneway interface IWifiStaIfaceEventCallback { @@ -61,4 +63,104 @@ oneway interface IWifiStaIfaceEventCallback { * @param currRssi RSSI of the currently connected access point. */ void onRssiThresholdBreached(in int cmdId, in byte[6] currBssid, in int currRssi); + + @VintfStability + @Backing(type="byte") + enum TwtErrorCode { + /** Unknown failure */ + FAILURE_UNKNOWN, + /** TWT session is already resumed */ + ALREADY_RESUMED, + /** TWT session is already suspended */ + ALREADY_SUSPENDED, + /** Invalid parameters */ + INVALID_PARAMS, + /** Maximum number of sessions reached */ + MAX_SESSION_REACHED, + /** Requested operation is not available */ + NOT_AVAILABLE, + /** Requested operation is not supported */ + NOT_SUPPORTED, + /** Requested operation is not supported by the peer */ + PEER_NOT_SUPPORTED, + /** Requested operation is rejected by the peer */ + PEER_REJECTED, + /** Requested operation is timed out */ + TIMEOUT, + } + + @VintfStability + @Backing(type="byte") + enum TwtTeardownReasonCode { + /** Unknown reason */ + UNKNOWN, + /** Teardown requested by the framework */ + LOCALLY_REQUESTED, + /** Teardown initiated internally by the firmware or driver */ + INTERNALLY_INITIATED, + /** Teardown initiated by the peer */ + PEER_INITIATED, + } + + /** + * Called to indicate a TWT failure. If there is no command associated with this failure cmdId + * will be 0. + * + * @param cmdId Id used to identify the command. The value 0 indicates no associated command. + * @param error error code. + */ + void onTwtFailure(in int cmdId, in TwtErrorCode error); + + /** + * Called when a Target Wake Time session is created. See |IWifiStaIface.twtSessionSetup|. + * + * @param cmdId Id used to identify the command. + * @param twtSession TWT session. + */ + void onTwtSessionCreate(in int cmdId, in TwtSession twtSession); + + /** + * Called when a Target Wake Time session is updated. See |IWifiStaIface.twtSessionUpdate|. + * + * @param cmdId Id used to identify the command. + * @param twtSession TWT session. + */ + void onTwtSessionUpdate(in int cmdId, in TwtSession twtSession); + + /** + * Called when the Target Wake Time session is torndown. + * See |IWifiStaIface.twtSessionTeardown|. + * + * @param cmdId Id used to identify the command. The value 0 indicates no associated command. + * @param twtSessionId TWT session id. + * @param reasonCode reason code for the TWT teardown. + */ + void onTwtSessionTeardown( + in int cmdId, in int twtSessionId, in TwtTeardownReasonCode reasonCode); + + /** + * Called when TWT session stats available. See |IWifiStaIface.twtSessionGetStats|. + * + * @param cmdId Id used to identify the command. + * @param twtSessionId TWT session id. + * @param twtSessionStats TWT session stats. + */ + void onTwtSessionStats(in int cmdId, in int twtSessionId, in TwtSessionStats twtSessionStats); + + /** + * Called when the Target Wake Time session is suspended. + * See |IWifiStaIface.twtSessionSuspend|. + * + * @param cmdId Id used to identify the command. The value 0 indicates no associated command. + * @param twtSessionId TWT session id. + */ + void onTwtSessionSuspend(in int cmdId, in int twtSessionId); + + /** + * Called when the Target Wake Time session is resumed. See |IWifiStaIface.twtSessionResume|. + * + * @param cmdId Id used to identify the command. The value 0 indicates no associated command. + * @param twtSessionId TWT session id. + */ + void onTwtSessionResume(in int cmdId, in int twtSessionId); } diff --git a/wifi/aidl/android/hardware/wifi/TwtCapabilities.aidl b/wifi/aidl/android/hardware/wifi/TwtCapabilities.aidl new file mode 100644 index 0000000000..9007d0e5be --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/TwtCapabilities.aidl @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 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 android.hardware.wifi; + +/** + * Target Wake Time (TWT) Capabilities supported. + */ +@VintfStability +parcelable TwtCapabilities { + /** + * Whether the TWT requester mode supported. + */ + boolean isTwtRequesterSupported; + /** + * Whether the TWT responder mode supported. + */ + boolean isTwtResponderSupported; + /** + * Whether the Broadcast TWT mode (TWT scheduling STA) supported. + */ + boolean isBroadcastTwtSupported; + /** + * Whether supports Flexible TWT schedules. + */ + boolean isFlexibleTwtScheduleSupported; + /** + * Minimum TWT wake duration in microseconds. + */ + int minWakeDurationMicros; + /** + * Maximum TWT wake duration in microseconds. + */ + int maxWakeDurationMicros; + /** + * Minimum TWT wake interval in microseconds. + */ + int minWakeIntervalMicros; + /** + * Maximum TWT wake interval in microseconds. + */ + int maxWakeIntervalMicros; +} diff --git a/wifi/aidl/android/hardware/wifi/TwtRequest.aidl b/wifi/aidl/android/hardware/wifi/TwtRequest.aidl new file mode 100644 index 0000000000..5191713f57 --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/TwtRequest.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 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 android.hardware.wifi; + +/** + * Target Wake Time (TWT) Request + */ +@VintfStability +parcelable TwtRequest { + /** + * MLO Link id in case TWT is requesting for MLO connection. Otherwise -1. + */ + int mloLinkId; + /** + * Minimum TWT wake duration in microseconds. + */ + int minWakeDurationMicros; + /** + * Maximum TWT wake duration in microseconds. + */ + int maxWakeDurationMicros; + /** + * Minimum TWT wake interval in microseconds. + */ + int minWakeIntervalMicros; + /** + * Maximum TWT wake interval in microseconds. + */ + int maxWakeIntervalMicros; +} diff --git a/wifi/aidl/android/hardware/wifi/TwtSession.aidl b/wifi/aidl/android/hardware/wifi/TwtSession.aidl new file mode 100644 index 0000000000..5a7ddb1a0b --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/TwtSession.aidl @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 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 android.hardware.wifi; + +/** + * Target Wake Time (TWT) Session + */ +@VintfStability +parcelable TwtSession { + @VintfStability + @Backing(type="byte") + enum TwtNegotiationType { + INDIVIDUAL = 0, + BROADCAST = 1, + } + + /** + * An unique identifier for the session. + */ + int sessionId; + + /** + * MLO Link id in case of MLO connection. Otherwise -1. + */ + int mloLinkId; + + /** + * TWT service period in microseconds. + */ + int wakeDurationMicros; + + /** + * Time interval in microseconds between two successive TWT service periods. + */ + int wakeIntervalMicros; + + /** + * TWT negotiation type. + */ + TwtNegotiationType negotiationType; + + /** + * Whether the TWT session is trigger enabled or non-trigger enabled. + */ + boolean isTriggerEnabled; + + /** + * Whether the TWT session is announced or unannounced. + */ + boolean isAnnounced; + + /** + * Whether the TWT session is implicit or explicit. + */ + boolean isImplicit; + + /** + * Whether the TWT session is protected or not. + */ + boolean isProtected; + + /** + * Whether the TWT session can be updated. + */ + boolean isUpdatable; + + /** + * Whether the TWT session can be suspended and then resumed. + */ + boolean isSuspendable; + + /** + * Whether AP (TWT responder) intends to go to doze state outside of TWT Service Periods. + * + * Refer IEEE 802.11 spec, Section 10.47.7 (TWT Sleep Setup). + */ + boolean isResponderPmModeEnabled; +} diff --git a/wifi/aidl/android/hardware/wifi/TwtSessionStats.aidl b/wifi/aidl/android/hardware/wifi/TwtSessionStats.aidl new file mode 100644 index 0000000000..e2e2d12b7e --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/TwtSessionStats.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023 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 android.hardware.wifi; + +/** + * Target Wake Time (TWT) Session Stats + */ +@VintfStability +parcelable TwtSessionStats { + /** + * Average number of Tx packets in each wake duration. + */ + int avgTxPktCount; + + /** + * Average number of Rx packets in each wake duration. + */ + int avgRxPktCount; + + /** + * Average bytes per Tx packets in each wake duration. + */ + int avgTxPktSize; + + /** + * Average bytes per Rx packets in each wake duration. + */ + int avgRxPktSize; + + /** + * Average End of Service period in microseconds. + */ + int avgEospDurationMicros; + + /** + * Count of early terminations. + */ + int eospCount; +} diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp index d2bfef6620..89212381ca 100644 --- a/wifi/aidl/default/aidl_struct_util.cpp +++ b/wifi/aidl/default/aidl_struct_util.cpp @@ -3574,6 +3574,132 @@ WifiRatePreamble convertScanResultFlagsToPreambleType(int flags) { return WifiRatePreamble::OFDM; } +bool convertTwtCapabilitiesToAidl(legacy_hal::wifi_twt_capabilities legacy_twt_capabs, + TwtCapabilities* aidl_twt_capabs) { + if (!aidl_twt_capabs) { + return false; + } + aidl_twt_capabs->isTwtRequesterSupported = legacy_twt_capabs.is_twt_requester_supported; + aidl_twt_capabs->isTwtResponderSupported = legacy_twt_capabs.is_twt_responder_supported; + aidl_twt_capabs->isBroadcastTwtSupported = legacy_twt_capabs.is_flexible_twt_supported; + if (legacy_twt_capabs.min_wake_duration_micros > legacy_twt_capabs.max_wake_duration_micros) { + return false; + } + aidl_twt_capabs->minWakeDurationMicros = legacy_twt_capabs.min_wake_duration_micros; + aidl_twt_capabs->maxWakeDurationMicros = legacy_twt_capabs.max_wake_duration_micros; + if (legacy_twt_capabs.min_wake_interval_micros > legacy_twt_capabs.max_wake_interval_micros) { + return false; + } + aidl_twt_capabs->minWakeIntervalMicros = legacy_twt_capabs.min_wake_interval_micros; + aidl_twt_capabs->maxWakeIntervalMicros = legacy_twt_capabs.max_wake_interval_micros; + return true; +} + +bool convertAidlTwtRequestToLegacy(const TwtRequest aidl_twt_request, + legacy_hal::wifi_twt_request* legacy_twt_request) { + if (legacy_twt_request == nullptr) { + return false; + } + legacy_twt_request->mlo_link_id = aidl_twt_request.mloLinkId; + if (aidl_twt_request.minWakeDurationMicros > aidl_twt_request.maxWakeDurationMicros) { + return false; + } + legacy_twt_request->min_wake_duration_micros = aidl_twt_request.minWakeDurationMicros; + legacy_twt_request->max_wake_duration_micros = aidl_twt_request.maxWakeDurationMicros; + if (aidl_twt_request.minWakeIntervalMicros > aidl_twt_request.maxWakeIntervalMicros) { + return false; + } + legacy_twt_request->min_wake_interval_micros = aidl_twt_request.minWakeIntervalMicros; + legacy_twt_request->max_wake_interval_micros = aidl_twt_request.maxWakeIntervalMicros; + return true; +} + +IWifiStaIfaceEventCallback::TwtErrorCode convertLegacyHalTwtErrorCodeToAidl( + legacy_hal::wifi_twt_error_code legacy_error_code) { + switch (legacy_error_code) { + case WIFI_TWT_ERROR_CODE_TIMEOUT: + return IWifiStaIfaceEventCallback::TwtErrorCode::TIMEOUT; + case WIFI_TWT_ERROR_CODE_PEER_REJECTED: + return IWifiStaIfaceEventCallback::TwtErrorCode::PEER_REJECTED; + case WIFI_TWT_ERROR_CODE_PEER_NOT_SUPPORTED: + return IWifiStaIfaceEventCallback::TwtErrorCode::PEER_NOT_SUPPORTED; + case WIFI_TWT_ERROR_CODE_NOT_SUPPORTED: + return IWifiStaIfaceEventCallback::TwtErrorCode::NOT_SUPPORTED; + case WIFI_TWT_ERROR_CODE_NOT_AVAILABLE: + return IWifiStaIfaceEventCallback::TwtErrorCode::NOT_AVAILABLE; + case WIFI_TWT_ERROR_CODE_MAX_SESSION_REACHED: + return IWifiStaIfaceEventCallback::TwtErrorCode::MAX_SESSION_REACHED; + case WIFI_TWT_ERROR_CODE_INVALID_PARAMS: + return IWifiStaIfaceEventCallback::TwtErrorCode::INVALID_PARAMS; + case WIFI_TWT_ERROR_CODE_ALREADY_SUSPENDED: + return IWifiStaIfaceEventCallback::TwtErrorCode::ALREADY_SUSPENDED; + case WIFI_TWT_ERROR_CODE_ALREADY_RESUMED: + return IWifiStaIfaceEventCallback::TwtErrorCode::ALREADY_RESUMED; + default: + return IWifiStaIfaceEventCallback::TwtErrorCode::FAILURE_UNKNOWN; + } +} + +IWifiStaIfaceEventCallback::TwtTeardownReasonCode convertLegacyHalTwtReasonCodeToAidl( + legacy_hal::wifi_twt_teardown_reason_code legacy_reason_code) { + switch (legacy_reason_code) { + case WIFI_TWT_TEARDOWN_REASON_CODE_LOCALLY_REQUESTED: + return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::LOCALLY_REQUESTED; + case WIFI_TWT_TEARDOWN_REASON_CODE_INTERNALLY_INITIATED: + return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::INTERNALLY_INITIATED; + case WIFI_TWT_TEARDOWN_REASON_CODE_PEER_INITIATED: + return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::PEER_INITIATED; + default: + return IWifiStaIfaceEventCallback::TwtTeardownReasonCode::UNKNOWN; + } +} + +bool convertLegacyHalTwtSessionToAidl(legacy_hal::wifi_twt_session twt_session, + TwtSession* aidl_twt_session) { + if (aidl_twt_session == nullptr) { + return false; + } + + aidl_twt_session->sessionId = twt_session.session_id; + aidl_twt_session->mloLinkId = twt_session.mlo_link_id; + aidl_twt_session->wakeDurationMicros = twt_session.wake_duration_micros; + aidl_twt_session->wakeIntervalMicros = twt_session.wake_interval_micros; + switch (twt_session.negotiation_type) { + case WIFI_TWT_NEGO_TYPE_INDIVIDUAL: + aidl_twt_session->negotiationType = TwtSession::TwtNegotiationType::INDIVIDUAL; + break; + case WIFI_TWT_NEGO_TYPE_BROADCAST: + aidl_twt_session->negotiationType = TwtSession::TwtNegotiationType::BROADCAST; + break; + default: + return false; + } + aidl_twt_session->isTriggerEnabled = twt_session.is_trigger_enabled; + aidl_twt_session->isAnnounced = twt_session.is_announced; + aidl_twt_session->isImplicit = twt_session.is_implicit; + aidl_twt_session->isProtected = twt_session.is_protected; + aidl_twt_session->isUpdatable = twt_session.is_updatable; + aidl_twt_session->isSuspendable = twt_session.is_suspendable; + aidl_twt_session->isResponderPmModeEnabled = twt_session.is_responder_pm_mode_enabled; + return true; +} + +bool convertLegacyHalTwtSessionStatsToAidl(legacy_hal::wifi_twt_session_stats twt_stats, + TwtSessionStats* aidl_twt_stats) { + if (aidl_twt_stats == nullptr) { + return false; + } + + aidl_twt_stats->avgTxPktCount = twt_stats.avg_pkt_num_tx; + aidl_twt_stats->avgRxPktCount = twt_stats.avg_pkt_num_rx; + aidl_twt_stats->avgTxPktSize = twt_stats.avg_tx_pkt_size; + aidl_twt_stats->avgRxPktSize = twt_stats.avg_rx_pkt_size; + aidl_twt_stats->avgEospDurationMicros = twt_stats.avg_eosp_dur_us; + aidl_twt_stats->eospCount = twt_stats.eosp_count; + + return true; +} + } // namespace aidl_struct_util } // namespace wifi } // namespace hardware diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h index 1942b5f484..708936354a 100644 --- a/wifi/aidl/default/aidl_struct_util.h +++ b/wifi/aidl/default/aidl_struct_util.h @@ -218,6 +218,18 @@ bool convertCachedScanReportToAidl(const legacy_hal::WifiCachedScanReport& repor bool convertCachedScanResultToAidl(const legacy_hal::wifi_cached_scan_result& legacy_scan_result, uint64_t ts_us, CachedScanResult* aidl_scan_result); WifiRatePreamble convertScanResultFlagsToPreambleType(int flags); +bool convertTwtCapabilitiesToAidl(const legacy_hal::wifi_twt_capabilities legacy_twt_capabs, + TwtCapabilities* aidl_twt_capabs); +bool convertAidlTwtRequestToLegacy(const TwtRequest aidl_twt_request, + legacy_hal::wifi_twt_request* legacy_twt_request); +IWifiStaIfaceEventCallback::TwtErrorCode convertLegacyHalTwtErrorCodeToAidl( + legacy_hal::wifi_twt_error_code legacy_error_code); +IWifiStaIfaceEventCallback::TwtTeardownReasonCode convertLegacyHalTwtReasonCodeToAidl( + legacy_hal::wifi_twt_teardown_reason_code legacy_reason_code); +bool convertLegacyHalTwtSessionToAidl(legacy_hal::wifi_twt_session twt_session, + TwtSession* aidl_twt_session); +bool convertLegacyHalTwtSessionStatsToAidl(legacy_hal::wifi_twt_session_stats twt_stats, + TwtSessionStats* aidl_twt_stats); } // namespace aidl_struct_util } // namespace wifi } // namespace hardware diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp index 2e80183436..55d6f59314 100644 --- a/wifi/aidl/default/wifi_legacy_hal.cpp +++ b/wifi/aidl/default/wifi_legacy_hal.cpp @@ -457,6 +457,76 @@ void onSyncCachedScanResults(wifi_cached_scan_report* cache_report) { } } +// Callback to be invoked for TWT failure +std::function + on_twt_failure_internal_callback; +void onAsyncTwtError(wifi_request_id id, wifi_twt_error_code error_code) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_twt_failure_internal_callback) { + on_twt_failure_internal_callback(id, error_code); + } +} + +// Callback to be invoked for TWT session creation +std::function + on_twt_session_create_internal_callback; +void onAsyncTwtSessionCreate(wifi_request_id id, wifi_twt_session twt_session) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_twt_session_create_internal_callback) { + on_twt_session_create_internal_callback(id, twt_session); + } +} + +// Callback to be invoked for TWT session update +std::function + on_twt_session_update_internal_callback; +void onAsyncTwtSessionUpdate(wifi_request_id id, wifi_twt_session twt_session) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_twt_session_update_internal_callback) { + on_twt_session_update_internal_callback(id, twt_session); + } +} + +// Callback to be invoked for TWT session teardown +std::function + on_twt_session_teardown_internal_callback; +void onAsyncTwtSessionTeardown(wifi_request_id id, int twt_session_id, + wifi_twt_teardown_reason_code reason_code) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_twt_session_teardown_internal_callback) { + on_twt_session_teardown_internal_callback(id, twt_session_id, reason_code); + } +} + +// Callback to be invoked for TWT session get stats +std::function + on_twt_session_stats_internal_callback; +void onAsyncTwtSessionStats(wifi_request_id id, int twt_session_id, wifi_twt_session_stats stats) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_twt_session_stats_internal_callback) { + on_twt_session_stats_internal_callback(id, twt_session_id, stats); + } +} + +// Callback to be invoked for TWT session suspend +std::function on_twt_session_suspend_internal_callback; +void onAsyncTwtSessionSuspend(wifi_request_id id, int twt_session_id) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_twt_session_suspend_internal_callback) { + on_twt_session_suspend_internal_callback(id, twt_session_id); + } +} + +// Callback to be invoked for TWT session resume +std::function on_twt_session_resume_internal_callback; +void onAsyncTwtSessionResume(wifi_request_id id, int twt_session_id) { + const auto lock = aidl_sync_util::acquireGlobalLock(); + if (on_twt_session_resume_internal_callback) { + on_twt_session_resume_internal_callback(id, twt_session_id); + } +} + // End of the free-standing "C" style callbacks. WifiLegacyHal::WifiLegacyHal(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool, @@ -1789,6 +1859,103 @@ wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, wifi_voip_m return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode); } +std::pair WifiLegacyHal::twtGetCapabilities( + const std::string& ifaceName) { + wifi_twt_capabilities capabs = {}; + wifi_error status = + global_func_table_.wifi_twt_get_capabilities(getIfaceHandle(ifaceName), &capabs); + return {capabs, status}; +} + +wifi_error WifiLegacyHal::twtSessionSetup( + const std::string& ifaceName, uint32_t cmdId, const wifi_twt_request& request, + const on_twt_failure& on_twt_failure_user_callback, + const on_twt_session_create& on_twt_session_create_user_callback, + const on_twt_session_update& on_twt_session_update_user_callback, + const on_twt_session_teardown& on_twt_session_teardown_user_callback, + const on_twt_session_stats& on_twt_session_stats_user_callback, + const on_twt_session_suspend& on_twt_session_suspend_user_callback, + const on_twt_session_resume& on_twt_session_resume_user_callback) { + if (on_twt_failure_internal_callback || on_twt_session_create_internal_callback || + on_twt_session_update_internal_callback || on_twt_session_teardown_internal_callback || + on_twt_session_stats_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + on_twt_failure_internal_callback = [on_twt_failure_user_callback]( + wifi_request_id id, wifi_twt_error_code error_code) { + on_twt_failure_user_callback(id, error_code); + }; + + on_twt_session_create_internal_callback = [on_twt_session_create_user_callback]( + wifi_request_id id, + wifi_twt_session twt_session) { + on_twt_session_create_user_callback(id, twt_session); + }; + + on_twt_session_update_internal_callback = [on_twt_session_update_user_callback]( + wifi_request_id id, + wifi_twt_session twt_session) { + on_twt_session_update_user_callback(id, twt_session); + }; + + on_twt_session_teardown_internal_callback = [on_twt_session_teardown_user_callback]( + wifi_request_id id, int session_id, + wifi_twt_teardown_reason_code reason_code) { + on_twt_session_teardown_user_callback(id, session_id, reason_code); + }; + + on_twt_session_stats_internal_callback = [on_twt_session_stats_user_callback]( + wifi_request_id id, int session_id, + wifi_twt_session_stats stats) { + on_twt_session_stats_user_callback(id, session_id, stats); + }; + + on_twt_session_suspend_internal_callback = [on_twt_session_suspend_user_callback]( + wifi_request_id id, int session_id) { + on_twt_session_suspend_user_callback(id, session_id); + }; + + on_twt_session_resume_internal_callback = [on_twt_session_resume_user_callback]( + wifi_request_id id, int session_id) { + on_twt_session_resume_user_callback(id, session_id); + }; + + return global_func_table_.wifi_twt_session_setup( + cmdId, getIfaceHandle(ifaceName), request, + {onAsyncTwtError, onAsyncTwtSessionCreate, onAsyncTwtSessionUpdate, + onAsyncTwtSessionTeardown, onAsyncTwtSessionStats, onAsyncTwtSessionSuspend, + onAsyncTwtSessionResume}); +} + +wifi_error WifiLegacyHal::twtSessionUpdate(const std::string& ifaceName, uint32_t cmdId, + uint32_t sessionId, const wifi_twt_request& request) { + return global_func_table_.wifi_twt_session_update(cmdId, getIfaceHandle(ifaceName), sessionId, + request); +} + +wifi_error WifiLegacyHal::twtSessionSuspend(const std::string& ifaceName, uint32_t cmdId, + uint32_t sessionId) { + return global_func_table_.wifi_twt_session_suspend(cmdId, getIfaceHandle(ifaceName), sessionId); +} + +wifi_error WifiLegacyHal::twtSessionResume(const std::string& ifaceName, uint32_t cmdId, + uint32_t sessionId) { + return global_func_table_.wifi_twt_session_resume(cmdId, getIfaceHandle(ifaceName), sessionId); +} + +wifi_error WifiLegacyHal::twtSessionTeardown(const std::string& ifaceName, uint32_t cmdId, + uint32_t sessionId) { + return global_func_table_.wifi_twt_session_teardown(cmdId, getIfaceHandle(ifaceName), + sessionId); +} + +wifi_error WifiLegacyHal::twtSessionGetStats(const std::string& ifaceName, uint32_t cmdId, + uint32_t sessionId) { + return global_func_table_.wifi_twt_session_get_stats(cmdId, getIfaceHandle(ifaceName), + sessionId); +} + wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name, const TwtCallbackHandlers& user_callbacks) { on_twt_event_setup_response_callback = user_callbacks.on_setup_response; diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h index 17509df3ec..121d1b5ed8 100644 --- a/wifi/aidl/default/wifi_legacy_hal.h +++ b/wifi/aidl/default/wifi_legacy_hal.h @@ -376,6 +376,13 @@ using ::wifi_scan_cmd_params; using ::WIFI_SCAN_FLAG_INTERRUPTED; using ::wifi_scan_result; using ::WIFI_SUCCESS; +using ::wifi_twt_capabilities; +using ::wifi_twt_error_code; +using ::wifi_twt_events; +using ::wifi_twt_request; +using ::wifi_twt_session; +using ::wifi_twt_session_stats; +using ::wifi_twt_teardown_reason_code; using ::wifi_tx_packet_fate; using ::wifi_tx_report; using ::wifi_usable_channel; @@ -555,6 +562,16 @@ struct CachedScanResultsCallbfackHandlers { std::function on_cached_scan_results; }; +using on_twt_failure = std::function; +using on_twt_session_create = std::function; +using on_twt_session_update = std::function; +using on_twt_session_teardown = std::function; +using on_twt_session_stats = + std::function; +using on_twt_session_suspend = std::function; +using on_twt_session_resume = std::function; + /** * Class that encapsulates all legacy HAL interactions. * This class manages the lifetime of the event loop thread used by legacy HAL. @@ -761,19 +778,39 @@ class WifiLegacyHal { wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode); + // TWT functions + std::pair twtGetCapabilities(const std::string& ifaceName); + wifi_error twtSessionSetup(const std::string& ifaceName, uint32_t cmdId, + const wifi_twt_request& request, + const on_twt_failure& on_twt_failure_user_callback, + const on_twt_session_create& on_twt_session_create_user_callback, + const on_twt_session_update& on_twt_session_update_user_callback, + const on_twt_session_teardown& on_twt_session_teardown_user_callback, + const on_twt_session_stats& on_twt_session_stats_user_callback, + const on_twt_session_suspend& on_twt_session_suspend_user_callback, + const on_twt_session_resume& on_twt_session_resume_user_callback); + wifi_error twtSessionUpdate(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId, + const wifi_twt_request& request); + wifi_error twtSessionSuspend(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId); + wifi_error twtSessionResume(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId); + wifi_error twtSessionTeardown(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId); + wifi_error twtSessionGetStats(const std::string& ifaceName, uint32_t cmdId, uint32_t sessionId); + + // Note: Following TWT functions are deprecated + // Deprecated wifi_error twtRegisterHandler(const std::string& iface_name, const TwtCallbackHandlers& handler); - + // Deprecated by twtGetCapabilities std::pair twtGetCapability(const std::string& iface_name); - + // Deprecated by twtSessionSetup wifi_error twtSetupRequest(const std::string& iface_name, const TwtSetupRequest& msg); - + // Deprecated by twtSessionTeardown wifi_error twtTearDownRequest(const std::string& iface_name, const TwtTeardownRequest& msg); - + // Deprecated by twtSessionSuspend and twtSessionResume wifi_error twtInfoFrameRequest(const std::string& iface_name, const TwtInfoFrameRequest& msg); - + // Deprecated by twtSessionGetStats std::pair twtGetStats(const std::string& iface_name, uint8_t configId); - + // Deprecated wifi_error twtClearStats(const std::string& iface_name, uint8_t configId); wifi_error setScanMode(const std::string& iface_name, bool enable); diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp index 3d59c658a1..3e4afd0427 100644 --- a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp +++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp @@ -181,6 +181,13 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { populateStubFor(&hal_fn->wifi_get_supported_iface_concurrency_matrix); populateStubFor(&hal_fn->wifi_get_rtt_capabilities_v3); populateStubFor(&hal_fn->wifi_rtt_range_request_v3); + populateStubFor(&hal_fn->wifi_twt_get_capabilities); + populateStubFor(&hal_fn->wifi_twt_session_setup); + populateStubFor(&hal_fn->wifi_twt_session_update); + populateStubFor(&hal_fn->wifi_twt_session_suspend); + populateStubFor(&hal_fn->wifi_twt_session_resume); + populateStubFor(&hal_fn->wifi_twt_session_teardown); + populateStubFor(&hal_fn->wifi_twt_session_get_stats); return true; } diff --git a/wifi/aidl/default/wifi_sta_iface.cpp b/wifi/aidl/default/wifi_sta_iface.cpp index 0ae428f179..f0509dc19e 100644 --- a/wifi/aidl/default/wifi_sta_iface.cpp +++ b/wifi/aidl/default/wifi_sta_iface.cpp @@ -224,6 +224,44 @@ ndk::ScopedAStatus WifiStaIface::getCachedScanData(CachedScanData* _aidl_return) &WifiStaIface::getCachedScanDataInternal, _aidl_return); } +ndk::ScopedAStatus WifiStaIface::twtGetCapabilities(TwtCapabilities* _aidl_return) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::twtGetCapabilitiesInternal, _aidl_return); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionSetup(int32_t in_cmdId, + const TwtRequest& in_twtRequest) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::twtSessionSetupInternal, in_cmdId, in_twtRequest); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionUpdate(int32_t in_cmdId, int32_t in_sessionId, + const TwtRequest& in_twtRequest) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::twtSessionUpdateInternal, in_cmdId, in_sessionId, + in_twtRequest); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionSuspend(int32_t in_cmdId, int32_t in_sessionId) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::twtSessionSuspendInternal, in_cmdId, in_sessionId); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionResume(int32_t in_cmdId, int32_t in_sessionId) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::twtSessionResumeInternal, in_cmdId, in_sessionId); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionTeardown(int32_t in_cmdId, int32_t in_sessionId) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::twtSessionTeardownInternal, in_cmdId, in_sessionId); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionGetStats(int32_t in_cmdId, int32_t in_sessionId) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::twtSessionGetStatsInternal, in_cmdId, in_sessionId); +} + std::pair WifiStaIface::getNameInternal() { return {ifname_, ndk::ScopedAStatus::ok()}; } @@ -560,6 +598,194 @@ std::pair WifiStaIface::getCachedScanDataInt return {aidl_scan_data, ndk::ScopedAStatus::ok()}; } +std::pair WifiStaIface::twtGetCapabilitiesInternal() { + legacy_hal::wifi_twt_capabilities legacyHaltwtCapabilities; + legacy_hal::wifi_error legacy_status; + std::tie(legacyHaltwtCapabilities, legacy_status) = + legacy_hal_.lock()->twtGetCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {TwtCapabilities{}, createWifiStatusFromLegacyError(legacy_status)}; + } + TwtCapabilities aidlTwtCapabilities; + if (!aidl_struct_util::convertTwtCapabilitiesToAidl(legacyHaltwtCapabilities, + &aidlTwtCapabilities)) { + return {TwtCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)}; + } + return {aidlTwtCapabilities, ndk::ScopedAStatus::ok()}; +} + +ndk::ScopedAStatus WifiStaIface::twtSessionSetupInternal(int32_t cmdId, + const TwtRequest& aidlTwtRequest) { + legacy_hal::wifi_twt_request legacyHalTwtRequest; + if (!aidl_struct_util::convertAidlTwtRequestToLegacy(aidlTwtRequest, &legacyHalTwtRequest)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + std::weak_ptr weak_ptr_this = weak_ptr_this_; + + // onTwtFailure callback + const auto& on_twt_failure = [weak_ptr_this](legacy_hal::wifi_request_id id, + legacy_hal::wifi_twt_error_code error_code) { + const auto shared_ptr_this = weak_ptr_this.lock(); + IWifiStaIfaceEventCallback::TwtErrorCode aidl_error_code = + aidl_struct_util::convertLegacyHalTwtErrorCodeToAidl(error_code); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onTwtFailure(id, aidl_error_code).isOk()) { + LOG(ERROR) << "Failed to invoke onTwtFailure callback"; + } + } + }; + // onTwtSessionCreate callback + const auto& on_twt_session_create = [weak_ptr_this](legacy_hal::wifi_request_id id, + legacy_hal::wifi_twt_session twt_session) { + const auto shared_ptr_this = weak_ptr_this.lock(); + TwtSession aidl_twt_session; + if (!aidl_struct_util::convertLegacyHalTwtSessionToAidl(twt_session, &aidl_twt_session)) { + LOG(ERROR) << "convertLegacyHalTwtSessionToAidl failed"; + return; + } + + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onTwtSessionCreate(id, aidl_twt_session).isOk()) { + LOG(ERROR) << "Failed to invoke onTwtSessionCreate callback"; + } + } + }; + // onTwtSessionUpdate callback + const auto& on_twt_session_update = [weak_ptr_this](legacy_hal::wifi_request_id id, + legacy_hal::wifi_twt_session twt_session) { + const auto shared_ptr_this = weak_ptr_this.lock(); + TwtSession aidl_twt_session; + if (!aidl_struct_util::convertLegacyHalTwtSessionToAidl(twt_session, &aidl_twt_session)) { + LOG(ERROR) << "convertLegacyHalTwtSessionToAidl failed"; + return; + } + + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onTwtSessionUpdate(id, aidl_twt_session).isOk()) { + LOG(ERROR) << "Failed to invoke onTwtSessionUpdate callback"; + } + } + }; + // onTwtSessionTeardown callback + const auto& on_twt_session_teardown = + [weak_ptr_this](legacy_hal::wifi_request_id id, int session_id, + legacy_hal::wifi_twt_teardown_reason_code reason_code) { + const auto shared_ptr_this = weak_ptr_this.lock(); + IWifiStaIfaceEventCallback::TwtTeardownReasonCode aidl_reason_code = + aidl_struct_util::convertLegacyHalTwtReasonCodeToAidl(reason_code); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onTwtSessionTeardown(id, session_id, aidl_reason_code).isOk()) { + LOG(ERROR) << "Failed to invoke onTwtSessionTeardown callback"; + } + } + }; + // onTwtSessionStats callback + const auto& on_twt_session_stats = [weak_ptr_this](legacy_hal::wifi_request_id id, + int session_id, + legacy_hal::wifi_twt_session_stats stats) { + const auto shared_ptr_this = weak_ptr_this.lock(); + TwtSessionStats aidl_session_stats; + if (!aidl_struct_util::convertLegacyHalTwtSessionStatsToAidl(stats, &aidl_session_stats)) { + LOG(ERROR) << "convertLegacyHalTwtSessionStatsToAidl failed"; + return; + } + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onTwtSessionStats(id, session_id, aidl_session_stats).isOk()) { + LOG(ERROR) << "Failed to invoke onTwtSessionStats callback"; + } + } + }; + // onTwtSessionSuspend callback + const auto& on_twt_session_suspend = [weak_ptr_this](legacy_hal::wifi_request_id id, + int session_id) { + const auto shared_ptr_this = weak_ptr_this.lock(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onTwtSessionSuspend(id, session_id).isOk()) { + LOG(ERROR) << "Failed to invoke onTwtSessionSuspend callback"; + } + } + }; + // onTwtSessionResume callback + const auto& on_twt_session_resume = [weak_ptr_this](legacy_hal::wifi_request_id id, + int session_id) { + const auto shared_ptr_this = weak_ptr_this.lock(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onTwtSessionResume(id, session_id).isOk()) { + LOG(ERROR) << "Failed to invoke onTwtSessionResume callback"; + } + } + }; + + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->twtSessionSetup( + ifname_, cmdId, legacyHalTwtRequest, on_twt_failure, on_twt_session_create, + on_twt_session_update, on_twt_session_teardown, on_twt_session_stats, + on_twt_session_suspend, on_twt_session_resume); + return createWifiStatusFromLegacyError(legacy_status); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionUpdateInternal(int32_t cmdId, int32_t sessionId, + const TwtRequest& aidlTwtRequest) { + legacy_hal::wifi_twt_request legacyHalTwtRequest; + if (!aidl_struct_util::convertAidlTwtRequestToLegacy(aidlTwtRequest, &legacyHalTwtRequest)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->twtSessionUpdate(ifname_, cmdId, sessionId, legacyHalTwtRequest); + return createWifiStatusFromLegacyError(legacy_status); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionSuspendInternal(int32_t cmdId, int32_t sessionId) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->twtSessionSuspend(ifname_, cmdId, sessionId); + return createWifiStatusFromLegacyError(legacy_status); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionResumeInternal(int32_t cmdId, int32_t sessionId) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->twtSessionResume(ifname_, cmdId, sessionId); + return createWifiStatusFromLegacyError(legacy_status); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionTeardownInternal(int32_t cmdId, int32_t sessionId) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->twtSessionTeardown(ifname_, cmdId, sessionId); + return createWifiStatusFromLegacyError(legacy_status); +} + +ndk::ScopedAStatus WifiStaIface::twtSessionGetStatsInternal(int32_t cmdId, int32_t sessionId) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->twtSessionGetStats(ifname_, cmdId, sessionId); + return createWifiStatusFromLegacyError(legacy_status); +} + } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/aidl/default/wifi_sta_iface.h b/wifi/aidl/default/wifi_sta_iface.h index fe05c21483..eb8f745475 100644 --- a/wifi/aidl/default/wifi_sta_iface.h +++ b/wifi/aidl/default/wifi_sta_iface.h @@ -91,6 +91,14 @@ class WifiStaIface : public BnWifiStaIface { ndk::ScopedAStatus setScanMode(bool in_enable) override; ndk::ScopedAStatus setDtimMultiplier(int32_t in_multiplier) override; ndk::ScopedAStatus getCachedScanData(CachedScanData* _aidl_return) override; + ndk::ScopedAStatus twtGetCapabilities(TwtCapabilities* _aidl_return) override; + ndk::ScopedAStatus twtSessionSetup(int in_cmdId, const TwtRequest& in_twtRequest) override; + ndk::ScopedAStatus twtSessionUpdate(int in_cmdId, int32_t in_sessionId, + const TwtRequest& in_twtRequest) override; + ndk::ScopedAStatus twtSessionSuspend(int in_cmdId, int32_t in_sessionId) override; + ndk::ScopedAStatus twtSessionResume(int in_cmdId, int32_t in_sessionId) override; + ndk::ScopedAStatus twtSessionTeardown(int in_cmdId, int32_t in_sessionId) override; + ndk::ScopedAStatus twtSessionGetStats(int in_cmdId, int32_t in_sessionId) override; private: // Corresponding worker functions for the AIDL methods. @@ -132,6 +140,14 @@ class WifiStaIface : public BnWifiStaIface { ndk::ScopedAStatus setScanModeInternal(bool enable); ndk::ScopedAStatus setDtimMultiplierInternal(const int multiplier); std::pair getCachedScanDataInternal(); + std::pair twtGetCapabilitiesInternal(); + ndk::ScopedAStatus twtSessionSetupInternal(int cmdId, const TwtRequest& twtRequest); + ndk::ScopedAStatus twtSessionUpdateInternal(int cmdId, int32_t sessionId, + const TwtRequest& twtRequest); + ndk::ScopedAStatus twtSessionSuspendInternal(int cmdId, int32_t sessionId); + ndk::ScopedAStatus twtSessionResumeInternal(int cmdId, int32_t sessionId); + ndk::ScopedAStatus twtSessionTeardownInternal(int cmdId, int32_t sessionId); + ndk::ScopedAStatus twtSessionGetStatsInternal(int cmdId, int32_t sessionId); void setWeakPtr(std::weak_ptr ptr);