/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2020. All rights reserved. * Description: * Author: * create: */ #define LOG_TAG "TVMW@Hwtvmw" #include "Hwtvmw.h" #include #include #include #include #include #include #include #include #include using namespace android; #ifndef TD_UNUSED #define TD_UNUSED(x) ((x) = (x)); #endif namespace vendor { namespace huanglong { namespace hardware { namespace hwtvmw { namespace V1_0 { namespace implementation { class TvmwDeathRecipient : public hidl_death_recipient { public: explicit TvmwDeathRecipient(const sp hTvmw) : mHwtvmw(hTvmw) {} ~TvmwDeathRecipient() override {} void serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>&) override { ALOGE("serviceDied cookie = 0x%" PRIu64, cookie); mHwtvmw->onObjectDeath(cookie); } sp mHwtvmw; }; static void CallBackRelay(void *user, unsigned int type, const void *data, unsigned int len, void *prev, const android::Parcel *request, android::Parcel *notifyReply) { ALOGD("Callback from TvService, line:%d", __LINE__); Hwtvmw *pthis = static_cast(user); if (pthis != nullptr) { pthis->NotifyCb(type, data, len, prev, request, notifyReply); } } Hwtvmw::Hwtvmw(): mDeathRecipient(new TvmwDeathRecipient(this)) { ALOGW("Hwtvmw constructor"); m_pTVSerice = nullptr; getTvmwService(); } Hwtvmw::~Hwtvmw() {} Return Hwtvmw::getTvmwService() { if (m_pTVSerice == nullptr) { m_pTVSerice = new TVService(); } return Void(); } Return Hwtvmw::getCapBuffer(uint32_t id, getCapBuffer_cb _hidl_cb) { ALOGD("Hwtvmw getCapBuffer id = %d", id); hidl_memory mBuffer = {}; _hidl_cb(mBuffer); return Void(); } Return Hwtvmw::hwInvoke(const hidl_string& request, hwInvoke_cb _hidl_cb) { const char *data = request.c_str(); size_t length = request.size(); android::Parcel parcelReq; android::Parcel parcelReply; parcelReq.setDataSize(length); parcelReq.setDataPosition(0); parcelReq.write(data, length); parcelReq.setDataPosition(0); if (m_pTVSerice != nullptr) { m_pTVSerice->invoke(parcelReq, &parcelReply); } else { ALOGE("m_pTVSerice is null"); } hidl_string inputStr((char *)parcelReply.data(), parcelReply.dataSize()); _hidl_cb(inputStr); return Void(); } Return Hwtvmw::onObjectDeath(uint64_t cookie) { Mutex::Autolock autoLock(mNotifyLock); uintptr_t cookiePtr = static_cast(cookie); IHwtvmwCallback *cb = reinterpret_cast(cookiePtr); std::vector>::iterator itr = mCallbacks.begin(); while (itr != mCallbacks.end()) { if (*itr == cb) { ALOGD("delete callback"); itr = mCallbacks.erase(itr); } else { itr++; } } ALOGD("after delete callback count = %d", mCallbacks.size()); return Void(); } Return Hwtvmw::hwRegistCallback(const sp& callback) { if (callback == nullptr) { ALOGE("sp is nullptr"); return -1; } ALOGD("registCallback, line:%d", __LINE__); Mutex::Autolock autoLock(mNotifyLock); uintptr_t cookiePtr = (uintptr_t)(callback.get()); uint64_t cookie = static_cast(cookiePtr); if (!callback->linkToDeath(mDeathRecipient, cookie)) { ALOGE("setCallback Failed to register death notification"); return -1; } mCallbacks.push_back(callback); ALOGI("hwRegistCallback registed success"); if (m_pTVSerice != nullptr && (m_pTVSerice->IsCallbackSet() == 0)) { m_pTVSerice->SetCallback(CallBackRelay, this); } return 0; } Return Hwtvmw::notifyEachClient( unsigned int type, android::Parcel *notifyReply, const hidl_string inputStr, const hidl_string inputStrReq) const { Parcel hwreply; ALOGD("NotifyCb callback size=%d", mCallbacks.size()); for (int i = 0; i < static_cast(mCallbacks.size()); i++) { sp c = mCallbacks[i]; if (c.get() == nullptr) { continue; } if (!c->ping().isOk()) { ALOGE("NotifyCb ping failed,callback[%d]", i); continue; } String8 retReply; auto cb = [&retReply](hidl_string strReply) { retReply = String8(strReply.c_str(), strReply.size()); }; Return ret = c->hwNotify(type, inputStr, inputStrReq, cb); if (!ret.isOk() || ret.isDeadObject()) { ALOGE("NotifyCb failed, client:%d is NOK or DEAD_OBJECT", i); continue; } if (notifyReply != nullptr) { hwreply.setDataSize(retReply.size()); hwreply.setDataPosition(0); hwreply.write(retReply.c_str(), retReply.size()); hwreply.setDataPosition(0); notifyReply->write(hwreply.data(), hwreply.dataSize()); notifyReply->setDataPosition(0); } } return Void(); } Return Hwtvmw::NotifyCb(unsigned int type, const void *data, unsigned int len, const void *prev, const android::Parcel *request, android::Parcel *notifyReply) const { Mutex::Autolock autoLock(const_cast(&mNotifyLock)); Parcel pParcelObj; pParcelObj.write(data, len); if (prev == nullptr) { ALOGV("prev is null"); } hidl_string inputStr((const char *)pParcelObj.data(), pParcelObj.dataSize()); Parcel hwrequest; hidl_string inputStrReq = nullptr; if (request != nullptr && request->dataSize() > 0) { hwrequest.setDataSize(request->dataSize()); hwrequest.setDataPosition(0); hwrequest.write(request->data(), request->dataSize()); request->setDataPosition(0); if (hwrequest.dataSize() > 0) { hidl_string inputStrTmp((const char *)hwrequest.data(), hwrequest.dataSize()); inputStrReq = inputStrTmp; } } else { ALOGV("request is null"); } notifyEachClient(type, notifyReply, inputStr, inputStrReq); return Void(); } IHwtvmw *HIDL_FETCH_IHwtvmw(const char* name) { TD_UNUSED(name); return new Hwtvmw(); } } // namespace implementation } // namespace V1_0 } // namespace hwtvmw } // namespace hardware } // namespace huanglong } // namespace vendor