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

Commit 380cf5d5 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

libaudiohal@aidl: Update FMQ error reporting handler

Switch to use the error handler mechanism of the FMQ.
Make the TimeCheck function which sends the debugger
signal to HALs available and use it in the error
handler.

Bug: 338974476
Test: m
Change-Id: I1525a9d3607cce470bf42d3bbcd555b5f9d53af2
parent 6413b8bf
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.