/* * Copyright (c) 2021-2022 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 #include #include #include #include #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) { HdfSbufRecycle(data); 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) { HdfSbufRecycle(data); 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); OsalMemFree(iServMgrClient); 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); }