audio: Provide operations common to input and output streams am: e9f10fc9dc
am: 66b60e7f79
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2256002 Change-Id: Ic68d33cfa0b38a4556104493fcf904669732c81f Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
e1570b3ff6
17 changed files with 690 additions and 64 deletions
|
@ -115,6 +115,7 @@ aidl_interface {
|
|||
"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 +125,7 @@ aidl_interface {
|
|||
"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",
|
||||
|
|
|
@ -61,6 +61,9 @@ interface IModule {
|
|||
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -29,6 +29,7 @@ import android.hardware.audio.core.ITelephony;
|
|||
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;
|
||||
|
@ -684,4 +685,47 @@ interface IModule {
|
|||
* @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);
|
||||
}
|
||||
|
|
89
audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
Normal file
89
audio/aidl/android/hardware/audio/core/IStreamCommon.aidl
Normal file
|
@ -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);
|
||||
}
|
|
@ -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 @@ import android.hardware.audio.core.MicrophoneDynamicInfo;
|
|||
@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.
|
||||
|
|
|
@ -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 @@ import android.hardware.audio.common.SourceMetadata;
|
|||
@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.
|
||||
|
|
39
audio/aidl/android/hardware/audio/core/VendorParameter.aidl
Normal file
39
audio/aidl/android/hardware/audio/core/VendorParameter.aidl
Normal file
|
@ -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;
|
||||
}
|
|
@ -532,9 +532,10 @@ ndk::ScopedAStatus Module::openInputStream(const OpenInputStreamArguments& in_ar
|
|||
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;
|
||||
}
|
||||
StreamWrapper streamWrapper(stream);
|
||||
|
@ -584,9 +585,10 @@ ndk::ScopedAStatus Module::openOutputStream(const OpenOutputStreamArguments& in_
|
|||
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;
|
||||
}
|
||||
StreamWrapper streamWrapper(stream);
|
||||
|
@ -947,4 +949,24 @@ ndk::ScopedAStatus Module::getSoundDose(std::shared_ptr<ISoundDose>* _aidl_retur
|
|||
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
|
||||
|
|
|
@ -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 @@ bool StreamOutWorkerLogic::write(size_t clientSize, StreamDescriptor::Reply* rep
|
|||
}
|
||||
|
||||
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 @@ StreamCommon<Metadata, StreamWorker>::~StreamCommon() {
|
|||
}
|
||||
|
||||
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 @@ ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::close() {
|
|||
}
|
||||
|
||||
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 @@ void StreamCommon<Metadata, StreamWorker>::stopWorker() {
|
|||
}
|
||||
|
||||
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 @@ ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::updateMetadata(const Me
|
|||
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 @@ static std::map<AudioDevice, std::string> transformMicrophones(
|
|||
}
|
||||
} // 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 @@ ndk::ScopedAStatus StreamIn::setMicrophoneFieldDimension(float in_zoom) {
|
|||
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__;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,11 @@ class Module : public BnModule {
|
|||
::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(
|
||||
|
|
|
@ -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 @@ class StreamOutWorkerLogic : public StreamWorkerCommonLogic {
|
|||
};
|
||||
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 @@ class StreamCommon {
|
|||
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,39 +302,61 @@ class StreamIn
|
|||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
|
||||
#include <android/binder_auto_utils.h>
|
||||
|
@ -45,6 +47,19 @@ inline ::testing::AssertionResult assertResult(const char* exp_expr, const char*
|
|||
<< "\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
|
||||
|
|
|
@ -58,6 +58,7 @@ 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;
|
||||
|
@ -65,6 +66,7 @@ using aidl::android::hardware::audio::core::MicrophoneDynamicInfo;
|
|||
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;
|
||||
|
@ -211,6 +213,56 @@ void TestAccessors(Instance* inst, Getter getter, Setter setter,
|
|||
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:
|
||||
|
@ -837,6 +889,13 @@ struct IOTraits {
|
|||
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;
|
||||
|
@ -844,7 +903,7 @@ class WithStream {
|
|||
~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)); }
|
||||
|
@ -1628,6 +1687,40 @@ TEST_P(AudioCoreModule, UpdateScreenState) {
|
|||
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 {
|
||||
|
@ -1733,6 +1826,23 @@ class AudioStream : public AudioCoreModule {
|
|||
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));
|
||||
EXPECT_NE(nullptr, streamCommon1);
|
||||
std::shared_ptr<IStreamCommon> streamCommon2;
|
||||
EXPECT_IS_OK(stream.get()->getStreamCommon(&streamCommon2));
|
||||
EXPECT_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()) {
|
||||
|
@ -1744,7 +1854,8 @@ class AudioStream : public AudioCoreModule {
|
|||
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() {
|
||||
|
@ -1849,6 +1960,65 @@ class AudioStream : public AudioCoreModule {
|
|||
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));
|
||||
|
@ -1914,6 +2084,7 @@ using AudioStreamOut = AudioStream<IStreamOut>;
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -1921,6 +2092,9 @@ TEST_IN_AND_OUT_STREAM(OpenOverMaxCount);
|
|||
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) {
|
||||
|
|
Loading…
Reference in a new issue