Merge "Audio HAL: Add new HAL for sound dose"

This commit is contained in:
Treehugger Robot 2022-12-19 19:07:33 +00:00 committed by Gerrit Code Review
commit 4c4ebb3208
18 changed files with 634 additions and 4 deletions

View file

@ -168,6 +168,53 @@ cc_defaults {
],
}
// Used for the standalone sounddose HAL
aidl_interface {
name: "android.hardware.audio.core.sounddose",
defaults: [
"android.hardware.audio_defaults",
],
srcs: [
"android/hardware/audio/core/ISoundDose.aidl",
],
imports: [
"android.media.audio.common.types-V2",
],
backend: {
// The C++ backend is disabled transitively due to use of FMQ by the core HAL.
cpp: {
enabled: false,
},
java: {
sdk_version: "module_current",
},
},
versions_with_info: [
// IMPORTANT: Update latest_android_hardware_audio_core_sounddose every time you
// add the latest frozen version to versions_with_info
],
}
// Note: This should always be one version ahead of the last frozen version
latest_android_hardware_audio_core_sounddose = "android.hardware.audio.core.sounddose-V1"
// Modules that depend on android.hardware.audio.core.sounddose directly can include
// the following cc_defaults to avoid explicitly managing dependency versions
// across many scattered files.
cc_defaults {
name: "latest_android_hardware_audio_core_sounddose_ndk_shared",
shared_libs: [
latest_android_hardware_audio_core_sounddose + "-ndk",
],
}
cc_defaults {
name: "latest_android_hardware_audio_core_sounddose_ndk_static",
static_libs: [
latest_android_hardware_audio_core_sounddose + "-ndk",
],
}
aidl_interface {
name: "android.hardware.audio.effect",
defaults: [

View file

@ -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;
}
}
}

View file

