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
232 lines
6.4 KiB
4 months ago
|
/*
|
||
|
* 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
|