Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe0d9296 authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Gerrit Code Review
Browse files

Merge "libaudiohal@aidl: Update FMQ error reporting handler" into main

parents f320a4a8 380cf5d5
Loading
Loading
Loading
Loading
+23 −7
Original line number Diff line number Diff line
@@ -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
@@ -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() {
@@ -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);
@@ -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;
}
+22 −13
Original line number Diff line number Diff line
@@ -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{};
@@ -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());

+1 −0
Original line number Diff line number Diff line
@@ -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.