/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2020-2020. All rights reserved. * Description: On behalf of a display device, hwcomposer is called for composition and sent for display * Author: Hisilicon * Created: 2020.08.04 */ #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL) #include #include #include #include "FenceMonitor.h" namespace android { HwcLayerFence::HwcLayerFence(const sp &fence, hwc2_layer_t layerId, uint64_t seq) : m_fence(fence), m_layerid(layerId), m_seq(seq) {} HwcLayerFence::~HwcLayerFence() {} nsecs_t HwcLayerFence::GetSignalTime() const { return m_fence->getSignalTime(); } status_t HwcLayerFence::WaitForever(std::string msg) { return m_fence->waitForever(msg.c_str()); } int HwcLayerFence::Get() const { return m_fence->get(); } bool HwcLayerFence::HasSignaled() const { return (m_fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING); } const sp &HwcLayerFence::GetFence() { return m_fence; } std::string HwcLayerFence::GetString() const { std::stringstream os; os << " "; os << "layer_id:" << m_layerid << " fence seq:" << m_seq << " State: " << (HasSignaled() ? "Signaled" : "Waiting"); if (!HasSignaled() && (m_timestamp != 0)) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); double dur = (now - m_timestamp) / static_cast((TIME_CONVERSION_LEVEL * TIME_CONVERSION_LEVEL)); os << " for " << dur << " ms"; } return os.str(); } hwc2_layer_t HwcLayerFence::GetLayerId() const { return m_layerid; } uint64_t HwcLayerFence::GetSeq() const { return m_seq; } inline void HwcLayerFence::UpdateTimeStamp() { if (m_timestamp == 0) { m_timestamp = systemTime(SYSTEM_TIME_MONOTONIC); } } FenceMonitor::FenceMonitor(const std::string &name) : mName(name), mFencesQueued(0), mFencesSignaled(0) { std::thread thread(&FenceMonitor::Loop, this); pthread_setname_np(thread.native_handle(), mName.c_str()); thread.detach(); } FenceMonitor::~FenceMonitor() {} std::string FenceMonitor::Dump() { std::stringstream os; std::lock_guard lock(mMutex); os << mName << ":" << std::endl; for (auto fence = mQueue.cbegin(); fence != mQueue.cend(); ++fence) { os << " " << (*fence)->GetString() << std::endl; } return os.str(); } void FenceMonitor::QueueFence(const sp &fence) { const int maxMsgLen = 100; char message[maxMsgLen] = {0}; std::lock_guard lock(mMutex); if (fence->GetSignalTime() != Fence::SIGNAL_TIME_PENDING) { int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "%s fence:%llu %llu - %llu has signaled", mName.c_str(), fence->GetSeq(), fence->GetLayerId(), mFencesQueued); HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret)); ATRACE_NAME(message); // Need an increment on both to make the trace number correct. mFencesQueued++; mFencesSignaled++; return; } int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "Trace %s fence:%llu %llu - %llu", mName.c_str(), fence->GetSeq(), fence->GetLayerId(), mFencesQueued); HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret)); ATRACE_NAME(message); fence->UpdateTimeStamp(); mQueue.push_back(fence); mCondition.notify_one(); mFencesQueued++; ATRACE_INT(mName.c_str(), int32_t(mQueue.size())); } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-noreturn" void FenceMonitor::Loop() { while (true) { ThreadLoop(); } } #pragma clang diagnostic pop void FenceMonitor::ThreadLoop() { sp fence; const int maxMsgLen = 100; uint64_t fenceNum; { std::unique_lock lock(mMutex); while (mQueue.empty()) { mCondition.wait(lock); } fence = mQueue[0]; fenceNum = mFencesSignaled; } { char message[maxMsgLen] = {0}; if (fence->GetSignalTime() != Fence::SIGNAL_TIME_PENDING) { int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "%s fence:%llu %llu - %llu has signaled", mName.c_str(), fence->GetSeq(), fence->GetLayerId(), fenceNum); HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret)); ATRACE_NAME(message); } else { int ret = snprintf_s(message, sizeof(message), sizeof(message) - 1, "waiting for %s:%llu %llu - %llu", mName.c_str(), fence->GetSeq(), fence->GetLayerId(), fenceNum); HWC_CHK_RETURN_NOT_VALUE((ret < 0), ALOGE("snprintf_s message failed(0x%x)", ret)); ATRACE_NAME(message); std::string msg = message; status_t result = fence->WaitForever(msg); if (result != OK) { ALOGE("Error waiting for fence: %d", result); } } } { std::lock_guard lock(mMutex); mQueue.pop_front(); mFencesSignaled++; ATRACE_INT(mName.c_str(), int32_t(mQueue.size())); } } FenceMonitorMng::FenceMonitorMng() {} FenceMonitorMng::~FenceMonitorMng() {} void FenceMonitorMng::AddFence(int fd, FENCE_TYPE type, hwc2_layer_t layerid, uint64_t seq) { if (type >= FENCE_TYPE_ENUM::FENCE_TYPE_NUM) { return; } if (m_fenceMonior[(int)type] == nullptr) { m_fenceMonior[(int)type] = std::make_unique(G_FENCE_TYPE_NMAE[(int)type]); } m_fenceMonior[(int)type]->QueueFence(new HwcLayerFence(new Fence(dup(fd)), layerid, seq)); } std::string FenceMonitorMng::Dump() const { std::stringstream os; os << "HWC fence monitor:" << std::endl; for (int i = 0; i < static_cast(FENCE_TYPE_ENUM::FENCE_TYPE_NUM); i++) { if (m_fenceMonior[i] != nullptr) { os << " " << m_fenceMonior[i]->Dump() << std::endl; } } return os.str(); } } // end namespace