* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <devsvc_manager_proxy.h>
#include <devsvc_manager_stub.h>
#include <hdf_base.h>
#include <hdf_log.h>
#include <osal_mem.h>
#include "hdf_service_status.h"
#include "servmgr_hdi.h"
struct HDIServiceManagerClient {
struct HDIServiceManager iservmgr;
struct HdfRemoteService *remote;
};
int ServiceStatusListenerMarshalling(struct ServiceStatusListener *listener, struct HdfSBuf *buf);
static int32_t ServiceManagerHdiCall(struct HDIServiceManagerClient *servMgrClient, int32_t id,
struct HdfSBuf *data, struct HdfSBuf *reply)
{
if (servMgrClient->remote == NULL || servMgrClient->remote->dispatcher == NULL ||
servMgrClient->remote->dispatcher->Dispatch == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
return servMgrClient->remote->dispatcher->Dispatch(servMgrClient->remote, id, data, reply);
}
struct HdfRemoteService *HDIServMgrGetService(struct HDIServiceManager *iServMgr, const char* serviceName)
{
if (iServMgr == NULL || serviceName == NULL) {
return NULL;
}
struct HDIServiceManagerClient *servMgrClient = CONTAINER_OF(iServMgr, struct HDIServiceManagerClient, iservmgr);
struct HdfSBuf *data = NULL;
struct HdfSBuf *reply = NULL;
struct HdfRemoteService *service = NULL;
do {
data = HdfSbufTypedObtain(SBUF_IPC);
reply = HdfSbufTypedObtain(SBUF_IPC);
if (data == NULL || reply == NULL) {
break;
}
if (!HdfRemoteServiceWriteInterfaceToken(servMgrClient->remote, data) ||
!HdfSbufWriteString(data, serviceName)) {
break;
}
int status = ServiceManagerHdiCall(servMgrClient, DEVSVC_MANAGER_GET_SERVICE, data, reply);
if (status == HDF_SUCCESS) {
service = HdfSbufReadRemoteService(reply);
} else {
HDF_LOGI("%{public}s: %{public}s not found", __func__, serviceName);
}
} while (0);
if (reply != NULL) {
HdfSbufRecycle(reply);
}
if (data != NULL) {
HdfSbufRecycle(data);
}
return service;
}
int32_t HDIServMgrRegisterServiceStatusListener(struct HDIServiceManager *self,
struct ServiceStatusListener *listener, uint16_t deviceClass)
{
if (self == NULL || listener == NULL) {
return HDF_ERR_INVALID_PARAM;
}
struct HDIServiceManagerClient *servMgrClient = CONTAINER_OF(self, struct HDIServiceManagerClient, iservmgr);
struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
if (data == NULL) {
return HDF_ERR_MALLOC_FAIL;
}
if (!HdfRemoteServiceWriteInterfaceToken(servMgrClient->remote, data) ||
!HdfSbufWriteUint16(data, deviceClass) ||
ServiceStatusListenerMarshalling(listener, data) != HDF_SUCCESS) {
return HDF_FAILURE;
}
int32_t ret = ServiceManagerHdiCall(servMgrClient, DEVSVC_MANAGER_REGISTER_SVCLISTENER, data, NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("failed to register hdi service listener");
}
HdfSbufRecycle(data);
return ret;
}
int32_t HDIServMgrUnregisterServiceStatusListener(struct HDIServiceManager *self,
struct ServiceStatusListener *listener)
{
if (self == NULL || listener == NULL) {
return HDF_ERR_INVALID_PARAM;
}
struct HDIServiceManagerClient *servMgrClient = CONTAINER_OF(self, struct HDIServiceManagerClient, iservmgr);
struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
if (data == NULL) {
return HDF_ERR_MALLOC_FAIL;
}
if (!HdfRemoteServiceWriteInterfaceToken(servMgrClient->remote, data) ||
ServiceStatusListenerMarshalling(listener, data) != HDF_SUCCESS) {
return HDF_FAILURE;
}
int32_t ret = ServiceManagerHdiCall(servMgrClient, DEVSVC_MANAGER_UNREGISTER_SVCLISTENER, data, NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("failed to unregister hdi service listener");
}
HdfSbufRecycle(data);
return ret;
}
void HDIServiceManagerConstruct(struct HDIServiceManager *inst)
{
inst->GetService = HDIServMgrGetService;
inst->RegisterServiceStatusListener = HDIServMgrRegisterServiceStatusListener;
inst->UnregisterServiceStatusListener = HDIServMgrUnregisterServiceStatusListener;
}
struct HDIServiceManager *HDIServiceManagerGet(void)
{
struct HdfRemoteService *remote = HdfRemoteServiceGet(DEVICE_SERVICE_MANAGER_SA_ID);
if (remote == NULL) {
HDF_LOGE("%{public}s: hdi service %{public}s not found", __func__, DEVICE_SERVICE_MANAGER);
return NULL;
}
struct HDIServiceManagerClient *iServMgrClient = OsalMemAlloc(sizeof(struct HDIServiceManagerClient));
if (iServMgrClient == NULL) {
HDF_LOGE("%{public}s: OOM", __func__);
HdfRemoteServiceRecycle(remote);
return NULL;
}
if (!HdfRemoteServiceSetInterfaceDesc(remote, "HDI.IServiceManager.V1_0")) {
HDF_LOGE("%{public}s: failed to init interface desc", __func__);
HdfRemoteServiceRecycle(remote);
return NULL;
}
iServMgrClient->remote = remote;
HDIServiceManagerConstruct(&iServMgrClient->iservmgr);
return &iServMgrClient->iservmgr;
}
void HDIServiceManagerRelease(struct HDIServiceManager *servmgr)
{
if (servmgr == NULL) {
return;
}
struct HDIServiceManagerClient *iServMgrClient = CONTAINER_OF(servmgr, struct HDIServiceManagerClient, iservmgr);
HdfRemoteServiceRecycle(iServMgrClient->remote);
OsalMemFree(iServMgrClient);
}