You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
7.9 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2019-2022. All rights reserved.
* Description: Support hwdisplay hal adaptation interface
* Author: Hisilicon
* Created: 2022-12-28
*/
#define LOG_TAG "HwDisplay"
#include "HwDisplay.h"
#include <hardware/hardware.h>
#include <log/log_main.h>
#include <hwbinder/Parcel.h>
#include <vector>
#include <cinttypes>
#include <dlfcn.h>
#include <utils/Mutex.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <vendor/huanglong/hardware/hwdisplay/2.0/BpHwDispmngCallback.h>
#define DISP_MNG_VERSION
namespace vendor {
namespace huanglong {
namespace hardware {
namespace hwdisplay {
namespace V2_0 {
namespace implementation {
using std::vector;
using android::Mutex;
Mutex g_mRegistrationLock;
#ifdef DISP_MNG_VERSION
struct DispmngCallBackData {
sp<IDispmngCallback> dispmngCallback;
vector<uint32_t> eventidList;
};
vector<DispmngCallBackData> g_mDispCallbackDataList;
void DispmngEventCallBack(uapi_svr_dispmng_event event,
void *msg, unsigned int msglen, void *privData)
{
(void)privData;
auto count = g_mDispCallbackDataList.size();
if (count == 0) {
ALOGI("g_mDispCallbackDataList count is 0");
return;
}
Mutex::Autolock lock(g_mRegistrationLock);
ALOGI("DispmngEventCallBack count [%d] event=%d", count, event);
for (const auto &it : g_mDispCallbackDataList) {
if (it.dispmngCallback == nullptr) {
ALOGI("DispmngEventCallBack dispmngCallback == nullptr\n");
continue;
}
const auto st = std::find_if(it.eventidList.cbegin(), it.eventidList.cend(), [event](uint32_t id) {
return id == UAPI_SVR_DISPMNG_EVENT_ALL || event == id;
});
if (st != it.eventidList.end()) {
ALOGI("DispmngEventCallBack ALL(event = %d)\n", event);
android::Parcel pParcelObj;
pParcelObj.write(msg, msglen);
hidl_string inputStr((const char *)pParcelObj.data(), pParcelObj.dataSize());
it.dispmngCallback->OnDispmngCallback((unsigned int)event, inputStr);
}
}
}
ClientId HwDisplay::GetDispmngClientId(const sp<IDispmngCallback> &callback)
{
if (callback->isRemote()) {
BpHwDispmngCallback *hwCallback = static_cast<BpHwDispmngCallback *>(callback.get());
return static_cast<ClientId>(reinterpret_cast<intptr_t>(hwCallback->onAsBinder()));
} else {
return static_cast<ClientId>(reinterpret_cast<intptr_t>(callback.get()));
}
}
void HwDisplay::HandleDispmngHidlDeath(ClientId deathid)
{
ALOGI("handleDispmngHidlDeath Death callback id is :%#llx size before:", deathid);
for (unsigned int i = 0; i < g_mDispCallbackDataList.size(); i++) {
if (deathid == GetDispmngClientId(g_mDispCallbackDataList[i].dispmngCallback)) {
g_mDispCallbackDataList.erase(g_mDispCallbackDataList.cbegin() + i);
} else {
ALOGI("the call back %#llx not in the list", deathid);
}
}
ALOGI("handleDispmngHidlDeath size at last %d", g_mDispCallbackDataList.size());
return;
}
#endif
HwDisplay::HwDisplay() : mDevice(nullptr)
{
ALOGW("HwDisplay constructor");
mDeathRecipient = new DispDeathRecipient();
int err = hw_get_module(DISPLAY_HARDWARE_MODULE_ID, &mModule);
if (err == 0) {
displayOpen(mModule, reinterpret_cast<hw_device_t **>(&mDevice));
} else {
ALOGE("open display module failed !\n");
}
if (mDevice == nullptr) {
ALOGE("mDevice is nullptr %s(%d)!\n", __func__, __LINE__);
} else {
ALOGI("mDevice ok set call back to hal %s(%d)!\n", __func__, __LINE__);
mDevice->registerDispmngCallback(0, DispmngEventCallBack, nullptr);
}
}
HwDisplay::~HwDisplay()
{}
Return<void> HwDisplay::hwInvoke(const hidl_string& request, hwInvoke_cb _hidl_cb)
{
ALOGI("===========HwDisplay::hwInvoke begin=========");
const char *data = request.c_str();
int length = static_cast<int>(request.size());
android::Parcel parcelReq;
android::Parcel parcelReply;
parcelReq.setDataSize(length);
parcelReq.setDataPosition(0);
parcelReq.write(data, length);
parcelReq.setDataPosition(0);
if (mDevice != nullptr) {
mDevice->invoke(parcelReq, parcelReply);
} else {
ALOGE("mDevice is null");
}
hidl_string inputStr((char *)parcelReply.data(), parcelReply.dataSize());
_hidl_cb(inputStr);
ALOGI("===========HwDisplay::hwInvoke end=========");
return Void();
}
Return<int32_t> HwDisplay::RegisterCallback(uint32_t eventid, const sp<IDispmngCallback> &cb)
{
if (cb == nullptr || mDevice == nullptr) {
return -1;
}
Mutex::Autolock lock(g_mRegistrationLock);
ClientId registid = GetDispmngClientId(cb);
auto it = std::find_if(g_mDispCallbackDataList.begin(),
g_mDispCallbackDataList.end(), [registid](DispmngCallBackData &ca) {
return registid == GetDispmngClientId(ca.dispmngCallback);
});
if (it != g_mDispCallbackDataList.end()) {
const auto st = std::find_if((*it).eventidList.cbegin(), (*it).eventidList.cend(), [eventid](uint32_t id) {
return eventid == id;
});
if (st != (*it).eventidList.end()) {
ALOGI("registid %#llx eventid %u already registered return ok\n", registid, eventid);
} else {
(*it).eventidList.emplace_back(eventid);
mDevice->registerDispmngCallback(eventid, DispmngEventCallBack, nullptr);
ALOGI("registid %#llx add eventid %u\n", registid, eventid);
}
} else {
DispmngCallBackData data {};
data.dispmngCallback = cb;
data.eventidList.emplace_back(eventid);
g_mDispCallbackDataList.emplace_back(data);
cb->linkToDeath(mDeathRecipient, registid);
mDevice->registerDispmngCallback(eventid, DispmngEventCallBack, nullptr);
ALOGI("registid %#llx add eventid %u\n", registid, eventid);
}
ALOGI("registerCallback size: %d\n", g_mDispCallbackDataList.size());
for (const auto &ls : g_mDispCallbackDataList) {
registid = GetDispmngClientId(ls.dispmngCallback);
for (const auto &ev : ls.eventidList) {
ALOGI("registid %#llx eventid %u", registid, ev);
}
}
return 0;
}
Return<int32_t> HwDisplay::UnRegisterCallback(uint32_t eventid, const sp<IDispmngCallback> &cb)
{
if (cb == nullptr || mDevice == nullptr) {
return -1;
}
Mutex::Autolock lock(g_mRegistrationLock);
ClientId ungistid = GetDispmngClientId(cb);
auto it = std::find_if(g_mDispCallbackDataList.begin(),
g_mDispCallbackDataList.end(), [ungistid](DispmngCallBackData &ca) {
return ungistid == GetDispmngClientId(ca.dispmngCallback);
});
if (it != g_mDispCallbackDataList.end()) {
auto st = std::find_if((*it).eventidList.cbegin(), (*it).eventidList.cend(), [eventid](uint32_t id) {
return eventid == id;
});
if (st != (*it).eventidList.end()) {
(*it).eventidList.erase(st);
mDevice->unregisterDispmngCallback(eventid, DispmngEventCallBack);
if ((*it).eventidList.size() == 0) {
g_mDispCallbackDataList.erase(it);
cb->unlinkToDeath(mDeathRecipient);
}
ALOGI("ungistid %#llx del eventid %u\n", ungistid, eventid);
}
}
ALOGI("unRegisterCallback size: %d\n", g_mDispCallbackDataList.size());
for (const auto &ls : g_mDispCallbackDataList) {
ungistid = GetDispmngClientId(ls.dispmngCallback);
for (const auto &ev : ls.eventidList) {
ALOGI("registid %#llx eventid %u", ungistid, ev);
}
}
return 0;
}
IHwdisplay *HIDL_FETCH_IHwdisplay(const char *) /* hal */
{
return new HwDisplay();
}
} // namespace implementation
} // namespace V2_0
} // namespace hwdisplay
} // namespace hardware
} // namespace huanglong
} // namespace vendor