/* * 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 #include #include #include #include #include #include #include #include #include #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 dispmngCallback; vector eventidList; }; vector 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 &callback) { if (callback->isRemote()) { BpHwDispmngCallback *hwCallback = static_cast(callback.get()); return static_cast(reinterpret_cast(hwCallback->onAsBinder())); } else { return static_cast(reinterpret_cast(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(&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 HwDisplay::hwInvoke(const hidl_string& request, hwInvoke_cb _hidl_cb) { ALOGI("===========HwDisplay::hwInvoke begin========="); const char *data = request.c_str(); int length = static_cast(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 HwDisplay::RegisterCallback(uint32_t eventid, const sp &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 HwDisplay::UnRegisterCallback(uint32_t eventid, const sp &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