* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_HDI_DISPLAY_V1_0_DISPLAY_CMD_REQUESTER_H
#define OHOS_HDI_DISPLAY_V1_0_DISPLAY_CMD_REQUESTER_H
#include <fstream>
#include <poll.h>
#include <securec.h>
#include <sstream>
#include <string>
#include <sys/time.h>
#include <unistd.h>
#include <unordered_map>
#include <queue>
#include "base/hdi_smq.h"
#include "buffer_handle_utils.h"
#include "command_pack/command_data_packer.h"
#include "command_pack/command_data_unpacker.h"
#include "display_cmd_utils.h"
#include "hdf_base.h"
#include "hdf_trace.h"
#include "hdifd_parcelable.h"
#include "hilog/log.h"
#include "idisplay_composer_vdi.h"
#include "parameter.h"
#include "v1_0/display_composer_type.h"
#include "v1_0/mapper_stub.h"
#include "common/include/display_vdi_adapter_interface.h"
#define DISPLAY_TRACE HdfTrace trace(__func__, "HDI:DISP:")
namespace OHOS {
namespace HDI {
namespace Display {
namespace Composer {
namespace V1_0 {
using namespace OHOS::HDI::Base;
using namespace OHOS::HDI::Display::Composer::V1_0;
using namespace OHOS::HDI::Display::Buffer::V1_0;
using HdifdSet = std::vector<std::shared_ptr<HdifdParcelable>>;
static constexpr uint32_t TIME_BUFFER_MAX_LEN = 15;
static constexpr uint32_t BUFFER_QUEUE_MAX_SIZE = 6;
static constexpr unsigned int REDUCE_COUNT = 50;
static constexpr int32_t ERROR_FENCE_COUNT = 500;
static sptr<IMapper> g_bufferServiceImpl = nullptr;
static constexpr uint32_t COMMIT_PRINT_INTERVAL = 1200;
template <typename Transfer, typename VdiImpl>
class DisplayCmdResponser {
public:
static std::unique_ptr<DisplayCmdResponser> Create(VdiImpl* impl, std::shared_ptr<DeviceCacheManager> cacheMgr)
{
DISPLAY_CHK_RETURN(impl == nullptr, nullptr,
HDF_LOGE("%{public}s: error, VdiImpl is nullptr", __func__));
DISPLAY_CHK_RETURN(cacheMgr == nullptr, nullptr,
HDF_LOGE("%{public}s: error, cacheMgr is nullptr", __func__));
return std::make_unique<DisplayCmdResponser>(impl, cacheMgr);
}
DisplayCmdResponser(VdiImpl* impl, std::shared_ptr<DeviceCacheManager> cacheMgr)
: impl_(impl),
cacheMgr_(cacheMgr),
request_(nullptr),
isReplyUpdated_(false),
reply_(nullptr),
replyCommandCnt_(0) {}
virtual ~DisplayCmdResponser()
{
while (delayFreeQueue_.size() > 0) {
BufferHandle *temp = delayFreeQueue_.front();
delayFreeQueue_.pop();
FreeBufferHandle(temp);
temp = nullptr;
}
}
int32_t InitCmdRequest(const std::shared_ptr<Transfer>& request)
{
DISPLAY_CHK_RETURN(request == nullptr, HDF_FAILURE,
HDF_LOGE("%{public}s: error, request is nullptr", __func__));
std::lock_guard<std::mutex> lock(requestMutex_);
if (request_ != nullptr) {
request_.reset();
}
request_ = request;
return HDF_SUCCESS;
}
int32_t GetCmdReply(std::shared_ptr<Transfer>& reply)
{
std::lock_guard<std::mutex> lock(replyMutex_);
int32_t ret = HDF_SUCCESS;
if (isReplyUpdated_ == false) {
ret = InitReply(CmdUtils::INIT_ELEMENT_COUNT);
}
if (ret == HDF_SUCCESS) {
if (reply_ != nullptr) {
reply = reply_;
} else {
ret = HDF_FAILURE;
}
}
isReplyUpdated_ = false;
if (ret != HDF_SUCCESS) {
HDF_LOGE("error: GetCmdReply failure");
}
return ret;
}
int32_t ProcessRequestCmd(CommandDataUnpacker& unpacker, int32_t cmd,
const std::vector<HdifdInfo>& inFds, std::vector<HdifdInfo>& outFds)
{
int32_t ret = HDF_SUCCESS;
switch (cmd) {
case REQUEST_CMD_PREPARE_DISPLAY_LAYERS: OnPrepareDisplayLayers(unpacker); break;
case REQUEST_CMD_SET_DISPLAY_CLIENT_BUFFER: OnSetDisplayClientBuffer(unpacker, inFds); break;
case REQUEST_CMD_SET_DISPLAY_CLIENT_DAMAGE: OnSetDisplayClientDamage(unpacker); break;
case REQUEST_CMD_COMMIT: OnCommit(unpacker, outFds); break;
case REQUEST_CMD_SET_LAYER_ALPHA: OnSetLayerAlpha(unpacker); break;
case REQUEST_CMD_SET_LAYER_REGION: OnSetLayerRegion(unpacker); break;
case REQUEST_CMD_SET_LAYER_CROP: OnSetLayerCrop(unpacker); break;
case REQUEST_CMD_SET_LAYER_ZORDER: OnSetLayerZorder(unpacker); break;
case REQUEST_CMD_SET_LAYER_PREMULTI: OnSetLayerPreMulti(unpacker); break;
case REQUEST_CMD_SET_LAYER_TRANSFORM_MODE: OnSetLayerTransformMode(unpacker); break;
case REQUEST_CMD_SET_LAYER_DIRTY_REGION: OnSetLayerDirtyRegion(unpacker); break;
case REQUEST_CMD_SET_LAYER_VISIBLE_REGION: OnSetLayerVisibleRegion(unpacker); break;
case REQUEST_CMD_SET_LAYER_BUFFER: OnSetLayerBuffer(unpacker, inFds); break;
case REQUEST_CMD_SET_LAYER_COMPOSITION_TYPE: OnSetLayerCompositionType(unpacker); break;
case REQUEST_CMD_SET_LAYER_BLEND_TYPE: OnSetLayerBlendType(unpacker); break;
case REQUEST_CMD_SET_LAYER_MASK_INFO: OnSetLayerMaskInfo(unpacker); break;
case CONTROL_CMD_REQUEST_END: ret = OnRequestEnd(unpacker); break;
case REQUEST_CMD_SET_LAYER_COLOR: OnSetLayerColor(unpacker); break;
default:
HDF_LOGE("%{public}s: not support this cmd, unpacked cmd = %{public}d", __func__, cmd);
ret = HDF_FAILURE;
break;
}
return ret;
}
int32_t CmdRequest(uint32_t inEleCnt, const std::vector<HdifdInfo>& inFds, uint32_t& outEleCnt,
std::vector<HdifdInfo>& outFds)
{
if (inEleCnt > CmdUtils::MAX_ELE_COUNT) {
HDF_LOGE("%{public}s: inEleCnt:%{public}u is too large", __func__, inEleCnt);
return HDF_FAILURE;
}
std::shared_ptr<char> requestData(new char[inEleCnt * CmdUtils::ELEMENT_SIZE], std::default_delete<char[]>());
int32_t ret = HDF_SUCCESS;
{
std::lock_guard<std::mutex> lock(requestMutex_);
ret = request_->Read(reinterpret_cast<int32_t *>(requestData.get()), inEleCnt,
CmdUtils::TRANSFER_WAIT_TIME);
}
CommandDataUnpacker unpacker;
unpacker.Init(requestData.get(), inEleCnt << CmdUtils::MOVE_SIZE);
#ifdef DEBUG_DISPLAY_CMD_RAW_DATA
unpacker.Dump();
#endif
int32_t unpackCmd = -1;
bool retBool = unpacker.PackBegin(unpackCmd);
DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
HDF_LOGE("%{public}s: error: Check RequestBegin failed", __func__));
DISPLAY_CHK_RETURN(unpackCmd != CONTROL_CMD_REQUEST_BEGIN, HDF_FAILURE,
HDF_LOGI("error: unpacker PackBegin cmd not match, cmd(%{public}d)=%{public}s.", unpackCmd,
CmdUtils::CommandToString(unpackCmd)));
while (ret == HDF_SUCCESS && unpacker.NextSection()) {
if (!unpacker.BeginSection(unpackCmd)) {
HDF_LOGE("error: PackSection failed, unpackCmd=%{public}s.", CmdUtils::CommandToString(unpackCmd));
ret = HDF_FAILURE;
break;
}
ret = ProcessRequestCmd(unpacker, unpackCmd, inFds, outFds);
}
DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret, HDF_LOGE("%{public}s:ProcessRequestCmd failed", __func__));
replyPacker_.PackEnd(CONTROL_CMD_REPLY_END);
#ifdef DEBUG_DISPLAY_CMD_RAW_DATA
replyPacker_.Dump();
HDF_LOGI("CmdReply command cnt=%{public}d", replyCommandCnt_);
#endif
outEleCnt = replyPacker_.ValidSize() >> CmdUtils::MOVE_SIZE;
ret = CmdRequestDataWrite(outEleCnt);
if (ret != HDF_SUCCESS) {
HDF_LOGE("Reply write failure, ret=%{public}d", ret);
outEleCnt = 0;
}
int32_t ec = PeriodDataReset();
return (ret == HDF_SUCCESS ? ec : ret);
}
protected:
int32_t CmdRequestDataRead(std::shared_ptr<char> requestData, uint32_t inEleCnt)
{
std::lock_guard<std::mutex> lock(requestMutex_);
if (request_ == nullptr || requestData == nullptr) {
HDF_LOGE("%{public}s: inEleCnt: %{public}u request_ is nullptr", __func__, inEleCnt);
return HDF_FAILURE;
}
return request_->Read(reinterpret_cast<int32_t *>(requestData.get()), inEleCnt,
CmdUtils::TRANSFER_WAIT_TIME);
}
int32_t CmdRequestDataWrite(uint32_t outEleCnt)
{
std::lock_guard<std::mutex> lock(replyMutex_);
if (reply_ == nullptr) {
HDF_LOGE("%{public}s: reply_ is nullptr", __func__);
return HDF_FAILURE;
}
return reply_->Write(reinterpret_cast<int32_t *>(replyPacker_.GetDataPtr()), outEleCnt,
CmdUtils::TRANSFER_WAIT_TIME);
}
int32_t InitReply(uint32_t size)
{
if (size > CmdUtils::MAX_MEMORY) {
HDF_LOGE("%{public}s: size:%{public}u is too large", __func__, size);
return HDF_FAILURE;
}
reply_ = std::make_shared<Transfer>(size, SmqType::SYNCED_SMQ);
DISPLAY_CHK_RETURN(reply_ == nullptr, HDF_FAILURE,
HDF_LOGE("%{public}s: reply_ construct failed", __func__));
bool retBool = replyPacker_.Init(reply_->GetSize() << CmdUtils::MOVE_SIZE);
DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
HDF_LOGE("%{public}s: replyPacker_ init failed", __func__));
return CmdUtils::StartPack(CONTROL_CMD_REPLY_BEGIN, replyPacker_);
}
int32_t OnRequestEnd(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
size_t errCnt = errMaps_.size();
if (errCnt >= 0) {
int32_t ret = CmdUtils::StartSection(REPLY_CMD_SET_ERROR, replyPacker_);
DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret,
HDF_LOGE("%{public}s: StartSection failed", __func__));
bool result = replyPacker_.WriteUint32(errCnt);
DISPLAY_CHK_RETURN(result == false, HDF_FAILURE,
HDF_LOGE("%{public}s: write errCnt failed", __func__));
for (auto it = errMaps_.begin(); it != errMaps_.end(); ++it) {
result = replyPacker_.WriteInt32(it->first);
DISPLAY_CHK_RETURN(result == false, HDF_FAILURE,
HDF_LOGE("%{public}s: write err-cmd failed, cmdId:%{public}s",
__func__, CmdUtils::CommandToString(it->first)));
result = replyPacker_.WriteInt32(it->second);
DISPLAY_CHK_RETURN(result == false, HDF_FAILURE,
HDF_LOGE("%{public}s: write errNo failed, errNo:%{public}d", __func__, it->second));
}
result = CmdUtils::EndSection(replyPacker_);
DISPLAY_CHK_RETURN(result == false, HDF_FAILURE,
HDF_LOGE("%{public}s: write replyPacker_ EndSection failed", __func__));
replyCommandCnt_++;
}
return HDF_SUCCESS;
}
void OnPrepareDisplayLayers(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
bool needFlush = false;
uint32_t vectSize = 0;
std::vector<uint32_t> layers;
std::vector<int32_t> types;
int32_t ret = unpacker.ReadUint32(devId) ? HDF_SUCCESS : HDF_FAILURE;
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("PrepareDisplayLayers", "HDI:DISP:HARDWARE");
ret = impl_->PrepareDisplayLayers(devId, needFlush);
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("GetDisplayCompChange", "HDI:DISP:HARDWARE");
ret = impl_->GetDisplayCompChange(devId, layers, types);
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = CmdUtils::StartSection(REPLY_CMD_PREPARE_DISPLAY_LAYERS, replyPacker_);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
DISPLAY_CHECK(replyPacker_.WriteUint32(devId) == false, goto EXIT);
DISPLAY_CHECK(replyPacker_.WriteBool(needFlush) == false, goto EXIT);
vectSize = static_cast<uint32_t>(layers.size());
DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false, goto EXIT);
for (uint32_t i = 0; i < vectSize; i++) {
DISPLAY_CHECK(replyPacker_.WriteUint32(layers[i]) == false, goto EXIT);
}
vectSize = static_cast<uint32_t>(types.size());
DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false, goto EXIT);
for (uint32_t i = 0; i < vectSize; i++) {
DISPLAY_CHECK(replyPacker_.WriteUint32(types[i]) == false, goto EXIT);
}
ret = CmdUtils::EndSection(replyPacker_);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
replyCommandCnt_++;
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_PREPARE_DISPLAY_LAYERS, ret);
}
return;
}
typedef struct ClientBufferData {
uint32_t devId;
uint32_t seqNo;
int32_t fence;
BufferHandle *buffer;
bool isValidBuffer;
} ClientBufferData;
int32_t UnpackDisplayClientBufferInfo(CommandDataUnpacker& unpacker,
const std::vector<HdifdInfo>& inFds, ClientBufferData& data)
{
if (!unpacker.ReadUint32(data.devId)) {
return HDF_FAILURE;
}
if (CmdUtils::BufferHandleUnpack(unpacker, inFds, data.buffer) != HDF_SUCCESS) {
data.isValidBuffer = false;
HDF_LOGE("%{public}s, read buffer handle error", __func__);
return HDF_FAILURE;
}
data.isValidBuffer = true;
if (!unpacker.ReadUint32(data.seqNo)) {
HDF_LOGE("%{public}s, read seqNo error", __func__);
return HDF_FAILURE;
}
if (CmdUtils::FileDescriptorUnpack(unpacker, inFds, data.fence) != HDF_SUCCESS) {
HDF_LOGE("%{public}s, FileDescriptorUnpack error", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SetDisplayClientBuffer(ClientBufferData& data, bool &needFreeBuffer, bool &needMoveFd, int fd)
{
if (cacheMgr_ == nullptr) {
HDF_LOGE("%{public}s, get cache manager error", __func__);
return HDF_FAILURE;
}
std::lock_guard<std::mutex> lock(cacheMgr_->GetCacheMgrMutex());
DeviceCache* devCache = cacheMgr_->DeviceCacheInstance(data.devId);
if (devCache == nullptr) {
HDF_LOGE("%{public}s, get device cache error", __func__);
return HDF_FAILURE;
}
int32_t ret = devCache->SetDisplayClientBuffer(data.buffer, data.seqNo, needFreeBuffer,
[&](const BufferHandle& handle)->int32_t {
#ifdef DISPLAY_COMSPOER_DEBUG_DUMP
DumpLayerBuffer(data.devId, data.seqNo, data.fence, handle, "client_");
#endif
std::string traceMsg = "";
if (data.buffer == nullptr) {
traceMsg = "data.buffer is nullptr! seqNo:" + std::to_string(data.seqNo);
} else {
traceMsg = "HDI:DISP:HARDWARE "
"height:" + std::to_string(data.buffer->height) +
" width:" + std::to_string(data.buffer->width) +
" data.buffer->fd:" + std::to_string(data.buffer->fd) +
" seqNo:" + std::to_string(data.seqNo);
}
traceMsg += " fd:" + std::to_string(fd);
if (data.fence > ERROR_FENCE_COUNT) {
HDF_LOGI("SetDisplayClientBuffer: %{public}s", traceMsg.c_str());
}
HdfTrace traceVdi("SetDisplayClientBuffer", traceMsg);
needMoveFd = true;
int rc = impl_->SetDisplayClientBuffer(data.devId, handle, fd);
DISPLAY_CHK_RETURN(rc != HDF_SUCCESS, HDF_FAILURE, HDF_LOGE(" fail"));
return HDF_SUCCESS;
});
return ret;
}
void OnSetDisplayClientBuffer(CommandDataUnpacker& unpacker, const std::vector<HdifdInfo>& inFds)
{
DISPLAY_TRACE;
ClientBufferData data = {0};
data.fence = -1;
bool needFreeBuffer = false;
bool needMoveFd = false;
int32_t ret = UnpackDisplayClientBufferInfo(unpacker, inFds, data);
HdifdParcelable fdParcel(data.fence);
if (ret == HDF_SUCCESS) {
ret = SetDisplayClientBuffer(data, needFreeBuffer, needMoveFd, fdParcel.GetFd());
}
#ifndef DISPLAY_COMMUNITY
if (data.buffer != nullptr && needFreeBuffer) {
FreeBufferWithDelay(data.buffer);
data.buffer = nullptr;
data.isValidBuffer = false;
}
if (needMoveFd) {
fdParcel.Move();
}
#endif
if (ret != HDF_SUCCESS) {
HDF_LOGE("%{public}s, SetDisplayClientBuffer error", __func__);
errMaps_.emplace(REQUEST_CMD_SET_DISPLAY_CLIENT_BUFFER, ret);
}
}
void OnSetDisplayClientDamage(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t vectSize = 0;
bool retBool = true;
DISPLAY_CHK_CONDITION(retBool, true, unpacker.ReadUint32(devId),
HDF_LOGE("%{public}s, read devId error", __func__));
DISPLAY_CHK_CONDITION(retBool, true, unpacker.ReadUint32(vectSize),
HDF_LOGE("%{public}s, read vectSize error", __func__));
int32_t ret = (retBool ? HDF_SUCCESS : HDF_FAILURE);
std::vector<IRect> rects(vectSize);
if (ret == HDF_SUCCESS) {
for (uint32_t i = 0; i < vectSize; i++) {
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::RectUnpack(unpacker, rects[i]),
HDF_LOGE("%{public}s, read vect error at i = %{public}d", __func__, i));
if (ret != HDF_SUCCESS) {
break;
}
}
}
if (ret == HDF_SUCCESS) {
HdfTrace traceVdi("SetDisplayClientDamage", "HDI:DISP:HARDWARE");
impl_->SetDisplayClientDamage(devId, rects);
} else {
HDF_LOGE("%{public}s, SetDisplayClientDamage error", __func__);
errMaps_.emplace(REQUEST_CMD_SET_DISPLAY_CLIENT_DAMAGE, ret);
}
return;
}
void OnCommit(CommandDataUnpacker& unpacker, std::vector<HdifdInfo>& outFds)
{
DISPLAY_TRACE;
uint32_t devId = 0;
int32_t fence = -1;
#ifdef DISPLAY_COMSPOER_DEBUG_DUMP
const std::string SWITCH_ON = "on";
const uint32_t DUMP_CACHE_SWITCH_LEN = 4;
char dumpSwitch[DUMP_CACHE_SWITCH_LEN] = {0};
GetParameter("hdi.composer.dumpcache", "off", dumpSwitch, DUMP_CACHE_SWITCH_LEN);
if (SWITCH_ON.compare(dumpSwitch) == 0) {
cacheMgr_->Dump();
}
#endif
int32_t ret = HDF_SUCCESS;
if (!unpacker.ReadUint32(devId)) {
HDF_LOGE("%{public}s, read devId error", __func__);
ret = HDF_FAILURE;
goto REPLY;
}
{
HdfTrace traceVdi("Commit", "HDI:DISP:HARDWARE");
ret = impl_->Commit(devId, fence);
}
static unsigned int count = 0;
if (ret == HDF_SUCCESS) {
count = 0;
} else {
if (++count > REDUCE_COUNT) {
HDF_LOGE("%{public}s, commit failed with ret = %{public}d", __func__, ret);
count = 0;
}
}
REPLY:
HdifdParcelable fdParcel(fence);
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::StartSection(REPLY_CMD_COMMIT, replyPacker_),
HDF_LOGE("%{public}s, StartSection error", __func__));
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::FileDescriptorPack(fdParcel.GetFd(), replyPacker_, outFds),
HDF_LOGE("%{public}s, FileDescriptorPack error", __func__));
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::EndSection(replyPacker_),
HDF_LOGE("%{public}s, EndSection error", __func__));
replyCommandCnt_++;
#ifndef DISPLAY_COMMUNITY
fdParcel.Move();
#endif
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_COMMIT, ret);
}
return;
}
void OnSetLayerAlpha(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
LayerAlpha alpha = {0};
bool retBool = true;
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
retBool = unpacker.ReadBool(alpha.enGlobalAlpha);
DISPLAY_CHECK(retBool == false, goto EXIT);
retBool = unpacker.ReadBool(alpha.enPixelAlpha);
DISPLAY_CHECK(retBool == false, goto EXIT);
retBool = unpacker.ReadUint8(alpha.alpha0);
DISPLAY_CHECK(retBool == false, goto EXIT);
retBool = unpacker.ReadUint8(alpha.alpha1);
DISPLAY_CHECK(retBool == false, goto EXIT);
retBool = unpacker.ReadUint8(alpha.gAlpha);
DISPLAY_CHECK(retBool == false, goto EXIT);
{
HdfTrace traceVdi("SetLayerAlpha", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerAlpha(devId, layerId, alpha);
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS || retBool == false) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_ALPHA, ret);
}
return;
}
void OnSetLayerRegion(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
IRect rect = {0};
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = CmdUtils::RectUnpack(unpacker, rect);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerRegion", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerRegion(devId, layerId, rect);
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_REGION, ret);
}
return;
}
void OnSetLayerCrop(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
IRect rect = {0};
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = CmdUtils::RectUnpack(unpacker, rect);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerCrop", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerCrop(devId, layerId, rect);
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_CROP, ret);
}
return;
}
int32_t CheckBufferNotExist(uint32_t devId, uint32_t layerId)
{
if (cacheMgr_ == nullptr) {
HDF_LOGE("%{public}s, cacheMgr_ is null, devId:%{public}d, layerId:%{public}d",
__func__, devId, layerId);
return HDF_FAILURE;
}
std::lock_guard<std::mutex> lock(cacheMgr_->GetCacheMgrMutex());
DeviceCache* devCache = cacheMgr_->DeviceCacheInstance(devId);
if (devCache == nullptr) {
HDF_LOGE("%{public}s, devCache is null, devId:%{public}d, layerId:%{public}d",
__func__, devId, layerId);
return HDF_FAILURE;
}
LayerCache* layerCache = devCache->LayerCacheInstance(layerId);
if (layerCache == nullptr) {
HDF_LOGE("%{public}s, layerCache is null, devId:%{public}d, layerId:%{public}d",
__func__, devId, layerId);
return HDF_FAILURE;
}
if (layerCache->IsBufferCacheNotExist()) {
HDF_LOGE("%{public}s, no buffer in devId:%{public}d, layerId:%{public}d",
__func__, devId, layerId);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
void OnSetLayerZorder(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
uint32_t zorder = 0;
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = unpacker.ReadUint32(zorder) ? HDF_SUCCESS : HDF_FAILURE;
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerZorder", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerZorder(devId, layerId, zorder);
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_ZORDER, ret);
}
return;
}
void OnSetLayerPreMulti(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
bool preMulti = false;
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = unpacker.ReadBool(preMulti) ? HDF_SUCCESS : HDF_FAILURE;
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerPreMulti", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerPreMulti(devId, layerId, preMulti);
}
DISPLAY_CHECK(ret != HDF_SUCCESS && ret != DISPLAY_NOT_SUPPORT && ret != HDF_ERR_NOT_SUPPORT, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_PREMULTI, ret);
}
return;
}
void OnSetLayerTransformMode(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
int32_t type = 0;
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = unpacker.ReadInt32(type) ? HDF_SUCCESS : HDF_FAILURE;
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerTransformMode", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerTransformMode(devId, layerId, static_cast<TransformType>(type));
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_TRANSFORM_MODE, ret);
}
return;
}
void OnSetLayerDirtyRegion(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
uint32_t vectSize = 0;
int32_t ret = HDF_SUCCESS;
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId),
HDF_LOGE("%{public}s, read devId error", __func__));
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, unpacker.ReadUint32(vectSize) ? HDF_SUCCESS : HDF_FAILURE,
HDF_LOGE("%{public}s, read vectSize error", __func__));
std::vector<IRect> rects(vectSize);
if (ret == HDF_SUCCESS) {
for (uint32_t i = 0; i < vectSize; i++) {
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::RectUnpack(unpacker, rects[i]),
HDF_LOGE("%{public}s, read vect error, at i = %{public}d", __func__, i));
if (ret != HDF_SUCCESS) {
break;
}
}
}
if (ret == HDF_SUCCESS) {
HdfTrace traceVdi("SetLayerDirtyRegion", "HDI:DISP:HARDWARE");
impl_->SetLayerDirtyRegion(devId, layerId, rects);
} else {
HDF_LOGE("%{public}s, SetLayerDirtyRegion error", __func__);
errMaps_.emplace(REQUEST_CMD_SET_LAYER_DIRTY_REGION, ret);
}
return;
}
void OnSetLayerVisibleRegion(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
uint32_t vectSize = 0;
int32_t ret = HDF_SUCCESS;
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId),
HDF_LOGE("%{public}s, read devId error", __func__));
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, unpacker.ReadUint32(vectSize) ? HDF_SUCCESS : HDF_FAILURE,
HDF_LOGE("%{public}s, read vectSize error", __func__));
std::vector<IRect> rects(vectSize);
if (ret == HDF_SUCCESS) {
for (uint32_t i = 0; i < vectSize; i++) {
DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::RectUnpack(unpacker, rects[i]),
HDF_LOGE("%{public}s, read vect error, at i = %{public}d", __func__, i));
if (ret != HDF_SUCCESS) {
break;
}
}
}
if (ret == HDF_SUCCESS) {
HdfTrace traceVdi("SetLayerVisibleRegion", "HDI:DISP:HARDWARE");
impl_->SetLayerVisibleRegion(devId, layerId, rects);
} else {
HDF_LOGE("%{public}s, SetLayerDirtyRegion error", __func__);
errMaps_.emplace(REQUEST_CMD_SET_LAYER_VISIBLE_REGION, ret);
}
return;
}
typedef struct LayerBufferData {
bool isValidBuffer;
uint32_t devId;
uint32_t layerId;
uint32_t seqNo;
int32_t fence;
BufferHandle *buffer;
} LayerBufferData;
int32_t UnPackLayerBufferInfo(CommandDataUnpacker& unpacker, const std::vector<HdifdInfo>& inFds,
struct LayerBufferData *data, std::vector<uint32_t> &deletingList)
{
DISPLAY_CHK_RETURN(HDF_SUCCESS != CmdUtils::SetupDeviceUnpack(unpacker, data->devId, data->layerId),
HDF_FAILURE, HDF_LOGE("%{public}s, read devId error", __func__));
DISPLAY_CHK_RETURN(HDF_SUCCESS != CmdUtils::BufferHandleUnpack(unpacker, inFds, data->buffer), HDF_FAILURE,
HDF_LOGE("%{public}s, read BufferHandleUnpack error", __func__));
data->isValidBuffer = true;
DISPLAY_CHK_RETURN(true != unpacker.ReadUint32(data->seqNo), HDF_FAILURE,
HDF_LOGE("%{public}s, read seqNo error", __func__));
DISPLAY_CHK_RETURN(HDF_SUCCESS != CmdUtils::FileDescriptorUnpack(unpacker, inFds, data->fence), HDF_FAILURE,
HDF_LOGE("%{public}s, FileDescriptorUnpack error", __func__));
uint32_t vectSize = 0;
DISPLAY_CHK_RETURN(true != unpacker.ReadUint32(vectSize), HDF_FAILURE,
HDF_LOGE("%{public}s, read vectSize error", __func__));
if (vectSize > CmdUtils::MAX_MEMORY) {
HDF_LOGE("%{public}s: vectSize:%{public}u is too large", __func__, vectSize);
return HDF_FAILURE;
}
deletingList.resize(vectSize);
for (uint32_t i = 0; i < vectSize; i++) {
DISPLAY_CHK_RETURN(true != unpacker.ReadUint32(deletingList[i]), HDF_FAILURE,
HDF_LOGE("%{public}s, read seqNo error, at i = %{public}d", __func__, i));
}
return HDF_SUCCESS;
}
int32_t SetLayerBuffer(LayerBufferData& data, std::vector<uint32_t> &deletingList,
bool &needFreeBuffer, bool &needMoveFd, int fd)
{
DISPLAY_CHECK(cacheMgr_ == nullptr, return HDF_FAILURE);
std::lock_guard<std::mutex> lock(cacheMgr_->GetCacheMgrMutex());
DeviceCache* devCache = nullptr;
LayerCache* layerCache = nullptr;
devCache = cacheMgr_->DeviceCacheInstance(data.devId);
DISPLAY_CHECK(devCache == nullptr, return HDF_FAILURE);
layerCache = devCache->LayerCacheInstance(data.layerId);
DISPLAY_CHECK(layerCache == nullptr, return HDF_FAILURE);
int32_t ret = layerCache->SetLayerBuffer(data.buffer, data.seqNo, needFreeBuffer, deletingList,
[&](const BufferHandle& handle)->int32_t {
#ifdef DISPLAY_COMSPOER_DEBUG_DUMP
DumpLayerBuffer(data.devId, data.layerId, data.fence, handle, "layer_");
#endif
std::string traceMsg = "";
if (data.buffer == nullptr) {
traceMsg = "data.buffer is nullptr! seqNo:" + std::to_string(data.seqNo);
} else {
traceMsg = "HDI:DISP:HARDWARE"
"height:" + std::to_string(data.buffer->height) +
" width:" + std::to_string(data.buffer->width) +
" data.buffer->fd:" + std::to_string(data.buffer->fd) +
" seqNo:" + std::to_string(data.seqNo);
}
traceMsg += " fd:" + std::to_string(fd);
if (data.fence > ERROR_FENCE_COUNT || fd > ERROR_FENCE_COUNT || handle.fd > ERROR_FENCE_COUNT) {
HDF_LOGI("SetLayerBuffer: %{public}s data.devId: %{public}d data.layerId: %{public}d, "
"data.buffer->fd:%{public}d, data.seqNo:%{public}d handle.fd:%{public}d, fd:%{public}d",
data.buffer == nullptr ? "data.buffer is nullptr!" : "",
data.devId, data.layerId, data.buffer == nullptr ? -1 : data.buffer->fd, data.seqNo, handle.fd, fd);
cacheMgr_->Dump();
}
HdfTrace traceVdi("SetLayerBuffer", traceMsg);
int rc = impl_->SetLayerBuffer(data.devId, data.layerId, handle, fd);
DISPLAY_CHK_RETURN(rc != HDF_SUCCESS, HDF_FAILURE, HDF_LOGE(" fail"));
needMoveFd = true;
return HDF_SUCCESS;
});
return ret;
}
void OnSetLayerBuffer(CommandDataUnpacker& unpacker, const std::vector<HdifdInfo>& inFds)
{
DISPLAY_TRACE;
struct LayerBufferData data;
std::vector<uint32_t> deletingList;
int32_t ret = UnPackLayerBufferInfo(unpacker, inFds, &data, deletingList);
HdifdParcelable fdParcel(data.fence);
bool needFreeBuffer = false;
bool needMoveFd = false;
if (ret == HDF_SUCCESS) {
ret = SetLayerBuffer(data, deletingList, needFreeBuffer, needMoveFd, fdParcel.GetFd());
}
#ifndef DISPLAY_COMMUNITY
if (data.buffer != nullptr && needFreeBuffer) {
FreeBufferWithDelay(data.buffer);
data.buffer = nullptr;
data.isValidBuffer = false;
}
if (needMoveFd) {
fdParcel.Move();
}
#endif
if (ret != HDF_SUCCESS) {
HDF_LOGE("%{public}s, SetLayerBuffer error", __func__);
errMaps_.emplace(REQUEST_CMD_SET_DISPLAY_CLIENT_BUFFER, ret);
}
return;
}
void OnSetLayerCompositionType(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
int32_t type;
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = unpacker.ReadInt32(type) ? HDF_SUCCESS : HDF_FAILURE;
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerCompositionType", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerCompositionType(devId, layerId, static_cast<CompositionType>(type));
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_COMPOSITION_TYPE, ret);
}
return;
}
void OnSetLayerBlendType(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
int32_t type;
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = unpacker.ReadInt32(type) ? HDF_SUCCESS : HDF_FAILURE;
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerBlendType", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerBlendType(devId, layerId, static_cast<BlendType>(type));
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_BLEND_TYPE, ret);
}
return;
}
void OnSetLayerMaskInfo(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
uint32_t maskInfo = 0;
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = unpacker.ReadUint32(maskInfo) ? HDF_SUCCESS : HDF_FAILURE;
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerMaskInfo", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerMaskInfo(devId, layerId, static_cast<MaskInfo>(maskInfo));
}
DISPLAY_CHECK(ret != HDF_SUCCESS && ret != DISPLAY_NOT_SUPPORT && ret != HDF_ERR_NOT_SUPPORT, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_MASK_INFO, ret);
}
return;
}
void OnSetLayerColor(CommandDataUnpacker& unpacker)
{
DISPLAY_TRACE;
uint32_t devId = 0;
uint32_t layerId = 0;
LayerColor layerColor = {0};
int32_t ret = CmdUtils::SetupDeviceUnpack(unpacker, devId, layerId);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
ret = CmdUtils::LayerColorUnpack(unpacker, layerColor);
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
{
HdfTrace traceVdi("SetLayerColor", "HDI:DISP:HARDWARE");
ret = impl_->SetLayerColor(devId, layerId, layerColor);
}
DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
EXIT:
if (ret != HDF_SUCCESS) {
errMaps_.emplace(REQUEST_CMD_SET_LAYER_COLOR, ret);
}
return;
}
int32_t PeriodDataReset()
{
replyCommandCnt_ = 0;
errMaps_.clear();
int32_t ret = CmdUtils::StartPack(CONTROL_CMD_REPLY_BEGIN, replyPacker_);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PackBegin failure, ret=%{public}d", ret);
}
return ret;
}
static std::string GetFileName(uint32_t devId, uint32_t layerId, const BufferHandle& buffer)
{
struct timeval tv;
char nowStr[TIME_BUFFER_MAX_LEN] = {0};
gettimeofday(&tv, nullptr);
if (strftime(nowStr, sizeof(nowStr), "%m-%d-%H-%M-%S", localtime(&tv.tv_sec)) == 0) {
HDF_LOGE("strftime failed");
return "";
};
std::ostringstream strStream;
const int32_t PIXEL_BYTES = 4;
strStream << "hdi_layer_" << devId << "_" << layerId << "_" << buffer.stride / PIXEL_BYTES << "x" <<
buffer.height << "_" << nowStr << "-" << tv.tv_usec;
return strStream.str();
}
#ifdef DISPLAY_COMSPOER_DEBUG_DUMP
static void DumpLayerBuffer(uint32_t devId, uint32_t layerId, int32_t fence, const BufferHandle& buffer,
std::string tag)
{
const std::string SWITCH_ON = "on";
const uint32_t DUMP_BUFFER_SWITCH_LEN = 4;
char dumpSwitch[DUMP_BUFFER_SWITCH_LEN] = {0};
GetParameter("hdi.composer.dumpbuffer", "off", dumpSwitch, DUMP_BUFFER_SWITCH_LEN);
if (SWITCH_ON.compare(dumpSwitch) != 0) {
return;
}
const uint32_t FENCE_TIMEOUT = 3000;
int32_t retCode = WaitFence(fence, FENCE_TIMEOUT);
if (retCode != HDF_SUCCESS) {
return;
}
if (g_bufferServiceImpl == nullptr) {
g_bufferServiceImpl = IMapper::Get(true);
DISPLAY_CHECK((g_bufferServiceImpl == nullptr), HDF_LOGE("get IMapper failed"));
}
std::string fileName = GetFileName(devId, layerId, buffer);
DISPLAY_CHECK((fileName == ""), HDF_LOGE("GetFileName failed"));
HDF_LOGI("fileName = %{public}s", fileName.c_str());
const std::string PATH_PREFIX = "/data/local/traces/";
std::stringstream filePath;
filePath << PATH_PREFIX << tag << fileName;
std::ofstream rawDataFile(filePath.str(), std::ofstream::binary);
DISPLAY_CHECK((!rawDataFile.good()), HDF_LOGE("open file failed, %{public}s",
std::strerror(errno)));
sptr<NativeBuffer> hdiBuffer = new NativeBuffer();
hdiBuffer->SetBufferHandle(const_cast<BufferHandle*>(&buffer));
int32_t ret = 0;
ret = g_bufferServiceImpl->Mmap(hdiBuffer);
DISPLAY_CHECK((ret != HDF_SUCCESS), HDF_LOGE("Mmap buffer failed"));
std::chrono::milliseconds time_before = std::chrono::duration_cast<std::chrono::milliseconds> (
std::chrono::system_clock::now().time_since_epoch()
);
rawDataFile.write(static_cast<const char *>(buffer.virAddr), buffer.size);
std::chrono::milliseconds time_after = std::chrono::duration_cast<std::chrono::milliseconds> (
std::chrono::system_clock::now().time_since_epoch()
);
HDF_LOGI("wirte file take time %{public}lld", time_after.count() - time_before.count());
rawDataFile.close();
ret = g_bufferServiceImpl->Unmap(hdiBuffer);
DISPLAY_CHECK((ret != HDF_SUCCESS), HDF_LOGE("Unmap buffer failed"));
}
#endif
static int32_t WaitFence(int32_t fence, uint32_t timeout)
{
int retCode = -1;
if (fence < 0) {
HDF_LOGE("The fence id is invalid.");
return retCode;
}
struct pollfd pollfds = {0};
pollfds.fd = fence;
pollfds.events = POLLIN;
do {
retCode = poll(&pollfds, 1, timeout);
} while (retCode == -1 && (errno == EINTR || errno == EAGAIN));
if (retCode == 0) {
retCode = -1;
errno = ETIME;
} else if (retCode > 0) {
retCode = 0;
if (pollfds.revents & (POLLERR | POLLNVAL)) {
retCode = -1;
errno = EINVAL;
}
}
return retCode < 0 ? -errno : HDF_SUCCESS;
}
void FreeBufferWithDelay(BufferHandle *handle)
{
delayFreeQueue_.push(handle);
if (delayFreeQueue_.size() >= BUFFER_QUEUE_MAX_SIZE) {
BufferHandle *temp = delayFreeQueue_.front();
delayFreeQueue_.pop();
FreeBufferHandle(temp);
temp = nullptr;
}
}
protected:
VdiImpl* impl_ = nullptr;
std::shared_ptr<DeviceCacheManager> cacheMgr_;
std::shared_ptr<Transfer> request_;
bool isReplyUpdated_;
std::shared_ptr<Transfer> reply_;
uint32_t replyCommandCnt_;
CommandDataPacker replyPacker_;
std::unordered_map<int32_t, int32_t> errMaps_;
std::queue<BufferHandle *> delayFreeQueue_;
std::mutex requestMutex_;
std::mutex replyMutex_;
};
using HdiDisplayCmdResponser = DisplayCmdResponser<SharedMemQueue<int32_t>, DisplayComposerVdiAdapter>;
}
}
}
}
}
#endif