@ -29,6 +29,29 @@ cc_defaults {
],
}
cc_library {
name: "libaudioservicesounddoseimpl",
vendor: true,
defaults: [
"latest_android_media_audio_common_types_ndk_shared",
"latest_android_hardware_audio_core_sounddose_ndk_shared",
"latest_android_hardware_audio_sounddose_ndk_shared",
],
export_include_dirs: ["include"],
srcs: [
"SoundDose.cpp",
],
shared_libs: [
"libbase",
"libbinder_ndk",
"libcutils",
"libutils",
],
visibility: [
"//hardware/interfaces/audio/aidl/sounddose/default",
],
}
cc_library_static {
name: "libaudioserviceexampleimpl",
defaults: [

View file

@ -0,0 +1,70 @@
/*
* 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 {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
aidl_interface {
name: "android.hardware.audio.sounddose",
host_supported: true,
vendor_available: true,
stability: "vintf",
srcs: [
"android/hardware/audio/sounddose/ISoundDoseFactory.aidl",
],
imports: [
latest_android_hardware_audio_core_sounddose,
],
backend: {
// The C++ backend is disabled transitively due to use by core audio HAL.
cpp: {
enabled: false,
},
java: {
sdk_version: "module_current",
},
},
versions_with_info: [
// IMPORTANT: Update latest_android_hardware_audio_sounddose every time you
// add the latest frozen version to versions_with_info
],
}
// Note: This should always be one version ahead of the last frozen version
latest_android_hardware_audio_sounddose = "android.hardware.audio.sounddose-V1"
// Modules that depend on android.hardware.audio.sounddose directly can include
// the following cc_defaults to avoid explicitly managing dependency versions
// across many scattered files.
cc_defaults {
name: "latest_android_hardware_audio_sounddose_ndk_shared",
shared_libs: [
latest_android_hardware_audio_sounddose + "-ndk",
],
}
cc_defaults {
name: "latest_android_hardware_audio_sounddose_ndk_static",
static_libs: [
latest_android_hardware_audio_sounddose + "-ndk",
],
}

View file

@ -0,0 +1,51 @@
/*
* 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;
@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;
}
}
}

View file

@ -0,0 +1,38 @@
/*
* 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.sounddose;
@VintfStability
interface ISoundDoseFactory {
@nullable android.hardware.audio.core.ISoundDose getSoundDose(in @utf8InCpp String module);
}

View file

@ -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.audio.sounddose;
import android.hardware.audio.core.ISoundDose;
/**
* This interface is used to provide an easy way to implement the ISoundDose interface
* without switching the audio HAL to AIDL. The implementation is intended as a workaround
* for the certification with IEC62368-1 3rd edition and EN50332-3.
* Note that this interface will be deprecated in favor of the audio AIDL HAL.
*/
@VintfStability
interface ISoundDoseFactory {
/**
* Retrieve the sound dose interface for a given audio HAL module name.
*
* 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.
*
* @param module for which we trigger sound dose updates.
* @return An instance of the ISoundDose interface implementation.
* @throws EX_ILLEGAL_STATE If there was an error creating an instance.
*/
@nullable ISoundDose getSoundDose(in @utf8InCpp String module);
}

View file

@ -0,0 +1,46 @@
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
cc_defaults {
name: "aidlsounddoseservice_defaults",
vendor: true,
header_libs: [
"libsounddoseaidl_headers",
],
}
cc_library {
name: "libsounddoseserviceexampleimpl",
defaults: [
"aidlsounddoseservice_defaults",
"latest_android_media_audio_common_types_ndk_shared",
"latest_android_hardware_audio_core_sounddose_ndk_shared",
"latest_android_hardware_audio_sounddose_ndk_shared",
],
export_include_dirs: ["include"],
srcs: [
"SoundDoseFactory.cpp",
],
shared_libs: [
"libaudioservicesounddoseimpl",
"libbase",
"libbinder_ndk",
],
visibility: [
"//hardware/interfaces/audio/common/all-versions/default/service",
],
}
cc_library_headers {
name: "libsounddoseaidl_headers",
export_include_dirs: ["include"],
vendor_available: true,
host_supported: true,
}

View file

@ -0,0 +1,49 @@
/*
* 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_SoundDoseFactory"
#include "SoundDoseFactory.h"
#include <android-base/logging.h>
#include <core-impl/SoundDose.h>
namespace aidl::android::hardware::audio::sounddose {
using ::aidl::android::hardware::audio::core::SoundDose;
ndk::ScopedAStatus SoundDoseFactory::getSoundDose(const std::string& in_module,
std::shared_ptr<ISoundDose>* _aidl_return) {
auto soundDoseIt = mSoundDoseBinderMap.find(in_module);
if (soundDoseIt != mSoundDoseBinderMap.end()) {
*_aidl_return = ISoundDose::fromBinder(soundDoseIt->second);
LOG(DEBUG) << __func__
<< ": returning cached instance of ISoundDose: " << _aidl_return->get()
<< " for module " << in_module;
return ndk::ScopedAStatus::ok();
}
auto soundDose = ndk::SharedRefBase::make<SoundDose>();
mSoundDoseBinderMap[in_module] = soundDose->asBinder();
*_aidl_return = soundDose;
LOG(DEBUG) << __func__ << ": returning new instance of ISoundDose: " << _aidl_return->get()
<< " for module " << in_module;
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::audio::sounddose

View file

@ -0,0 +1,38 @@
/*
* 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/android/hardware/audio/core/ISoundDose.h>
#include <aidl/android/hardware/audio/sounddose/BnSoundDoseFactory.h>
#include <android/binder_interface_utils.h>
#include <unordered_map>
namespace aidl::android::hardware::audio::sounddose {
using ::aidl::android::hardware::audio::core::ISoundDose;
class SoundDoseFactory : public BnSoundDoseFactory {
public:
ndk::ScopedAStatus getSoundDose(const std::string& module,
std::shared_ptr<ISoundDose>* _aidl_return) override;
private:
std::unordered_map<std::string, ndk::SpAIBinder> mSoundDoseBinderMap;
};
} // namespace aidl::android::hardware::audio::sounddose

View file

@ -0,0 +1,36 @@
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
cc_test {
name: "VtsHalSoundDoseFactoryTargetTest",
defaults: [
"latest_android_hardware_audio_core_sounddose_ndk_static",
"latest_android_hardware_audio_sounddose_ndk_static",
"latest_android_media_audio_common_types_ndk_static",
"use_libaidlvintf_gtest_helper_static",
"VtsHalTargetTestDefaults",
],
shared_libs: [
"libbinder_ndk",
"libcutils",
],
srcs: [
"VtsHalSoundDoseFactoryTargetTest.cpp",
],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-Wthread-safety",
],
test_suites: [
"general-tests",
"vts",
],
}

View file

@ -0,0 +1,7 @@
{
"presubmit": [
{
"name": "VtsHalSoundDoseFactoryTargetTest"
}
]
}

View file

@ -0,0 +1,96 @@
/*
* 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 "VtsHalSoundDose.Factory"
#include <android-base/logging.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
#include <android/binder_manager.h>
#include <memory>
namespace android::hardware::audio::common::testing {
namespace detail {
inline ::testing::AssertionResult assertIsOk(const char* expr, const ::ndk::ScopedAStatus& status) {
if (status.isOk()) {
return ::testing::AssertionSuccess();
}
return ::testing::AssertionFailure()
<< "Expected the transaction \'" << expr << "\' to succeed\n"
<< " but it has failed with: " << status;
}
} // namespace detail
} // namespace android::hardware::audio::common::testing
// Test that the transaction status 'isOk'
#define EXPECT_IS_OK(ret) \
EXPECT_PRED_FORMAT1(::android::hardware::audio::common::testing::detail::assertIsOk, ret)
using namespace android;
using aidl::android::hardware::audio::core::ISoundDose;
using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
class SoundDoseFactory : public testing::TestWithParam<std::string> {
public:
void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService(GetParam())); }
void TearDown() override {}
void ConnectToService(const std::string& interfaceName) {
ndk::SpAIBinder binder =
ndk::SpAIBinder(AServiceManager_waitForService(interfaceName.c_str()));
if (binder == nullptr) {
LOG(ERROR) << "Failed to get service " << interfaceName;
} else {
LOG(DEBUG) << "Succeeded to get service " << interfaceName;
}
soundDoseFactory = ISoundDoseFactory::fromBinder(binder);
ASSERT_NE(soundDoseFactory, nullptr);
}
std::shared_ptr<ISoundDoseFactory> soundDoseFactory;
};
TEST_P(SoundDoseFactory, GetSoundDoseForSameModule) {
const std::string module = "primary";
std::shared_ptr<ISoundDose> soundDose1;
EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose1));
if (soundDose1 == nullptr) {
LOG(WARNING) << "Primary module does not support sound dose";
return;
}
std::shared_ptr<ISoundDose> soundDose2;
EXPECT_IS_OK(soundDoseFactory->getSoundDose(module, &soundDose2));
EXPECT_NE(nullptr, soundDose2);
EXPECT_EQ(soundDose1->asBinder(), soundDose2->asBinder())
<< "getSoundDose must return the same interface for the same module";
}
INSTANTIATE_TEST_SUITE_P(
SoundDoseFactoryTest, SoundDoseFactory,
testing::ValuesIn(android::getAidlHalInstanceNames(ISoundDoseFactory::descriptor)),
android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundDoseFactory);

View file

@ -24,6 +24,7 @@ cc_defaults {
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"libaudioaidlcommon",
"libaidlcommonsupport",
],
header_libs: ["libaudioaidl_headers"],
cflags: [

View file

@ -38,9 +38,15 @@ cc_binary {
name: "android.hardware.audio.service",
init_rc: ["android.hardware.audio.service.rc"],
vintf_fragments: ["android.hardware.audio.sounddose-aidl.xml"],
relative_install_path: "hw",
vendor: true,
defaults: [
"android_hardware_audio_config_defaults",
"latest_android_hardware_audio_sounddose_ndk_shared",
],
srcs: ["service.cpp"],
cflags: [
@ -50,6 +56,7 @@ cc_binary {
],
shared_libs: [
"//hardware/interfaces/audio/aidl/sounddose/default:libsounddoseserviceexampleimpl",
"libcutils",
"libbinder",
"libbinder_ndk",
@ -58,10 +65,6 @@ cc_binary {
"libutils",
"libhardware",
],
defaults: [
"android_hardware_audio_config_defaults",
],
}
// Legacy service name, use android.hardware.audio.service instead

View file

@ -0,0 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.audio.sounddose</name>
<version>1</version>
<fqname>ISoundDoseFactory/default</fqname>
</hal>
</manifest>

View file

@ -20,6 +20,10 @@
#include <string>
#include <vector>
#include <SoundDoseFactory.h>
#include <android-base/logging.h>
#include <android/binder_ibinder_platform.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
@ -33,6 +37,8 @@ using android::OK;
using InterfacesList = std::vector<std::string>;
using aidl::android::hardware::audio::sounddose::SoundDoseFactory;
/** Try to register the provided factories in the provided order.
* If any registers successfully, do not register any other and return true.
* If all fail, return false.
@ -164,5 +170,13 @@ int main(int /* argc */, char* /* argv */ []) {
}
}
// Register ISoundDoseFactory interface as a workaround for using the audio AIDL HAL
auto soundDoseDefault = ndk::SharedRefBase::make<SoundDoseFactory>();
const std::string soundDoseDefaultName =
std::string() + SoundDoseFactory::descriptor + "/default";
binder_status_t status = AServiceManager_addService(soundDoseDefault->asBinder().get(),
soundDoseDefaultName.c_str());
CHECK_EQ(STATUS_OK, status);
joinRpcThreadpool();
}

View file

@ -52,6 +52,14 @@
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.audio.sounddose</name>
<version>1</version>
<interface>
<name>ISoundDoseFactory</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.authsecret</name>
<version>1</version>