Merge changes from topic "JpegRCompositeStream"
* changes:
Camera: Add Jpeg/R stream configuration metadata
graphics/common: Add Jpeg/R dataspace
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 6b948dd..c3647b0 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -114,7 +114,9 @@
"android/hardware/audio/core/AudioRoute.aidl",
"android/hardware/audio/core/IConfig.aidl",
"android/hardware/audio/core/IModule.aidl",
+ "android/hardware/audio/core/ISoundDose.aidl",
"android/hardware/audio/core/IStreamCallback.aidl",
+ "android/hardware/audio/core/IStreamCommon.aidl",
"android/hardware/audio/core/IStreamIn.aidl",
"android/hardware/audio/core/IStreamOut.aidl",
"android/hardware/audio/core/ITelephony.aidl",
@@ -124,6 +126,7 @@
"android/hardware/audio/core/ModuleDebug.aidl",
"android/hardware/audio/core/StreamDescriptor.aidl",
"android/hardware/audio/core/SurroundSoundConfig.aidl",
+ "android/hardware/audio/core/VendorParameter.aidl",
],
imports: [
"android.hardware.common-V2",
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index 484320f..b4607f9 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -14,6 +14,9 @@
},
{
"name": "VtsHalLoudnessEnhancerTargetTest"
+ },
+ {
+ "name": "VtsHalVisualizerTargetTest"
}
]
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
index 0c7ca27..ebfa94b 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
@@ -60,6 +60,10 @@
void updateAudioMode(android.hardware.audio.core.AudioMode mode);
void updateScreenRotation(android.hardware.audio.core.IModule.ScreenRotation rotation);
void updateScreenState(boolean isTurnedOn);
+ @nullable android.hardware.audio.core.ISoundDose getSoundDose();
+ int generateHwAvSyncId();
+ android.hardware.audio.core.VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ void setVendorParameters(in android.hardware.audio.core.VendorParameter[] parameters, boolean async);
@VintfStability
parcelable OpenInputStreamArguments {
int portConfigId;
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..bc010ca
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.audio.core;
+@VintfStability
+interface ISoundDose {
+ void setOutputRs2(float rs2ValueDbA);
+ float getOutputRs2();
+ void registerSoundDoseCallback(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback callback);
+ const int DEFAULT_MAX_RS2 = 100;
+ const int MIN_RS2 = 80;
+ @VintfStability
+ interface IHalSoundDoseCallback {
+ oneway void onMomentaryExposureWarning(float currentDbA, in android.media.audio.common.AudioDevice audioDevice);
+ oneway void onNewMelValues(in android.hardware.audio.core.ISoundDose.IHalSoundDoseCallback.MelRecord melRecord, in android.media.audio.common.AudioDevice audioDevice);
+ @VintfStability
+ parcelable MelRecord {
+ float[] melValues;
+ long timestamp;
+ }
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl
new file mode 100644
index 0000000..8471c79
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamCommon.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.audio.core;
+@VintfStability
+interface IStreamCommon {
+ void close();
+ void updateHwAvSyncId(int hwAvSyncId);
+ android.hardware.audio.core.VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ void setVendorParameters(in android.hardware.audio.core.VendorParameter[] parameters, boolean async);
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
index e9c727f..98acf5f 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamIn.aidl
@@ -34,7 +34,7 @@
package android.hardware.audio.core;
@VintfStability
interface IStreamIn {
- void close();
+ android.hardware.audio.core.IStreamCommon getStreamCommon();
android.hardware.audio.core.MicrophoneDynamicInfo[] getActiveMicrophones();
android.hardware.audio.core.IStreamIn.MicrophoneDirection getMicrophoneDirection();
void setMicrophoneDirection(android.hardware.audio.core.IStreamIn.MicrophoneDirection direction);
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
index 3021d94..5ea2a12 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IStreamOut.aidl
@@ -34,6 +34,6 @@
package android.hardware.audio.core;
@VintfStability
interface IStreamOut {
- void close();
+ android.hardware.audio.core.IStreamCommon getStreamCommon();
void updateMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/VendorParameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/VendorParameter.aidl
new file mode 100644
index 0000000..bfe33ee
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/VendorParameter.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable VendorParameter {
+ @utf8InCpp String id;
+ ParcelableHolder ext;
+}
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index 786d5ee..7facc6c 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -21,6 +21,7 @@
import android.hardware.audio.core.AudioMode;
import android.hardware.audio.core.AudioPatch;
import android.hardware.audio.core.AudioRoute;
+import android.hardware.audio.core.ISoundDose;
import android.hardware.audio.core.IStreamCallback;
import android.hardware.audio.core.IStreamIn;
import android.hardware.audio.core.IStreamOut;
@@ -28,6 +29,7 @@
import android.hardware.audio.core.MicrophoneInfo;
import android.hardware.audio.core.ModuleDebug;
import android.hardware.audio.core.StreamDescriptor;
+import android.hardware.audio.core.VendorParameter;
import android.media.audio.common.AudioOffloadInfo;
import android.media.audio.common.AudioPort;
import android.media.audio.common.AudioPortConfig;
@@ -668,4 +670,62 @@
* @param isTurnedOn True if the screen is turned on.
*/
void updateScreenState(boolean isTurnedOn);
+
+ /**
+ * Retrieve the sound dose interface.
+ *
+ * If a device must comply to IEC62368-1 3rd edition audio safety requirements and is
+ * implementing audio offload decoding or other direct playback paths where volume control
+ * happens below the audio HAL, it must return an instance of the ISoundDose interface.
+ * The same instance must be returned during the lifetime of the HAL module.
+ * If the HAL module does not support sound dose, null must be returned, without throwing
+ * any errors.
+ *
+ * @return An instance of the ISoundDose interface implementation.
+ * @throws EX_ILLEGAL_STATE If there was an error creating an instance.
+ */
+ @nullable ISoundDose getSoundDose();
+
+ /**
+ * Generate a HW AV Sync identifier for a new audio session.
+ *
+ * Creates a new unique identifier which can be further used by the client
+ * for tagging input / output streams that belong to the same audio
+ * session and thus must use the same HW AV Sync timestamps sequence.
+ *
+ * HW AV Sync timestamps are used for "tunneled" I/O modes and thus
+ * are not mandatory.
+ *
+ * @throws EX_ILLEGAL_STATE If the identifier can not be provided at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If synchronization with HW AV Sync markers
+ * is not supported.
+ */
+ int generateHwAvSyncId();
+
+ /**
+ * Get current values of vendor parameters.
+ *
+ * Return current values for the parameters corresponding to the provided ids.
+ *
+ * @param ids Ids of the parameters to retrieve values of.
+ * @return Current values of parameters, one per each id.
+ * @throws EX_ILLEGAL_ARGUMENT If the module does not recognize provided ids.
+ * @throws EX_ILLEGAL_STATE If parameter values can not be retrieved at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support vendor parameters.
+ */
+ VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ /**
+ * Set vendor parameters.
+ *
+ * Update values for provided vendor parameters. If the 'async' parameter
+ * is set to 'true', the implementation must return the control back without
+ * waiting for the application of parameters to complete.
+ *
+ * @param parameters Ids and values of parameters to set.
+ * @param async Whether to return from the method as early as possible.
+ * @throws EX_ILLEGAL_ARGUMENT If the module does not recognize provided parameters.
+ * @throws EX_ILLEGAL_STATE If parameters can not be set at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the module does not support vendor parameters.
+ */
+ void setVendorParameters(in VendorParameter[] parameters, boolean async);
}
diff --git a/audio/aidl/android/hardware/audio/core/ISoundDose.aidl b/audio/aidl/android/hardware/audio/core/ISoundDose.aidl
new file mode 100644
index 0000000..89fd69b
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/ISoundDose.aidl
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.core;
+
+import android.media.audio.common.AudioDevice;
+
+/**
+ * This interface provides functions related to sound exposure control required for compliance to
+ * EN/IEC 62368-1 3rd edition. Implementing this interface is mandatory for devices for which
+ * compliance to this standard is mandated and implementing audio offload decoding or other direct
+ * playback paths where volume control happens below the audio HAL.
+ */
+@VintfStability
+interface ISoundDose {
+ /**
+ * Max value in dBA used for momentary exposure warnings as defined by IEC62368-1
+ * 3rd edition. This value represents the default RS2 value.
+ */
+ const int DEFAULT_MAX_RS2 = 100;
+ /** Min value of the RS2 threshold in dBA as defined by IEC62368-1 3rd edition. */
+ const int MIN_RS2 = 80;
+
+ /**
+ * Sets the RS2 value used for momentary exposure warnings. Default value is
+ * DEFAULT_MAX_RS2 as specified in IEC62368-1 3rd edition.
+ *
+ * @param rs2ValueDbA custom RS2 value to use. Must not be higher than DEFAULT_MAX_RS2
+ * @throws EX_ILLEGAL_ARGUMENT if rs2ValueDbA is greater than DEFAULT_MAX_RS2 or lower
+ * than 80dBA
+ */
+ void setOutputRs2(float rs2ValueDbA);
+
+ /**
+ * Gets the RS2 value used for momentary exposure warnings.
+ *
+ * @return the RS2 value in dBA
+ */
+ float getOutputRs2();
+
+ /**
+ * Registers the HAL callback for sound dose computation. If sound dose is supported
+ * the MEL values and exposure notifications will be received through this callback
+ * only. The internal framework MEL computation will be disabled.
+ * It is not possible to unregister the callback. The HAL is responsible to provide
+ * the MEL values throughout its lifecycle.
+ * This method should only be called once (no updates allowed) with a valid callback.
+ *
+ * @param callback to use when new updates are available for sound dose
+ * @throws EX_ILLEGAL_STATE if the method is called more than once
+ * @throws EX_ILLEGAL_ARGUMENT if the passed callback is null
+ */
+ void registerSoundDoseCallback(in IHalSoundDoseCallback callback);
+
+ @VintfStability
+ oneway interface IHalSoundDoseCallback {
+ /**
+ * Called whenever the current MEL value exceeds the set RS2 value.
+ *
+ * @param currentDbA the current MEL value which exceeds the RS2 value
+ * @param audioDevice the audio device where the MEL exposure warning was recorded
+ */
+ void onMomentaryExposureWarning(float currentDbA, in AudioDevice audioDevice);
+
+ @VintfStability
+ parcelable MelRecord {
+ /**
+ * Array of continuously recorded MEL values >= RS1 (1 per second).
+ * First value in the array was recorded at 'timestamp'.
+ */
+ float[] melValues;
+ /**
+ * Corresponds to the time in seconds when the first MEL entry in melValues
+ * was recorded. The timestamp values have to be consistent throughout all
+ * audio ports, equal timestamp values will be aggregated.
+ */
+ long timestamp;
+ }
+
+ /**
+ * Provides a MelRecord containing continuous MEL values sorted by timestamp.
+ * Note that all the MEL values originate from the audio device specified by audioDevice.
+ * In case values from multiple devices need to be reported, the caller should execute
+ * this callback once for every device.
+ *
+ * @param melRecord contains the MEL values used for CSD
+ * @param audioDevice the audio device where the MEL values were recorded
+ */
+ void onNewMelValues(in MelRecord melRecord, in AudioDevice audioDevice);
+ }
+}
diff --git a/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl b/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
new file mode 100644
index 0000000..84f7309
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.core;
+
+import android.hardware.audio.core.VendorParameter;
+
+/**
+ * This interface contains operations that are common to input and output
+ * streams (IStreamIn and IStreamOut). The lifetime of the server-side
+ * implementation object is the same as of the "parent" IStreamIn/Out object.
+ * The client must release all references to this object together with
+ * references to the "parent" object.
+ */
+@VintfStability
+interface IStreamCommon {
+ /**
+ * Close the stream.
+ *
+ * Releases any resources allocated for this stream on the HAL module side.
+ * This includes the fast message queues and shared memories returned via
+ * the StreamDescriptor. Thus, the stream can not be operated anymore after
+ * it has been closed. The client needs to release the audio data I/O
+ * objects after the call to this method returns.
+ *
+ * Methods of IStream* interfaces throw EX_ILLEGAL_STATE for a closed stream.
+ *
+ * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ */
+ void close();
+
+ /**
+ * Update the HW AV Sync identifier for the stream.
+ *
+ * The argument to this method must be one of the identifiers previously
+ * returned by the 'IModule.generateHwAvSyncId' method. By tagging streams
+ * with the same identifier, the client indicates to the HAL that they all
+ * use the same HW AV Sync timestamps sequence.
+ *
+ * HW AV Sync timestamps are used for "tunneled" I/O modes and thus
+ * are not mandatory.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT If the provided ID is unknown to the HAL module.
+ * @throws EX_ILLEGAL_STATE If the stream is closed.
+ * @throws EX_UNSUPPORTED_OPERATION If synchronization with HW AV Sync markers
+ * is not supported.
+ */
+ void updateHwAvSyncId(int hwAvSyncId);
+
+ /**
+ * Get current values of vendor parameters.
+ *
+ * Return current values for the parameters corresponding to the provided ids.
+ *
+ * @param ids Ids of the parameters to retrieve values of.
+ * @return Current values of parameters.
+ * @throws EX_ILLEGAL_ARGUMENT If the stream does not recognize provided ids.
+ * @throws EX_ILLEGAL_STATE If parameter values can not be retrieved at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the stream does not support vendor parameters.
+ */
+ VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
+ /**
+ * Set vendor parameters.
+ *
+ * Update values for provided vendor parameters. If the 'async' parameter
+ * is set to 'true', the implementation must return the control back without
+ * waiting for the application of parameters to complete.
+ *
+ * @param parameters Ids and values of parameters to set.
+ * @param async Whether to return from the method as early as possible.
+ * @throws EX_ILLEGAL_ARGUMENT If the stream does not recognize provided parameters.
+ * @throws EX_ILLEGAL_STATE If parameters can not be set at the moment.
+ * @throws EX_UNSUPPORTED_OPERATION If the stream does not support vendor parameters.
+ */
+ void setVendorParameters(in VendorParameter[] parameters, boolean async);
+}
diff --git a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
index 0b6e02c..92788a6 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamIn.aidl
@@ -17,6 +17,7 @@
package android.hardware.audio.core;
import android.hardware.audio.common.SinkMetadata;
+import android.hardware.audio.core.IStreamCommon;
import android.hardware.audio.core.MicrophoneDynamicInfo;
/**
@@ -25,19 +26,15 @@
@VintfStability
interface IStreamIn {
/**
- * Close the stream.
+ * Return the interface for common stream operations.
*
- * Releases any resources allocated for this stream on the HAL module side.
- * This includes the fast message queues and shared memories returned via
- * the StreamDescriptor. Thus, the stream can not be operated anymore after
- * it has been closed. The client needs to release the audio data I/O
- * objects after the call to this method returns.
+ * This method must always succeed. The implementation must
+ * return the same instance object for all subsequent calls to
+ * this method.
*
- * Methods of this interface throw EX_ILLEGAL_STATE for a closed stream.
- *
- * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @return The interface for common operations.
*/
- void close();
+ IStreamCommon getStreamCommon();
/**
* Provides information on the microphones that are active for this stream.
diff --git a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
index 9fdb37d..f7fc77a 100644
--- a/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
+++ b/audio/aidl/android/hardware/audio/core/IStreamOut.aidl
@@ -17,6 +17,7 @@
package android.hardware.audio.core;
import android.hardware.audio.common.SourceMetadata;
+import android.hardware.audio.core.IStreamCommon;
/**
* This interface provides means for sending audio data to output devices.
@@ -24,19 +25,15 @@
@VintfStability
interface IStreamOut {
/**
- * Close the stream.
+ * Return the interface for common stream operations.
*
- * Releases any resources allocated for this stream on the HAL module side.
- * This includes the fast message queues and shared memories returned via
- * the StreamDescriptor. Thus, the stream can not be operated anymore after
- * it has been closed. The client needs to release the audio data I/O
- * objects after the call to this method returns.
+ * This method must always succeed. The implementation must
+ * return the same instance object for all subsequent calls to
+ * this method.
*
- * Methods of this interface throw EX_ILLEGAL_STATE for a closed stream.
- *
- * @throws EX_ILLEGAL_STATE If the stream has already been closed.
+ * @return The interface for common operations.
*/
- void close();
+ IStreamCommon getStreamCommon();
/**
* Update stream metadata.
diff --git a/audio/aidl/android/hardware/audio/core/VendorParameter.aidl b/audio/aidl/android/hardware/audio/core/VendorParameter.aidl
new file mode 100644
index 0000000..206bd9d
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/VendorParameter.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.core;
+
+/**
+ * Vendor parameters are used as a lightweight way to pass vendor-specific
+ * configuration data back and forth between the HAL and vendor's extension
+ * to the Android framework, without the need to extend audio interfaces
+ * from AOSP.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable VendorParameter {
+ /**
+ * Vendor-generated unique ID of the parameter. In order to avoid
+ * collisions, vendors must use a vendor-specific prefix for parameter
+ * ids. The Android framework always passes ids as-is, without any attempt
+ * to parse their content.
+ */
+ @utf8InCpp String id;
+ /**
+ * The payload of the parameter.
+ */
+ ParcelableHolder ext;
+}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index f2cebbf..b9b8cd8 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -43,6 +43,7 @@
"Configuration.cpp",
"EngineConfigXmlConverter.cpp",
"Module.cpp",
+ "SoundDose.cpp",
"Stream.cpp",
"Telephony.cpp",
],
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index 7ae9a66..3b40ae0 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -40,12 +40,13 @@
}
Factory::~Factory() {
- if (auto count = mEffectUuidMap.size()) {
+ if (auto count = mEffectMap.size()) {
LOG(ERROR) << __func__ << " remaining " << count
<< " effect instances not destroyed indicating resource leak!";
- for (const auto& it : mEffectUuidMap) {
+ for (const auto& it : mEffectMap) {
if (auto spEffect = it.first.lock()) {
- LOG(ERROR) << __func__ << " erase remaining instance UUID " << it.second.toString();
+ LOG(ERROR) << __func__ << " erase remaining instance UUID "
+ << it.second.first.toString();
destroyEffectImpl(spEffect);
}
}
@@ -109,9 +110,10 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
}
*_aidl_return = effectSp;
- AIBinder_setMinSchedulerPolicy(effectSp->asBinder().get(), SCHED_NORMAL,
- ANDROID_PRIORITY_AUDIO);
- mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
+ ndk::SpAIBinder effectBinder = effectSp->asBinder();
+ AIBinder_setMinSchedulerPolicy(effectBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ mEffectMap[std::weak_ptr<IEffect>(effectSp)] =
+ std::make_pair(in_impl_uuid, std::move(effectBinder));
LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
return ndk::ScopedAStatus::ok();
} else {
@@ -123,9 +125,9 @@
ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle) {
std::weak_ptr<IEffect> wpHandle(in_handle);
- // find UUID with key (std::weak_ptr<IEffect>)
- if (auto uuidIt = mEffectUuidMap.find(wpHandle); uuidIt != mEffectUuidMap.end()) {
- auto& uuid = uuidIt->second;
+ // find the effect entry with key (std::weak_ptr<IEffect>)
+ if (auto effectIt = mEffectMap.find(wpHandle); effectIt != mEffectMap.end()) {
+ auto& uuid = effectIt->second.first;
// find implementation library with UUID
if (auto libIt = mEffectLibMap.find(uuid); libIt != mEffectLibMap.end()) {
auto& interface = std::get<kMapEntryInterfaceIndex>(libIt->second);
@@ -136,7 +138,7 @@
LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- mEffectUuidMap.erase(uuidIt);
+ mEffectMap.erase(effectIt);
return ndk::ScopedAStatus::ok();
} else {
LOG(ERROR) << __func__ << ": instance " << in_handle << " does not exist!";
@@ -146,9 +148,9 @@
// go over the map and cleanup all expired weak_ptrs.
void Factory::cleanupEffectMap() {
- for (auto it = mEffectUuidMap.begin(); it != mEffectUuidMap.end();) {
+ for (auto it = mEffectMap.begin(); it != mEffectMap.end();) {
if (nullptr == it->first.lock()) {
- it = mEffectUuidMap.erase(it);
+ it = mEffectMap.erase(it);
} else {
++it;
}
diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp
index 71b4b0e..5f17d71 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -20,7 +20,9 @@
#include <functional>
#include <unordered_map>
+#include <aidl/android/media/audio/common/AudioFlag.h>
#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
#include "core-impl/EngineConfigXmlConverter.h"
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 47d6fa4..d52e328 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -26,6 +26,7 @@
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include "core-impl/Module.h"
+#include "core-impl/SoundDose.h"
#include "core-impl/Telephony.h"
#include "core-impl/utils.h"
@@ -315,7 +316,8 @@
ndk::ScopedAStatus Module::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
if (mTelephony == nullptr) {
mTelephony = ndk::SharedRefBase::make<Telephony>();
- AIBinder_setMinSchedulerPolicy(mTelephony->asBinder().get(), SCHED_NORMAL,
+ mTelephonyBinder = mTelephony->asBinder();
+ AIBinder_setMinSchedulerPolicy(mTelephonyBinder.get(), SCHED_NORMAL,
ANDROID_PRIORITY_AUDIO);
}
*_aidl_return = mTelephony;
@@ -530,13 +532,15 @@
return status;
}
context.fillDescriptor(&_aidl_return->desc);
- auto stream = ndk::SharedRefBase::make<StreamIn>(in_args.sinkMetadata, std::move(context),
- mConfig->microphones);
- if (auto status = stream->init(); !status.isOk()) {
+ std::shared_ptr<StreamIn> stream;
+ if (auto status = StreamIn::createInstance(in_args.sinkMetadata, std::move(context),
+ mConfig->microphones, &stream);
+ !status.isOk()) {
return status;
}
- AIBinder_setMinSchedulerPolicy(stream->asBinder().get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
StreamWrapper streamWrapper(stream);
+ AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
auto patchIt = mPatches.find(in_args.portConfigId);
if (patchIt != mPatches.end()) {
streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
@@ -581,13 +585,15 @@
return status;
}
context.fillDescriptor(&_aidl_return->desc);
- auto stream = ndk::SharedRefBase::make<StreamOut>(in_args.sourceMetadata, std::move(context),
- in_args.offloadInfo);
- if (auto status = stream->init(); !status.isOk()) {
+ std::shared_ptr<StreamOut> stream;
+ if (auto status = StreamOut::createInstance(in_args.sourceMetadata, std::move(context),
+ in_args.offloadInfo, &stream);
+ !status.isOk()) {
return status;
}
- AIBinder_setMinSchedulerPolicy(stream->asBinder().get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
StreamWrapper streamWrapper(stream);
+ AIBinder_setMinSchedulerPolicy(streamWrapper.getBinder().get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
auto patchIt = mPatches.find(in_args.portConfigId);
if (patchIt != mPatches.end()) {
streamWrapper.setStreamIsConnected(findConnectedDevices(in_args.portConfigId));
@@ -931,4 +937,36 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Module::getSoundDose(std::shared_ptr<ISoundDose>* _aidl_return) {
+ if (mSoundDose == nullptr) {
+ mSoundDose = ndk::SharedRefBase::make<SoundDose>();
+ mSoundDoseBinder = mSoundDose->asBinder();
+ AIBinder_setMinSchedulerPolicy(mSoundDoseBinder.get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
+ }
+ *_aidl_return = mSoundDose;
+ LOG(DEBUG) << __func__ << ": returning instance of ISoundDose: " << _aidl_return->get();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::generateHwAvSyncId(int32_t* _aidl_return) {
+ LOG(DEBUG) << __func__;
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) {
+ LOG(DEBUG) << __func__ << ": id count: " << in_ids.size();
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Module::setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) {
+ LOG(DEBUG) << __func__ << ": parameter count " << in_parameters.size()
+ << ", async: " << in_async;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/SoundDose.cpp b/audio/aidl/default/SoundDose.cpp
new file mode 100644
index 0000000..3d222a8
--- /dev/null
+++ b/audio/aidl/default/SoundDose.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_SoundDose"
+
+#include "core-impl/SoundDose.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus SoundDose::setOutputRs2(float in_rs2ValueDbA) {
+ if (in_rs2ValueDbA < MIN_RS2 || in_rs2ValueDbA > DEFAULT_MAX_RS2) {
+ LOG(ERROR) << __func__ << ": RS2 value is invalid: " << in_rs2ValueDbA;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ mRs2Value = in_rs2ValueDbA;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SoundDose::getOutputRs2(float* _aidl_return) {
+ *_aidl_return = mRs2Value;
+ LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SoundDose::registerSoundDoseCallback(
+ const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& in_callback) {
+ if (in_callback.get() == nullptr) {
+ LOG(ERROR) << __func__ << ": Callback is nullptr";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (mCallback != nullptr) {
+ LOG(ERROR) << __func__ << ": Sound dose callback was already registered";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ mCallback = in_callback;
+ LOG(DEBUG) << __func__ << ": Registered sound dose callback ";
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index be5887c..424c3e4 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "AHAL_Stream"
#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
#include <utils/SystemClock.h>
#include <Utils.h>
@@ -486,7 +487,7 @@
}
template <class Metadata, class StreamWorker>
-StreamCommon<Metadata, StreamWorker>::~StreamCommon() {
+StreamCommonImpl<Metadata, StreamWorker>::~StreamCommonImpl() {
if (!isClosed()) {
LOG(ERROR) << __func__ << ": stream was not closed prior to destruction, resource leak";
stopWorker();
@@ -495,7 +496,52 @@
}
template <class Metadata, class StreamWorker>
-ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::close() {
+void StreamCommonImpl<Metadata, StreamWorker>::createStreamCommon(
+ const std::shared_ptr<StreamCommonInterface>& delegate) {
+ if (mCommon != nullptr) {
+ LOG(FATAL) << __func__ << ": attempting to create the common interface twice";
+ }
+ mCommon = ndk::SharedRefBase::make<StreamCommon>(delegate);
+ mCommonBinder = mCommon->asBinder();
+ AIBinder_setMinSchedulerPolicy(mCommonBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::getStreamCommon(
+ std::shared_ptr<IStreamCommon>* _aidl_return) {
+ if (mCommon == nullptr) {
+ LOG(FATAL) << __func__ << ": the common interface was not created";
+ }
+ *_aidl_return = mCommon;
+ LOG(DEBUG) << __func__ << ": returning " << _aidl_return->get()->asBinder().get();
+ return ndk::ScopedAStatus::ok();
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::updateHwAvSyncId(
+ int32_t in_hwAvSyncId) {
+ LOG(DEBUG) << __func__ << ": id " << in_hwAvSyncId;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::getVendorParameters(
+ const std::vector<std::string>& in_ids, std::vector<VendorParameter>* _aidl_return) {
+ LOG(DEBUG) << __func__ << ": id count: " << in_ids.size();
+ (void)_aidl_return;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::setVendorParameters(
+ const std::vector<VendorParameter>& in_parameters, bool in_async) {
+ LOG(DEBUG) << __func__ << ": parameters count " << in_parameters.size()
+ << ", async: " << in_async;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+template <class Metadata, class StreamWorker>
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::close() {
LOG(DEBUG) << __func__;
if (!isClosed()) {
stopWorker();
@@ -512,7 +558,7 @@
}
template <class Metadata, class StreamWorker>
-void StreamCommon<Metadata, StreamWorker>::stopWorker() {
+void StreamCommonImpl<Metadata, StreamWorker>::stopWorker() {
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
LOG(DEBUG) << __func__ << ": asking the worker to exit...";
auto cmd = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::halReservedExit>(
@@ -529,7 +575,8 @@
}
template <class Metadata, class StreamWorker>
-ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::updateMetadata(const Metadata& metadata) {
+ndk::ScopedAStatus StreamCommonImpl<Metadata, StreamWorker>::updateMetadata(
+ const Metadata& metadata) {
LOG(DEBUG) << __func__;
if (!isClosed()) {
mMetadata = metadata;
@@ -539,6 +586,20 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
+// static
+ndk::ScopedAStatus StreamIn::createInstance(const common::SinkMetadata& sinkMetadata,
+ StreamContext context,
+ const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) {
+ auto stream = ndk::SharedRefBase::make<StreamIn>(sinkMetadata, std::move(context), microphones);
+ if (auto status = stream->init(); !status.isOk()) {
+ return status;
+ }
+ stream->createStreamCommon(stream);
+ *result = std::move(stream);
+ return ndk::ScopedAStatus::ok();
+}
+
namespace {
static std::map<AudioDevice, std::string> transformMicrophones(
const std::vector<MicrophoneInfo>& microphones) {
@@ -549,9 +610,9 @@
}
} // namespace
-StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext context,
+StreamIn::StreamIn(const SinkMetadata& sinkMetadata, StreamContext&& context,
const std::vector<MicrophoneInfo>& microphones)
- : StreamCommon<SinkMetadata, StreamInWorker>(sinkMetadata, std::move(context)),
+ : StreamCommonImpl<SinkMetadata, StreamInWorker>(sinkMetadata, std::move(context)),
mMicrophones(transformMicrophones(microphones)) {
LOG(DEBUG) << __func__;
}
@@ -597,9 +658,24 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext context,
+// static
+ndk::ScopedAStatus StreamOut::createInstance(const SourceMetadata& sourceMetadata,
+ StreamContext context,
+ const std::optional<AudioOffloadInfo>& offloadInfo,
+ std::shared_ptr<StreamOut>* result) {
+ auto stream =
+ ndk::SharedRefBase::make<StreamOut>(sourceMetadata, std::move(context), offloadInfo);
+ if (auto status = stream->init(); !status.isOk()) {
+ return status;
+ }
+ stream->createStreamCommon(stream);
+ *result = std::move(stream);
+ return ndk::ScopedAStatus::ok();
+}
+
+StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext&& context,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamCommon<SourceMetadata, StreamOutWorker>(sourceMetadata, std::move(context)),
+ : StreamCommonImpl<SourceMetadata, StreamOutWorker>(sourceMetadata, std::move(context)),
mOffloadInfo(offloadInfo) {
LOG(DEBUG) << __func__;
}
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index f4ac8fe..d22c349 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -61,7 +61,10 @@
-->
<effects>
- <effect name="bassboost" library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
+ <effectProxy name="bassboost" uuid="14804144-a5ee-4d24-aa88-0002a5d5c51b">
+ <libsw library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
+ <libsw library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
+ </effectProxy>
<effect name="dynamics_processing" library="dynamics_processingsw" uuid="fa818d78-588b-11ed-9b6a-0242ac120002"/>
<effect name="haptic_generator" library="haptic_generatorsw" uuid="fa819110-588b-11ed-9b6a-0242ac120002"/>
<effect name="loudness_enhancer" library="loudness_enhancersw" uuid="fa819610-588b-11ed-9b6a-0242ac120002"/>
diff --git a/audio/aidl/default/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp
index 61976c8..8e4779d 100644
--- a/audio/aidl/default/bassboost/BassBoostSw.cpp
+++ b/audio/aidl/default/bassboost/BassBoostSw.cpp
@@ -66,7 +66,7 @@
const Descriptor BassBoostSw::kDescriptor = {
.common = {.id = {.type = kBassBoostTypeUUID,
.uuid = kBassBoostSwImplUUID,
- .proxy = std::nullopt},
+ .proxy = kBassBoostProxyUUID},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index c0ffe70..ad79a0c 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -167,6 +167,7 @@
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+ enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_PCM;
}
public enum AudioFormat {
@@ -280,6 +281,7 @@
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_ULTRASOUND;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
+ enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_BIT_PERFECT;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
enum_constant public static final android.audio.policy.configuration.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index 2c18a1e..301c969 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -181,6 +181,7 @@
<xs:enumeration value="AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_SPATIALIZER" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_ULTRASOUND" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_BIT_PERFECT" />
<xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
<xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
<xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
@@ -575,6 +576,7 @@
<xs:restriction base="xs:string">
<xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
<xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
+ <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_PCM"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="profile">
diff --git a/audio/aidl/default/equalizer/EqualizerSw.h b/audio/aidl/default/equalizer/EqualizerSw.h
index 81bcd7a..65a8002 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.h
+++ b/audio/aidl/default/equalizer/EqualizerSw.h
@@ -53,8 +53,9 @@
LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - "
<< it.levelMb;
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ } else {
+ mBandLevels[it.index] = it.levelMb;
}
- mBandLevels[it.index] = it.levelMb;
}
return ret;
}
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 52fb54c..6baaa76 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -86,6 +86,12 @@
ndk::ScopedAStatus updateScreenRotation(
::aidl::android::hardware::audio::core::IModule::ScreenRotation in_rotation) override;
ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override;
+ ndk::ScopedAStatus getSoundDose(std::shared_ptr<ISoundDose>* _aidl_return) override;
+ ndk::ScopedAStatus generateHwAvSyncId(int32_t* _aidl_return) override;
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) override;
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) override;
void cleanUpPatch(int32_t patchId);
ndk::ScopedAStatus createStreamContext(
@@ -114,6 +120,7 @@
// Since it is required to return the same instance of the ITelephony, even
// if the client has released it on its side, we need to hold it via a strong pointer.
std::shared_ptr<ITelephony> mTelephony;
+ ndk::SpAIBinder mTelephonyBinder;
// ids of ports created at runtime via 'connectExternalDevice'.
std::set<int32_t> mConnectedDevicePorts;
Streams mStreams;
@@ -123,6 +130,8 @@
bool mMasterMute = false;
float mMasterVolume = 1.0f;
bool mMicMute = false;
+ std::shared_ptr<ISoundDose> mSoundDose;
+ ndk::SpAIBinder mSoundDoseBinder;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/SoundDose.h b/audio/aidl/default/include/core-impl/SoundDose.h
new file mode 100644
index 0000000..54a6cbf
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/SoundDose.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mutex>
+
+#include <aidl/android/hardware/audio/core/BnSoundDose.h>
+#include <aidl/android/media/audio/common/AudioDevice.h>
+
+using aidl::android::media::audio::common::AudioDevice;
+
+namespace aidl::android::hardware::audio::core {
+
+class SoundDose : public BnSoundDose {
+ public:
+ SoundDose() : mRs2Value(DEFAULT_MAX_RS2){};
+
+ ndk::ScopedAStatus setOutputRs2(float in_rs2ValueDbA) override;
+ ndk::ScopedAStatus getOutputRs2(float* _aidl_return) override;
+ ndk::ScopedAStatus registerSoundDoseCallback(
+ const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& in_callback) override;
+
+ private:
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> mCallback;
+ float mRs2Value;
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 7a07eeb..5746f9d 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -27,6 +27,7 @@
#include <StreamWorker.h>
#include <aidl/android/hardware/audio/common/SinkMetadata.h>
#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
#include <aidl/android/hardware/audio/core/BnStreamIn.h>
#include <aidl/android/hardware/audio/core/BnStreamOut.h>
#include <aidl/android/hardware/audio/core/IStreamCallback.h>
@@ -197,10 +198,67 @@
};
using StreamOutWorker = ::android::hardware::audio::common::StreamWorker<StreamOutWorkerLogic>;
-template <class Metadata, class StreamWorker>
-class StreamCommon {
+// This provides a C++ interface with methods of the IStreamCommon Binder interface,
+// but intentionally does not inherit from it. This is needed to avoid inheriting
+// StreamIn and StreamOut from two Binder interface classes, as these parts of the class
+// will be reference counted separately.
+//
+// The implementation of these common methods is in the StreamCommonImpl template class.
+struct StreamCommonInterface {
+ virtual ~StreamCommonInterface() = default;
+ virtual ndk::ScopedAStatus close() = 0;
+ virtual ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) = 0;
+ virtual ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) = 0;
+ virtual ndk::ScopedAStatus setVendorParameters(
+ const std::vector<VendorParameter>& in_parameters, bool in_async) = 0;
+};
+
+class StreamCommon : public BnStreamCommon {
public:
- ndk::ScopedAStatus close();
+ explicit StreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate)
+ : mDelegate(delegate) {}
+
+ private:
+ ndk::ScopedAStatus close() override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->close()
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->updateHwAvSyncId(in_hwAvSyncId)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->getVendorParameters(in_ids, _aidl_return)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) override {
+ auto delegate = mDelegate.lock();
+ return delegate != nullptr ? delegate->setVendorParameters(in_parameters, in_async)
+ : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ // It is possible that on the client side the proxy for IStreamCommon will outlive
+ // the IStream* instance, and the server side IStream* instance will get destroyed
+ // while this IStreamCommon instance is still alive.
+ std::weak_ptr<StreamCommonInterface> mDelegate;
+};
+
+template <class Metadata, class StreamWorker>
+class StreamCommonImpl : public StreamCommonInterface {
+ public:
+ ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
+ std::vector<VendorParameter>* _aidl_return) override;
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool in_async) override;
+
+ ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return);
ndk::ScopedAStatus init() {
return mWorker.start(StreamWorker::kThreadName, ANDROID_PRIORITY_AUDIO)
? ndk::ScopedAStatus::ok()
@@ -215,23 +273,26 @@
ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
protected:
- StreamCommon(const Metadata& metadata, StreamContext context)
+ StreamCommonImpl(const Metadata& metadata, StreamContext&& context)
: mMetadata(metadata), mContext(std::move(context)), mWorker(mContext) {}
- ~StreamCommon();
+ ~StreamCommonImpl();
void stopWorker();
+ void createStreamCommon(const std::shared_ptr<StreamCommonInterface>& delegate);
+ std::shared_ptr<StreamCommon> mCommon;
+ ndk::SpAIBinder mCommonBinder;
Metadata mMetadata;
StreamContext mContext;
StreamWorker mWorker;
std::vector<::aidl::android::media::audio::common::AudioDevice> mConnectedDevices;
};
-class StreamIn
- : public StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata, StreamInWorker>,
- public BnStreamIn {
- ndk::ScopedAStatus close() override {
- return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
- StreamInWorker>::close();
+class StreamIn : public StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>,
+ public BnStreamIn {
+ ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>::getStreamCommon(_aidl_return);
}
ndk::ScopedAStatus getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) override;
@@ -241,46 +302,71 @@
ndk::ScopedAStatus setMicrophoneFieldDimension(float in_zoom) override;
ndk::ScopedAStatus updateMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
in_sinkMetadata) override {
- return StreamCommon<::aidl::android::hardware::audio::common::SinkMetadata,
- StreamInWorker>::updateMetadata(in_sinkMetadata);
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>::updateMetadata(in_sinkMetadata);
}
public:
- StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
- StreamContext context, const std::vector<MicrophoneInfo>& microphones);
+ static ndk::ScopedAStatus createInstance(
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext context, const std::vector<MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result);
private:
+ friend class ndk::SharedRefBase;
+ StreamIn(const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ StreamContext&& context, const std::vector<MicrophoneInfo>& microphones);
+ void createStreamCommon(const std::shared_ptr<StreamIn>& myPtr) {
+ StreamCommonImpl<::aidl::android::hardware::audio::common::SinkMetadata,
+ StreamInWorker>::createStreamCommon(myPtr);
+ }
+
const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
};
-class StreamOut : public StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
- StreamOutWorker>,
+class StreamOut : public StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>,
public BnStreamOut {
- ndk::ScopedAStatus close() override {
- return StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
- StreamOutWorker>::close();
+ ndk::ScopedAStatus getStreamCommon(std::shared_ptr<IStreamCommon>* _aidl_return) override {
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>::getStreamCommon(_aidl_return);
}
ndk::ScopedAStatus updateMetadata(
const ::aidl::android::hardware::audio::common::SourceMetadata& in_sourceMetadata)
override {
- return StreamCommon<::aidl::android::hardware::audio::common::SourceMetadata,
- StreamOutWorker>::updateMetadata(in_sourceMetadata);
+ return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>::updateMetadata(in_sourceMetadata);
}
public:
- StreamOut(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
- StreamContext context,
- const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
- offloadInfo);
+ static ndk::ScopedAStatus createInstance(
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result);
private:
+ friend class ndk::SharedRefBase;
+ StreamOut(const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ StreamContext&& context,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo);
+ void createStreamCommon(const std::shared_ptr<StreamOut>& myPtr) {
+ StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata,
+ StreamOutWorker>::createStreamCommon(myPtr);
+ }
+
std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
};
class StreamWrapper {
public:
- explicit StreamWrapper(std::shared_ptr<StreamIn> streamIn) : mStream(streamIn) {}
- explicit StreamWrapper(std::shared_ptr<StreamOut> streamOut) : mStream(streamOut) {}
+ explicit StreamWrapper(const std::shared_ptr<StreamIn>& streamIn)
+ : mStream(streamIn), mStreamBinder(streamIn->asBinder()) {}
+ explicit StreamWrapper(const std::shared_ptr<StreamOut>& streamOut)
+ : mStream(streamOut), mStreamBinder(streamOut->asBinder()) {}
+ ndk::SpAIBinder getBinder() const { return mStreamBinder; }
bool isStreamOpen() const {
return std::visit(
[](auto&& ws) -> bool {
@@ -301,6 +387,7 @@
private:
std::variant<std::weak_ptr<StreamIn>, std::weak_ptr<StreamOut>> mStream;
+ ndk::SpAIBinder mStreamBinder;
};
class Streams {
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
index 95645d5..1f39db0 100644
--- a/audio/aidl/default/include/effect-impl/EffectContext.h
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -72,13 +72,11 @@
float* getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); }
- // reset buffer status by abandon all data and status in FMQ
+ // reset buffer status by abandon input data in FMQ
void resetBuffer() {
auto buffer = static_cast<float*>(mWorkBuffer.data());
std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
mInputMQ->read(buffer, mInputMQ->availableToRead());
- mOutputMQ->read(buffer, mOutputMQ->availableToRead());
- mStatusMQ->read(status.data(), mStatusMQ->availableToRead());
}
void dupeFmq(IEffect::OpenEffectReturn* effectRet) {
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
index 7709eab..d3c7666 100644
--- a/audio/aidl/default/include/effect-impl/EffectUUID.h
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -45,6 +45,18 @@
0x11ed,
0x9b6a,
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 8631f300-72e2-11df-b57e-0002a5d5c51b
+static const AudioUuid kBassBoostBundleImplUUID = {static_cast<int32_t>(0x8631f300),
+ 0x72e2,
+ 0x11df,
+ 0xb57e,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// 14804144-a5ee-4d24-aa88-0002a5d5c51b
+static const AudioUuid kBassBoostProxyUUID = {static_cast<int32_t>(0x14804144),
+ 0xa5ee,
+ 0x4d24,
+ 0xaa88,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81862a-588b-11ed-9b6a-0242ac120002
static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
0x588b,
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index 5903276..04bd1bb 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -96,9 +96,8 @@
std::map<aidl::android::media::audio::common::AudioUuid /* implUUID */, DlEntry> mEffectLibMap;
- std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
- std::owner_less<>>
- mEffectUuidMap;
+ typedef std::pair<aidl::android::media::audio::common::AudioUuid, ndk::SpAIBinder> EffectEntry;
+ std::map<std::weak_ptr<IEffect>, EffectEntry, std::owner_less<>> mEffectMap;
ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
void cleanupEffectMap();
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index b11af4e..b66c134 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -16,6 +16,7 @@
#include <cstdlib>
#include <ctime>
+#include <utility>
#include <android-base/logging.h>
#include <android/binder_ibinder_platform.h>
@@ -44,19 +45,17 @@
CHECK_EQ(STATUS_OK, status);
// Make modules
- auto moduleDefault = ndk::SharedRefBase::make<Module>(Module::Type::DEFAULT);
- const std::string moduleDefaultName = std::string() + Module::descriptor + "/default";
- AIBinder_setMinSchedulerPolicy(moduleDefault->asBinder().get(), SCHED_NORMAL,
- ANDROID_PRIORITY_AUDIO);
- status = AServiceManager_addService(moduleDefault->asBinder().get(), moduleDefaultName.c_str());
- CHECK_EQ(STATUS_OK, status);
-
- auto moduleRSubmix = ndk::SharedRefBase::make<Module>(Module::Type::R_SUBMIX);
- const std::string moduleRSubmixName = std::string() + Module::descriptor + "/r_submix";
- AIBinder_setMinSchedulerPolicy(moduleRSubmix->asBinder().get(), SCHED_NORMAL,
- ANDROID_PRIORITY_AUDIO);
- status = AServiceManager_addService(moduleRSubmix->asBinder().get(), moduleRSubmixName.c_str());
- CHECK_EQ(STATUS_OK, status);
+ auto createModule = [](Module::Type type, const std::string& instance) {
+ auto module = ndk::SharedRefBase::make<Module>(type);
+ ndk::SpAIBinder moduleBinder = module->asBinder();
+ const std::string moduleName = std::string(Module::descriptor).append("/").append(instance);
+ AIBinder_setMinSchedulerPolicy(moduleBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+ binder_status_t status = AServiceManager_addService(moduleBinder.get(), moduleName.c_str());
+ CHECK_EQ(STATUS_OK, status);
+ return std::make_pair(module, moduleBinder);
+ };
+ auto modules = {createModule(Module::Type::DEFAULT, "default"),
+ createModule(Module::Type::R_SUBMIX, "r_submix")};
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp
index b898c00..37eb30b 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.cpp
+++ b/audio/aidl/default/visualizer/VisualizerSw.cpp
@@ -14,14 +14,9 @@
* limitations under the License.
*/
-#include <cstddef>
#define LOG_TAG "AHAL_VisualizerSw"
-#include <Utils.h>
-#include <algorithm>
-#include <unordered_set>
#include <android-base/logging.h>
-#include <fmq/AidlMessageQueue.h>
#include "VisualizerSw.h"
@@ -60,7 +55,10 @@
namespace aidl::android::hardware::audio::effect {
const std::string VisualizerSw::kEffectName = "VisualizerSw";
-const Visualizer::Capability VisualizerSw::kCapability;
+/* capabilities */
+const Visualizer::CaptureSizeRange mCaptureSizeRange = {MIN_CAPTURE_SIZE, MAX_CAPTURE_SIZE};
+const Visualizer::Capability VisualizerSw::kCapability = {.maxLatencyMs = MAX_LATENCY,
+ .captureSizeRange = mCaptureSizeRange};
const Descriptor VisualizerSw::kDescriptor = {
.common = {.id = {.type = kVisualizerTypeUUID,
.uuid = kVisualizerSwImplUUID,
@@ -82,8 +80,53 @@
RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
- mSpecificParam = specific.get<Parameter::Specific::visualizer>();
- LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ auto& vsParam = specific.get<Parameter::Specific::visualizer>();
+ auto tag = vsParam.getTag();
+
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ RETURN_IF(mContext->setVsCaptureSize(vsParam.get<Visualizer::captureSizeBytes>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "captureSizeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::scalingMode: {
+ RETURN_IF(mContext->setVsScalingMode(vsParam.get<Visualizer::scalingMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "scalingModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::measurementMode: {
+ RETURN_IF(mContext->setVsMeasurementMode(vsParam.get<Visualizer::measurementMode>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "measurementModeNotSupported");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Visualizer::setOnlyParameters: {
+ return setSetOnlyParameterVisualizer(vsParam.get<Visualizer::setOnlyParameters>());
+ }
+ case Visualizer::getOnlyParameters: {
+ LOG(ERROR) << __func__ << " unsupported settable getOnlyParam";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "SetofGetOnlyParamsNotSupported");
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus VisualizerSw::setSetOnlyParameterVisualizer(
+ Visualizer::SetOnlyParameters setOnlyParam) {
+ auto tag = setOnlyParam.getTag();
+ RETURN_IF(Visualizer::SetOnlyParameters::latencyMs != tag, EX_ILLEGAL_ARGUMENT,
+ "SetOnlyParametersTagNotSupported");
+ RETURN_IF(
+ mContext->setVsLatency(setOnlyParam.get<Visualizer::SetOnlyParameters::latencyMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "latencyNotSupported");
return ndk::ScopedAStatus::ok();
}
@@ -91,7 +134,76 @@
Parameter::Specific* specific) {
auto tag = id.getTag();
RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
- specific->set<Parameter::Specific::visualizer>(mSpecificParam);
+ auto vsId = id.get<Parameter::Id::visualizerTag>();
+ auto vsIdTag = vsId.getTag();
+ switch (vsIdTag) {
+ case Visualizer::Id::commonTag:
+ return getParameterVisualizer(vsId.get<Visualizer::Id::commonTag>(), specific);
+ case Visualizer::Id::getOnlyParamTag:
+ return getGetOnlyParameterVisualizer(vsId.get<Visualizer::Id::getOnlyParamTag>(),
+ specific);
+ case Visualizer::Id::setOnlyParamTag: {
+ LOG(ERROR) << __func__ << " unsupported gettable setOnlyParam";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "GetofSetOnlyParamsNotSupported");
+ }
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+}
+ndk::ScopedAStatus VisualizerSw::getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific) {
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Visualizer vsParam;
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ vsParam.set<Visualizer::captureSizeBytes>(mContext->getVsCaptureSize());
+ break;
+ }
+ case Visualizer::scalingMode: {
+ vsParam.set<Visualizer::scalingMode>(mContext->getVsScalingMode());
+ break;
+ }
+ case Visualizer::measurementMode: {
+ vsParam.set<Visualizer::measurementMode>(mContext->getVsMeasurementMode());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "VisualizerTagNotSupported");
+ }
+ }
+ specific->set<Parameter::Specific::visualizer>(vsParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerSw::getGetOnlyParameterVisualizer(
+ const Visualizer::GetOnlyParameters::Tag& tag, Parameter::Specific* specific) {
+ Visualizer::GetOnlyParameters getOnlyParam;
+ switch (tag) {
+ case Visualizer::GetOnlyParameters::measurement: {
+ getOnlyParam.set<Visualizer::GetOnlyParameters::measurement>(
+ mContext->getVsMeasurement());
+ break;
+ }
+ case Visualizer::GetOnlyParameters::captureBytes: {
+ getOnlyParam.set<Visualizer::GetOnlyParameters::captureBytes>(
+ mContext->getVsCaptureBytes());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "GetOnlyParameterTagNotSupported");
+ }
+ }
+ Visualizer vsParam;
+ vsParam.set<Visualizer::getOnlyParameters>(getOnlyParam);
+ specific->set<Parameter::Specific::visualizer>(vsParam);
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h
index 24b92dd..a95537c 100644
--- a/audio/aidl/default/visualizer/VisualizerSw.h
+++ b/audio/aidl/default/visualizer/VisualizerSw.h
@@ -17,13 +17,16 @@
#pragma once
#include <aidl/android/hardware/audio/effect/BnEffect.h>
-#include <fmq/AidlMessageQueue.h>
-#include <cstdlib>
-#include <memory>
+#include <vector>
#include "effect-impl/EffectImpl.h"
#include "effect-impl/EffectUUID.h"
+#define MIN_CAPTURE_SIZE 128
+#define MAX_CAPTURE_SIZE 1024
+#define MAX_LATENCY 3000
+#define CAPTURE_BUF_SIZE 65536
+
namespace aidl::android::hardware::audio::effect {
class VisualizerSwContext final : public EffectContext {
@@ -31,8 +34,55 @@
VisualizerSwContext(int statusDepth, const Parameter::Common& common)
: EffectContext(statusDepth, common) {
LOG(DEBUG) << __func__;
+ mCaptureBytes.resize(CAPTURE_BUF_SIZE);
+ fill(mCaptureBytes.begin(), mCaptureBytes.end(), 0x80);
}
- // TODO: add specific context here
+
+ RetCode setVsCaptureSize(int captureSize) {
+ if (captureSize < MIN_CAPTURE_SIZE || captureSize > MAX_CAPTURE_SIZE) {
+ LOG(ERROR) << __func__ << " invalid captureSize " << captureSize;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to apply new captureSize
+ mCaptureSize = captureSize;
+ return RetCode::SUCCESS;
+ }
+ int getVsCaptureSize() const { return mCaptureSize; }
+
+ RetCode setVsScalingMode(Visualizer::ScalingMode scalingMode) {
+ // TODO : Add implementation to apply new scalingMode
+ mScalingMode = scalingMode;
+ return RetCode::SUCCESS;
+ }
+ Visualizer::ScalingMode getVsScalingMode() const { return mScalingMode; }
+
+ RetCode setVsMeasurementMode(Visualizer::MeasurementMode measurementMode) {
+ // TODO : Add implementation to apply new measurementMode
+ mMeasurementMode = measurementMode;
+ return RetCode::SUCCESS;
+ }
+ Visualizer::MeasurementMode getVsMeasurementMode() const { return mMeasurementMode; }
+
+ RetCode setVsLatency(int latency) {
+ if (latency < 0 || latency > MAX_LATENCY) {
+ LOG(ERROR) << __func__ << " invalid latency " << latency;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // TODO : Add implementation to modify latency
+ mLatency = latency;
+ return RetCode::SUCCESS;
+ }
+
+ Visualizer::GetOnlyParameters::Measurement getVsMeasurement() const { return mMeasurement; }
+ std::vector<uint8_t> getVsCaptureBytes() const { return mCaptureBytes; }
+
+ private:
+ int mCaptureSize = MAX_CAPTURE_SIZE;
+ Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
+ Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
+ int mLatency;
+ const Visualizer::GetOnlyParameters::Measurement mMeasurement = {0, 0};
+ std::vector<uint8_t> mCaptureBytes;
};
class VisualizerSw final : public EffectImpl {
@@ -60,7 +110,11 @@
private:
std::shared_ptr<VisualizerSwContext> mContext;
- /* parameters */
- Visualizer mSpecificParam;
+
+ ndk::ScopedAStatus setSetOnlyParameterVisualizer(Visualizer::SetOnlyParameters setOnlyParam);
+ ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
+ Parameter::Specific* specific);
+ ndk::ScopedAStatus getGetOnlyParameterVisualizer(const Visualizer::GetOnlyParameters::Tag& tag,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 068742d..4414e26 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -83,3 +83,9 @@
defaults: ["VtsHalAudioTargetTestDefaults"],
srcs: ["VtsHalLoudnessEnhancerTargetTest.cpp"],
}
+
+cc_test {
+ name: "VtsHalVisualizerTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalVisualizerTargetTest.cpp"],
+}
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
index b649d9e..0d5c649 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -49,11 +49,11 @@
std::shared_ptr<IFactory> GetFactory() const { return mEffectFactory; }
- static std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>
- getAllEffectDescriptors(std::string serviceName, std::optional<AudioUuid> type = std::nullopt) {
+ static std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> getAllEffectDescriptors(
+ std::string serviceName, std::optional<AudioUuid> type = std::nullopt) {
AudioHalBinderServiceUtil util;
auto names = android::getAidlHalInstanceNames(serviceName);
- std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>> result;
+ std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> result;
for (const auto& name : names) {
auto factory = IFactory::fromBinder(util.connectToService(name));
@@ -62,11 +62,10 @@
factory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs)
.isOk()) {
for (const auto& desc : descs) {
- const auto& id = desc.common.id;
- if (type.has_value() && id.type != type.value()) {
+ if (type.has_value() && desc.common.id.type != type.value()) {
continue;
}
- result.emplace_back(factory, id);
+ result.emplace_back(factory, desc);
}
}
}
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index 73a1f49..7222d4f 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -58,26 +58,34 @@
class EffectHelper {
public:
static void create(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect>& effect,
- Descriptor::Identity id, binder_status_t status = EX_NONE) {
+ Descriptor& desc, binder_status_t status = EX_NONE) {
ASSERT_NE(factory, nullptr);
- EXPECT_STATUS(status, factory->createEffect(id.uuid, &effect));
+ auto& id = desc.common.id;
+ ASSERT_STATUS(status, factory->createEffect(id.uuid, &effect));
if (status == EX_NONE) {
ASSERT_NE(effect, nullptr) << id.uuid.toString();
}
}
+ static void destroyIgnoreRet(std::shared_ptr<IFactory> factory,
+ std::shared_ptr<IEffect> effect) {
+ if (factory && effect) {
+ factory->destroyEffect(effect);
+ }
+ }
+
static void destroy(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect> effect,
binder_status_t status = EX_NONE) {
ASSERT_NE(factory, nullptr);
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, factory->destroyEffect(effect));
+ ASSERT_STATUS(status, factory->destroyEffect(effect));
}
static void open(std::shared_ptr<IEffect> effect, const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
IEffect::OpenEffectReturn* ret, binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, effect->open(common, specific, ret));
+ ASSERT_STATUS(status, effect->open(common, specific, ret));
}
static void open(std::shared_ptr<IEffect> effect, int session = 0,
@@ -85,30 +93,40 @@
ASSERT_NE(effect, nullptr);
Parameter::Common common = EffectHelper::createParamCommon(session);
IEffect::OpenEffectReturn ret;
- open(effect, common, std::nullopt /* specific */, &ret, status);
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, status));
}
+ static void closeIgnoreRet(std::shared_ptr<IEffect> effect) {
+ if (effect) {
+ effect->close();
+ }
+ }
static void close(std::shared_ptr<IEffect> effect, binder_status_t status = EX_NONE) {
if (effect) {
- EXPECT_STATUS(status, effect->close());
+ ASSERT_STATUS(status, effect->close());
}
}
static void getDescriptor(std::shared_ptr<IEffect> effect, Descriptor& desc,
binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, effect->getDescriptor(&desc));
+ ASSERT_STATUS(status, effect->getDescriptor(&desc));
}
static void expectState(std::shared_ptr<IEffect> effect, State expectState,
binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
State state;
- EXPECT_STATUS(status, effect->getState(&state));
- EXPECT_EQ(expectState, state);
+ ASSERT_STATUS(status, effect->getState(&state));
+ ASSERT_EQ(expectState, state);
+ }
+ static void commandIgnoreRet(std::shared_ptr<IEffect> effect, CommandId command) {
+ if (effect) {
+ effect->command(command);
+ }
}
static void command(std::shared_ptr<IEffect> effect, CommandId command,
binder_status_t status = EX_NONE) {
ASSERT_NE(effect, nullptr);
- EXPECT_STATUS(status, effect->command(command));
+ ASSERT_STATUS(status, effect->command(command));
}
static void allocateInputData(const Parameter::Common common, std::unique_ptr<DataMQ>& mq,
std::vector<float>& buffer) {
@@ -116,29 +134,29 @@
auto frameSize = android::hardware::audio::common::getFrameSizeInBytes(
common.input.base.format, common.input.base.channelMask);
const size_t floatsToWrite = mq->availableToWrite();
- EXPECT_NE(0UL, floatsToWrite);
- EXPECT_EQ(frameSize * common.input.frameCount, floatsToWrite * sizeof(float));
+ ASSERT_NE(0UL, floatsToWrite);
+ ASSERT_EQ(frameSize * common.input.frameCount, floatsToWrite * sizeof(float));
buffer.resize(floatsToWrite);
std::fill(buffer.begin(), buffer.end(), 0x5a);
}
static void writeToFmq(std::unique_ptr<DataMQ>& mq, const std::vector<float>& buffer) {
const size_t available = mq->availableToWrite();
- EXPECT_NE(0Ul, available);
+ ASSERT_NE(0Ul, available);
auto bufferFloats = buffer.size();
auto floatsToWrite = std::min(available, bufferFloats);
- EXPECT_TRUE(mq->write(buffer.data(), floatsToWrite));
+ ASSERT_TRUE(mq->write(buffer.data(), floatsToWrite));
}
static void readFromFmq(std::unique_ptr<StatusMQ>& statusMq, size_t statusNum,
std::unique_ptr<DataMQ>& dataMq, size_t expectFloats,
std::vector<float>& buffer) {
IEffect::Status status{};
- EXPECT_TRUE(statusMq->readBlocking(&status, statusNum));
- EXPECT_EQ(STATUS_OK, status.status);
+ ASSERT_TRUE(statusMq->readBlocking(&status, statusNum));
+ ASSERT_EQ(STATUS_OK, status.status);
if (statusNum != 0) {
- EXPECT_EQ(expectFloats, (unsigned)status.fmqProduced);
- EXPECT_EQ(expectFloats, dataMq->availableToRead());
+ ASSERT_EQ(expectFloats, (unsigned)status.fmqProduced);
+ ASSERT_EQ(expectFloats, dataMq->availableToRead());
if (expectFloats != 0) {
- EXPECT_TRUE(dataMq->read(buffer.data(), expectFloats));
+ ASSERT_TRUE(dataMq->read(buffer.data(), expectFloats));
}
}
}
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
index 5e4d56a..4c1d42c 100644
--- a/audio/aidl/vts/TestUtils.h
+++ b/audio/aidl/vts/TestUtils.h
@@ -16,6 +16,8 @@
#pragma once
+#include <algorithm>
+#include <initializer_list>
#include <iostream>
#include <android/binder_auto_utils.h>
@@ -45,6 +47,19 @@
<< "\n but is has completed with: " << status;
}
+template <typename T>
+inline ::testing::AssertionResult assertResult(const char* exp_expr, const char* act_expr,
+ const std::initializer_list<T>& expected,
+ const ::ndk::ScopedAStatus& status) {
+ if (std::find(expected.begin(), expected.end(), status.getExceptionCode()) != expected.end()) {
+ return ::testing::AssertionSuccess();
+ }
+ return ::testing::AssertionFailure() << "Expected the transaction \'" << act_expr
+ << "\' to complete with one of: " << exp_expr
+ << "\n which is: " << ::testing::PrintToString(expected)
+ << "\n but is has completed with: " << status;
+}
+
} // namespace detail
} // namespace android::hardware::audio::common::testing
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index bf73648..e7f5817 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -10,6 +10,8 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/media/audio/common/AudioFlag.h>
+#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
#include "AudioHalBinderServiceUtil.h"
#include "TestUtils.h"
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 99771e6..d21b118 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -36,6 +36,7 @@
#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/hardware/audio/core/ISoundDose.h>
#include <aidl/android/hardware/audio/core/ITelephony.h>
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
@@ -56,6 +57,8 @@
using aidl::android::hardware::audio::core::AudioPatch;
using aidl::android::hardware::audio::core::AudioRoute;
using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::core::IStreamCommon;
using aidl::android::hardware::audio::core::IStreamIn;
using aidl::android::hardware::audio::core::IStreamOut;
using aidl::android::hardware::audio::core::ITelephony;
@@ -63,6 +66,7 @@
using aidl::android::hardware::audio::core::MicrophoneInfo;
using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::StreamDescriptor;
+using aidl::android::hardware::audio::core::VendorParameter;
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using aidl::android::media::audio::common::AudioContentType;
using aidl::android::media::audio::common::AudioDevice;
@@ -209,6 +213,56 @@
EXPECT_IS_OK((inst->*setter)(initialValue)) << "Failed to restore the initial value";
}
+template <class Instance>
+void TestGetVendorParameters(Instance* inst, bool* isSupported) {
+ static const std::vector<std::vector<std::string>> kIdsLists = {{}, {"zero"}, {"one", "two"}};
+ static const auto kStatuses = {EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE, EX_UNSUPPORTED_OPERATION};
+ for (const auto& ids : kIdsLists) {
+ std::vector<VendorParameter> params;
+ if (ndk::ScopedAStatus status = inst->getVendorParameters(ids, ¶ms); status.isOk()) {
+ EXPECT_EQ(ids.size(), params.size()) << "Size of the returned parameters list must "
+ << "match the size of the provided ids list";
+ for (const auto& param : params) {
+ EXPECT_NE(ids.end(), std::find(ids.begin(), ids.end(), param.id))
+ << "Returned parameter id \"" << param.id << "\" is unexpected";
+ }
+ for (const auto& id : ids) {
+ EXPECT_NE(params.end(),
+ std::find_if(params.begin(), params.end(),
+ [&](const auto& param) { return param.id == id; }))
+ << "Requested parameter with id \"" << id << "\" was not returned";
+ }
+ } else {
+ EXPECT_STATUS(kStatuses, status);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ *isSupported = false;
+ return;
+ }
+ }
+ }
+ *isSupported = true;
+}
+
+template <class Instance>
+void TestSetVendorParameters(Instance* inst, bool* isSupported) {
+ static const auto kStatuses = {EX_NONE, EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE,
+ EX_UNSUPPORTED_OPERATION};
+ static const std::vector<std::vector<VendorParameter>> kParamsLists = {
+ {}, {VendorParameter{"zero"}}, {VendorParameter{"one"}, VendorParameter{"two"}}};
+ for (const auto& params : kParamsLists) {
+ ndk::ScopedAStatus status = inst->setVendorParameters(params, false);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ *isSupported = false;
+ return;
+ }
+ EXPECT_STATUS(kStatuses, status)
+ << ::android::internal::ToString(params) << ", async: false";
+ EXPECT_STATUS(kStatuses, inst->setVendorParameters(params, true))
+ << ::android::internal::ToString(params) << ", async: true";
+ }
+ *isSupported = true;
+}
+
// Can be used as a base for any test here, does not depend on the fixture GTest parameters.
class AudioCoreModuleBase {
public:
@@ -835,6 +889,13 @@
template <typename Stream>
class WithStream {
public:
+ static ndk::ScopedAStatus callClose(std::shared_ptr<Stream> stream) {
+ std::shared_ptr<IStreamCommon> common;
+ ndk::ScopedAStatus status = stream->getStreamCommon(&common);
+ if (!status.isOk()) return status;
+ return common->close();
+ }
+
WithStream() {}
explicit WithStream(const AudioPortConfig& portConfig) : mPortConfig(portConfig) {}
WithStream(const WithStream&) = delete;
@@ -842,7 +903,7 @@
~WithStream() {
if (mStream != nullptr) {
mContext.reset();
- EXPECT_IS_OK(mStream->close()) << "port config id " << getPortId();
+ EXPECT_IS_OK(callClose(mStream)) << "port config id " << getPortId();
}
}
void SetUpPortConfig(IModule* module) { ASSERT_NO_FATAL_FAILURE(mPortConfig.SetUp(module)); }
@@ -1626,6 +1687,40 @@
EXPECT_IS_OK(module->updateScreenState(true));
}
+TEST_P(AudioCoreModule, GenerateHwAvSyncId) {
+ const auto kStatuses = {EX_NONE, EX_ILLEGAL_STATE};
+ int32_t id1;
+ ndk::ScopedAStatus status = module->generateHwAvSyncId(&id1);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "HW AV Sync is not supported";
+ }
+ EXPECT_STATUS(kStatuses, status);
+ if (status.isOk()) {
+ int32_t id2;
+ ASSERT_IS_OK(module->generateHwAvSyncId(&id2));
+ EXPECT_NE(id1, id2) << "HW AV Sync IDs must be unique";
+ }
+}
+
+TEST_P(AudioCoreModule, GetVendorParameters) {
+ bool isGetterSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestGetVendorParameters(module.get(), &isGetterSupported));
+ ndk::ScopedAStatus status = module->setVendorParameters({}, false);
+ EXPECT_EQ(isGetterSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
+ << "Support for getting and setting of vendor parameters must be consistent";
+ if (!isGetterSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+}
+
+TEST_P(AudioCoreModule, SetVendorParameters) {
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestSetVendorParameters(module.get(), &isSupported));
+ if (!isSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+}
+
class AudioCoreTelephony : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
public:
void SetUp() override {
@@ -1731,6 +1826,23 @@
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
}
+ void GetStreamCommon() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon1;
+ EXPECT_IS_OK(stream.get()->getStreamCommon(&streamCommon1));
+ std::shared_ptr<IStreamCommon> streamCommon2;
+ EXPECT_IS_OK(stream.get()->getStreamCommon(&streamCommon2));
+ ASSERT_NE(nullptr, streamCommon1);
+ ASSERT_NE(nullptr, streamCommon2);
+ EXPECT_EQ(streamCommon1->asBinder(), streamCommon2->asBinder())
+ << "getStreamCommon must return the same interface instance across invocations";
+ }
+
void CloseTwice() {
const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
if (!portConfig.has_value()) {
@@ -1742,7 +1854,8 @@
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
heldStream = stream.getSharedPointer();
}
- EXPECT_STATUS(EX_ILLEGAL_STATE, heldStream->close()) << "when closing the stream twice";
+ EXPECT_STATUS(EX_ILLEGAL_STATE, WithStream<Stream>::callClose(heldStream))
+ << "when closing the stream twice";
}
void OpenAllConfigs() {
@@ -1847,6 +1960,65 @@
EXPECT_NO_FATAL_FAILURE(SendInvalidCommandImpl(portConfig.value()));
}
+ void UpdateHwAvSyncId() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon;
+ ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+ ASSERT_NE(nullptr, streamCommon);
+ const auto kStatuses = {EX_NONE, EX_ILLEGAL_ARGUMENT, EX_ILLEGAL_STATE};
+ for (const auto id : {-100, -1, 0, 1, 100}) {
+ ndk::ScopedAStatus status = streamCommon->updateHwAvSyncId(id);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "HW AV Sync is not supported";
+ }
+ EXPECT_STATUS(kStatuses, status) << "id: " << id;
+ }
+ }
+
+ void GetVendorParameters() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon;
+ ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+ ASSERT_NE(nullptr, streamCommon);
+
+ bool isGetterSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestGetVendorParameters(module.get(), &isGetterSupported));
+ ndk::ScopedAStatus status = module->setVendorParameters({}, false);
+ EXPECT_EQ(isGetterSupported, status.getExceptionCode() != EX_UNSUPPORTED_OPERATION)
+ << "Support for getting and setting of vendor parameters must be consistent";
+ if (!isGetterSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+ }
+
+ void SetVendorParameters() {
+ const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ WithStream<Stream> stream(portConfig.value());
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ std::shared_ptr<IStreamCommon> streamCommon;
+ ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
+ ASSERT_NE(nullptr, streamCommon);
+
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestSetVendorParameters(module.get(), &isSupported));
+ if (!isSupported) {
+ GTEST_SKIP() << "Vendor parameters are not supported";
+ }
+ }
+
void OpenTwiceSamePortConfigImpl(const AudioPortConfig& portConfig) {
WithStream<Stream> stream1(portConfig);
ASSERT_NO_FATAL_FAILURE(stream1.SetUp(module.get(), kDefaultBufferSizeFrames));
@@ -1912,6 +2084,7 @@
}
TEST_IN_AND_OUT_STREAM(CloseTwice);
+TEST_IN_AND_OUT_STREAM(GetStreamCommon);
TEST_IN_AND_OUT_STREAM(OpenAllConfigs);
TEST_IN_AND_OUT_STREAM(OpenInvalidBufferSize);
TEST_IN_AND_OUT_STREAM(OpenInvalidDirection);
@@ -1919,6 +2092,9 @@
TEST_IN_AND_OUT_STREAM(OpenTwiceSamePortConfig);
TEST_IN_AND_OUT_STREAM(ResetPortConfigWithOpenStream);
TEST_IN_AND_OUT_STREAM(SendInvalidCommand);
+TEST_IN_AND_OUT_STREAM(UpdateHwAvSyncId);
+TEST_IN_AND_OUT_STREAM(GetVendorParameters);
+TEST_IN_AND_OUT_STREAM(SetVendorParameters);
namespace aidl::android::hardware::audio::core {
std::ostream& operator<<(std::ostream& os, const IStreamIn::MicrophoneDirection& md) {
@@ -2468,6 +2644,92 @@
}
}
+class AudioCoreSoundDose : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
+ public:
+ class NoOpHalSoundDoseCallback : public ISoundDose::BnHalSoundDoseCallback {
+ public:
+ ndk::ScopedAStatus onMomentaryExposureWarning(float in_currentDbA,
+ const AudioDevice& in_audioDevice) override;
+ ndk::ScopedAStatus onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const AudioDevice& in_audioDevice) override;
+ };
+
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
+ ASSERT_IS_OK(module->getSoundDose(&soundDose));
+ callback = ndk::SharedRefBase::make<NoOpHalSoundDoseCallback>();
+ }
+
+ void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
+
+ std::shared_ptr<ISoundDose> soundDose;
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> callback;
+};
+
+ndk::ScopedAStatus AudioCoreSoundDose::NoOpHalSoundDoseCallback::onMomentaryExposureWarning(
+ float in_currentDbA, const AudioDevice& in_audioDevice) {
+ // Do nothing
+ (void)in_currentDbA;
+ (void)in_audioDevice;
+ LOG(INFO) << "NoOpHalSoundDoseCallback::onMomentaryExposureWarning called";
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AudioCoreSoundDose::NoOpHalSoundDoseCallback::onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const AudioDevice& in_audioDevice) {
+ // Do nothing
+ (void)in_melRecord;
+ (void)in_audioDevice;
+ LOG(INFO) << "NoOpHalSoundDoseCallback::onNewMelValues called";
+
+ return ndk::ScopedAStatus::ok();
+}
+
+TEST_P(AudioCoreSoundDose, GetSetOutputRs2) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(soundDose.get(), &ISoundDose::getOutputRs2,
+ &ISoundDose::setOutputRs2,
+ /*validValues=*/{80.f, 90.f, 100.f},
+ /*invalidValues=*/{79.f, 101.f}, &isSupported));
+ EXPECT_TRUE(isSupported) << "Getting/Setting RS2 must be supported";
+}
+
+TEST_P(AudioCoreSoundDose, CheckDefaultRs2Value) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ float rs2Value;
+ ASSERT_IS_OK(soundDose->getOutputRs2(&rs2Value));
+ EXPECT_EQ(rs2Value, ISoundDose::DEFAULT_MAX_RS2);
+}
+
+TEST_P(AudioCoreSoundDose, RegisterSoundDoseCallbackTwiceThrowsException) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ ASSERT_IS_OK(soundDose->registerSoundDoseCallback(callback));
+ EXPECT_STATUS(EX_ILLEGAL_STATE, soundDose->registerSoundDoseCallback(callback))
+ << "Registering sound dose callback twice should throw EX_ILLEGAL_STATE";
+}
+
+TEST_P(AudioCoreSoundDose, RegisterSoundDoseNullCallbackThrowsException) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, soundDose->registerSoundDoseCallback(nullptr))
+ << "Registering nullptr sound dose callback should throw EX_ILLEGAL_ARGUMENT";
+}
+
INSTANTIATE_TEST_SUITE_P(AudioCoreModuleTest, AudioCoreModule,
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
@@ -2484,6 +2746,10 @@
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamOut);
+INSTANTIATE_TEST_SUITE_P(AudioCoreSoundDoseTest, AudioCoreSoundDose,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreSoundDose);
// This is the value used in test sequences for which the test needs to ensure
// that the HAL stays in a transient state long enough to receive the next command.
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 4f14bf0..8938618 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -49,18 +49,30 @@
using aidl::android::hardware::audio::effect::State;
enum ParamName { PARAM_INSTANCE_NAME };
-using EffectTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>;
+using EffectTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>>;
class AudioEffectTest : public testing::TestWithParam<EffectTestParam>, public EffectHelper {
public:
- AudioEffectTest() { std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam()); }
+ AudioEffectTest() {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
void SetUp() override {}
- void TearDown() override {}
+
+ void TearDown() override {
+ // Do the cleanup for every test case
+ if (mEffect) {
+ ASSERT_NO_FATAL_FAILURE(commandIgnoreRet(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(closeIgnoreRet(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroyIgnoreRet(mFactory, mEffect));
+ mEffect.reset();
+ }
+ }
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
- Descriptor::Identity mIdentity;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
};
TEST_P(AudioEffectTest, SetupAndTearDown) {
@@ -68,30 +80,27 @@
}
TEST_P(AudioEffectTest, CreateAndDestroy) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, OpenAndClose) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, CloseUnopenedEffect) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, DoubleOpenAndClose) {
std::shared_ptr<IEffect> effect1, effect2;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(effect1));
ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
ASSERT_NO_FATAL_FAILURE(close(effect1));
@@ -102,9 +111,9 @@
TEST_P(AudioEffectTest, TripleOpenAndClose) {
std::shared_ptr<IEffect> effect1, effect2, effect3;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect3, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect3, mDescriptor));
ASSERT_NO_FATAL_FAILURE(open(effect1));
ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
ASSERT_NO_FATAL_FAILURE(open(effect3, 2 /* session */));
@@ -117,513 +126,505 @@
}
TEST_P(AudioEffectTest, GetDescritorBeforeOpen) {
- std::shared_ptr<IEffect> effect;
Descriptor desc;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
- EXPECT_EQ(mIdentity.toString(), desc.common.id.toString());
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, desc));
+ EXPECT_EQ(mDescriptor.common, desc.common);
+ // Effect implementation Must fill in implementor and name
EXPECT_NE("", desc.common.name);
EXPECT_NE("", desc.common.implementor);
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, GetDescritorAfterOpen) {
- std::shared_ptr<IEffect> effect;
Descriptor beforeOpen, afterOpen, afterClose;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, beforeOpen));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterOpen));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, beforeOpen));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, afterOpen));
EXPECT_EQ(beforeOpen.toString(), afterOpen.toString()) << "\n"
<< beforeOpen.toString() << "\n"
<< afterOpen.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterClose));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, afterClose));
EXPECT_EQ(beforeOpen.toString(), afterClose.toString()) << "\n"
<< beforeOpen.toString() << "\n"
<< afterClose.toString();
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, DescriptorExistAndUnique) {
- std::shared_ptr<IEffect> effect;
Descriptor desc;
auto descList = EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor);
std::set<Descriptor::Identity> idSet;
for (const auto& it : descList) {
- auto& id = it.second;
+ auto& id = it.second.common.id;
EXPECT_EQ(0ul, idSet.count(id));
idSet.insert(id);
}
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(mEffect, desc));
EXPECT_EQ(1ul, idSet.count(desc.common.id));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
/// State testing.
// An effect instance is in INIT state by default after it was created.
TEST_P(AudioEffectTest, InitStateAfterCreation) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to IDLE state after IEffect.ASSERT_NO_FATAL_FAILURE(open().
TEST_P(AudioEffectTest, IdleStateAfterOpen) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance is in PROCESSING state after it receive an START command.
TEST_P(AudioEffectTest, ProcessingStateAfterStart) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to IDLE state after Command.Id.STOP in PROCESSING state.
TEST_P(AudioEffectTest, IdleStateAfterStop) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to IDLE state after Command.Id.RESET in PROCESSING state.
TEST_P(AudioEffectTest, IdleStateAfterReset) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance transfer to INIT after IEffect.ASSERT_NO_FATAL_FAILURE(close().
TEST_P(AudioEffectTest, InitStateAfterClose) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// An effect instance shouldn't accept any command before open.
TEST_P(AudioEffectTest, NoCommandAcceptedBeforeOpen) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// No-op when receive STOP command in IDLE state.
TEST_P(AudioEffectTest, StopCommandInIdleStateNoOp) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// No-op when receive RESET command in IDLE state.
TEST_P(AudioEffectTest, ResetCommandInIdleStateNoOp) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Repeat START and STOP command.
TEST_P(AudioEffectTest, RepeatStartAndStop) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Repeat START and RESET command.
TEST_P(AudioEffectTest, RepeatStartAndReset) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Try to close an effect instance at PROCESSING state.
TEST_P(AudioEffectTest, CloseProcessingStateEffects) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(close(effect, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect, EX_ILLEGAL_STATE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
TEST_P(AudioEffectTest, DestroyOpenEffects) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
TEST_P(AudioEffectTest, DestroyProcessingEffects) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect, EX_ILLEGAL_STATE));
+
+ // cleanup
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
TEST_P(AudioEffectTest, NormalSequenceStates) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
/// Parameter testing.
// Verify parameters pass in open can be successfully get.
TEST_P(AudioEffectTest, VerifyCommonParametersAfterOpen) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon();
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
Parameter get = Parameter(), expect = Parameter();
expect.set<Parameter::common>(common);
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(expect, get) << expect.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify parameters pass in set can be successfully get.
TEST_P(AudioEffectTest, SetAndGetCommonParameter) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify parameters set and get in PROCESSING state.
TEST_P(AudioEffectTest, SetAndGetParameterInProcessing) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify parameters set and get in IDLE state.
TEST_P(AudioEffectTest, SetAndGetParameterInIdle) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify Parameters kept after stop.
TEST_P(AudioEffectTest, SetAndGetParameterAfterStop) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify Parameters kept after reset.
TEST_P(AudioEffectTest, SetAndGetParameterAfterReset) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
- ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
Parameter get = Parameter(), set = Parameter();
set.set<Parameter::common>(common);
- EXPECT_IS_OK(effect->setParameter(set));
+ EXPECT_IS_OK(mEffect->setParameter(set));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
Parameter::Id id;
id.set<Parameter::Id::commonTag>(Parameter::common);
- EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_IS_OK(mEffect->getParameter(id, &get));
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
-
/// Data processing test
// Send data to effects and expect it to be consumed by checking statusMQ.
TEST_P(AudioEffectTest, ConsumeDataInProcessingState) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to effects and expect it to be consumed after effect restart.
TEST_P(AudioEffectTest, ConsumeDataAfterRestart) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to IDLE effects and expect it to be consumed after effect start.
TEST_P(AudioEffectTest, SendDataAtIdleAndConsumeDataInProcessing) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data multiple times.
TEST_P(AudioEffectTest, ProcessDataMultipleTimes) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
// expect no status and data after consume
@@ -634,77 +635,81 @@
// expect no status and data after consume
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to IDLE state effects and expect it not be consumed.
TEST_P(AudioEffectTest, NotConsumeDataInIdleState) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
- ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
- ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to closed effects and expect it not be consumed.
TEST_P(AudioEffectTest, NotConsumeDataByClosedEffect) {
- std::shared_ptr<IEffect> effect;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
- ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+ ASSERT_TRUE(outputMQ->isValid());
std::vector<float> buffer;
EffectHelper::allocateInputData(common, inputMQ, buffer);
EffectHelper::writeToFmq(inputMQ, buffer);
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to multiple effects.
TEST_P(AudioEffectTest, ConsumeDataMultipleEffects) {
std::shared_ptr<IEffect> effect1, effect2;
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
- ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mDescriptor));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mDescriptor));
Parameter::Common common1 = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
@@ -721,8 +726,11 @@
ASSERT_NO_FATAL_FAILURE(expectState(effect2, State::PROCESSING));
auto statusMQ1 = std::make_unique<EffectHelper::StatusMQ>(ret1.statusMQ);
+ ASSERT_TRUE(statusMQ1->isValid());
auto inputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.inputDataMQ);
+ ASSERT_TRUE(inputMQ1->isValid());
auto outputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.outputDataMQ);
+ ASSERT_TRUE(outputMQ1->isValid());
std::vector<float> buffer1, buffer2;
EffectHelper::allocateInputData(common1, inputMQ1, buffer1);
@@ -730,8 +738,11 @@
EffectHelper::readFromFmq(statusMQ1, 1, outputMQ1, buffer1.size(), buffer1);
auto statusMQ2 = std::make_unique<EffectHelper::StatusMQ>(ret2.statusMQ);
+ ASSERT_TRUE(statusMQ2->isValid());
auto inputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.inputDataMQ);
+ ASSERT_TRUE(inputMQ2->isValid());
auto outputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.outputDataMQ);
+ ASSERT_TRUE(outputMQ2->isValid());
EffectHelper::allocateInputData(common2, inputMQ2, buffer2);
EffectHelper::writeToFmq(inputMQ2, buffer2);
EffectHelper::readFromFmq(statusMQ2, 1, outputMQ2, buffer2.size(), buffer2);
@@ -752,9 +763,11 @@
::testing::Combine(testing::ValuesIn(
EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
[](const testing::TestParamInfo<AudioEffectTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
- std::string name = "TYPE_" + instance.second.type.toString() + "_UUID_" +
- instance.second.uuid.toString();
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_TYPE_" +
+ descriptor.common.id.type.toString() + "_UUID_" +
+ descriptor.common.id.uuid.toString();
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index 7adf63c..724a9c3 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -37,8 +37,7 @@
* VtsAudioEffectTargetTest.
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_STRENGTH };
-using BassBoostParamTestParam =
- std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+using BassBoostParamTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
/*
* Testing parameter range, assuming the parameter supported by effect is in this range.
@@ -60,12 +59,12 @@
public EffectHelper {
public:
BassBoostParamTest() : mParamStrength(std::get<PARAM_STRENGTH>(GetParam())) {
- std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
}
void SetUp() override {
ASSERT_NE(nullptr, mFactory);
- ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Specific specific = getDefaultParamSpecific();
Parameter::Common common = EffectHelper::createParamCommon(
@@ -91,7 +90,7 @@
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
- Descriptor::Identity mIdentity;
+ Descriptor mDescriptor;
int mParamStrength = BassBoost::MIN_PER_MILLE_STRENGTH;
void SetAndGetBassBoostParameters() {
@@ -167,9 +166,11 @@
IFactory::descriptor, kBassBoostTypeUUID)),
testing::ValuesIn(kStrengthValues)),
[](const testing::TestParamInfo<BassBoostParamTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string strength = std::to_string(std::get<PARAM_STRENGTH>(info.param));
- std::string name = instance.second.uuid.toString() + "_strength_" + strength;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_strength_" + strength;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 1b147a6..e11a936 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -57,8 +57,7 @@
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_BAND_LEVEL };
-using EqualizerParamTestParam =
- std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+using EqualizerParamTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
/*
Testing parameter range, assuming the parameter supported by effect is in this range.
@@ -71,12 +70,12 @@
public EffectHelper {
public:
EqualizerTest() : mBandLevel(std::get<PARAM_BAND_LEVEL>(GetParam())) {
- std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
}
void SetUp() override {
ASSERT_NE(nullptr, mFactory);
- ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Specific specific = getDefaultParamSpecific();
Parameter::Common common = EffectHelper::createParamCommon(
@@ -115,7 +114,7 @@
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
- Descriptor::Identity mIdentity;
+ Descriptor mDescriptor;
std::pair<int, int> mPresetIndex;
std::pair<int, int> mBandIndex;
const int mBandLevel;
@@ -327,9 +326,11 @@
IFactory::descriptor, kEqualizerTypeUUID)),
testing::ValuesIn(kBandLevels)),
[](const testing::TestParamInfo<EqualizerTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string bandLevel = std::to_string(std::get<PARAM_BAND_LEVEL>(info.param));
- std::string name = instance.second.uuid.toString() + "_bandLevel_" + bandLevel;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_bandLevel_" + bandLevel;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
index 3fd2812..305c243 100644
--- a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
@@ -38,7 +38,7 @@
*/
enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
using LoudnessEnhancerParamTestParam =
- std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
// Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
// TODO : Update the test values once range/capability is updated by implementation.
@@ -49,12 +49,12 @@
public EffectHelper {
public:
LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
- std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
}
void SetUp() override {
ASSERT_NE(nullptr, mFactory);
- ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Specific specific = getDefaultParamSpecific();
Parameter::Common common = EffectHelper::createParamCommon(
@@ -79,7 +79,7 @@
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
- Descriptor::Identity mIdentity;
+ Descriptor mDescriptor;
int mParamGainMb = 0;
void SetAndGetParameters() {
@@ -130,9 +130,11 @@
IFactory::descriptor, kLoudnessEnhancerTypeUUID)),
testing::ValuesIn(kGainMbValues)),
[](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
- auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
- std::string name = instance.second.uuid.toString() + "_gainMb_" + gainMb;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_gainMb_" + gainMb;
std::replace_if(
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
new file mode 100644
index 0000000..a7834fb
--- /dev/null
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/Vintf.h>
+
+#define LOG_TAG "VtsHalVisualizerTest"
+
+#include <Utils.h>
+#include "EffectHelper.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kVisualizerTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::Visualizer;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName {
+ PARAM_INSTANCE_NAME,
+ PARAM_CAPTURE_SIZE,
+ PARAM_SCALING_MODE,
+ PARAM_MEASUREMENT_MODE,
+ PARAM_LATENCY,
+};
+using VisualizerParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, Visualizer::ScalingMode,
+ Visualizer::MeasurementMode, int>;
+
+const int MIN_CAPTURE_SIZE = 128;
+const int MAX_CAPTURE_SIZE = 1024;
+const int MAX_LATENCY = 3000;
+
+const std::vector<int> kCaptureSizeValues = {MIN_CAPTURE_SIZE - 1, MIN_CAPTURE_SIZE,
+ MAX_CAPTURE_SIZE, MAX_CAPTURE_SIZE + 1};
+const std::vector<Visualizer::ScalingMode> kScalingModeValues = {
+ Visualizer::ScalingMode::NORMALIZED, Visualizer::ScalingMode::AS_PLAYED};
+const std::vector<Visualizer::MeasurementMode> kMeasurementModeValues = {
+ Visualizer::MeasurementMode::NONE, Visualizer::MeasurementMode::PEAK_RMS};
+const std::vector<int> kLatencyValues = {-1, 0, MAX_LATENCY, MAX_LATENCY + 1};
+
+class VisualizerParamTest : public ::testing::TestWithParam<VisualizerParamTestParam>,
+ public EffectHelper {
+ public:
+ VisualizerParamTest()
+ : mCaptureSize(std::get<PARAM_CAPTURE_SIZE>(GetParam())),
+ mScalingMode(std::get<PARAM_SCALING_MODE>(GetParam())),
+ mMeasurementMode(std::get<PARAM_MEASUREMENT_MODE>(GetParam())),
+ mLatency(std::get<PARAM_LATENCY>(GetParam())) {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
+
+ void SetUp() override {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+
+ Parameter::Specific specific = getDefaultParamSpecific();
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ }
+
+ void TearDown() override {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ Visualizer vs = Visualizer::make<Visualizer::captureSizeBytes>(MIN_CAPTURE_SIZE);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::visualizer>(vs);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+ int mCaptureSize = MAX_CAPTURE_SIZE;
+ Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
+ Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
+ int mLatency = 0;
+
+ void SetAndGetCommonParameters() {
+ for (auto& it : mCommonTags) {
+ auto& tag = it.first;
+ auto& vs = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isTagInRange(tag, vs, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::visualizer>(vs);
+ expectParam.set<Parameter::specific>(specific);
+ EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+ // only get if parameter in range and set success
+ if (expected == EX_NONE) {
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::commonTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
+ << "\ngetParam:" << getParam.toString();
+ }
+ }
+ }
+
+ void SetAndGetSetOnlyParameters() {
+ for (auto& it : mSetOnlyParamTags) {
+ auto& tag = it.first;
+ auto& vs = it.second;
+
+ // validate parameter
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ const bool valid = isSetOnlyParamTagInRange(tag, vs, desc);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::visualizer>(vs);
+ expectParam.set<Parameter::specific>(specific);
+ ASSERT_STATUS(expected, mEffect->setParameter(expectParam));
+
+ // parameter defined in this setOnlyParameter union must be settable via
+ // setParameter(), but must not be gettable
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::setOnlyParamTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->getParameter(id, &getParam));
+ }
+ }
+
+ void GetandSetGetOnlyParameters() {
+ for (auto& tag : mGetOnlyParamTags) {
+ // get parameter
+ Parameter getParam;
+ Parameter::Id id;
+ Visualizer::Id vsId;
+ vsId.set<Visualizer::Id::getOnlyParamTag>(tag);
+ id.set<Parameter::Id::visualizerTag>(vsId);
+ ASSERT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ // parameter defined in this getOnlyParameter union must be gettable via
+ // getParameter(), but must not be settable
+ // set parameter
+ ASSERT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->setParameter(getParam));
+ }
+ }
+
+ void addCaptureSizeParam(int captureSize) {
+ Visualizer vs;
+ vs.set<Visualizer::captureSizeBytes>(captureSize);
+ mCommonTags.push_back({Visualizer::captureSizeBytes, vs});
+ }
+
+ void addScalingModeParam(Visualizer::ScalingMode scalingMode) {
+ Visualizer vs;
+ vs.set<Visualizer::scalingMode>(scalingMode);
+ mCommonTags.push_back({Visualizer::scalingMode, vs});
+ }
+
+ void addMeasurementModeParam(Visualizer::MeasurementMode measurementMode) {
+ Visualizer vs;
+ vs.set<Visualizer::measurementMode>(measurementMode);
+ mCommonTags.push_back({Visualizer::measurementMode, vs});
+ }
+
+ void addLatencyParam(int latency) {
+ Visualizer vs;
+ Visualizer::SetOnlyParameters setOnlyParam;
+ setOnlyParam.set<Visualizer::SetOnlyParameters::latencyMs>(latency);
+ vs.set<Visualizer::setOnlyParameters>(setOnlyParam);
+ mSetOnlyParamTags.push_back({Visualizer::SetOnlyParameters::latencyMs, vs});
+ }
+
+ void addMeasurementTag() {
+ mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::measurement);
+ }
+
+ void addCaptureBytesTag() {
+ mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::captureBytes);
+ }
+
+ bool isTagInRange(const Visualizer::Tag& tag, const Visualizer& vs,
+ const Descriptor& desc) const {
+ const Visualizer::Capability& vsCap = desc.capability.get<Capability::visualizer>();
+ switch (tag) {
+ case Visualizer::captureSizeBytes: {
+ int captureSize = vs.get<Visualizer::captureSizeBytes>();
+ return isCaptureSizeInRange(vsCap, captureSize);
+ }
+ case Visualizer::scalingMode:
+ case Visualizer::measurementMode:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isSetOnlyParamTagInRange(Visualizer::SetOnlyParameters::Tag, const Visualizer& vs,
+ const Descriptor& desc) const {
+ const Visualizer::Capability& vsCap = desc.capability.get<Capability::visualizer>();
+ if (vs.getTag() != Visualizer::setOnlyParameters) return false;
+ Visualizer::SetOnlyParameters setOnlyParam = vs.get<Visualizer::setOnlyParameters>();
+ if (setOnlyParam.getTag() != Visualizer::SetOnlyParameters::latencyMs) return false;
+ int latency = setOnlyParam.get<Visualizer::SetOnlyParameters::latencyMs>();
+ return isLatencyInRange(vsCap, latency);
+ }
+
+ bool isCaptureSizeInRange(const Visualizer::Capability& cap, int captureSize) const {
+ return (captureSize >= cap.captureSizeRange.minBytes &&
+ captureSize <= cap.captureSizeRange.maxBytes);
+ }
+
+ bool isLatencyInRange(const Visualizer::Capability& cap, int latency) const {
+ return (latency >= 0 && latency <= cap.maxLatencyMs);
+ }
+
+ private:
+ std::vector<std::pair<Visualizer::Tag, Visualizer>> mCommonTags;
+ std::vector<std::pair<Visualizer::SetOnlyParameters::Tag, Visualizer>> mSetOnlyParamTags;
+ std::vector<Visualizer::GetOnlyParameters::Tag> mGetOnlyParamTags;
+ void CleanUp() {
+ mCommonTags.clear();
+ mSetOnlyParamTags.clear();
+ mGetOnlyParamTags.clear();
+ }
+};
+
+TEST_P(VisualizerParamTest, SetAndGetCaptureSize) {
+ EXPECT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetScalingMode) {
+ EXPECT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetMeasurementMode) {
+ EXPECT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
+ SetAndGetCommonParameters();
+}
+
+TEST_P(VisualizerParamTest, SetAndGetLatency) {
+ EXPECT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
+ SetAndGetSetOnlyParameters();
+}
+
+TEST_P(VisualizerParamTest, GetAndSetMeasurement) {
+ EXPECT_NO_FATAL_FAILURE(addMeasurementTag());
+ GetandSetGetOnlyParameters();
+}
+
+TEST_P(VisualizerParamTest, GetAndSetCaptureBytes) {
+ EXPECT_NO_FATAL_FAILURE(addCaptureBytesTag());
+ GetandSetGetOnlyParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VisualizerTest, VisualizerParamTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kVisualizerTypeUUID)),
+ testing::ValuesIn(kCaptureSizeValues),
+ testing::ValuesIn(kScalingModeValues),
+ testing::ValuesIn(kMeasurementModeValues),
+ testing::ValuesIn(kLatencyValues)),
+ [](const testing::TestParamInfo<VisualizerParamTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string captureSize = std::to_string(std::get<PARAM_CAPTURE_SIZE>(info.param));
+ std::string scalingMode =
+ std::to_string(static_cast<int>(std::get<PARAM_SCALING_MODE>(info.param)));
+ std::string measurementMode =
+ std::to_string(static_cast<int>(std::get<PARAM_MEASUREMENT_MODE>(info.param)));
+ std::string latency = std::to_string(std::get<PARAM_LATENCY>(info.param));
+
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString() + "_captureSize" + captureSize +
+ "_scalingMode" + scalingMode + "_measurementMode" + measurementMode +
+ "_latency" + latency;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VisualizerParamTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.service.rc b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
index f859f21..0de4eea 100644
--- a/audio/common/all-versions/default/service/android.hardware.audio.service.rc
+++ b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
@@ -3,7 +3,7 @@
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
- capabilities BLOCK_SUSPEND
+ capabilities BLOCK_SUSPEND SYS_NICE
# setting RLIMIT_RTPRIO allows binder RT priority inheritance
rlimit rtprio 10 10
ioprio rt 4
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index f51a8d0..9d93bb0 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -30,6 +30,7 @@
"android.hardware.audio.common.test.utility",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudio_aidl_conversion_common_cpp",
"libstagefright_foundation",
],
shared_libs: [
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 5dc42dc..87e1ab7 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -25,8 +25,11 @@
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include <HidlUtils.h>
#include <android/log.h>
+#include <cutils/properties.h>
#include <media/EffectsFactoryApi.h>
#include <mediautils/ScopedStatistics.h>
+#include <sys/syscall.h>
+#include <system/audio_effects/effect_spatializer.h>
#include <util/EffectUtils.h>
#include <utils/Trace.h>
@@ -47,6 +50,160 @@
namespace {
+/**
+ * Some basic scheduling tools.
+ */
+namespace scheduler {
+
+int getCpu() {
+ return sched_getcpu();
+}
+
+uint64_t getAffinity(pid_t tid) {
+ cpu_set_t set;
+ CPU_ZERO_S(sizeof(set), &set);
+
+ if (sched_getaffinity(tid, sizeof(set), &set)) {
+ ALOGW("%s: for tid:%d returning 0, failed %s", __func__, tid, strerror(errno));
+ return 0;
+ }
+ const int count = CPU_COUNT_S(sizeof(set), &set);
+ uint64_t mask = 0;
+ for (int i = 0; i < CPU_SETSIZE; ++i) {
+ if (CPU_ISSET_S(i, sizeof(set), &set)) {
+ mask |= 1 << i;
+ }
+ }
+ ALOGV("%s: for tid:%d returning cpu count %d mask %llu", __func__, tid, count,
+ (unsigned long long)mask);
+ return mask;
+}
+
+status_t setAffinity(pid_t tid, uint64_t mask) {
+ cpu_set_t set;
+ CPU_ZERO_S(sizeof(set), &set);
+
+ for (uint64_t m = mask; m != 0;) {
+ uint64_t tz = __builtin_ctz(m);
+ CPU_SET_S(tz, sizeof(set), &set);
+ m &= ~(1 << tz);
+ }
+ if (sched_setaffinity(tid, sizeof(set), &set)) {
+ ALOGW("%s: for tid:%d setting cpu mask %llu failed %s", __func__, tid,
+ (unsigned long long)mask, strerror(errno));
+ return -errno;
+ }
+ ALOGV("%s: for tid:%d setting cpu mask %llu", __func__, tid, (unsigned long long)mask);
+ return OK;
+}
+
+__unused status_t setPriority(pid_t tid, int policy, int priority) {
+ struct sched_param param {
+ .sched_priority = priority,
+ };
+ if (sched_setscheduler(tid, policy, ¶m) != 0) {
+ ALOGW("%s: Cannot set FIFO priority for tid %d to policy %d priority %d %s", __func__, tid,
+ policy, priority, strerror(errno));
+ return -errno;
+ }
+ ALOGV("%s: Successfully set priority for tid %d to policy %d priority %d", __func__, tid,
+ policy, priority);
+ return NO_ERROR;
+}
+
+status_t setUtilMin(pid_t tid, uint32_t utilMin) {
+ // Currently, there is no wrapper in bionic: b/183240349.
+ struct {
+ uint32_t size;
+ uint32_t sched_policy;
+ uint64_t sched_flags;
+ int32_t sched_nice;
+ uint32_t sched_priority;
+ uint64_t sched_runtime;
+ uint64_t sched_deadline;
+ uint64_t sched_period;
+ uint32_t sched_util_min;
+ uint32_t sched_util_max;
+ } attr{
+ .size = sizeof(attr),
+ .sched_flags = SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP_MIN,
+ .sched_util_min = utilMin,
+ };
+
+ if (syscall(__NR_sched_setattr, tid, &attr, 0 /* flags */)) {
+ ALOGW("%s: Cannot set sched_util_min for pid %d to %u %s", __func__, tid, utilMin,
+ strerror(errno));
+ return -errno;
+ }
+ ALOGV("%s: Successfully set sched_util_min for pid %d to %u", __func__, tid, utilMin);
+ return NO_ERROR;
+}
+
+/*
+ Attempts to raise the priority and usage of tid for spatialization.
+ Returns OK if everything works.
+*/
+status_t updateSpatializerPriority(pid_t tid) {
+ status_t status = OK;
+
+ const int cpu = getCpu();
+ ALOGV("%s: current CPU:%d", __func__, cpu);
+
+ const auto currentAffinity = getAffinity(tid);
+ ALOGV("%s: current Affinity:%llx", __func__, (unsigned long long)currentAffinity);
+
+ // Set the desired CPU core affinity.
+ // Typically this would be done to move the Spatializer effect off of the little cores.
+ // The mid cores and large cores typically have more FP/NEON units
+ // and will advantageously reduce power and prevent glitches due CPU limitations.
+ //
+ // Since this is SOC dependent, we do not set the core affinity here but
+ // prefer to set the util_clamp_min below.
+ //
+ constexpr uint64_t kDefaultAffinity = 0;
+ const int32_t desiredAffinity =
+ property_get_int32("audio.spatializer.effect.affinity", kDefaultAffinity);
+ if (desiredAffinity != 0 && (desiredAffinity & ~currentAffinity) == 0) {
+ const status_t localStatus = setAffinity(tid, desiredAffinity);
+ status = status ? status : localStatus;
+ }
+
+ // Set the util_clamp_min.
+ // This is beneficial to reduce glitches when starting up, or due to scheduler
+ // thread statistics reset (e.g. core migration), which cause the CPU frequency to drop
+ // to minimum.
+ //
+ // Experimentation has found that moving to a mid core over a little core reduces
+ // power if the mid core (e.g. A76/78) has more (e.g. 2x) FP/NEON units
+ // than the little core (e.g. A55).
+ // A possible value is 300.
+ //
+ constexpr uint32_t kUtilMin = 0;
+ const int32_t utilMin = property_get_int32("audio.spatializer.effect.util_clamp_min", kUtilMin);
+ if (utilMin > 0 && utilMin <= 1024) {
+ const status_t localStatus = setUtilMin(tid, utilMin);
+ status = status ? status : localStatus;
+ }
+
+#if 0
+ // Provided for local vendor testing but not enabled as audioserver does this for us.
+ //
+ // Set priority if specified.
+ constexpr int32_t kRTPriorityMin = 1;
+ constexpr int32_t kRTPriorityMax = 3;
+ const int32_t priorityBoost =
+ property_get_int32("audio.spatializer.priority", kRTPriorityMin);
+ if (priorityBoost >= kRTPriorityMin && priorityBoost <= kRTPriorityMax) {
+ const status_t localStatus = scheduler::setPriority(threadId, SCHED_FIFO, priorityBoost);
+ status = status ? status : localStatus;
+ }
+#endif
+
+ return status;
+}
+
+} // namespace scheduler
+
#define SCOPED_STATS() \
::android::mediautils::ScopedStatistics scopedStatistics { \
std::string("EffectHal::").append(__func__), mEffectHal->mStatistics \
@@ -83,6 +240,16 @@
};
bool ProcessThread::threadLoop() {
+ // For a spatializer effect, we perform scheduler adjustments to reduce glitches and power.
+ {
+ effect_descriptor_t halDescriptor{};
+ if ((*mEffect)->get_descriptor(mEffect, &halDescriptor) == NO_ERROR &&
+ memcmp(&halDescriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0) {
+ const status_t status = scheduler::updateSpatializerPriority(gettid());
+ ALOGW_IF(status != OK, "Failed to update Spatializer priority");
+ }
+ }
+
// This implementation doesn't return control back to the Thread until it decides to stop,
// as the Thread uses mutexes, and this can lead to priority inversion.
while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
diff --git a/automotive/can/1.0/tools/configurator/canhalconfigurator.cpp b/automotive/can/1.0/tools/configurator/canhalconfigurator.cpp
index a100f06..3fb4259 100644
--- a/automotive/can/1.0/tools/configurator/canhalconfigurator.cpp
+++ b/automotive/can/1.0/tools/configurator/canhalconfigurator.cpp
@@ -70,6 +70,9 @@
static bool configuratorStart(const std::string& filepath) {
base::SetDefaultTag("CanConfigurator");
+ LOG(WARNING) << "The HIDL version of CAN HAL has been deprecated, if this tool fails with "
+ << "SIGABRT, you may need canhalconfigurator-aidl instead.";
+
auto pb_cfg = config::parseConfigFile(filepath);
if (!pb_cfg.has_value()) {
return false;
diff --git a/automotive/can/1.0/tools/libcanhaltools/libcanhaltools.cpp b/automotive/can/1.0/tools/libcanhaltools/libcanhaltools.cpp
index 9192e2f..fabe75f 100644
--- a/automotive/can/1.0/tools/libcanhaltools/libcanhaltools.cpp
+++ b/automotive/can/1.0/tools/libcanhaltools/libcanhaltools.cpp
@@ -34,8 +34,8 @@
auto manager = hidl::manager::V1_2::IServiceManager::getService();
hidl_vec<hidl_string> services;
manager->listManifestByInterface(ICanController::descriptor, hidl_utils::fill(&services));
- CHECK(services.size() > 0) << "No ICanController services registered (missing privileges?)"
- << std::endl;
+ CHECK(services.size() > 0) << "No ICanController services registered (missing privileges?). "
+ << "are you using the AIDL CanController?" << std::endl;
return services;
}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
index b93a11b..6960894 100644
--- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
@@ -41,4 +41,5 @@
long maxInt64Value;
float minFloatValue;
float maxFloatValue;
+ @nullable long[] supportedEnumValues;
}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
index b44996d..abd9540 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
@@ -40,4 +40,11 @@
float minFloatValue;
float maxFloatValue;
+
+ /**
+ * If the property has a @data_enum, then it is possible to specify a supported subset of the
+ * @data_enum. If the property has a @data_enum and supportedEnumValues is null, then it is
+ * assumed all @data_enum values are supported unless specified through another mechanism.
+ */
+ @nullable long[] supportedEnumValues;
}
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
index e4f13e8..20048a2 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
@@ -105,6 +105,7 @@
FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST | FAN_DIRECTION_FACE},
{"FUEL_DOOR_REAR_LEFT", FUEL_DOOR_REAR_LEFT},
{"LIGHT_STATE_ON", LIGHT_STATE_ON},
+ {"LIGHT_STATE_OFF", LIGHT_STATE_OFF},
{"LIGHT_SWITCH_OFF", LIGHT_SWITCH_OFF},
{"LIGHT_SWITCH_AUTO", LIGHT_SWITCH_AUTO},
{"MIRROR_DRIVER_LEFT_RIGHT",
@@ -460,6 +461,13 @@
&areaConfig.minFloatValue, errors);
tryParseJsonValueToVariable(jsonAreaConfig, "maxFloatValue", /*optional=*/true,
&areaConfig.maxFloatValue, errors);
+
+ std::vector<int64_t> supportedEnumValues;
+ tryParseJsonArrayToVariable(jsonAreaConfig, "supportedEnumValues", /*optional=*/true,
+ &supportedEnumValues, errors);
+ if (!supportedEnumValues.empty()) {
+ areaConfig.supportedEnumValues = std::move(supportedEnumValues);
+ }
config->config.areaConfigs.push_back(std::move(areaConfig));
RawPropValues areaValue = {};
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp
index 9ff8c1b..9882653 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp
@@ -616,6 +616,89 @@
<< "Wrong type for DefaultValue for one area must cause error";
}
+TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesNoSupportedEnumValuesDeclared) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_STATE",
+ "areas": [{
+ "areaId": 0,
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+ ASSERT_TRUE(result.ok());
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 1u);
+
+ const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
+ ASSERT_EQ(areaConfig.areaId, 0);
+ ASSERT_FALSE(areaConfig.supportedEnumValues);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesSupportedEnumValues) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_STATE",
+ "areas": [{
+ "areaId": 0,
+ "supportedEnumValues": ["Constants::LIGHT_STATE_ON", "Constants::LIGHT_STATE_OFF"]
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+ ASSERT_TRUE(result.ok());
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 1u);
+
+ const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
+ ASSERT_EQ(areaConfig.areaId, 0);
+ ASSERT_TRUE(areaConfig.supportedEnumValues);
+ ASSERT_EQ(areaConfig.supportedEnumValues.value().size(), 2u);
+ ASSERT_EQ(areaConfig.supportedEnumValues.value(),
+ std::vector<int64_t>({LIGHT_STATE_ON, LIGHT_STATE_OFF}));
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesEmptySupportedEnumValues) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_STATE",
+ "areas": [{
+ "areaId": 0,
+ "supportedEnumValues": []
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+ ASSERT_TRUE(result.ok());
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 1u);
+
+ const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
+ ASSERT_EQ(areaConfig.areaId, 0);
+ ASSERT_FALSE(areaConfig.supportedEnumValues);
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
index caf17e8..bf27c95 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
@@ -96,6 +96,7 @@
constexpr int CHARGE_PORT_FRONT_LEFT = toInt(propertyutils_impl::PortLocationType::FRONT_LEFT);
constexpr int CHARGE_PORT_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT);
constexpr int LIGHT_STATE_ON = toInt(propertyutils_impl::VehicleLightState::ON);
+constexpr int LIGHT_STATE_OFF = toInt(propertyutils_impl::VehicleLightState::OFF);
constexpr int LIGHT_SWITCH_OFF = toInt(propertyutils_impl::VehicleLightSwitch::OFF);
constexpr int LIGHT_SWITCH_AUTO = toInt(propertyutils_impl::VehicleLightSwitch::AUTOMATIC);
constexpr int WHEEL_FRONT_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_FRONT);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
index 7b8099f..89d8625 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable AidlCasPluginDescriptor {
int caSystemId;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
index dd355af..b69cc33 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
union DestinationBuffer {
android.hardware.cas.SharedBuffer nonsecureMemory;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
index e169beb..28c9eb0 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface ICas {
void closeSession(in byte[] sessionId);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
index ebc13ce..db75062 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface ICasListener {
void onEvent(in int event, in int arg, in byte[] data);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
index 9bf7903..411891b 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface IDescrambler {
int descramble(in android.hardware.cas.ScramblingControl scramblingControl, in android.hardware.cas.SubSample[] subSamples, in android.hardware.cas.SharedBuffer srcBuffer, in long srcOffset, in android.hardware.cas.DestinationBuffer dstBuffer, in long dstOffset);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
index f5c8018..1f945a7 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
interface IMediaCasService {
android.hardware.cas.IDescrambler createDescrambler(in int CA_system_id);
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
index e3923c7..c73f482 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
@@ -44,9 +44,9 @@
DVB_IDSA = 7,
MULTI2 = 8,
AES128 = 9,
- AES_CBC = 10,
- AES_ECB = 11,
- AES_SCTE52 = 12,
- TDES_ECB = 13,
- TDES_SCTE52 = 14,
+ AES_ECB = 10,
+ AES_SCTE52 = 11,
+ TDES_ECB = 12,
+ TDES_SCTE52 = 13,
+ AES_CBC = 14,
}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
index a18aa57..9200b1d 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable SharedBuffer {
android.hardware.common.Ashmem heapBase;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
index 3d3a8a0..343c810 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable Status {
const int OK = 0;
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
index 178cabc..165c0d4 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@Backing(type="byte") @VintfStability
enum StatusEvent {
PLUGIN_PHYSICAL_MODULE_CHANGED = 0,
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
index d9ee3b4..5bd1a1e 100644
--- a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.cas;
+/* @hide */
@VintfStability
parcelable SubSample {
int numBytesOfClearData;
diff --git a/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
index 55b328a..1dc7ac6 100644
--- a/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
+++ b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -18,6 +18,7 @@
/**
* Describes a CAS plugin with its system ID and name.
+ * @hide
*/
@VintfStability
parcelable AidlCasPluginDescriptor {
diff --git a/cas/aidl/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
index 068f29d..74336c2 100644
--- a/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
+++ b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
@@ -19,6 +19,9 @@
import android.hardware.cas.SharedBuffer;
import android.hardware.common.NativeHandle;
+/**
+ * @hide
+ */
@VintfStability
union DestinationBuffer {
/**
diff --git a/cas/aidl/android/hardware/cas/ICas.aidl b/cas/aidl/android/hardware/cas/ICas.aidl
index 4c938c7..e6494ae 100644
--- a/cas/aidl/android/hardware/cas/ICas.aidl
+++ b/cas/aidl/android/hardware/cas/ICas.aidl
@@ -23,6 +23,7 @@
* ICas is the API to control the CAS. It is used to manage sessions, provision/refresh the cas
* system, and process the EMM/ECM messages. It also allows bi-directional, scheme-specific
* communications between the client and the cas system.
+ * @hide
*/
@VintfStability
interface ICas {
diff --git a/cas/aidl/android/hardware/cas/ICasListener.aidl b/cas/aidl/android/hardware/cas/ICasListener.aidl
index 32d843f..21cd257 100644
--- a/cas/aidl/android/hardware/cas/ICasListener.aidl
+++ b/cas/aidl/android/hardware/cas/ICasListener.aidl
@@ -18,6 +18,9 @@
import android.hardware.cas.StatusEvent;
+/**
+ * @hide
+ */
@VintfStability
interface ICasListener {
/**
diff --git a/cas/aidl/android/hardware/cas/IDescrambler.aidl b/cas/aidl/android/hardware/cas/IDescrambler.aidl
index 33fbe75..0ac995c 100644
--- a/cas/aidl/android/hardware/cas/IDescrambler.aidl
+++ b/cas/aidl/android/hardware/cas/IDescrambler.aidl
@@ -23,6 +23,7 @@
/**
* IDescrambler is the API to control the descrambling operations.
+ * @hide
*/
@VintfStability
interface IDescrambler {
diff --git a/cas/aidl/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
index 8bc31f6..641c4a9 100644
--- a/cas/aidl/android/hardware/cas/IMediaCasService.aidl
+++ b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
@@ -26,6 +26,7 @@
* cas HAL to create cas and descrambler plugin instances. A cas plugin instance
* opens cas sessions which are used to obtain keys for a descrambler session,
* which can in turn be used to descramble protected video content.
+ * @hide
*/
@VintfStability
interface IMediaCasService {
diff --git a/cas/aidl/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
index 9d73eba..2a4858a 100644
--- a/cas/aidl/android/hardware/cas/ScramblingMode.aidl
+++ b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
@@ -70,11 +70,6 @@
AES128,
/**
- * Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
- */
- AES_CBC,
-
- /**
* Advanced Encryption System (AES) Electronic Code Book (ECB) mode.
*/
AES_ECB,
@@ -95,4 +90,9 @@
* Engineers (SCTE) 52 mode.
*/
TDES_SCTE52,
+
+ /**
+ * Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
+ */
+ AES_CBC,
}
diff --git a/cas/aidl/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
index 8a94ff7..0c89cfe 100644
--- a/cas/aidl/android/hardware/cas/SharedBuffer.aidl
+++ b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
@@ -22,6 +22,7 @@
* SharedBuffer describes a shared buffer which is defined by a heapBase, an
* offset and a size. The offset is relative to the shared memory base for the
* memory region identified by heapBase.
+ * @hide
*/
@VintfStability
parcelable SharedBuffer {
diff --git a/cas/aidl/android/hardware/cas/Status.aidl b/cas/aidl/android/hardware/cas/Status.aidl
index b2be34b..e7ae8ff 100644
--- a/cas/aidl/android/hardware/cas/Status.aidl
+++ b/cas/aidl/android/hardware/cas/Status.aidl
@@ -16,6 +16,9 @@
package android.hardware.cas;
+/**
+ * @hide
+ */
@VintfStability
parcelable Status {
/**
diff --git a/cas/aidl/android/hardware/cas/StatusEvent.aidl b/cas/aidl/android/hardware/cas/StatusEvent.aidl
index 0f62634..1fe732e 100644
--- a/cas/aidl/android/hardware/cas/StatusEvent.aidl
+++ b/cas/aidl/android/hardware/cas/StatusEvent.aidl
@@ -18,6 +18,7 @@
/**
* The Event Type for status change.
+ * @hide
*/
@VintfStability
@Backing(type="byte")
diff --git a/cas/aidl/android/hardware/cas/SubSample.aidl b/cas/aidl/android/hardware/cas/SubSample.aidl
index c1353cb..8e1ff77 100644
--- a/cas/aidl/android/hardware/cas/SubSample.aidl
+++ b/cas/aidl/android/hardware/cas/SubSample.aidl
@@ -19,6 +19,7 @@
/**
* A subsample consists of some number of bytes of clear (unscrambled)
* data followed by a number of bytes of scrambled data.
+ * @hide
*/
@VintfStability
parcelable SubSample {
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index d4b1fad..a907f20 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -513,6 +513,16 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.radio.sap</name>
+ <version>1</version>
+ <interface>
+ <name>ISap</name>
+ <instance>slot1</instance>
+ <instance>slot2</instance>
+ <instance>slot3</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.radio.voice</name>
<version>2</version>
<interface>
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 930b6d4..9caa97a 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -153,6 +153,23 @@
}
aidl_interface {
+ name: "android.hardware.radio.sap",
+ vendor_available: true,
+ host_supported: true,
+ srcs: ["android/hardware/radio/sap/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: true,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+
+}
+
+aidl_interface {
name: "android.hardware.radio.sim",
vendor_available: true,
host_supported: true,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/ISap.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/ISap.aidl
new file mode 100644
index 0000000..37391e9
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/ISap.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@VintfStability
+interface ISap {
+ oneway void apduReq(in int serial, in android.hardware.radio.sap.SapApduType type, in byte[] command);
+ oneway void connectReq(in int serial, in int maxMsgSizeBytes);
+ oneway void disconnectReq(in int serial);
+ oneway void powerReq(in int serial, in boolean powerOn);
+ oneway void resetSimReq(in int serial);
+ oneway void setCallback(in android.hardware.radio.sap.ISapCallback sapCallback);
+ oneway void setTransferProtocolReq(in int serial, in android.hardware.radio.sap.SapTransferProtocol transferProtocol);
+ oneway void transferAtrReq(in int serial);
+ oneway void transferCardReaderStatusReq(in int serial);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/ISapCallback.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/ISapCallback.aidl
new file mode 100644
index 0000000..d507709
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/ISapCallback.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@VintfStability
+interface ISapCallback {
+ oneway void apduResponse(in int serial, in android.hardware.radio.sap.SapResultCode resultCode, in byte[] apduRsp);
+ oneway void connectResponse(in int serial, in android.hardware.radio.sap.SapConnectRsp sapConnectRsp, in int maxMsgSizeBytes);
+ oneway void disconnectIndication(in int serial, in android.hardware.radio.sap.SapDisconnectType disconnectType);
+ oneway void disconnectResponse(in int serial);
+ oneway void errorResponse(in int serial);
+ oneway void powerResponse(in int serial, in android.hardware.radio.sap.SapResultCode resultCode);
+ oneway void resetSimResponse(in int serial, in android.hardware.radio.sap.SapResultCode resultCode);
+ oneway void statusIndication(in int serial, in android.hardware.radio.sap.SapStatus status);
+ oneway void transferAtrResponse(in int serial, in android.hardware.radio.sap.SapResultCode resultCode, in byte[] atr);
+ oneway void transferCardReaderStatusResponse(in int serial, in android.hardware.radio.sap.SapResultCode resultCode, in int cardReaderStatus);
+ oneway void transferProtocolResponse(in int serial, in android.hardware.radio.sap.SapResultCode resultCode);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapApduType.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapApduType.aidl
new file mode 100644
index 0000000..e0e2a03
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapApduType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@Backing(type="int") @VintfStability
+enum SapApduType {
+ APDU = 0,
+ APDU7816 = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapConnectRsp.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapConnectRsp.aidl
new file mode 100644
index 0000000..aceac37
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapConnectRsp.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@Backing(type="int") @VintfStability
+enum SapConnectRsp {
+ SUCCESS = 0,
+ CONNECT_FAILURE = 1,
+ MSG_SIZE_TOO_LARGE = 2,
+ MSG_SIZE_TOO_SMALL = 3,
+ CONNECT_OK_CALL_ONGOING = 4,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapDisconnectType.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapDisconnectType.aidl
new file mode 100644
index 0000000..0447f9b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapDisconnectType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@Backing(type="int") @VintfStability
+enum SapDisconnectType {
+ GRACEFUL = 0,
+ IMMEDIATE = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapResultCode.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapResultCode.aidl
new file mode 100644
index 0000000..1db226b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapResultCode.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@Backing(type="int") @VintfStability
+enum SapResultCode {
+ SUCCESS = 0,
+ GENERIC_FAILURE = 1,
+ CARD_NOT_ACCESSSIBLE = 2,
+ CARD_ALREADY_POWERED_OFF = 3,
+ CARD_REMOVED = 4,
+ CARD_ALREADY_POWERED_ON = 5,
+ DATA_NOT_AVAILABLE = 6,
+ NOT_SUPPORTED = 7,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapStatus.aidl
new file mode 100644
index 0000000..32f71c2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapStatus.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@Backing(type="int") @VintfStability
+enum SapStatus {
+ UNKNOWN_ERROR = 0,
+ CARD_RESET = 1,
+ CARD_NOT_ACCESSIBLE = 2,
+ CARD_REMOVED = 3,
+ CARD_INSERTED = 4,
+ RECOVERED = 5,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapTransferProtocol.aidl b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapTransferProtocol.aidl
new file mode 100644
index 0000000..e3ffdb0
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sap/current/android/hardware/radio/sap/SapTransferProtocol.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.radio.sap;
+@Backing(type="int") @VintfStability
+enum SapTransferProtocol {
+ T0 = 0,
+ T1 = 1,
+}
diff --git a/radio/aidl/android/hardware/radio/sap/ISap.aidl b/radio/aidl/android/hardware/radio/sap/ISap.aidl
new file mode 100644
index 0000000..552e602
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/ISap.aidl
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+import android.hardware.radio.sap.ISapCallback;
+import android.hardware.radio.sap.SapApduType;
+import android.hardware.radio.sap.SapTransferProtocol;
+
+@VintfStability
+oneway interface ISap {
+ /**
+ * TRANSFER_APDU_REQ from SAP 1.1 spec 5.1.6
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ * @param type APDU command type
+ * @param command CommandAPDU/CommandAPDU7816 parameter depending on type
+ */
+ void apduReq(in int serial, in SapApduType type, in byte[] command);
+
+ /**
+ * CONNECT_REQ from SAP 1.1 spec 5.1.1
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ * @param maxMsgSizeBytes MaxMsgSize to be used for SIM Access Profile connection
+ */
+ void connectReq(in int serial, in int maxMsgSizeBytes);
+
+ /**
+ * DISCONNECT_REQ from SAP 1.1 spec 5.1.3
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ */
+ void disconnectReq(in int serial);
+
+ /**
+ * POWER_SIM_OFF_REQ and POWER_SIM_ON_REQ from SAP 1.1 spec 5.1.10 + 5.1.12
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ * @param powerOn true for on, false for off
+ */
+ void powerReq(in int serial, in boolean powerOn);
+
+ /**
+ * RESET_SIM_REQ from SAP 1.1 spec 5.1.14
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ */
+ void resetSimReq(in int serial);
+
+ /**
+ * Set callback that has response and unsolicited indication functions
+ *
+ * @param sapCallback Object containing response and unosolicited indication callbacks
+ */
+ void setCallback(in ISapCallback sapCallback);
+
+ /**
+ * SET_TRANSPORT_PROTOCOL_REQ from SAP 1.1 spec 5.1.20
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ * @param transferProtocol Transport Protocol
+ */
+ void setTransferProtocolReq(in int serial, in SapTransferProtocol transferProtocol);
+
+ /**
+ * TRANSFER_ATR_REQ from SAP 1.1 spec 5.1.8
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ */
+ void transferAtrReq(in int serial);
+
+ /**
+ * TRANSFER_CARD_READER_STATUS_REQ from SAP 1.1 spec 5.1.17
+ *
+ * @param serial Id to match req-resp. Resp must include same serial.
+ */
+ void transferCardReaderStatusReq(in int serial);
+}
diff --git a/radio/aidl/android/hardware/radio/sap/ISapCallback.aidl b/radio/aidl/android/hardware/radio/sap/ISapCallback.aidl
new file mode 100644
index 0000000..34111eb
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/ISapCallback.aidl
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+import android.hardware.radio.sap.SapConnectRsp;
+import android.hardware.radio.sap.SapDisconnectType;
+import android.hardware.radio.sap.SapResultCode;
+import android.hardware.radio.sap.SapStatus;
+
+@VintfStability
+oneway interface ISapCallback {
+ /**
+ * TRANSFER_APDU_RESP from SAP 1.1 spec 5.1.7
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param resultCode ResultCode to indicate if command was processed correctly
+ * Possible values:
+ * SapResultCode:SUCCESS,
+ * SapResultCode:GENERIC_FAILURE,
+ * SapResultCode:CARD_NOT_ACCESSSIBLE,
+ * SapResultCode:CARD_ALREADY_POWERED_OFF,
+ * SapResultCode:CARD_REMOVED
+ * @param apduRsp APDU Response. Valid only if command was processed correctly and no error
+ * occurred.
+ */
+ void apduResponse(in int serial, in SapResultCode resultCode, in byte[] apduRsp);
+
+ /**
+ * CONNECT_RESP from SAP 1.1 spec 5.1.2
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param sapConnectRsp Connection Status
+ * @param maxMsgSizeBytes MaxMsgSize supported by server if request cannot be fulfilled.
+ * Valid only if connectResponse is SapConnectResponse:MSG_SIZE_TOO_LARGE.
+ */
+ void connectResponse(in int serial, in SapConnectRsp sapConnectRsp, in int maxMsgSizeBytes);
+
+ /**
+ * DISCONNECT_IND from SAP 1.1 spec 5.1.5
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param disconnectType Disconnect Type to indicate if shutdown is graceful or immediate
+ */
+ void disconnectIndication(in int serial, in SapDisconnectType disconnectType);
+
+ /**
+ * DISCONNECT_RESP from SAP 1.1 spec 5.1.4
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ */
+ void disconnectResponse(in int serial);
+
+ /**
+ * ERROR_RESP from SAP 1.1 spec 5.1.19
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ */
+ void errorResponse(in int serial);
+
+ /**
+ * POWER_SIM_OFF_RESP and POWER_SIM_ON_RESP from SAP 1.1 spec 5.1.11 + 5.1.13
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param resultCode ResultCode to indicate if command was processed correctly
+ * Possible values:
+ * SapResultCode:SUCCESS,
+ * SapResultCode:GENERIC_FAILURE,
+ * SapResultCode:CARD_NOT_ACCESSSIBLE, (possible only for power on req)
+ * SapResultCode:CARD_ALREADY_POWERED_OFF, (possible only for power off req)
+ * SapResultCode:CARD_REMOVED,
+ * SapResultCode:CARD_ALREADY_POWERED_ON (possible only for power on req)
+ */
+ void powerResponse(in int serial, in SapResultCode resultCode);
+
+ /**
+ * RESET_SIM_RESP from SAP 1.1 spec 5.1.15
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param resultCode ResultCode to indicate if command was processed correctly
+ * Possible values:
+ * SapResultCode:SUCCESS,
+ * SapResultCode:GENERIC_FAILURE,
+ * SapResultCode:CARD_NOT_ACCESSSIBLE,
+ * SapResultCode:CARD_ALREADY_POWERED_OFF,
+ * SapResultCode:CARD_REMOVED
+ */
+ void resetSimResponse(in int serial, in SapResultCode resultCode);
+
+ /**
+ * STATUS_IND from SAP 1.1 spec 5.1.16
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param status Parameter to indicate reason for the status change.
+ */
+ void statusIndication(in int serial, in SapStatus status);
+
+ /**
+ * TRANSFER_ATR_RESP from SAP 1.1 spec 5.1.9
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param resultCode ResultCode to indicate if command was processed correctly
+ * Possible values:
+ * SapResultCode:SUCCESS,
+ * SapResultCode:GENERIC_FAILURE,
+ * SapResultCode:CARD_ALREADY_POWERED_OFF,
+ * SapResultCode:CARD_REMOVED,
+ * SapResultCode:DATA_NOT_AVAILABLE
+ * @param atr Answer to Reset from the subscription module. Included only if no error occurred,
+ * otherwise empty.
+ */
+ void transferAtrResponse(in int serial, in SapResultCode resultCode, in byte[] atr);
+
+ /**
+ * TRANSFER_CARD_READER_STATUS_REQ from SAP 1.1 spec 5.1.18
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param resultCode ResultCode to indicate if command was processed correctly
+ * Possible values:
+ * SapResultCode:SUCCESS,
+ * SapResultCode:GENERIC_FAILURE
+ * SapResultCode:DATA_NOT_AVAILABLE
+ * @param cardReaderStatus Card Reader Status coded as described in 3GPP TS 11.14 Section 12.33
+ * and TS 31.111 Section 8.33
+ */
+ void transferCardReaderStatusResponse(
+ in int serial, in SapResultCode resultCode, in int cardReaderStatus);
+
+ /**
+ * SET_TRANSPORT_PROTOCOL_RESP from SAP 1.1 spec 5.1.21
+ *
+ * @param serial Id to match req-resp. Value must match the one in req.
+ * @param resultCode ResultCode to indicate if command was processed correctly
+ * Possible values:
+ * SapResultCode:SUCCESS
+ * SapResultCode:NOT_SUPPORTED
+ */
+ void transferProtocolResponse(in int serial, in SapResultCode resultCode);
+}
diff --git a/radio/aidl/android/hardware/radio/sap/SapApduType.aidl b/radio/aidl/android/hardware/radio/sap/SapApduType.aidl
new file mode 100644
index 0000000..ab8ffb9
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/SapApduType.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+@VintfStability
+@Backing(type="int")
+enum SapApduType {
+ APDU,
+ APDU7816,
+}
diff --git a/radio/aidl/android/hardware/radio/sap/SapConnectRsp.aidl b/radio/aidl/android/hardware/radio/sap/SapConnectRsp.aidl
new file mode 100644
index 0000000..0e1d528
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/SapConnectRsp.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+@VintfStability
+@Backing(type="int")
+enum SapConnectRsp {
+ SUCCESS,
+ CONNECT_FAILURE,
+ MSG_SIZE_TOO_LARGE,
+ MSG_SIZE_TOO_SMALL,
+ CONNECT_OK_CALL_ONGOING,
+}
diff --git a/radio/aidl/android/hardware/radio/sap/SapDisconnectType.aidl b/radio/aidl/android/hardware/radio/sap/SapDisconnectType.aidl
new file mode 100644
index 0000000..16d7cc6
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/SapDisconnectType.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+@VintfStability
+@Backing(type="int")
+enum SapDisconnectType {
+ GRACEFUL,
+ IMMEDIATE,
+}
diff --git a/radio/aidl/android/hardware/radio/sap/SapResultCode.aidl b/radio/aidl/android/hardware/radio/sap/SapResultCode.aidl
new file mode 100644
index 0000000..4728ebe
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/SapResultCode.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+@VintfStability
+@Backing(type="int")
+enum SapResultCode {
+ SUCCESS,
+ GENERIC_FAILURE,
+ CARD_NOT_ACCESSSIBLE,
+ CARD_ALREADY_POWERED_OFF,
+ CARD_REMOVED,
+ CARD_ALREADY_POWERED_ON,
+ DATA_NOT_AVAILABLE,
+ NOT_SUPPORTED,
+}
diff --git a/radio/aidl/android/hardware/radio/sap/SapStatus.aidl b/radio/aidl/android/hardware/radio/sap/SapStatus.aidl
new file mode 100644
index 0000000..309352d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/SapStatus.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+@VintfStability
+@Backing(type="int")
+enum SapStatus {
+ UNKNOWN_ERROR,
+ CARD_RESET,
+ CARD_NOT_ACCESSIBLE,
+ CARD_REMOVED,
+ CARD_INSERTED,
+ RECOVERED,
+}
diff --git a/radio/aidl/android/hardware/radio/sap/SapTransferProtocol.aidl b/radio/aidl/android/hardware/radio/sap/SapTransferProtocol.aidl
new file mode 100644
index 0000000..823c5f2
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sap/SapTransferProtocol.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sap;
+
+@VintfStability
+@Backing(type="int")
+enum SapTransferProtocol {
+ T0,
+ T1,
+}
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index c40ca30..95953ac 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -41,6 +41,7 @@
"android.hardware.radio.messaging-V2-ndk",
"android.hardware.radio.modem-V2-ndk",
"android.hardware.radio.network-V2-ndk",
+ "android.hardware.radio.sap-V1-ndk",
"android.hardware.radio.sim-V2-ndk",
"android.hardware.radio.voice-V2-ndk",
"android.hardware.radio@1.0",
@@ -86,6 +87,9 @@
"network/RadioResponse-network.cpp",
"network/structs.cpp",
"network/utils.cpp",
+ "sap/Sap.cpp",
+ "sap/SapCallback.cpp",
+ "sap/structs.cpp",
"sim/RadioIndication-sim.cpp",
"sim/RadioResponse-sim.cpp",
"sim/RadioSim.cpp",
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.cpp b/radio/aidl/compat/libradiocompat/commonStructs.cpp
index 6e4c873..d65ed1a 100644
--- a/radio/aidl/compat/libradiocompat/commonStructs.cpp
+++ b/radio/aidl/compat/libradiocompat/commonStructs.cpp
@@ -48,6 +48,10 @@
return v;
}
+uint8_t toHidl(int8_t v) {
+ return v;
+}
+
aidl::RadioIndicationType toAidl(V1_0::RadioIndicationType type) {
return aidl::RadioIndicationType(type);
}
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.h b/radio/aidl/compat/libradiocompat/commonStructs.h
index a4a4869..f43a599 100644
--- a/radio/aidl/compat/libradiocompat/commonStructs.h
+++ b/radio/aidl/compat/libradiocompat/commonStructs.h
@@ -28,6 +28,7 @@
uint8_t toAidl(int8_t v);
int8_t toAidl(uint8_t v);
int32_t toAidl(uint32_t v);
+uint8_t toHidl(int8_t v);
aidl::android::hardware::radio::RadioIndicationType toAidl(V1_0::RadioIndicationType type);
aidl::android::hardware::radio::RadioResponseType toAidl(V1_0::RadioResponseType type);
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/Sap.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/Sap.h
new file mode 100644
index 0000000..a293d11
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/Sap.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+#include "SapCallback.h"
+
+#include <aidl/android/hardware/radio/sap/BnSap.h>
+#include <android/hardware/radio/1.0/ISap.h>
+#include <android/hardware/radio/1.0/ISapCallback.h>
+
+namespace android::hardware::radio::compat {
+
+/**
+ * HAL translator from HIDL ISap to AIDL ISap
+ *
+ * This class wraps existing HIDL implementation (either a binder stub or real
+ * class implementing the HAL) and implements AIDL HAL. It's up to the caller to
+ * fetch source implementation and publish resulting HAL instance.
+ */
+class Sap : public aidl::android::hardware::radio::sap::BnSap {
+ const sp<radio::V1_0::ISap> mHal;
+
+ const sp<SapCallback> mSapCallback;
+
+ ::ndk::ScopedAStatus apduReq(int32_t serial,
+ aidl::android::hardware::radio::sap::SapApduType type,
+ const std::vector<uint8_t>& command) override;
+ ::ndk::ScopedAStatus connectReq(int32_t serial, int32_t maxMsgSize) override;
+ ::ndk::ScopedAStatus disconnectReq(int32_t serial) override;
+ ::ndk::ScopedAStatus powerReq(int32_t serial, bool state) override;
+ ::ndk::ScopedAStatus resetSimReq(int32_t serial) override;
+ ::ndk::ScopedAStatus setCallback(
+ const std::shared_ptr<::aidl::android::hardware::radio::sap::ISapCallback>& sapCallback)
+ override;
+ ::ndk::ScopedAStatus setTransferProtocolReq(
+ int32_t serial,
+ aidl::android::hardware::radio::sap::SapTransferProtocol transferProtocol) override;
+ ::ndk::ScopedAStatus transferAtrReq(int32_t serial) override;
+ ::ndk::ScopedAStatus transferCardReaderStatusReq(int32_t serial) override;
+
+ public:
+ /**
+ * Constructs AIDL ISap instance wrapping existing HIDL ISap instance.
+ *
+ * \param hidlHal existing HIDL ISap HAL instance
+ */
+ Sap(sp<V1_0::ISap> hidlHal);
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/SapCallback.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/SapCallback.h
new file mode 100644
index 0000000..7e72106
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/SapCallback.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/sap/ISapCallback.h>
+#include <android/hardware/radio/1.0/ISapCallback.h>
+
+namespace android::hardware::radio::compat {
+
+class SapCallback : public V1_0::ISapCallback {
+ GuaranteedCallback<aidl::android::hardware::radio::sap::ISapCallback,
+ aidl::android::hardware::radio::sap::ISapCallbackDefault>
+ mCallback;
+
+ Return<void> apduResponse(int32_t serial, V1_0::SapResultCode resultCode,
+ const ::android::hardware::hidl_vec<uint8_t>& apduRsp) override;
+ Return<void> connectResponse(int32_t serial, V1_0::SapConnectRsp sapConnectRsp,
+ int32_t maxMsgSize) override;
+ Return<void> disconnectIndication(int32_t serial,
+ V1_0::SapDisconnectType disconnectType) override;
+ Return<void> disconnectResponse(int32_t serial) override;
+ Return<void> errorResponse(int32_t serial) override;
+ Return<void> powerResponse(int32_t serial, V1_0::SapResultCode resultCode) override;
+ Return<void> resetSimResponse(int32_t serial, V1_0::SapResultCode resultCode) override;
+ Return<void> statusIndication(int32_t serial, V1_0::SapStatus status) override;
+ Return<void> transferAtrResponse(int32_t serial, V1_0::SapResultCode resultCode,
+ const ::android::hardware::hidl_vec<uint8_t>& atr) override;
+ Return<void> transferCardReaderStatusResponse(int32_t serial, V1_0::SapResultCode resultCode,
+ int32_t cardReaderStatus) override;
+ Return<void> transferProtocolResponse(int32_t serial, V1_0::SapResultCode resultCode) override;
+
+ public:
+ void setResponseFunction(
+ const std::shared_ptr<aidl::android::hardware::radio::sap::ISapCallback>& callback);
+
+ std::shared_ptr<aidl::android::hardware::radio::sap::ISapCallback> respond();
+};
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sap/Sap.cpp b/radio/aidl/compat/libradiocompat/sap/Sap.cpp
new file mode 100644
index 0000000..1a77169
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sap/Sap.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/Sap.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Sap"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::sap;
+constexpr auto ok = &ScopedAStatus::ok;
+
+Sap::Sap(sp<V1_0::ISap> hidlHal) : mHal(hidlHal), mSapCallback(sp<SapCallback>::make()) {}
+
+ScopedAStatus Sap::apduReq(int32_t serial, aidl::SapApduType type,
+ const std::vector<uint8_t>& command) {
+ LOG_CALL << serial;
+ mHal->apduReq(serial, toHidl(type), toHidl(command));
+ return ok();
+}
+
+ScopedAStatus Sap::connectReq(int32_t serial, int32_t maxMsgSize) {
+ LOG_CALL << serial;
+ mHal->connectReq(serial, maxMsgSize);
+ return ok();
+}
+
+ScopedAStatus Sap::disconnectReq(int32_t serial) {
+ LOG_CALL << serial;
+ mHal->disconnectReq(serial);
+ return ok();
+}
+
+ScopedAStatus Sap::powerReq(int32_t serial, bool state) {
+ LOG_CALL << serial;
+ mHal->powerReq(serial, state);
+ return ok();
+}
+
+ScopedAStatus Sap::resetSimReq(int32_t serial) {
+ LOG_CALL << serial;
+ mHal->resetSimReq(serial);
+ return ok();
+}
+
+ScopedAStatus Sap::setCallback(
+ const std::shared_ptr<::aidl::android::hardware::radio::sap::ISapCallback>& sapCallback) {
+ LOG_CALL << sapCallback;
+
+ CHECK(sapCallback);
+
+ mSapCallback->setResponseFunction(sapCallback);
+ mHal->setCallback(mSapCallback).assertOk();
+ return ok();
+}
+ScopedAStatus Sap::setTransferProtocolReq(int32_t serial,
+ aidl::SapTransferProtocol transferProtocol) {
+ LOG_CALL << serial;
+ mHal->setTransferProtocolReq(serial, toHidl(transferProtocol));
+ return ok();
+}
+
+ScopedAStatus Sap::transferAtrReq(int32_t serial) {
+ LOG_CALL << serial;
+ mHal->transferAtrReq(serial);
+ return ok();
+}
+ScopedAStatus Sap::transferCardReaderStatusReq(int32_t serial) {
+ LOG_CALL << serial;
+ mHal->transferCardReaderStatusReq(serial);
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sap/SapCallback.cpp b/radio/aidl/compat/libradiocompat/sap/SapCallback.cpp
new file mode 100644
index 0000000..a40dff8
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sap/SapCallback.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/SapCallback.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "SapCallback"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sap;
+
+void SapCallback::setResponseFunction(const std::shared_ptr<aidl::ISapCallback>& callback) {
+ mCallback = callback;
+}
+
+std::shared_ptr<aidl::ISapCallback> SapCallback::respond() {
+ return mCallback.get();
+}
+
+Return<void> SapCallback::apduResponse(int32_t serial, V1_0::SapResultCode resultCode,
+ const hidl_vec<uint8_t>& apduRsp) {
+ LOG_CALL << serial;
+ respond()->apduResponse(serial, toAidl(resultCode), apduRsp);
+ return {};
+}
+
+Return<void> SapCallback::connectResponse(int32_t serial, V1_0::SapConnectRsp sapConnectRsp,
+ int32_t maxMsgSize) {
+ LOG_CALL << serial;
+ respond()->connectResponse(serial, toAidl(sapConnectRsp), maxMsgSize);
+ return {};
+}
+
+Return<void> SapCallback::disconnectIndication(int32_t serial,
+ V1_0::SapDisconnectType disconnectType) {
+ LOG_CALL << serial;
+ respond()->disconnectIndication(serial, toAidl(disconnectType));
+ return {};
+}
+
+Return<void> SapCallback::disconnectResponse(int32_t serial) {
+ LOG_CALL << serial;
+ respond()->disconnectResponse(serial);
+ return {};
+}
+
+Return<void> SapCallback::errorResponse(int32_t serial) {
+ LOG_CALL << serial;
+ respond()->errorResponse(serial);
+ return {};
+}
+
+Return<void> SapCallback::powerResponse(int32_t serial, V1_0::SapResultCode resultCode) {
+ LOG_CALL << serial;
+ respond()->powerResponse(serial, toAidl(resultCode));
+ return {};
+}
+
+Return<void> SapCallback::resetSimResponse(int32_t serial, V1_0::SapResultCode resultCode) {
+ LOG_CALL << serial;
+ respond()->resetSimResponse(serial, toAidl(resultCode));
+ return {};
+}
+
+Return<void> SapCallback::statusIndication(int32_t serial, V1_0::SapStatus status) {
+ LOG_CALL << serial;
+ respond()->statusIndication(serial, toAidl(status));
+ return {};
+}
+
+Return<void> SapCallback::transferAtrResponse(int32_t serial, V1_0::SapResultCode resultCode,
+ const hidl_vec<uint8_t>& atr) {
+ LOG_CALL << serial;
+ respond()->transferAtrResponse(serial, toAidl(resultCode), atr);
+ return {};
+}
+
+Return<void> SapCallback::transferCardReaderStatusResponse(int32_t serial,
+ V1_0::SapResultCode resultCode,
+ int32_t cardReaderStatus) {
+ LOG_CALL << serial;
+ respond()->transferCardReaderStatusResponse(serial, toAidl(resultCode), cardReaderStatus);
+ return {};
+}
+
+Return<void> SapCallback::transferProtocolResponse(int32_t serial, V1_0::SapResultCode resultCode) {
+ LOG_CALL << serial;
+ respond()->transferProtocolResponse(serial, toAidl(resultCode));
+ return {};
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sap/structs.cpp b/radio/aidl/compat/libradiocompat/sap/structs.cpp
new file mode 100644
index 0000000..522056b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sap/structs.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sap;
+
+V1_0::SapApduType toHidl(const aidl::SapApduType sapApduType) {
+ return V1_0::SapApduType(sapApduType);
+}
+
+V1_0::SapTransferProtocol toHidl(const aidl::SapTransferProtocol sapTransferProtocol) {
+ return V1_0::SapTransferProtocol(sapTransferProtocol);
+}
+
+aidl::SapResultCode toAidl(const V1_0::SapResultCode sapResultCode) {
+ return aidl::SapResultCode(sapResultCode);
+}
+
+aidl::SapConnectRsp toAidl(const V1_0::SapConnectRsp sapConnectRsp) {
+ return aidl::SapConnectRsp(sapConnectRsp);
+}
+
+aidl::SapDisconnectType toAidl(const V1_0::SapDisconnectType sapDisconnectType) {
+ return aidl::SapDisconnectType(sapDisconnectType);
+}
+
+aidl::SapStatus toAidl(const V1_0::SapStatus sapStatus) {
+ return aidl::SapStatus(sapStatus);
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sap/structs.h b/radio/aidl/compat/libradiocompat/sap/structs.h
new file mode 100644
index 0000000..d88120d
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sap/structs.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, eithe r express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/sap/ISap.h>
+#include <android/hardware/radio/1.0/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::SapApduType toHidl(aidl::android::hardware::radio::sap::SapApduType sapAdpuType);
+V1_0::SapTransferProtocol toHidl(
+ aidl::android::hardware::radio::sap::SapTransferProtocol sapTransferProtocol);
+
+aidl::android::hardware::radio::sap::SapResultCode toAidl(V1_0::SapResultCode sapResultCode);
+aidl::android::hardware::radio::sap::SapConnectRsp toAidl(V1_0::SapConnectRsp sapConnectRsp);
+aidl::android::hardware::radio::sap::SapDisconnectType toAidl(
+ V1_0::SapDisconnectType sapDisconnectType);
+aidl::android::hardware::radio::sap::SapStatus toAidl(V1_0::SapStatus sapStatus);
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
index 7a48da2..56674c1 100644
--- a/radio/aidl/compat/service/Android.bp
+++ b/radio/aidl/compat/service/Android.bp
@@ -44,6 +44,7 @@
"android.hardware.radio.messaging-V2-ndk",
"android.hardware.radio.modem-V2-ndk",
"android.hardware.radio.network-V2-ndk",
+ "android.hardware.radio.sap-V1-ndk",
"android.hardware.radio.sim-V2-ndk",
"android.hardware.radio.voice-V2-ndk",
"android.hardware.radio@1.0",
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index 5a0dbd0..99c3d71 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -53,6 +53,8 @@
"radio_network_indication.cpp",
"radio_network_response.cpp",
"radio_network_test.cpp",
+ "radio_sap_callback.cpp",
+ "radio_sap_test.cpp",
"radio_sim_indication.cpp",
"radio_sim_response.cpp",
"radio_sim_test.cpp",
@@ -73,6 +75,7 @@
"android.hardware.radio.messaging-V2-ndk",
"android.hardware.radio.modem-V2-ndk",
"android.hardware.radio.network-V2-ndk",
+ "android.hardware.radio.sap-V1-ndk",
"android.hardware.radio.sim-V2-ndk",
"android.hardware.radio.voice-V2-ndk",
],
diff --git a/radio/aidl/vts/VtsHalRadioTargetTest.cpp b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
index 67a2672..c25f930 100644
--- a/radio/aidl/vts/VtsHalRadioTargetTest.cpp
+++ b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
@@ -22,6 +22,7 @@
#include "radio_messaging_utils.h"
#include "radio_modem_utils.h"
#include "radio_network_utils.h"
+#include "radio_sap_utils.h"
#include "radio_sim_utils.h"
#include "radio_voice_utils.h"
@@ -55,6 +56,11 @@
testing::ValuesIn(android::getAidlHalInstanceNames(IRadioNetwork::descriptor)),
android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioSapTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, SapTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(ISap::descriptor)),
+ android::PrintInstanceNameToString);
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioSimTest);
INSTANTIATE_TEST_SUITE_P(PerInstance, RadioSimTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IRadioSim::descriptor)),
diff --git a/radio/aidl/vts/radio_sap_callback.cpp b/radio/aidl/vts/radio_sap_callback.cpp
new file mode 100644
index 0000000..3b21ede
--- /dev/null
+++ b/radio/aidl/vts/radio_sap_callback.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "radio_sap_utils.h"
+
+#include <android-base/logging.h>
+
+SapCallback::SapCallback(SapTest& parent) : parent_sap(parent) {}
+
+::ndk::ScopedAStatus SapCallback::apduResponse(int32_t serialNumber, SapResultCode resultCode,
+ const std::vector<uint8_t>& /*apduRsp*/) {
+ sapResponseSerial = serialNumber;
+ sapResultCode = resultCode;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
+::ndk::ScopedAStatus SapCallback::connectResponse(int32_t serialNumber,
+ SapConnectRsp /*sapConnectRsp*/,
+ int32_t /*maxMsgSize*/) {
+ sapResponseSerial = serialNumber;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::disconnectIndication(int32_t /*serialNumber*/,
+ SapDisconnectType /*sapDisconnectType*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::disconnectResponse(int32_t serialNumber) {
+ sapResponseSerial = serialNumber;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::errorResponse(int32_t /*serialNumber*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::powerResponse(int32_t serialNumber, SapResultCode resultCode) {
+ sapResponseSerial = serialNumber;
+ sapResultCode = resultCode;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::resetSimResponse(int32_t serialNumber, SapResultCode resultCode) {
+ sapResponseSerial = serialNumber;
+ sapResultCode = resultCode;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::statusIndication(int32_t /*serialNumber*/,
+ SapStatus /*sapStatus*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::transferAtrResponse(int32_t serialNumber,
+ SapResultCode resultCode,
+ const std::vector<uint8_t>& /*atr*/) {
+ sapResponseSerial = serialNumber;
+ sapResultCode = resultCode;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::transferCardReaderStatusResponse(int32_t serialNumber,
+ SapResultCode resultCode,
+ int32_t /*cardReaderStatus*/) {
+ sapResponseSerial = serialNumber;
+ sapResultCode = resultCode;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SapCallback::transferProtocolResponse(int32_t serialNumber,
+ SapResultCode resultCode) {
+ sapResponseSerial = serialNumber;
+ sapResultCode = resultCode;
+ parent_sap.notify(serialNumber);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_sap_test.cpp b/radio/aidl/vts/radio_sap_test.cpp
new file mode 100644
index 0000000..c94379c
--- /dev/null
+++ b/radio/aidl/vts/radio_sap_test.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_sap_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE((ret).isOk())
+#define TIMEOUT_PERIOD 40
+
+void SapTest::SetUp() {
+ std::string serviceName = GetParam();
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ LOG(DEBUG) << "Skipped the test due to device configuration.";
+ GTEST_SKIP();
+ }
+ sap = ISap::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+ ASSERT_NE(sap.get(), nullptr);
+
+ sapCb = ndk::SharedRefBase::make<SapCallback>(*this);
+ ASSERT_NE(sapCb.get(), nullptr);
+
+ count = 0;
+
+ ndk::ScopedAStatus res = sap->setCallback(sapCb);
+ ASSERT_OK(res) << res;
+}
+
+void SapTest::TearDown() {}
+
+::testing::AssertionResult SapTest::CheckAnyOfErrors(SapResultCode err,
+ std::vector<SapResultCode> errors) {
+ for (size_t i = 0; i < errors.size(); i++) {
+ if (err == errors[i]) {
+ return testing::AssertionSuccess();
+ }
+ }
+ return testing::AssertionFailure() << "SapError:" + toString(err) + " is returned";
+}
+
+void SapTest::notify(int receivedSerial) {
+ std::unique_lock<std::mutex> lock(mtx);
+ count++;
+ if (serial == receivedSerial) {
+ cv.notify_one();
+ }
+}
+
+std::cv_status SapTest::wait() {
+ std::unique_lock<std::mutex> lock(mtx);
+
+ std::cv_status status = std::cv_status::no_timeout;
+ auto now = std::chrono::system_clock::now();
+ while (count == 0) {
+ status = cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ if (status == std::cv_status::timeout) {
+ return status;
+ }
+ }
+ count--;
+ return status;
+}
+
+/*
+ * Test ISap.connectReq() for the response returned.
+ */
+TEST_P(SapTest, connectReq) {
+ LOG(DEBUG) << "connectReq";
+ serial = GetRandomSerialNumber();
+ int32_t maxMsgSize = 100;
+
+ ndk::ScopedAStatus res = sap->connectReq(serial, maxMsgSize);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+
+ // Modem side need time for connect to finish. Adding a waiting time to prevent
+ // disconnect being requested right after connect request.
+ sleep(1);
+}
+
+/*
+ * Test ISap.disconnectReq() for the response returned
+ */
+TEST_P(SapTest, disconnectReq) {
+ LOG(DEBUG) << "disconnectReq";
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = sap->disconnectReq(serial);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+ LOG(DEBUG) << "disconnectReq finished";
+}
+
+/*
+ * Test ISap.apduReq() for the response returned.
+ */
+TEST_P(SapTest, apduReq) {
+ LOG(DEBUG) << "apduReq";
+ serial = GetRandomSerialNumber();
+ SapApduType sapApduType = SapApduType::APDU;
+ std::vector<uint8_t> command = {};
+
+ ndk::ScopedAStatus res = sap->apduReq(serial, sapApduType, command);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ sapCb->sapResultCode,
+ {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_ALREADY_POWERED_OFF,
+ SapResultCode::CARD_NOT_ACCESSSIBLE, SapResultCode::CARD_REMOVED,
+ SapResultCode::SUCCESS}));
+ LOG(DEBUG) << "apduReq finished";
+}
+
+/*
+ * Test ISap.transferAtrReq() for the response returned.
+ */
+TEST_P(SapTest, transferAtrReq) {
+ LOG(DEBUG) << "transferAtrReq";
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = sap->transferAtrReq(serial);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(sapCb->sapResultCode,
+ {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE,
+ SapResultCode::CARD_ALREADY_POWERED_OFF,
+ SapResultCode::CARD_REMOVED, SapResultCode::SUCCESS}));
+ LOG(DEBUG) << "transferAtrReq finished";
+}
+
+/*
+ * Test ISap.powerReq() for the response returned.
+ */
+TEST_P(SapTest, powerReq) {
+ LOG(DEBUG) << "powerReq";
+ serial = GetRandomSerialNumber();
+ bool state = true;
+
+ ndk::ScopedAStatus res = sap->powerReq(serial, state);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+
+ ASSERT_TRUE(
+ CheckAnyOfErrors(sapCb->sapResultCode,
+ {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
+ SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED,
+ SapResultCode::CARD_ALREADY_POWERED_ON, SapResultCode::SUCCESS}));
+ LOG(DEBUG) << "powerReq finished";
+}
+
+/*
+ * Test ISap.resetSimReq() for the response returned.
+ */
+TEST_P(SapTest, resetSimReq) {
+ LOG(DEBUG) << "resetSimReq";
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = sap->resetSimReq(serial);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+
+ ASSERT_TRUE(
+ CheckAnyOfErrors(sapCb->sapResultCode,
+ {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
+ SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED,
+ SapResultCode::SUCCESS}));
+ LOG(DEBUG) << "resetSimReq finished";
+}
+
+/*
+ * Test ISap.transferCardReaderStatusReq() for the response returned.
+ */
+TEST_P(SapTest, transferCardReaderStatusReq) {
+ LOG(DEBUG) << "transferCardReaderStatusReq";
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = sap->transferCardReaderStatusReq(serial);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(sapCb->sapResultCode,
+ {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE,
+ SapResultCode::SUCCESS}));
+ LOG(DEBUG) << "transferCardReaderStatusReq finished";
+}
+
+/*
+ * Test ISap.setTransferProtocolReq() for the response returned.
+ */
+TEST_P(SapTest, setTransferProtocolReq) {
+ LOG(DEBUG) << "setTransferProtocolReq";
+ serial = GetRandomSerialNumber();
+ SapTransferProtocol sapTransferProtocol = SapTransferProtocol::T0;
+
+ ndk::ScopedAStatus res = sap->setTransferProtocolReq(serial, sapTransferProtocol);
+ ASSERT_OK(res) << res;
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(sapCb->sapResponseSerial, serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(sapCb->sapResultCode,
+ {SapResultCode::NOT_SUPPORTED, SapResultCode::SUCCESS}));
+ LOG(DEBUG) << "setTransferProtocolReq finished";
+}
diff --git a/radio/aidl/vts/radio_sap_utils.h b/radio/aidl/vts/radio_sap_utils.h
new file mode 100644
index 0000000..bf17006
--- /dev/null
+++ b/radio/aidl/vts/radio_sap_utils.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/Gtest.h>
+#include <aidl/android/hardware/radio/sap/BnSapCallback.h>
+#include <aidl/android/hardware/radio/sap/ISap.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::sap;
+
+class SapTest;
+
+/* Callback class for radio sap response */
+class SapCallback : public BnSapCallback {
+ protected:
+ SapTest& parent_sap;
+
+ public:
+ SapCallback(SapTest& parent_config);
+ virtual ~SapCallback() = default;
+
+ int32_t sapResponseSerial;
+ SapResultCode sapResultCode;
+
+ virtual ::ndk::ScopedAStatus apduResponse(int32_t serial, SapResultCode resultCode,
+ const std::vector<uint8_t>& adpuRsp) override;
+
+ virtual ::ndk::ScopedAStatus connectResponse(int32_t serial, SapConnectRsp sapConnectRsp,
+ int32_t maxMsgSize) override;
+
+ virtual ::ndk::ScopedAStatus disconnectIndication(int32_t serial,
+ SapDisconnectType sapDisconnectType) override;
+
+ virtual ::ndk::ScopedAStatus disconnectResponse(int32_t serial) override;
+
+ virtual ::ndk::ScopedAStatus errorResponse(int32_t serial) override;
+
+ virtual ::ndk::ScopedAStatus powerResponse(int32_t serial, SapResultCode resultCode) override;
+
+ virtual ::ndk::ScopedAStatus resetSimResponse(int32_t serial,
+ SapResultCode resultCode) override;
+
+ virtual ::ndk::ScopedAStatus statusIndication(int32_t serial, SapStatus sapStatus) override;
+
+ virtual ::ndk::ScopedAStatus transferAtrResponse(int32_t serial, SapResultCode resultCode,
+ const std::vector<uint8_t>& atr) override;
+
+ virtual ::ndk::ScopedAStatus transferCardReaderStatusResponse(
+ int32_t serial, SapResultCode resultCode, int32_t cardReaderStatus) override;
+
+ virtual ::ndk::ScopedAStatus transferProtocolResponse(int32_t serial,
+ SapResultCode resultCode) override;
+};
+
+// The main test class for AIDL SAP.
+class SapTest : public ::testing::TestWithParam<std::string> {
+ private:
+ std::mutex mtx;
+ std::condition_variable cv;
+ int count;
+
+ public:
+ virtual void SetUp() override;
+
+ virtual void TearDown() override;
+
+ ::testing::AssertionResult CheckAnyOfErrors(SapResultCode err,
+ std::vector<SapResultCode> errors);
+
+ /* Used as a mechanism to inform the test about data/event callback */
+ void notify(int receivedSerial);
+
+ /* Test code calls this function to wait for response */
+ std::cv_status wait();
+
+ /* Sap service */
+ std::shared_ptr<ISap> sap;
+
+ /* Sap Callback object */
+ std::shared_ptr<SapCallback> sapCb;
+
+ /* Serial for sap request */
+ int32_t serial;
+};
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index 31a17db..305383e 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -351,7 +351,7 @@
return Return<void>();
}
-Return<void> HalProxy::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /*args*/) {
+Return<void> HalProxy::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
ALOGE("%s: missing fd for writing", __FUNCTION__);
return Void();
@@ -385,7 +385,7 @@
stream << " Name: " << subHal->getName() << std::endl;
stream << " Debug dump: " << std::endl;
android::base::WriteStringToFd(stream.str(), writeFd);
- subHal->debug(fd, {});
+ subHal->debug(fd, args);
stream.str("");
stream << std::endl;
}
diff --git a/threadnetwork/OWNERS b/threadnetwork/OWNERS
new file mode 100644
index 0000000..54fd66d
--- /dev/null
+++ b/threadnetwork/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1288834
+
+include platform/packages/modules/ThreadNetwork:/OWNERS
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
index cf68fc6..a419207 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
@@ -34,16 +34,5 @@
package android.hardware.wifi;
@VintfStability
parcelable StaLinkLayerIfaceStats {
- int beaconRx;
- int avgRssiMgmt;
- android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBePktStats;
- android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBkPktStats;
- android.hardware.wifi.StaLinkLayerIfacePacketStats wmeViPktStats;
- android.hardware.wifi.StaLinkLayerIfacePacketStats wmeVoPktStats;
- byte timeSliceDutyCycleInPercent;
- android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats;
- android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats;
- android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats;
- android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats;
- android.hardware.wifi.StaPeerInfo[] peers;
+ android.hardware.wifi.StaLinkLayerLinkStats[] links;
}
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerLinkStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerLinkStats.aidl
new file mode 100644
index 0000000..2bc3254
--- /dev/null
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerLinkStats.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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 StaLinkLayerLinkStats {
+ int linkId;
+ int radioId;
+ int frequencyMhz;
+ int beaconRx;
+ int avgRssiMgmt;
+ android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBePktStats;
+ android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBkPktStats;
+ android.hardware.wifi.StaLinkLayerIfacePacketStats wmeViPktStats;
+ android.hardware.wifi.StaLinkLayerIfacePacketStats wmeVoPktStats;
+ byte timeSliceDutyCycleInPercent;
+ android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats;
+ android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats;
+ android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats;
+ android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats;
+ android.hardware.wifi.StaPeerInfo[] peers;
+}
diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
index 78f8caa..3f8718f 100644
--- a/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
+++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl
@@ -16,64 +16,13 @@
package android.hardware.wifi;
-import android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats;
-import android.hardware.wifi.StaLinkLayerIfacePacketStats;
-import android.hardware.wifi.StaPeerInfo;
+import android.hardware.wifi.StaLinkLayerLinkStats;
/**
- * Iface statistics for the current connection.
+ * Iface statistics for the current connection. Current connection may have
+ * single or multiple links.
*/
@VintfStability
parcelable StaLinkLayerIfaceStats {
- /**
- * Number beacons received from the connected AP.
- */
- int beaconRx;
- /**
- * Access Point Beacon and Management frames RSSI (averaged).
- */
- int avgRssiMgmt;
- /**
- * WME Best Effort Access Category packet counters.
- */
- StaLinkLayerIfacePacketStats wmeBePktStats;
- /**
- * WME Background Access Category packet counters.
- */
- StaLinkLayerIfacePacketStats wmeBkPktStats;
- /**
- * WME Video Access Category packet counters.
- */
- StaLinkLayerIfacePacketStats wmeViPktStats;
- /**
- * WME Voice Access Category packet counters.
- */
- StaLinkLayerIfacePacketStats wmeVoPktStats;
- /**
- * Duty cycle for the iface.
- * If this iface is being served using time slicing on a radio with one or more ifaces
- * (i.e MCC), then the duty cycle assigned to this iface in %.
- * If not using time slicing (i.e SCC or DBS), set to 100.
- */
- byte timeSliceDutyCycleInPercent;
- /**
- * WME Best Effort (BE) Access Category (AC) contention time statistics.
- */
- StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats;
- /**
- * WME Background (BK) Access Category (AC) contention time statistics.
- */
- StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats;
- /**
- * WME Video (VI) Access Category (AC) contention time statistics.
- */
- StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats;
- /**
- * WME Voice (VO) Access Category (AC) contention time statistics.
- */
- StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats;
- /**
- * Per peer statistics.
- */
- StaPeerInfo[] peers;
+ StaLinkLayerLinkStats[] links;
}
diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerLinkStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerLinkStats.aidl
new file mode 100644
index 0000000..d8d7975
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerLinkStats.aidl
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats;
+import android.hardware.wifi.StaLinkLayerIfacePacketStats;
+import android.hardware.wifi.StaPeerInfo;
+
+/**
+ * Per Link statistics for the current connection. For MLO, this is
+ * the statistics for one link in the connection.
+ */
+@VintfStability
+parcelable StaLinkLayerLinkStats {
+ /**
+ * Identifier for the link within MLO. For single link operation this field
+ * is not relevant and can be set to 0.
+ */
+ int linkId;
+ /**
+ * Radio identifier on which the link is currently operating. Refer
+ * |StaLinkLayerRadioStats.radioId|.
+ */
+ int radioId;
+ /**
+ * Frequency of the link in Mhz.
+ */
+ int frequencyMhz;
+ /**
+ * Number of beacons received from the connected AP on the link.
+ */
+ int beaconRx;
+ /**
+ * Access Point Beacon and Management frames RSSI (averaged) on the link.
+ */
+ int avgRssiMgmt;
+ /**
+ * WME Best Effort Access Category packet counters on the link.
+ */
+ StaLinkLayerIfacePacketStats wmeBePktStats;
+ /**
+ * WME Background Access Category packet counters on the link.
+ */
+ StaLinkLayerIfacePacketStats wmeBkPktStats;
+ /**
+ * WME Video Access Category packet counters on the link.
+ */
+ StaLinkLayerIfacePacketStats wmeViPktStats;
+ /**
+ * WME Voice Access Category packet counters on the link.
+ */
+ StaLinkLayerIfacePacketStats wmeVoPktStats;
+ /**
+ * Duty cycle for the link.
+ * If this link is being served using time slicing on a radio with one or
+ * more links then the duty cycle assigned to this link in %. If not using
+ * time slicing, set to 100.
+ */
+ byte timeSliceDutyCycleInPercent;
+ /**
+ * WME Best Effort (BE) Access Category (AC) contention time statistics on
+ * the link.
+ */
+ StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats;
+ /**
+ * WME Background (BK) Access Category (AC) contention time statistics on
+ * the link.
+ */
+ StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats;
+ /**
+ * WME Video (VI) Access Category (AC) contention time statistics on the
+ * link.
+ */
+ StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats;
+ /**
+ * WME Voice (VO) Access Category (AC) contention time statistics on the
+ * link.
+ */
+ StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats;
+ /**
+ * Per peer statistics for the link.
+ */
+ StaPeerInfo[] peers;
+}
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index ec8b396..3087d66 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -940,69 +940,160 @@
return true;
}
+bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& legacy_ml_stats,
+ StaLinkLayerStats* aidl_stats) {
+ if (!aidl_stats) {
+ return false;
+ }
+ *aidl_stats = {};
+ std::vector<StaLinkLayerLinkStats> links;
+ // Iterate over each links
+ for (const auto& link : legacy_ml_stats.links) {
+ StaLinkLayerLinkStats linkStats = {};
+ linkStats.linkId = link.stat.link_id;
+ linkStats.radioId = link.stat.radio;
+ linkStats.frequencyMhz = link.stat.frequency;
+ linkStats.beaconRx = link.stat.beacon_rx;
+ linkStats.avgRssiMgmt = link.stat.rssi_mgmt;
+ linkStats.wmeBePktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
+ linkStats.wmeBePktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
+ linkStats.wmeBePktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
+ linkStats.wmeBePktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_BE].retries;
+ linkStats.wmeBeContentionTimeStats.contentionTimeMinInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_min;
+ linkStats.wmeBeContentionTimeStats.contentionTimeMaxInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_max;
+ linkStats.wmeBeContentionTimeStats.contentionTimeAvgInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_avg;
+ linkStats.wmeBeContentionTimeStats.contentionNumSamples =
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_num_samples;
+ linkStats.wmeBkPktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
+ linkStats.wmeBkPktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
+ linkStats.wmeBkPktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
+ linkStats.wmeBkPktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_BK].retries;
+ linkStats.wmeBkContentionTimeStats.contentionTimeMinInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_min;
+ linkStats.wmeBkContentionTimeStats.contentionTimeMaxInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_max;
+ linkStats.wmeBkContentionTimeStats.contentionTimeAvgInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_avg;
+ linkStats.wmeBkContentionTimeStats.contentionNumSamples =
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_num_samples;
+ linkStats.wmeViPktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
+ linkStats.wmeViPktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
+ linkStats.wmeViPktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
+ linkStats.wmeViPktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_VI].retries;
+ linkStats.wmeViContentionTimeStats.contentionTimeMinInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_min;
+ linkStats.wmeViContentionTimeStats.contentionTimeMaxInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_max;
+ linkStats.wmeViContentionTimeStats.contentionTimeAvgInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_avg;
+ linkStats.wmeViContentionTimeStats.contentionNumSamples =
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_num_samples;
+ linkStats.wmeVoPktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
+ linkStats.wmeVoPktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
+ linkStats.wmeVoPktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
+ linkStats.wmeVoPktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_VO].retries;
+ linkStats.wmeVoContentionTimeStats.contentionTimeMinInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_min;
+ linkStats.wmeVoContentionTimeStats.contentionTimeMaxInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_max;
+ linkStats.wmeVoContentionTimeStats.contentionTimeAvgInUsec =
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_avg;
+ linkStats.wmeVoContentionTimeStats.contentionNumSamples =
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_num_samples;
+ linkStats.timeSliceDutyCycleInPercent = link.stat.time_slicing_duty_cycle_percent;
+ // peer info legacy_stats conversion.
+ std::vector<StaPeerInfo> aidl_peers_info_stats;
+ for (const auto& legacy_peer_info_stats : link.peers) {
+ StaPeerInfo aidl_peer_info_stats;
+ if (!convertLegacyPeerInfoStatsToAidl(legacy_peer_info_stats, &aidl_peer_info_stats)) {
+ return false;
+ }
+ aidl_peers_info_stats.push_back(aidl_peer_info_stats);
+ }
+ linkStats.peers = aidl_peers_info_stats;
+ // Push link stats to aidl stats.
+ links.push_back(linkStats);
+ }
+ aidl_stats->iface.links = links;
+ // radio legacy_stats conversion.
+ std::vector<StaLinkLayerRadioStats> aidl_radios_stats;
+ for (const auto& legacy_radio_stats : legacy_ml_stats.radios) {
+ StaLinkLayerRadioStats aidl_radio_stats;
+ if (!convertLegacyLinkLayerRadioStatsToAidl(legacy_radio_stats, &aidl_radio_stats)) {
+ return false;
+ }
+ aidl_radios_stats.push_back(aidl_radio_stats);
+ }
+ aidl_stats->radios = aidl_radios_stats;
+ aidl_stats->timeStampInMs = ::android::uptimeMillis();
+
+ return true;
+}
+
bool convertLegacyLinkLayerStatsToAidl(const legacy_hal::LinkLayerStats& legacy_stats,
StaLinkLayerStats* aidl_stats) {
if (!aidl_stats) {
return false;
}
*aidl_stats = {};
+ std::vector<StaLinkLayerLinkStats> links;
+ StaLinkLayerLinkStats linkStats = {};
// iface legacy_stats conversion.
- aidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx;
- aidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
- aidl_stats->iface.wmeBePktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
- aidl_stats->iface.wmeBePktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
- aidl_stats->iface.wmeBePktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
- aidl_stats->iface.wmeBePktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
- aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec =
+ linkStats.linkId = 0;
+ linkStats.beaconRx = legacy_stats.iface.beacon_rx;
+ linkStats.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
+ linkStats.wmeBePktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
+ linkStats.wmeBePktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
+ linkStats.wmeBePktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
+ linkStats.wmeBePktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
+ linkStats.wmeBeContentionTimeStats.contentionTimeMinInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min;
- aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec =
+ linkStats.wmeBeContentionTimeStats.contentionTimeMaxInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max;
- aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec =
+ linkStats.wmeBeContentionTimeStats.contentionTimeAvgInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg;
- aidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples =
+ linkStats.wmeBeContentionTimeStats.contentionNumSamples =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples;
- aidl_stats->iface.wmeBkPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
- aidl_stats->iface.wmeBkPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
- aidl_stats->iface.wmeBkPktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
- aidl_stats->iface.wmeBkPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
- aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec =
+ linkStats.wmeBkPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
+ linkStats.wmeBkPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
+ linkStats.wmeBkPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
+ linkStats.wmeBkPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
+ linkStats.wmeBkContentionTimeStats.contentionTimeMinInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min;
- aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec =
+ linkStats.wmeBkContentionTimeStats.contentionTimeMaxInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max;
- aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec =
+ linkStats.wmeBkContentionTimeStats.contentionTimeAvgInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg;
- aidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples =
+ linkStats.wmeBkContentionTimeStats.contentionNumSamples =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples;
- aidl_stats->iface.wmeViPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
- aidl_stats->iface.wmeViPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
- aidl_stats->iface.wmeViPktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
- aidl_stats->iface.wmeViPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
- aidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec =
+ linkStats.wmeViPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
+ linkStats.wmeViPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
+ linkStats.wmeViPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
+ linkStats.wmeViPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
+ linkStats.wmeViContentionTimeStats.contentionTimeMinInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min;
- aidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec =
+ linkStats.wmeViContentionTimeStats.contentionTimeMaxInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max;
- aidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec =
+ linkStats.wmeViContentionTimeStats.contentionTimeAvgInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg;
- aidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples =
+ linkStats.wmeViContentionTimeStats.contentionNumSamples =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples;
- aidl_stats->iface.wmeVoPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
- aidl_stats->iface.wmeVoPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
- aidl_stats->iface.wmeVoPktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
- aidl_stats->iface.wmeVoPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
- aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec =
+ linkStats.wmeVoPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
+ linkStats.wmeVoPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
+ linkStats.wmeVoPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
+ linkStats.wmeVoPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
+ linkStats.wmeVoContentionTimeStats.contentionTimeMinInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min;
- aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec =
+ linkStats.wmeVoContentionTimeStats.contentionTimeMaxInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max;
- aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec =
+ linkStats.wmeVoContentionTimeStats.contentionTimeAvgInUsec =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg;
- aidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples =
+ linkStats.wmeVoContentionTimeStats.contentionNumSamples =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples;
- aidl_stats->iface.timeSliceDutyCycleInPercent =
- legacy_stats.iface.info.time_slicing_duty_cycle_percent;
+ linkStats.timeSliceDutyCycleInPercent = legacy_stats.iface.info.time_slicing_duty_cycle_percent;
// peer info legacy_stats conversion.
std::vector<StaPeerInfo> aidl_peers_info_stats;
for (const auto& legacy_peer_info_stats : legacy_stats.peers) {
@@ -1012,7 +1103,9 @@
}
aidl_peers_info_stats.push_back(aidl_peer_info_stats);
}
- aidl_stats->iface.peers = aidl_peers_info_stats;
+ linkStats.peers = aidl_peers_info_stats;
+ links.push_back(linkStats);
+ aidl_stats->iface.links = links;
// radio legacy_stats conversion.
std::vector<StaLinkLayerRadioStats> aidl_radios_stats;
for (const auto& legacy_radio_stats : legacy_stats.radios) {
diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h
index d8e1fd4..ac86755 100644
--- a/wifi/aidl/default/aidl_struct_util.h
+++ b/wifi/aidl/default/aidl_struct_util.h
@@ -89,6 +89,8 @@
bool convertLegacyVectorOfCachedGscanResultsToAidl(
const std::vector<legacy_hal::wifi_cached_scan_results>& legacy_cached_scan_results,
std::vector<StaScanData>* aidl_scan_datas);
+bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& legacy_ml_stats,
+ StaLinkLayerStats* aidl_stats);
bool convertLegacyLinkLayerStatsToAidl(const legacy_hal::LinkLayerStats& legacy_stats,
StaLinkLayerStats* aidl_stats);
bool convertLegacyRoamingCapabilitiesToAidl(
diff --git a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
index 4a69c24..df788b8 100644
--- a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
+++ b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
@@ -112,6 +112,290 @@
EXPECT_EQ(static_cast<int32_t>(legacy_iface_info2.channel), aidl_iface_info2.channel);
}
+TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerMlStatsToAidl) {
+ legacy_hal::LinkLayerMlStats legacy_ml_stats{};
+ // Add two radio stats
+ legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ // Add two links.
+ legacy_ml_stats.links.push_back(legacy_hal::LinkStats{});
+ legacy_ml_stats.links.push_back(legacy_hal::LinkStats{});
+ // Set stats for each link.
+ for (legacy_hal::LinkStats& link : legacy_ml_stats.links) {
+ link.peers.push_back(legacy_hal::WifiPeerInfo{});
+ link.peers.push_back(legacy_hal::WifiPeerInfo{});
+ link.stat.beacon_rx = rand();
+ link.stat.link_id = rand() % 15;
+ link.stat.radio = rand() % 4;
+ link.stat.frequency = rand();
+ link.stat.rssi_mgmt = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].retries = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_min = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_max = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_avg = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BE].contention_num_samples = rand();
+
+ link.stat.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BK].retries = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_min = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_max = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_avg = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_BK].contention_num_samples = rand();
+
+ link.stat.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VI].retries = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_min = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_max = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_avg = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VI].contention_num_samples = rand();
+
+ link.stat.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VO].retries = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_min = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_max = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_avg = rand();
+ link.stat.ac[legacy_hal::WIFI_AC_VO].contention_num_samples = rand();
+
+ link.stat.time_slicing_duty_cycle_percent = rand();
+ link.stat.num_peers = 2;
+
+ // Set peer stats for each of the peers.
+ for (auto& peer : link.peers) {
+ peer.peer_info.bssload.sta_count = rand();
+ peer.peer_info.bssload.chan_util = rand();
+ wifi_rate_stat rate_stat1 = {
+ .rate = {3, 1, 2, 5, 0, 0},
+ .tx_mpdu = 0,
+ .rx_mpdu = 1,
+ .mpdu_lost = 2,
+ .retries = 3,
+ .retries_short = 4,
+ .retries_long = 5,
+ };
+ wifi_rate_stat rate_stat2 = {
+ .rate = {2, 2, 1, 6, 0, 1},
+ .tx_mpdu = 6,
+ .rx_mpdu = 7,
+ .mpdu_lost = 8,
+ .retries = 9,
+ .retries_short = 10,
+ .retries_long = 11,
+ };
+ peer.rate_stats.push_back(rate_stat1);
+ peer.rate_stats.push_back(rate_stat2);
+ }
+ }
+ // Set radio stats
+ for (auto& radio : legacy_ml_stats.radios) {
+ radio.stats.radio = rand();
+ radio.stats.on_time = rand();
+ radio.stats.tx_time = rand();
+ radio.stats.rx_time = rand();
+ radio.stats.on_time_scan = rand();
+ radio.stats.on_time_nbd = rand();
+ radio.stats.on_time_gscan = rand();
+ radio.stats.on_time_roam_scan = rand();
+ radio.stats.on_time_pno_scan = rand();
+ radio.stats.on_time_hs20 = rand();
+ for (int i = 0; i < 4; i++) {
+ radio.tx_time_per_levels.push_back(rand());
+ }
+
+ legacy_hal::wifi_channel_stat channel_stat1 = {
+ .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 2437, 2437, 0},
+ .on_time = 0x1111,
+ .cca_busy_time = 0x55,
+ };
+ legacy_hal::wifi_channel_stat channel_stat2 = {
+ .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 5180, 5180, 0},
+ .on_time = 0x2222,
+ .cca_busy_time = 0x66,
+ };
+ radio.channel_stats.push_back(channel_stat1);
+ radio.channel_stats.push_back(channel_stat2);
+ }
+ // Convert to AIDL
+ StaLinkLayerStats converted{};
+ aidl_struct_util::convertLegacyLinkLayerMlStatsToAidl(legacy_ml_stats, &converted);
+ // Validate
+ int l = 0;
+ for (legacy_hal::LinkStats& link : legacy_ml_stats.links) {
+ EXPECT_EQ(link.stat.link_id, (uint8_t)converted.iface.links[l].linkId);
+ EXPECT_EQ(link.stat.radio, converted.iface.links[l].radioId);
+ EXPECT_EQ(link.stat.frequency, (uint32_t)converted.iface.links[l].frequencyMhz);
+ EXPECT_EQ(link.stat.beacon_rx, (uint32_t)converted.iface.links[l].beaconRx);
+ EXPECT_EQ(link.stat.rssi_mgmt, converted.iface.links[l].avgRssiMgmt);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
+ converted.iface.links[l].wmeBePktStats.rxMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
+ converted.iface.links[l].wmeBePktStats.txMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
+ converted.iface.links[l].wmeBePktStats.lostMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].retries,
+ converted.iface.links[l].wmeBePktStats.retries);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_min,
+ (uint32_t)converted.iface.links[l]
+ .wmeBeContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_max,
+ (uint32_t)converted.iface.links[l]
+ .wmeBeContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_avg,
+ (uint32_t)converted.iface.links[l]
+ .wmeBeContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_num_samples,
+ (uint32_t)converted.iface.links[l].wmeBeContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
+ converted.iface.links[l].wmeBkPktStats.rxMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
+ converted.iface.links[l].wmeBkPktStats.txMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
+ converted.iface.links[l].wmeBkPktStats.lostMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].retries,
+ converted.iface.links[l].wmeBkPktStats.retries);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_min,
+ (uint32_t)converted.iface.links[l]
+ .wmeBkContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_max,
+ (uint32_t)converted.iface.links[l]
+ .wmeBkContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_avg,
+ (uint32_t)converted.iface.links[l]
+ .wmeBkContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_num_samples,
+ (uint32_t)converted.iface.links[l].wmeBkContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
+ converted.iface.links[l].wmeViPktStats.rxMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
+ converted.iface.links[l].wmeViPktStats.txMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
+ converted.iface.links[l].wmeViPktStats.lostMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].retries,
+ converted.iface.links[l].wmeViPktStats.retries);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_min,
+ (uint32_t)converted.iface.links[l]
+ .wmeViContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_max,
+ (uint32_t)converted.iface.links[l]
+ .wmeViContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_avg,
+ (uint32_t)converted.iface.links[l]
+ .wmeViContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_num_samples,
+ (uint32_t)converted.iface.links[l].wmeViContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
+ converted.iface.links[l].wmeVoPktStats.rxMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
+ converted.iface.links[l].wmeVoPktStats.txMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
+ converted.iface.links[l].wmeVoPktStats.lostMpdu);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].retries,
+ converted.iface.links[l].wmeVoPktStats.retries);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_min,
+ (uint32_t)converted.iface.links[l]
+ .wmeVoContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_max,
+ (uint32_t)converted.iface.links[l]
+ .wmeVoContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_avg,
+ (uint32_t)converted.iface.links[l]
+ .wmeVoContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_num_samples,
+ (uint32_t)converted.iface.links[l].wmeVoContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(link.stat.time_slicing_duty_cycle_percent,
+ converted.iface.links[l].timeSliceDutyCycleInPercent);
+
+ EXPECT_EQ(link.peers.size(), converted.iface.links[l].peers.size());
+ for (size_t i = 0; i < link.peers.size(); i++) {
+ EXPECT_EQ(link.peers[i].peer_info.bssload.sta_count,
+ converted.iface.links[l].peers[i].staCount);
+ EXPECT_EQ(link.peers[i].peer_info.bssload.chan_util,
+ converted.iface.links[l].peers[i].chanUtil);
+ for (size_t j = 0; j < link.peers[i].rate_stats.size(); j++) {
+ EXPECT_EQ(
+ link.peers[i].rate_stats[j].rate.preamble,
+ (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rateInfo.preamble);
+ EXPECT_EQ(link.peers[i].rate_stats[j].rate.nss,
+ (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rateInfo.nss);
+ EXPECT_EQ(link.peers[i].rate_stats[j].rate.bw,
+ (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rateInfo.bw);
+ EXPECT_EQ(link.peers[i].rate_stats[j].rate.rateMcsIdx,
+ (uint32_t)converted.iface.links[l]
+ .peers[i]
+ .rateStats[j]
+ .rateInfo.rateMcsIdx);
+ EXPECT_EQ(link.peers[i].rate_stats[j].tx_mpdu,
+ (uint32_t)converted.iface.links[l].peers[i].rateStats[j].txMpdu);
+ EXPECT_EQ(link.peers[i].rate_stats[j].rx_mpdu,
+ (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rxMpdu);
+ EXPECT_EQ(link.peers[i].rate_stats[j].mpdu_lost,
+ (uint32_t)converted.iface.links[l].peers[i].rateStats[j].mpduLost);
+ EXPECT_EQ(link.peers[i].rate_stats[j].retries,
+ (uint32_t)converted.iface.links[l].peers[i].rateStats[j].retries);
+ }
+ }
+ ++l;
+ } // loop over links
+
+ EXPECT_EQ(legacy_ml_stats.radios.size(), converted.radios.size());
+ for (size_t i = 0; i < legacy_ml_stats.radios.size(); i++) {
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.radio, converted.radios[i].radioId);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time,
+ (uint32_t)converted.radios[i].onTimeInMs);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.tx_time,
+ (uint32_t)converted.radios[i].txTimeInMs);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.rx_time,
+ (uint32_t)converted.radios[i].rxTimeInMs);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_scan,
+ (uint32_t)converted.radios[i].onTimeInMsForScan);
+ EXPECT_EQ(legacy_ml_stats.radios[i].tx_time_per_levels.size(),
+ converted.radios[i].txTimeInMsPerLevel.size());
+ for (size_t j = 0; j < legacy_ml_stats.radios[i].tx_time_per_levels.size(); j++) {
+ EXPECT_EQ(legacy_ml_stats.radios[i].tx_time_per_levels[j],
+ (uint32_t)converted.radios[i].txTimeInMsPerLevel[j]);
+ }
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_nbd,
+ (uint32_t)converted.radios[i].onTimeInMsForNanScan);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_gscan,
+ (uint32_t)converted.radios[i].onTimeInMsForBgScan);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_roam_scan,
+ (uint32_t)converted.radios[i].onTimeInMsForRoamScan);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_pno_scan,
+ (uint32_t)converted.radios[i].onTimeInMsForPnoScan);
+ EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_hs20,
+ (uint32_t)converted.radios[i].onTimeInMsForHs20Scan);
+ EXPECT_EQ(legacy_ml_stats.radios[i].channel_stats.size(),
+ converted.radios[i].channelStats.size());
+ for (size_t k = 0; k < legacy_ml_stats.radios[i].channel_stats.size(); k++) {
+ auto& legacy_channel_st = legacy_ml_stats.radios[i].channel_stats[k];
+ EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20,
+ converted.radios[i].channelStats[k].channel.width);
+ EXPECT_EQ(legacy_channel_st.channel.center_freq,
+ converted.radios[i].channelStats[k].channel.centerFreq);
+ EXPECT_EQ(legacy_channel_st.channel.center_freq0,
+ converted.radios[i].channelStats[k].channel.centerFreq0);
+ EXPECT_EQ(legacy_channel_st.channel.center_freq1,
+ converted.radios[i].channelStats[k].channel.centerFreq1);
+ EXPECT_EQ(legacy_channel_st.cca_busy_time,
+ (uint32_t)converted.radios[i].channelStats[k].ccaBusyTimeInMs);
+ EXPECT_EQ(legacy_channel_st.on_time,
+ (uint32_t)converted.radios[i].channelStats[k].onTimeInMs);
+ }
+ }
+}
+
TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerStatsToAidl) {
legacy_hal::LinkLayerStats legacy_stats{};
legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
@@ -215,78 +499,79 @@
StaLinkLayerStats converted{};
aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &converted);
- EXPECT_EQ(legacy_stats.iface.beacon_rx, (uint32_t)converted.iface.beaconRx);
- EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt);
+ EXPECT_EQ(0, converted.iface.links[0].linkId);
+ EXPECT_EQ(legacy_stats.iface.beacon_rx, (uint32_t)converted.iface.links[0].beaconRx);
+ EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.links[0].avgRssiMgmt);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
- converted.iface.wmeBePktStats.rxMpdu);
+ converted.iface.links[0].wmeBePktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
- converted.iface.wmeBePktStats.txMpdu);
+ converted.iface.links[0].wmeBePktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
- converted.iface.wmeBePktStats.lostMpdu);
+ converted.iface.links[0].wmeBePktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries,
- converted.iface.wmeBePktStats.retries);
+ converted.iface.links[0].wmeBePktStats.retries);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min,
- (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeMinInUsec);
+ (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionTimeMinInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max,
- (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec);
+ (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionTimeMaxInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg,
- (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec);
+ (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionTimeAvgInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples,
- (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionNumSamples);
+ (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionNumSamples);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
- converted.iface.wmeBkPktStats.rxMpdu);
+ converted.iface.links[0].wmeBkPktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
- converted.iface.wmeBkPktStats.txMpdu);
+ converted.iface.links[0].wmeBkPktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
- converted.iface.wmeBkPktStats.lostMpdu);
+ converted.iface.links[0].wmeBkPktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries,
- converted.iface.wmeBkPktStats.retries);
+ converted.iface.links[0].wmeBkPktStats.retries);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min,
- (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeMinInUsec);
+ (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionTimeMinInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max,
- (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec);
+ (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionTimeMaxInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg,
- (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec);
+ (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionTimeAvgInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples,
- (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionNumSamples);
+ (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionNumSamples);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
- converted.iface.wmeViPktStats.rxMpdu);
+ converted.iface.links[0].wmeViPktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
- converted.iface.wmeViPktStats.txMpdu);
+ converted.iface.links[0].wmeViPktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
- converted.iface.wmeViPktStats.lostMpdu);
+ converted.iface.links[0].wmeViPktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries,
- converted.iface.wmeViPktStats.retries);
+ converted.iface.links[0].wmeViPktStats.retries);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min,
- (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeMinInUsec);
+ (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionTimeMinInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max,
- (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeMaxInUsec);
+ (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionTimeMaxInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg,
- (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeAvgInUsec);
+ (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionTimeAvgInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples,
- (uint32_t)converted.iface.wmeViContentionTimeStats.contentionNumSamples);
+ (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionNumSamples);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
- converted.iface.wmeVoPktStats.rxMpdu);
+ converted.iface.links[0].wmeVoPktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
- converted.iface.wmeVoPktStats.txMpdu);
+ converted.iface.links[0].wmeVoPktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
- converted.iface.wmeVoPktStats.lostMpdu);
+ converted.iface.links[0].wmeVoPktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries,
- converted.iface.wmeVoPktStats.retries);
+ converted.iface.links[0].wmeVoPktStats.retries);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min,
- (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeMinInUsec);
+ (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionTimeMinInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max,
- (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec);
+ (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionTimeMaxInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg,
- (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec);
+ (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionTimeAvgInUsec);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples,
- (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionNumSamples);
+ (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionNumSamples);
EXPECT_EQ(legacy_stats.iface.info.time_slicing_duty_cycle_percent,
- converted.iface.timeSliceDutyCycleInPercent);
+ converted.iface.links[0].timeSliceDutyCycleInPercent);
EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
for (size_t i = 0; i < legacy_stats.radios.size(); i++) {
@@ -331,29 +616,29 @@
}
}
- EXPECT_EQ(legacy_stats.peers.size(), converted.iface.peers.size());
+ EXPECT_EQ(legacy_stats.peers.size(), converted.iface.links[0].peers.size());
for (size_t i = 0; i < legacy_stats.peers.size(); i++) {
EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.sta_count,
- converted.iface.peers[i].staCount);
+ converted.iface.links[0].peers[i].staCount);
EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.chan_util,
- converted.iface.peers[i].chanUtil);
+ converted.iface.links[0].peers[i].chanUtil);
for (size_t j = 0; j < legacy_stats.peers[i].rate_stats.size(); j++) {
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.preamble,
- (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.preamble);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.preamble);
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.nss,
- (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.nss);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.nss);
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.bw,
- (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.bw);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.bw);
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.rateMcsIdx,
- (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.rateMcsIdx);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.rateMcsIdx);
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].tx_mpdu,
- (uint32_t)converted.iface.peers[i].rateStats[j].txMpdu);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].txMpdu);
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rx_mpdu,
- (uint32_t)converted.iface.peers[i].rateStats[j].rxMpdu);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rxMpdu);
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].mpdu_lost,
- (uint32_t)converted.iface.peers[i].rateStats[j].mpduLost);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].mpduLost);
EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].retries,
- (uint32_t)converted.iface.peers[i].rateStats[j].retries);
+ (uint32_t)converted.iface.links[0].peers[i].rateStats[j].retries);
}
}
}
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
index e4883d1..83f368e 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -119,6 +119,16 @@
}
}
+// Callback to be invoked for Multi link layer stats results.
+std::function<void((wifi_request_id, wifi_iface_ml_stat*, int, wifi_radio_stat*))>
+ on_link_layer_ml_stats_result_internal_callback;
+void onSyncLinkLayerMlStatsResult(wifi_request_id id, wifi_iface_ml_stat* iface_ml_stat,
+ int num_radios, wifi_radio_stat* radio_stat) {
+ if (on_link_layer_ml_stats_result_internal_callback) {
+ on_link_layer_ml_stats_result_internal_callback(id, iface_ml_stat, num_radios, radio_stat);
+ }
+}
+
// Callback to be invoked for rssi threshold breach.
std::function<void((wifi_request_id, uint8_t*, int8_t))>
on_rssi_threshold_breached_internal_callback;
@@ -682,10 +692,44 @@
&clear_mask_rsp, 1, &stop_rsp);
}
-std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats(
- const std::string& iface_name) {
- LinkLayerStats link_stats{};
+// Copies wifi_peer_info* to vector<WifiPeerInfo> and returns poiner to next element.
+wifi_peer_info* WifiLegacyHal::copyPeerInfo(wifi_peer_info* peer_ptr,
+ std::vector<WifiPeerInfo> peers) {
+ WifiPeerInfo peer;
+ peer.peer_info = *peer_ptr;
+ if (peer_ptr->num_rate > 0) {
+ // Copy the rate stats.
+ peer.rate_stats.assign(peer_ptr->rate_stats, peer_ptr->rate_stats + peer_ptr->num_rate);
+ }
+ peer.peer_info.num_rate = 0;
+ // Push peer info.
+ peers.push_back(peer);
+ // Return the address of next peer info.
+ return (wifi_peer_info*)((u8*)peer_ptr + sizeof(wifi_peer_info) +
+ (sizeof(wifi_rate_stat) * peer_ptr->num_rate));
+}
+// Copies wifi_link_stat* to vector<LinkStats> and returns poiner to next element.
+wifi_link_stat* WifiLegacyHal::copyLinkStat(wifi_link_stat* stat_ptr,
+ std::vector<LinkStats> stats) {
+ LinkStats linkStat;
+ linkStat.stat = *stat_ptr;
+ wifi_peer_info* l_peer_info_stats_ptr = stat_ptr->peer_info;
+ for (uint32_t i = 0; i < linkStat.stat.num_peers; i++) {
+ l_peer_info_stats_ptr = copyPeerInfo(l_peer_info_stats_ptr, linkStat.peers);
+ }
+ // Copied all peers to linkStat.peers.
+ linkStat.stat.num_peers = 0;
+ // Push link stat.
+ stats.push_back(linkStat);
+ // Read all peers, return the address of next wifi_link_stat.
+ return (wifi_link_stat*)l_peer_info_stats_ptr;
+}
+
+wifi_error WifiLegacyHal::getLinkLayerStats(const std::string& iface_name,
+ LinkLayerStats& link_stats,
+ LinkLayerMlStats& link_ml_stats) {
LinkLayerStats* link_stats_ptr = &link_stats;
+ link_stats_ptr->valid = false;
on_link_layer_stats_result_internal_callback = [&link_stats_ptr](
wifi_request_id /* id */,
@@ -694,6 +738,7 @@
wifi_radio_stat* radio_stats_ptr) {
wifi_radio_stat* l_radio_stats_ptr;
wifi_peer_info* l_peer_info_stats_ptr;
+ link_stats_ptr->valid = true;
if (iface_stats_ptr != nullptr) {
link_stats_ptr->iface = *iface_stats_ptr;
@@ -751,10 +796,69 @@
}
};
- wifi_error status = global_func_table_.wifi_get_link_stats(0, getIfaceHandle(iface_name),
- {onSyncLinkLayerStatsResult});
+ LinkLayerMlStats* link_ml_stats_ptr = &link_ml_stats;
+ link_ml_stats_ptr->valid = false;
+
+ on_link_layer_ml_stats_result_internal_callback =
+ [this, &link_ml_stats_ptr](wifi_request_id /* id */,
+ wifi_iface_ml_stat* iface_ml_stats_ptr, int num_radios,
+ wifi_radio_stat* radio_stats_ptr) {
+ wifi_radio_stat* l_radio_stats_ptr;
+ wifi_link_stat* l_link_stat_ptr;
+ link_ml_stats_ptr->valid = true;
+
+ if (iface_ml_stats_ptr != nullptr && iface_ml_stats_ptr->num_links > 0) {
+ // Copy stats from wifi_iface_ml_stat to LinkLayerMlStats,
+ // - num_links * links[] to vector of links.
+ // - num_peers * peer_info[] to vector of links[i].peers.
+ link_ml_stats_ptr->iface = *iface_ml_stats_ptr;
+ l_link_stat_ptr = iface_ml_stats_ptr->links;
+ for (int l = 0; l < iface_ml_stats_ptr->num_links; ++l) {
+ l_link_stat_ptr = copyLinkStat(l_link_stat_ptr, link_ml_stats_ptr->links);
+ }
+ } else {
+ LOG(ERROR) << "Invalid iface stats in link layer stats";
+ }
+ if (num_radios <= 0 || radio_stats_ptr == nullptr) {
+ LOG(ERROR) << "Invalid radio stats in link layer stats";
+ return;
+ }
+ l_radio_stats_ptr = radio_stats_ptr;
+ for (int i = 0; i < num_radios; i++) {
+ LinkLayerRadioStats radio;
+
+ radio.stats = *l_radio_stats_ptr;
+ // Copy over the tx level array to the separate vector.
+ if (l_radio_stats_ptr->num_tx_levels > 0 &&
+ l_radio_stats_ptr->tx_time_per_levels != nullptr) {
+ radio.tx_time_per_levels.assign(l_radio_stats_ptr->tx_time_per_levels,
+ l_radio_stats_ptr->tx_time_per_levels +
+ l_radio_stats_ptr->num_tx_levels);
+ }
+ radio.stats.num_tx_levels = 0;
+ radio.stats.tx_time_per_levels = nullptr;
+ /* Copy over the channel stat to separate vector */
+ if (l_radio_stats_ptr->num_channels > 0) {
+ /* Copy the channel stats */
+ radio.channel_stats.assign(
+ l_radio_stats_ptr->channels,
+ l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels);
+ }
+ link_ml_stats_ptr->radios.push_back(radio);
+ l_radio_stats_ptr =
+ (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) +
+ (sizeof(wifi_channel_stat) *
+ l_radio_stats_ptr->num_channels));
+ }
+ };
+
+ wifi_error status = global_func_table_.wifi_get_link_stats(
+ 0, getIfaceHandle(iface_name),
+ {onSyncLinkLayerStatsResult, onSyncLinkLayerMlStatsResult});
on_link_layer_stats_result_internal_callback = nullptr;
- return {status, link_stats};
+ on_link_layer_ml_stats_result_internal_callback = nullptr;
+
+ return status;
}
wifi_error WifiLegacyHal::startRssiMonitoring(
@@ -1624,6 +1728,7 @@
on_gscan_event_internal_callback = nullptr;
on_gscan_full_result_internal_callback = nullptr;
on_link_layer_stats_result_internal_callback = nullptr;
+ on_link_layer_ml_stats_result_internal_callback = nullptr;
on_rssi_threshold_breached_internal_callback = nullptr;
on_ring_buffer_data_internal_callback = nullptr;
on_error_alert_internal_callback = nullptr;
diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h
index 33ed359..c40118e 100644
--- a/wifi/aidl/default/wifi_legacy_hal.h
+++ b/wifi/aidl/default/wifi_legacy_hal.h
@@ -363,7 +363,21 @@
wifi_iface_stat iface;
std::vector<LinkLayerRadioStats> radios;
std::vector<WifiPeerInfo> peers;
+ bool valid;
};
+
+struct LinkStats {
+ wifi_link_stat stat;
+ std::vector<WifiPeerInfo> peers;
+};
+
+struct LinkLayerMlStats {
+ wifi_iface_ml_stat iface;
+ std::vector<LinkStats> links;
+ std::vector<LinkLayerRadioStats> radios;
+ bool valid;
+};
+
#pragma GCC diagnostic pop
// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and
@@ -537,7 +551,9 @@
// Link layer stats functions.
wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug);
wifi_error disableLinkLayerStats(const std::string& iface_name);
- std::pair<wifi_error, LinkLayerStats> getLinkLayerStats(const std::string& iface_name);
+ wifi_error getLinkLayerStats(const std::string& iface_name,
+ legacy_hal::LinkLayerStats& legacy_stats,
+ legacy_hal::LinkLayerMlStats& legacy_ml_stats);
// RSSI monitor functions.
wifi_error startRssiMonitoring(
const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
@@ -710,6 +726,8 @@
// Handles wifi (error) status of Virtual interface create/delete
wifi_error handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
wifi_error status);
+ wifi_link_stat* copyLinkStat(wifi_link_stat* stat_ptr, std::vector<LinkStats> stats);
+ wifi_peer_info* copyPeerInfo(wifi_peer_info* peer_ptr, std::vector<WifiPeerInfo> peers);
// Global function table of legacy HAL.
wifi_hal_fn global_func_table_;
diff --git a/wifi/aidl/default/wifi_sta_iface.cpp b/wifi/aidl/default/wifi_sta_iface.cpp
index 57384bf..08ed9d2 100644
--- a/wifi/aidl/default/wifi_sta_iface.cpp
+++ b/wifi/aidl/default/wifi_sta_iface.cpp
@@ -404,13 +404,22 @@
std::pair<StaLinkLayerStats, ndk::ScopedAStatus> WifiStaIface::getLinkLayerStatsInternal() {
legacy_hal::wifi_error legacy_status;
- legacy_hal::LinkLayerStats legacy_stats;
- std::tie(legacy_status, legacy_stats) = legacy_hal_.lock()->getLinkLayerStats(ifname_);
+ legacy_hal::LinkLayerStats legacy_stats{};
+ legacy_hal::LinkLayerMlStats legacy_ml_stats{};
+ legacy_status = legacy_hal_.lock()->getLinkLayerStats(ifname_, legacy_stats, legacy_ml_stats);
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
return {StaLinkLayerStats{}, createWifiStatusFromLegacyError(legacy_status)};
}
StaLinkLayerStats aidl_stats;
- if (!aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &aidl_stats)) {
+ if (legacy_stats.valid) {
+ if (!aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &aidl_stats)) {
+ return {StaLinkLayerStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ } else if (legacy_ml_stats.valid) {
+ if (!aidl_struct_util::convertLegacyLinkLayerMlStatsToAidl(legacy_ml_stats, &aidl_stats)) {
+ return {StaLinkLayerStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ } else {
return {StaLinkLayerStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
}
return {aidl_stats, ndk::ScopedAStatus::ok()};
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
index ef7e274..5e55315 100644
--- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -145,7 +145,7 @@
std::shared_ptr<IWifiStaIface> iface;
auto status = createStaIface(&iface);
if (status.isOk()) {
- EXPECT_GT(link_layer_stats.iface.timeSliceDutyCycleInPercent, 0);
+ EXPECT_GT(link_layer_stats.iface.links[0].timeSliceDutyCycleInPercent, 0);
}
// Disable link layer stats collection.
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index 53d5770..3740a10 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -95,4 +95,5 @@
void stopDppInitiator();
void stopDppResponder(in int ownBootstrapId);
void stopRxFilter();
+ android.hardware.wifi.supplicant.SignalPollResult[] getSignalPollResults();
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SignalPollResult.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SignalPollResult.aidl
new file mode 100644
index 0000000..52d3f24
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SignalPollResult.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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 <name>-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.supplicant;
+@VintfStability
+parcelable SignalPollResult {
+ int linkId;
+ int currentRssiDbm;
+ int txBitrateMbps;
+ int rxBitrateMbps;
+ int frequencyMhz;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index 9edf210..9ceb3c0 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -31,6 +31,7 @@
import android.hardware.wifi.supplicant.MloLinksInfo;
import android.hardware.wifi.supplicant.QosPolicyStatus;
import android.hardware.wifi.supplicant.RxFilterType;
+import android.hardware.wifi.supplicant.SignalPollResult;
import android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask;
import android.hardware.wifi.supplicant.WpsConfigMethods;
@@ -781,4 +782,15 @@
* |SupplicantStatusCode.FAILURE_IFACE_INVALID|
*/
void stopRxFilter();
+
+ /**
+ * This method returns the signal poll results. Results will be for each
+ * link in case of Multiple Link Operation (MLO).
+ *
+ * @return Signal Poll Results per link.
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+ */
+ SignalPollResult[] getSignalPollResults();
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SignalPollResult.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SignalPollResult.aidl
new file mode 100644
index 0000000..a3b11a0
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SignalPollResult.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Signal polling results.
+ */
+@VintfStability
+parcelable SignalPollResult {
+ /**
+ * Link identifier.
+ */
+ int linkId;
+ /**
+ * RSSI value in dBM.
+ */
+ int currentRssiDbm;
+ /**
+ * Last transmitted packet bit rate in Mbps.
+ */
+ int txBitrateMbps;
+ /**
+ * Last received packet bit rate in Mbps.
+ */
+ int rxBitrateMbps;
+ /**
+ * Frequency in MHz.
+ */
+ int frequencyMhz;
+}