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
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
|