Merge "send kDumpFromAudioServerArgument to the HAL modules" into 24D1-dev
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index ed11056..a44ba8b 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -506,27 +506,31 @@
"%s %s: must be invoked from the worker thread (%d)",
__func__, command.toString().c_str(), workerTid);
}
- if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
- ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
- return NOT_ENOUGH_DATA;
- }
StreamDescriptor::Reply localReply{};
- if (reply == nullptr) {
- reply = &localReply;
- }
- if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
- ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str());
- return NOT_ENOUGH_DATA;
- }
{
- std::lock_guard l(mLock);
- // Not every command replies with 'latencyMs' field filled out, substitute the last
- // returned value in that case.
- if (reply->latencyMs <= 0) {
- reply->latencyMs = mLastReply.latencyMs;
+ std::lock_guard l(mCommandReplyLock);
+ if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
+ ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
+ return NOT_ENOUGH_DATA;
}
- mLastReply = *reply;
- mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs;
+ if (reply == nullptr) {
+ reply = &localReply;
+ }
+ if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
+ ALOGE("%s: failed to read from reply MQ, command %s",
+ __func__, command.toString().c_str());
+ return NOT_ENOUGH_DATA;
+ }
+ {
+ std::lock_guard l(mLock);
+ // Not every command replies with 'latencyMs' field filled out, substitute the last
+ // returned value in that case.
+ if (reply->latencyMs <= 0) {
+ reply->latencyMs = mLastReply.latencyMs;
+ }
+ mLastReply = *reply;
+ mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs;
+ }
}
switch (reply->status) {
case STATUS_OK: return OK;
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 53d46e5..b20eb00 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -243,6 +243,15 @@
const bool mIsInput;
const audio_config_base_t mConfig;
const StreamContextAidl mContext;
+ // This lock is used to make sending of a command and receiving a reply an atomic
+ // operation. Otherwise, when two threads are trying to send a command, they may both advance to
+ // reading of the reply once the HAL has consumed the command from the MQ, and that creates a
+ // race condition between them.
+ //
+ // Note that only access to command and reply MQs needs to be protected because the data MQ is
+ // only accessed by the I/O thread. Also, there is no need to protect lookup operations on the
+ // queues as they are thread-safe, only send/receive operation must be protected.
+ std::mutex mCommandReplyLock;
private:
static audio_config_base_t configToBase(const audio_config& config) {
@@ -256,6 +265,8 @@
std::lock_guard l(mLock);
return mLastReply.state;
}
+ // Note: Since `sendCommand` takes mLock while holding mCommandReplyLock, never call
+ // it with `mLock` being held.
status_t sendCommand(
const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr,
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
index da28204..a88ef83 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
@@ -147,8 +147,12 @@
return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
}
default: {
- ALOGE("%s %d invalid command %u", __func__, __LINE__, command);
- return BAD_VALUE;
+ // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+ VendorExtension ext = VALUE_OR_RETURN_STATUS(
+ aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param));
+ aidlParam =
+ MAKE_SPECIFIC_PARAMETER(Spatializer, spatializer, vendor, ext);
+ break;
}
}
} else {
@@ -317,8 +321,7 @@
return OK;
}
default: {
- ALOGE("%s %d invalid command %u", __func__, __LINE__, command);
- return BAD_VALUE;
+ VENDOR_EXTENSION_GET_AND_RETURN(Spatializer, spatializer, param);
}
}
} else {
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index 90406e9..fff2feb 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -564,10 +564,40 @@
RetCode BundleContext::setForcedDevice(
const ::aidl::android::media::audio::common::AudioDeviceDescription& device) {
- RETURN_VALUE_IF(true != isDeviceSupportedVirtualizer({device}), RetCode::ERROR_EFFECT_LIB_ERROR,
- " deviceNotSupportVirtualizer");
- mForceDevice = device;
- return RetCode::SUCCESS;
+ RetCode ret = RetCode::SUCCESS;
+ bool enableVirtualizer = mType == lvm::BundleEffectType::VIRTUALIZER && mEnabled;
+
+ if (isDeviceSupportedVirtualizer({device})) {
+ mVirtualizerForcedDevice = device;
+ } else {
+ // disabling forced virtualization mode
+ AudioDeviceDescription noneDevice;
+ if (device != noneDevice) {
+ // device is not supported, make it behave as a reset of forced mode but return an error
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ // verify whether the virtualization should be enabled or disabled
+ if (!isDeviceSupportedVirtualizer(mOutputDevice)) {
+ enableVirtualizer = false;
+ }
+ mVirtualizerForcedDevice = noneDevice;
+ }
+
+ if (enableVirtualizer) {
+ if (mVirtualizerTempDisabled) {
+ LOG(VERBOSE) << __func__ << " re-enable virtualizer";
+ enableOperatingMode();
+ mVirtualizerTempDisabled = false;
+ }
+ } else {
+ if (!mVirtualizerTempDisabled) {
+ LOG(VERBOSE) << __func__ << " disable virtualizer";
+ disableOperatingMode();
+ mVirtualizerTempDisabled = true;
+ }
+ }
+
+ return ret;
}
RetCode BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index ba3997a..044c8dd 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -76,7 +76,7 @@
RetCode setForcedDevice(
const ::aidl::android::media::audio::common::AudioDeviceDescription& device);
aidl::android::media::audio::common::AudioDeviceDescription getForcedDevice() const {
- return mForceDevice;
+ return mVirtualizerForcedDevice;
}
std::vector<Virtualizer::ChannelAngle> getSpeakerAngles(
const Virtualizer::SpeakerAnglesPayload payload);
@@ -93,8 +93,6 @@
bool mEnabled = false;
LVM_Handle_t mInstance;
- aidl::android::media::audio::common::AudioDeviceDescription mVirtualizerForcedDevice;
-
int mSamplesPerSecond = 0;
int mSamplesToExitCountEq = 0;
int mSamplesToExitCountBb = 0;
@@ -120,7 +118,7 @@
// Virtualizer
int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
bool mVirtualizerTempDisabled = false;
- ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice;
+ ::aidl::android::media::audio::common::AudioDeviceDescription mVirtualizerForcedDevice;
// Volume
float mLevelSaveddB = 0; /* for when mute is set, level must be saved */
float mVolumedB = 0;
diff --git a/services/audioflinger/datapath/AudioStreamOut.cpp b/services/audioflinger/datapath/AudioStreamOut.cpp
index 9851f3a..aad538f 100644
--- a/services/audioflinger/datapath/AudioStreamOut.cpp
+++ b/services/audioflinger/datapath/AudioStreamOut.cpp
@@ -64,7 +64,7 @@
int32_t deltaHalPosition; // initialization not needed, overwitten by __builtin_sub_overflow()
(void) __builtin_sub_overflow(halPosition, truncatedPosition, &deltaHalPosition);
- if (deltaHalPosition > 0) {
+ if (deltaHalPosition >= 0) {
mRenderPosition += deltaHalPosition;
} else if (mExpectRetrograde) {
mExpectRetrograde = false;
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index c2e4b11..b92cd70 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -32,11 +32,15 @@
class EffectDescriptor : public RefBase
{
public:
- EffectDescriptor(const effect_descriptor_t *desc, bool isMusicEffect,
- int id, audio_io_handle_t io, audio_session_t session) :
- mId(id), mIo(io), mSession(session), mEnabled(false), mSuspended(false),
- mIsMusicEffect(isMusicEffect)
- {
+ EffectDescriptor(const effect_descriptor_t* desc, bool isMusicEffect, int id,
+ audio_io_handle_t io, audio_session_t session)
+ : mId(id),
+ mIo(io),
+ mIsOrphan(io == AUDIO_IO_HANDLE_NONE),
+ mSession(session),
+ mEnabled(false),
+ mSuspended(false),
+ mIsMusicEffect(isMusicEffect) {
memcpy (&mDesc, desc, sizeof(effect_descriptor_t));
}
@@ -95,11 +99,22 @@
* @return ioHandle if found, AUDIO_IO_HANDLE_NONE otherwise.
*/
audio_io_handle_t getIoForSession(audio_session_t sessionId,
- const effect_uuid_t *effectType = nullptr);
- bool hasOrphansForSession(audio_session_t sessionId);
+ const effect_uuid_t *effectType = nullptr) const;
+ bool hasOrphansForSession(audio_session_t sessionId) const;
EffectDescriptorCollection getOrphanEffectsForSession(audio_session_t sessionId) const;
void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
+ /**
+ * @brief Checks if there is at least one orphan effect with given sessionId and effect type
+ * uuid.
+ * @param sessionId Session ID.
+ * @param effectType Effect type UUID, the implementation will be same as hasOrphansForSession
+ * if null.
+ * @return True if there is an orphan effect for given sessionId and type UUID, false otherwise.
+ */
+ bool hasOrphanEffectsForSessionAndType(audio_session_t sessionId,
+ const effect_uuid_t* effectType) const;
+
private:
status_t setEffectEnabled(const sp<EffectDescriptor> &effectDesc, bool enabled);
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index c85df0f..7971b61 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -210,7 +210,7 @@
}
}
-bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId)
+bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId) const
{
for (size_t i = 0; i < size(); ++i) {
sp<EffectDescriptor> effect = valueAt(i);
@@ -221,6 +221,22 @@
return false;
}
+bool EffectDescriptorCollection::hasOrphanEffectsForSessionAndType(
+ audio_session_t sessionId, const effect_uuid_t* effectType) const {
+ if (effectType == nullptr) {
+ return hasOrphansForSession(sessionId);
+ }
+
+ for (size_t i = 0; i < size(); ++i) {
+ sp<EffectDescriptor> effect = valueAt(i);
+ if (effect->mIsOrphan && effect->mSession == sessionId &&
+ memcmp(&effect->mDesc.type, effectType, sizeof(effect_uuid_t)) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
EffectDescriptorCollection EffectDescriptorCollection::getOrphanEffectsForSession(
audio_session_t sessionId) const
{
@@ -235,7 +251,7 @@
}
audio_io_handle_t EffectDescriptorCollection::getIoForSession(audio_session_t sessionId,
- const effect_uuid_t *effectType)
+ const effect_uuid_t *effectType) const
{
for (size_t i = 0; i < size(); ++i) {
sp<EffectDescriptor> effect = valueAt(i);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8ef76c6..f767522 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2069,6 +2069,8 @@
// matching criteria values in priority order for best matching output so far
std::vector<uint32_t> bestMatchCriteria(8, 0);
+ const bool hasOrphanHaptic =
+ mEffects.hasOrphanEffectsForSessionAndType(sessionId, FX_IID_HAPTICGENERATOR);
const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(
channelMask & AUDIO_CHANNEL_HAPTIC_ALL);
@@ -2089,13 +2091,20 @@
// When using haptic output, same audio format and sample rate are required.
const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
- if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
+ // skip if haptic channel specified but output does not support it, or output support haptic
+ // but there is no haptic channel requested AND no orphan haptic effect exist
+ if ((hapticChannelCount != 0 && outputHapticChannelCount == 0) ||
+ (hapticChannelCount == 0 && outputHapticChannelCount != 0 && !hasOrphanHaptic)) {
continue;
}
- if (outputHapticChannelCount >= hapticChannelCount
- && format == outputDesc->getFormat()
- && samplingRate == outputDesc->getSamplingRate()) {
- currentMatchCriteria[0] = outputHapticChannelCount;
+ // In the case of audio-coupled-haptic playback, there is no format conversion and
+ // resampling in the framework, same format/channel/sampleRate for client and the output
+ // thread is required. In the case of HapticGenerator effect, do not require format
+ // matching.
+ if ((outputHapticChannelCount >= hapticChannelCount && format == outputDesc->getFormat() &&
+ samplingRate == outputDesc->getSamplingRate()) ||
+ (hapticChannelCount == 0 && hasOrphanHaptic)) {
+ currentMatchCriteria[0] = outputHapticChannelCount;
}
// functional flags match