Loading media/libaudiohal/impl/StreamHalAidl.cpp +23 −7 Original line number Diff line number Diff line Loading @@ -59,6 +59,16 @@ template<HalCommand::Tag cmd> HalCommand makeHalCommand() { template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) { return HalCommand::make<cmd>(data); } template <typename MQTypeError> auto fmqErrorHandler(const char* mqName) { return [m = std::string(mqName)](MQTypeError fmqError, std::string&& errorMessage) { mediautils::TimeCheck::signalAudioHals(); LOG_ALWAYS_FATAL_IF(fmqError != MQTypeError::NONE, "%s: %s", m.c_str(), errorMessage.c_str()); }; } } // namespace // static Loading Loading @@ -103,6 +113,17 @@ StreamHalAidl::StreamHalAidl(std::string_view className, bool isInput, const aud StreamHalAidl::getAudioProperties(&config) == NO_ERROR) { mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format); } if (mStream != nullptr) { mContext.getCommandMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::CommandMQ::Error>("CommandMQ")); mContext.getReplyMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::ReplyMQ::Error>("ReplyMQ")); if (mContext.getDataMQ() != nullptr) { mContext.getDataMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::DataMQ::Error>("DataMQ")); } } } StreamHalAidl::~StreamHalAidl() { Loading Loading @@ -388,11 +409,8 @@ status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred return INVALID_OPERATION; } } StreamContextAidl::DataMQ::Error fmqError = StreamContextAidl::DataMQ::Error::NONE; std::string fmqErrorMsg; if (!mIsInput) { bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite(&fmqError, &fmqErrorMsg)); bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite()); } StreamDescriptor::Command burst = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes); Loading @@ -409,14 +427,12 @@ status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred LOG_ALWAYS_FATAL_IF(*transferred > bytes, "%s: HAL module read %zu bytes, which exceeds requested count %zu", __func__, *transferred, bytes); if (auto toRead = mContext.getDataMQ()->availableToRead(&fmqError, &fmqErrorMsg); if (auto toRead = mContext.getDataMQ()->availableToRead(); toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) { AUGMENT_LOG(E, "failed to read %zu bytes to data MQ", toRead); return NOT_ENOUGH_DATA; } } LOG_ALWAYS_FATAL_IF(fmqError != StreamContextAidl::DataMQ::Error::NONE, "%s", fmqErrorMsg.c_str()); mStreamPowerLog.log(buffer, *transferred); return OK; } Loading media/utils/TimeCheck.cpp +22 −13 Original line number Diff line number Diff line Loading @@ -183,6 +183,22 @@ std::vector<pid_t> TimeCheck::getAudioHalPids() { return pids; } /* static */ std::string TimeCheck::signalAudioHals() { std::vector<pid_t> pids = getAudioHalPids(); std::string halPids; if (pids.size() != 0) { for (const auto& pid : pids) { ALOGI("requesting tombstone for pid: %d", pid); halPids.append(std::to_string(pid)).append(" "); signalAudioHAL(pid); } // Allow time to complete, usually the caller is forcing restart afterwards. sleep(1); } return halPids; } /* static */ TimerThread& TimeCheck::getTimeCheckThread() { static TimerThread sTimeCheckThread{}; Loading Loading @@ -302,21 +318,14 @@ void TimeCheck::TimeCheckHandler::onTimeout(TimerThread::Handle timerHandle) con // HAL processes which can affect thread behavior. const auto snapshotAnalysis = getTimeCheckThread().getSnapshotAnalysis(4 /* retiredCount */); // Generate audio HAL processes tombstones and allow time to complete // before forcing restart std::vector<pid_t> pids = TimeCheck::getAudioHalPids(); std::string halPids = "HAL pids [ "; if (pids.size() != 0) { for (const auto& pid : pids) { ALOGI("requesting tombstone for pid: %d", pid); halPids.append(std::to_string(pid)).append(" "); signalAudioHAL(pid); } sleep(1); // Generate audio HAL processes tombstones. std::string halPids = signalAudioHals(); if (!halPids.empty()) { halPids = "HAL pids [ " + halPids + "]"; } else { ALOGI("No HAL process pid available, skipping tombstones"); halPids = "No HAL process pids available"; ALOGI("%s", (halPids + ", skipping tombstones").c_str()); } halPids.append("]"); LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag.c_str()); Loading media/utils/include/mediautils/TimeCheck.h +1 −0 Original line number Diff line number Diff line Loading @@ -107,6 +107,7 @@ class TimeCheck { static std::string toString(); static void setAudioHalPids(const std::vector<pid_t>& pids); static std::vector<pid_t> getAudioHalPids(); static std::string signalAudioHals(); private: // Helper class for handling events. Loading Loading
media/libaudiohal/impl/StreamHalAidl.cpp +23 −7 Original line number Diff line number Diff line Loading @@ -59,6 +59,16 @@ template<HalCommand::Tag cmd> HalCommand makeHalCommand() { template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) { return HalCommand::make<cmd>(data); } template <typename MQTypeError> auto fmqErrorHandler(const char* mqName) { return [m = std::string(mqName)](MQTypeError fmqError, std::string&& errorMessage) { mediautils::TimeCheck::signalAudioHals(); LOG_ALWAYS_FATAL_IF(fmqError != MQTypeError::NONE, "%s: %s", m.c_str(), errorMessage.c_str()); }; } } // namespace // static Loading Loading @@ -103,6 +113,17 @@ StreamHalAidl::StreamHalAidl(std::string_view className, bool isInput, const aud StreamHalAidl::getAudioProperties(&config) == NO_ERROR) { mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format); } if (mStream != nullptr) { mContext.getCommandMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::CommandMQ::Error>("CommandMQ")); mContext.getReplyMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::ReplyMQ::Error>("ReplyMQ")); if (mContext.getDataMQ() != nullptr) { mContext.getDataMQ()->setErrorHandler( fmqErrorHandler<StreamContextAidl::DataMQ::Error>("DataMQ")); } } } StreamHalAidl::~StreamHalAidl() { Loading Loading @@ -388,11 +409,8 @@ status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred return INVALID_OPERATION; } } StreamContextAidl::DataMQ::Error fmqError = StreamContextAidl::DataMQ::Error::NONE; std::string fmqErrorMsg; if (!mIsInput) { bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite(&fmqError, &fmqErrorMsg)); bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite()); } StreamDescriptor::Command burst = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes); Loading @@ -409,14 +427,12 @@ status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred LOG_ALWAYS_FATAL_IF(*transferred > bytes, "%s: HAL module read %zu bytes, which exceeds requested count %zu", __func__, *transferred, bytes); if (auto toRead = mContext.getDataMQ()->availableToRead(&fmqError, &fmqErrorMsg); if (auto toRead = mContext.getDataMQ()->availableToRead(); toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) { AUGMENT_LOG(E, "failed to read %zu bytes to data MQ", toRead); return NOT_ENOUGH_DATA; } } LOG_ALWAYS_FATAL_IF(fmqError != StreamContextAidl::DataMQ::Error::NONE, "%s", fmqErrorMsg.c_str()); mStreamPowerLog.log(buffer, *transferred); return OK; } Loading
media/utils/TimeCheck.cpp +22 −13 Original line number Diff line number Diff line Loading @@ -183,6 +183,22 @@ std::vector<pid_t> TimeCheck::getAudioHalPids() { return pids; } /* static */ std::string TimeCheck::signalAudioHals() { std::vector<pid_t> pids = getAudioHalPids(); std::string halPids; if (pids.size() != 0) { for (const auto& pid : pids) { ALOGI("requesting tombstone for pid: %d", pid); halPids.append(std::to_string(pid)).append(" "); signalAudioHAL(pid); } // Allow time to complete, usually the caller is forcing restart afterwards. sleep(1); } return halPids; } /* static */ TimerThread& TimeCheck::getTimeCheckThread() { static TimerThread sTimeCheckThread{}; Loading Loading @@ -302,21 +318,14 @@ void TimeCheck::TimeCheckHandler::onTimeout(TimerThread::Handle timerHandle) con // HAL processes which can affect thread behavior. const auto snapshotAnalysis = getTimeCheckThread().getSnapshotAnalysis(4 /* retiredCount */); // Generate audio HAL processes tombstones and allow time to complete // before forcing restart std::vector<pid_t> pids = TimeCheck::getAudioHalPids(); std::string halPids = "HAL pids [ "; if (pids.size() != 0) { for (const auto& pid : pids) { ALOGI("requesting tombstone for pid: %d", pid); halPids.append(std::to_string(pid)).append(" "); signalAudioHAL(pid); } sleep(1); // Generate audio HAL processes tombstones. std::string halPids = signalAudioHals(); if (!halPids.empty()) { halPids = "HAL pids [ " + halPids + "]"; } else { ALOGI("No HAL process pid available, skipping tombstones"); halPids = "No HAL process pids available"; ALOGI("%s", (halPids + ", skipping tombstones").c_str()); } halPids.append("]"); LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag.c_str()); Loading
media/utils/include/mediautils/TimeCheck.h +1 −0 Original line number Diff line number Diff line Loading @@ -107,6 +107,7 @@ class TimeCheck { static std::string toString(); static void setAudioHalPids(const std::vector<pid_t>& pids); static std::vector<pid_t> getAudioHalPids(); static std::string signalAudioHals(); private: // Helper class for handling events. Loading