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.

232 lines
6.4 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2020. All rights reserved.
* Description:
* Author:
* create:
*/
#define LOG_TAG "TVMW@Hwtvmw"
#include "Hwtvmw.h"
#include <hardware/hardware.h>
#include <log/log_main.h>
#include <hwbinder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <cinttypes>
#include <dlfcn.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
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<Hwtvmw> 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<Hwtvmw> 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<Hwtvmw *>(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<void> Hwtvmw::getTvmwService()
{
if (m_pTVSerice == nullptr) {
m_pTVSerice = new TVService();
}
return Void();
}
Return<void> Hwtvmw::getCapBuffer(uint32_t id, getCapBuffer_cb _hidl_cb)
{
ALOGD("Hwtvmw getCapBuffer id = %d", id);
hidl_memory mBuffer = {};
_hidl_cb(mBuffer);
return Void();
}
Return<void> 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<void> Hwtvmw::onObjectDeath(uint64_t cookie)
{
Mutex::Autolock autoLock(mNotifyLock);
uintptr_t cookiePtr = static_cast<uintptr_t>(cookie);
IHwtvmwCallback *cb = reinterpret_cast<IHwtvmwCallback *>(cookiePtr);
std::vector<sp<IHwtvmwCallback>>::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<int32_t> Hwtvmw::hwRegistCallback(const sp<IHwtvmwCallback>& callback)
{
if (callback == nullptr) {
ALOGE("sp<IHwtvmwCallback> 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<uint64_t>(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<void> 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<int>(mCallbacks.size()); i++) {
sp<IHwtvmwCallback> 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<void> 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<void> 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<Mutex *>(&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