From 83a6d8279336aabffeb2f2e3c9f27e85075708cf Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Mon, 7 Nov 2022 13:53:57 +0100 Subject: [PATCH] Add HAL interface definition for sound dose The interface is used to configure the sound dose parameters and retrieve new changes that can affect the dose. Used for the certification with IEC62368-1 3rd edition. Test: TODO Bug: 257937004 Change-Id: Id2816580fdbfbf09c2278720b4d78d0b3604fbf4 Merged-In: Id2816580fdbfbf09c2278720b4d78d0b3604fbf4 (cherry picked from commit 10905ef92e086e7f7d63d674d5f00bd83a976551) --- audio/aidl/Android.bp | 1 + .../android/hardware/audio/core/IModule.aidl | 1 + .../hardware/audio/core/ISoundDose.aidl | 52 +++++++++ .../android/hardware/audio/core/IModule.aidl | 16 +++ .../hardware/audio/core/ISoundDose.aidl | 104 ++++++++++++++++++ audio/aidl/default/Module.cpp | 6 + audio/aidl/default/include/core-impl/Module.h | 1 + 7 files changed, 181 insertions(+) create mode 100644 audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ISoundDose.aidl create mode 100644 audio/aidl/android/hardware/audio/core/ISoundDose.aidl diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp index 05c7649c90..8f0286f397 100644 --- a/audio/aidl/Android.bp +++ b/audio/aidl/Android.bp @@ -113,6 +113,7 @@ aidl_interface { "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/IStreamIn.aidl", "android/hardware/audio/core/IStreamOut.aidl", 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 0c7ca27c61..42b12d94b3 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,7 @@ interface IModule { 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(); @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 0000000000..bc010caaf5 --- /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 -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/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl index 786d5eecbe..2d34df6297 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.common.SourceMetadata; 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; @@ -668,4 +669,19 @@ interface IModule { * @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(); } 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 0000000000..89fd69b80f --- /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/default/Module.cpp b/audio/aidl/default/Module.cpp index 47d6fa44be..2b199dcd35 100644 --- a/audio/aidl/default/Module.cpp +++ b/audio/aidl/default/Module.cpp @@ -931,4 +931,10 @@ ndk::ScopedAStatus Module::updateScreenState(bool in_isTurnedOn) { return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Module::getSoundDose(std::shared_ptr* _aidl_return) { + *_aidl_return = nullptr; + LOG(DEBUG) << __func__ << ": ISoundDose not implemented"; + return ndk::ScopedAStatus::ok(); +} + } // namespace aidl::android::hardware::audio::core diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h index 52fb54ca9d..de1fbe810e 100644 --- a/audio/aidl/default/include/core-impl/Module.h +++ b/audio/aidl/default/include/core-impl/Module.h @@ -86,6 +86,7 @@ class Module : public BnModule { 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* _aidl_return) override; void cleanUpPatch(int32_t patchId); ndk::ScopedAStatus createStreamContext(