audio: Mitigate double receiving of the "exit" command
In rare cases, a worker thread from a new stream created via StreamSwitcher can read again from the command FMQ the "exit" command which was sent to the worker of the previous stream. The underlying reason for that has to be investigated. For now, mitigate the issue by salting the cookie of the "exit" command with the worker's TID. Bug: 300130515 Test: atest VtsHalAudioCoreTargetTest Change-Id: Ie7d2e847e8b39414ffd31afd64e32d4c9a292c03
This commit is contained in:
parent
05f682fd3d
commit
0e7bcae462
2 changed files with 14 additions and 3 deletions
|
@ -14,6 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define LOG_TAG "AHAL_Stream"
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_ibinder_platform.h>
|
||||
|
@ -94,6 +96,14 @@ void StreamContext::reset() {
|
|||
mDataMQ.reset();
|
||||
}
|
||||
|
||||
pid_t StreamWorkerCommonLogic::getTid() const {
|
||||
#if defined(__ANDROID__)
|
||||
return pthread_gettid_np(pthread_self());
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string StreamWorkerCommonLogic::init() {
|
||||
if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
|
||||
if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
|
||||
|
@ -164,7 +174,7 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
|
|||
switch (command.getTag()) {
|
||||
case Tag::halReservedExit:
|
||||
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
||||
cookie == mContext->getInternalCommandCookie()) {
|
||||
cookie == (mContext->getInternalCommandCookie() ^ getTid())) {
|
||||
mDriver->shutdown();
|
||||
setClosed();
|
||||
// This is an internal command, no need to reply.
|
||||
|
@ -384,7 +394,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
|||
switch (command.getTag()) {
|
||||
case Tag::halReservedExit:
|
||||
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
||||
cookie == mContext->getInternalCommandCookie()) {
|
||||
cookie == (mContext->getInternalCommandCookie() ^ getTid())) {
|
||||
mDriver->shutdown();
|
||||
setClosed();
|
||||
// This is an internal command, no need to reply.
|
||||
|
@ -717,7 +727,7 @@ void StreamCommonImpl::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>(
|
||||
mContext.getInternalCommandCookie());
|
||||
mContext.getInternalCommandCookie() ^ mWorker->getTid());
|
||||
// Note: never call 'pause' and 'resume' methods of StreamWorker
|
||||
// in the HAL implementation. These methods are to be used by
|
||||
// the client side only. Preventing the worker loop from running
|
||||
|
|
|
@ -223,6 +223,7 @@ class StreamWorkerCommonLogic : public ::android::hardware::audio::common::Strea
|
|||
: mContext(context),
|
||||
mDriver(driver),
|
||||
mTransientStateDelayMs(context->getTransientStateDelayMs()) {}
|
||||
pid_t getTid() const;
|
||||
std::string init() override;
|
||||
void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
|
||||
void populateReplyWrongState(StreamDescriptor::Reply* reply,
|
||||
|
|
Loading…
Reference in a new issue