Merge "audio: Add AudioOffloadMetadata and a method to update it" into udc-dev
This commit is contained in:
commit
e6c11eea73
10 changed files with 179 additions and 10 deletions
|
@ -36,12 +36,13 @@ aidl_interface {
|
|||
"android.hardware.audio_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"android/hardware/audio/common/AudioOffloadMetadata.aidl",
|
||||
"android/hardware/audio/common/PlaybackTrackMetadata.aidl",
|
||||
"android/hardware/audio/common/RecordTrackMetadata.aidl",
|
||||
"android/hardware/audio/common/SinkMetadata.aidl",
|
||||
"android/hardware/audio/common/SourceMetadata.aidl",
|
||||
],
|
||||
frozen: true,
|
||||
frozen: false,
|
||||
imports: [
|
||||
"android.media.audio.common.types-V2",
|
||||
],
|
||||
|
@ -77,7 +78,7 @@ aidl_interface {
|
|||
}
|
||||
|
||||
// Note: This should always be one version ahead of the last frozen version
|
||||
latest_android_hardware_audio_common = "android.hardware.audio.common-V1"
|
||||
latest_android_hardware_audio_common = "android.hardware.audio.common-V2"
|
||||
|
||||
// Modules that depend on android.hardware.audio.common directly can include
|
||||
// the following cc_defaults to avoid explicitly managing dependency versions
|
||||
|
@ -129,7 +130,7 @@ aidl_interface {
|
|||
imports: [
|
||||
"android.hardware.common-V2",
|
||||
"android.hardware.common.fmq-V1",
|
||||
"android.hardware.audio.common-V1",
|
||||
"android.hardware.audio.common-V2",
|
||||
"android.hardware.audio.core.sounddose-V1",
|
||||
"android.hardware.audio.effect-V1",
|
||||
"android.media.audio.common.types-V2",
|
||||
|
@ -253,7 +254,7 @@ aidl_interface {
|
|||
imports: [
|
||||
"android.hardware.common-V2",
|
||||
"android.hardware.common.fmq-V1",
|
||||
"android.hardware.audio.common-V1",
|
||||
"android.hardware.audio.common-V2",
|
||||
"android.media.audio.common.types-V2",
|
||||
],
|
||||
backend: {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <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.common;
|
||||
@JavaDerive(equals=true, toString=true) @VintfStability
|
||||
parcelable AudioOffloadMetadata {
|
||||
int sampleRate;
|
||||
android.media.audio.common.AudioChannelLayout channelMask;
|
||||
int averageBitRatePerSecond;
|
||||
int delayFrames;
|
||||
int paddingFrames;
|
||||
}
|
|
@ -36,6 +36,7 @@ package android.hardware.audio.core;
|
|||
interface IStreamOut {
|
||||
android.hardware.audio.core.IStreamCommon getStreamCommon();
|
||||
void updateMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
|
||||
void updateOffloadMetadata(in android.hardware.audio.common.AudioOffloadMetadata offloadMetadata);
|
||||
float[] getHwVolume();
|
||||
void setHwVolume(in float[] channelVolumes);
|
||||
float getAudioDescriptionMixLevel();
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.audio.common;
|
||||
|
||||
import android.media.audio.common.AudioChannelLayout;
|
||||
|
||||
/**
|
||||
* Dynamic metadata for offloaded compressed audio.
|
||||
* For static metadata, see android.media.audio.common.AudioOffloadInfo.
|
||||
*/
|
||||
@JavaDerive(equals=true, toString=true)
|
||||
@VintfStability
|
||||
parcelable AudioOffloadMetadata {
|
||||
int sampleRate;
|
||||
AudioChannelLayout channelMask;
|
||||
/** Average bit rate in bits per second. */
|
||||
int averageBitRatePerSecond;
|
||||
/**
|
||||
* Number of frames to be ignored at the beginning of the stream.
|
||||
* The value must be non-negative. A value of 0 indicates no delay
|
||||
* has to be applied.
|
||||
*/
|
||||
int delayFrames;
|
||||
/**
|
||||
* Number of frames to be ignored at the end of the stream.
|
||||
* The value must be non-negative. A value of 0 indicates no padding
|
||||
* has to be applied.
|
||||
*/
|
||||
int paddingFrames;
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package android.hardware.audio.core;
|
||||
|
||||
import android.hardware.audio.common.AudioOffloadMetadata;
|
||||
import android.hardware.audio.common.SourceMetadata;
|
||||
import android.hardware.audio.core.IStreamCommon;
|
||||
import android.media.audio.common.AudioDualMonoMode;
|
||||
|
@ -48,6 +49,18 @@ interface IStreamOut {
|
|||
*/
|
||||
void updateMetadata(in SourceMetadata sourceMetadata);
|
||||
|
||||
/**
|
||||
* Update offload metadata for a compressed stream.
|
||||
*
|
||||
* Updates the offload metadata initially provided at the stream creation.
|
||||
*
|
||||
* @param offloadMetadata Updated offload metadata.
|
||||
* @throws EX_ILLEGAL_STATE If the stream is closed.
|
||||
* @throws EX_ILLEGAL_ARGUMENT If the metadata contains invalid values.
|
||||
* @throws EX_UNSUPPORTED_OPERATION If the stream is not for compressed offload.
|
||||
*/
|
||||
void updateOffloadMetadata(in AudioOffloadMetadata offloadMetadata);
|
||||
|
||||
const int HW_VOLUME_MIN = 0;
|
||||
const int HW_VOLUME_MAX = 1;
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "core-impl/Module.h"
|
||||
#include "core-impl/Stream.h"
|
||||
|
||||
using aidl::android::hardware::audio::common::AudioOffloadMetadata;
|
||||
using aidl::android::hardware::audio::common::SinkMetadata;
|
||||
using aidl::android::hardware::audio::common::SourceMetadata;
|
||||
using aidl::android::media::audio::common::AudioDevice;
|
||||
|
@ -785,6 +786,40 @@ StreamOut::StreamOut(const SourceMetadata& sourceMetadata, StreamContext&& conte
|
|||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus StreamOut::updateOffloadMetadata(
|
||||
const AudioOffloadMetadata& in_offloadMetadata) {
|
||||
LOG(DEBUG) << __func__;
|
||||
if (isClosed()) {
|
||||
LOG(ERROR) << __func__ << ": stream was closed";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
if (!mOffloadInfo.has_value()) {
|
||||
LOG(ERROR) << __func__ << ": not a compressed offload stream";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
if (in_offloadMetadata.sampleRate < 0) {
|
||||
LOG(ERROR) << __func__ << ": invalid sample rate value: " << in_offloadMetadata.sampleRate;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
if (in_offloadMetadata.averageBitRatePerSecond < 0) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": invalid average BPS value: " << in_offloadMetadata.averageBitRatePerSecond;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
if (in_offloadMetadata.delayFrames < 0) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": invalid delay frames value: " << in_offloadMetadata.delayFrames;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
if (in_offloadMetadata.paddingFrames < 0) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": invalid padding frames value: " << in_offloadMetadata.paddingFrames;
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
mOffloadMetadata = in_offloadMetadata;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus StreamOut::getHwVolume(std::vector<float>* _aidl_return) {
|
||||
LOG(DEBUG) << __func__;
|
||||
(void)_aidl_return;
|
||||
|
|
|
@ -463,6 +463,9 @@ class StreamOut : public StreamCommonImpl<::aidl::android::hardware::audio::comm
|
|||
return StreamCommonImpl<::aidl::android::hardware::audio::common::SourceMetadata>::
|
||||
updateMetadata(in_sourceMetadata);
|
||||
}
|
||||
ndk::ScopedAStatus updateOffloadMetadata(
|
||||
const ::aidl::android::hardware::audio::common::AudioOffloadMetadata&
|
||||
in_offloadMetadata) override;
|
||||
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
|
||||
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
|
||||
ndk::ScopedAStatus getAudioDescriptionMixLevel(float* _aidl_return) override;
|
||||
|
@ -500,6 +503,7 @@ class StreamOut : public StreamCommonImpl<::aidl::android::hardware::audio::comm
|
|||
offloadInfo);
|
||||
|
||||
std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
|
||||
std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
|
||||
|
||||
public:
|
||||
using CreateInstance = std::function<ndk::ScopedAStatus(
|
||||
|
|
|
@ -56,7 +56,7 @@ std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
|
|||
offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
|
||||
offloadInfo.base.channelMask = portConfig.channelMask.value();
|
||||
offloadInfo.base.format = portConfig.format.value();
|
||||
offloadInfo.bitRatePerSecond = 256; // Arbitrary value.
|
||||
offloadInfo.bitRatePerSecond = 256000; // Arbitrary value.
|
||||
offloadInfo.durationUs = std::chrono::microseconds(1min).count(); // Arbitrary value.
|
||||
offloadInfo.usage = AudioUsage::MEDIA;
|
||||
offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "TestUtils.h"
|
||||
|
||||
using namespace android;
|
||||
using aidl::android::hardware::audio::common::AudioOffloadMetadata;
|
||||
using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
|
||||
using aidl::android::hardware::audio::common::RecordTrackMetadata;
|
||||
using aidl::android::hardware::audio::common::SinkMetadata;
|
||||
|
@ -401,8 +402,9 @@ void TestSetVendorParameters(Instance* inst, bool* isSupported) {
|
|||
// Can be used as a base for any test here, does not depend on the fixture GTest parameters.
|
||||
class AudioCoreModuleBase {
|
||||
public:
|
||||
// The default buffer size is used mostly for negative tests.
|
||||
// Default buffer sizes are used mostly for negative tests.
|
||||
static constexpr int kDefaultBufferSizeFrames = 256;
|
||||
static constexpr int kDefaultLargeBufferSizeFrames = 48000;
|
||||
|
||||
void SetUpImpl(const std::string& moduleName) {
|
||||
ASSERT_NO_FATAL_FAILURE(ConnectToService(moduleName));
|
||||
|
@ -2696,7 +2698,7 @@ TEST_P(AudioStreamOut, RequireOffloadInfo) {
|
|||
aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
|
||||
args.portConfigId = portConfig.getId();
|
||||
args.sourceMetadata = GenerateSourceMetadata(portConfig.get());
|
||||
args.bufferSizeFrames = kDefaultBufferSizeFrames;
|
||||
args.bufferSizeFrames = kDefaultLargeBufferSizeFrames;
|
||||
aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
|
||||
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, module->openOutputStream(args, &ret))
|
||||
<< "when no offload info is provided for a compressed offload mix port";
|
||||
|
@ -2876,7 +2878,7 @@ TEST_P(AudioStreamOut, PlaybackRate) {
|
|||
const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
|
||||
ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
|
||||
WithStream<IStreamOut> stream(portConfig.value());
|
||||
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
|
||||
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
|
||||
bool isSupported = false;
|
||||
EXPECT_NO_FATAL_FAILURE(TestAccessors<AudioPlaybackRate>(
|
||||
stream.get(), &IStreamOut::getPlaybackRateParameters,
|
||||
|
@ -2901,7 +2903,7 @@ TEST_P(AudioStreamOut, SelectPresentation) {
|
|||
const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
|
||||
ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
|
||||
WithStream<IStreamOut> stream(portConfig.value());
|
||||
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
|
||||
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
|
||||
ndk::ScopedAStatus status;
|
||||
EXPECT_STATUS(kStatuses, status = stream.get()->selectPresentation(0, 0));
|
||||
if (status.getExceptionCode() != EX_UNSUPPORTED_OPERATION) atLeastOneSupports = true;
|
||||
|
@ -2911,6 +2913,33 @@ TEST_P(AudioStreamOut, SelectPresentation) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_P(AudioStreamOut, UpdateOffloadMetadata) {
|
||||
const auto offloadMixPorts =
|
||||
moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, false /*singlePort*/);
|
||||
if (offloadMixPorts.empty()) {
|
||||
GTEST_SKIP()
|
||||
<< "No mix port for compressed offload that could be routed to attached devices";
|
||||
}
|
||||
for (const auto& port : offloadMixPorts) {
|
||||
const auto portConfig = moduleConfig->getSingleConfigForMixPort(false, port);
|
||||
ASSERT_TRUE(portConfig.has_value()) << "No profiles specified for output mix port";
|
||||
WithStream<IStreamOut> stream(portConfig.value());
|
||||
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultLargeBufferSizeFrames));
|
||||
AudioOffloadMetadata validMetadata{
|
||||
.sampleRate = portConfig.value().sampleRate.value().value,
|
||||
.channelMask = portConfig.value().channelMask.value(),
|
||||
.averageBitRatePerSecond = 256000,
|
||||
.delayFrames = 0,
|
||||
.paddingFrames = 0};
|
||||
EXPECT_IS_OK(stream.get()->updateOffloadMetadata(validMetadata));
|
||||
AudioOffloadMetadata invalidMetadata{.sampleRate = -1,
|
||||
.averageBitRatePerSecond = -1,
|
||||
.delayFrames = -1,
|
||||
.paddingFrames = -1};
|
||||
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, stream.get()->updateOffloadMetadata(invalidMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
class StreamLogicDefaultDriver : public StreamLogicDriver {
|
||||
public:
|
||||
StreamLogicDefaultDriver(std::shared_ptr<StateSequence> commands, size_t frameSizeBytes)
|
||||
|
|
|
@ -25,7 +25,6 @@ cc_test {
|
|||
name: "VtsAidlHalAudioControlTest",
|
||||
defaults: [
|
||||
"latest_android_media_audio_common_types_cpp_static",
|
||||
"latest_android_hardware_audio_common_cpp_static",
|
||||
"VtsHalTargetTestDefaults",
|
||||
"use_libaidlvintf_gtest_helper_static",
|
||||
],
|
||||
|
@ -40,6 +39,7 @@ cc_test {
|
|||
],
|
||||
static_libs: [
|
||||
"android.hardware.automotive.audiocontrol-V3-cpp",
|
||||
"android.hardware.audio.common-V1-cpp",
|
||||
"libgmock",
|
||||
],
|
||||
test_suites: [
|
||||
|
|
Loading…
Reference in a new issue