Loading media/libaudiohal/impl/StreamHalAidl.cpp +23 −19 Original line number Diff line number Diff line Loading @@ -506,6 +506,8 @@ status_t StreamHalAidl::sendCommand( "%s %s: must be invoked from the worker thread (%d)", __func__, command.toString().c_str(), workerTid); } { 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; Loading @@ -515,7 +517,8 @@ status_t StreamHalAidl::sendCommand( reply = &localReply; } if (!mContext.getReplyMQ()->readBlocking(reply, 1)) { ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str()); ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str()); return NOT_ENOUGH_DATA; } { Loading @@ -528,6 +531,7 @@ status_t StreamHalAidl::sendCommand( mLastReply = *reply; mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs; } } switch (reply->status) { case STATUS_OK: return OK; case STATUS_BAD_VALUE: return BAD_VALUE; Loading media/libaudiohal/impl/StreamHalAidl.h +11 −0 Original line number Diff line number Diff line Loading @@ -243,6 +243,15 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper 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) { Loading @@ -256,6 +265,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper 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, Loading Loading
media/libaudiohal/impl/StreamHalAidl.cpp +23 −19 Original line number Diff line number Diff line Loading @@ -506,6 +506,8 @@ status_t StreamHalAidl::sendCommand( "%s %s: must be invoked from the worker thread (%d)", __func__, command.toString().c_str(), workerTid); } { 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; Loading @@ -515,7 +517,8 @@ status_t StreamHalAidl::sendCommand( reply = &localReply; } if (!mContext.getReplyMQ()->readBlocking(reply, 1)) { ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str()); ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str()); return NOT_ENOUGH_DATA; } { Loading @@ -528,6 +531,7 @@ status_t StreamHalAidl::sendCommand( mLastReply = *reply; mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs; } } switch (reply->status) { case STATUS_OK: return OK; case STATUS_BAD_VALUE: return BAD_VALUE; Loading
media/libaudiohal/impl/StreamHalAidl.h +11 −0 Original line number Diff line number Diff line Loading @@ -243,6 +243,15 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper 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) { Loading @@ -256,6 +265,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper 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, Loading