3e1a6e88创建于 2022年4月7日历史提交
/*
 * 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 "devhost_service.h"
#include "devhost_service_full.h"
#include "device_service_stub.h"
#include "devsvc_manager_stub.h"
#include "hdf_base.h"
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "osal_mem.h"

#define HDF_LOG_TAG devsvc_manager_proxy

static int WriteServiceInfo(
    struct HdfSBuf *data, const char *svcName, uint16_t devClass, struct HdfDeviceObject *service, const char *servInfo)
{
    int ret = HDF_FAILURE;
    if (!HdfSbufWriteString(data, svcName)) {
        HDF_LOGE("Add service failed, failed to write service name");
        return ret;
    }

    if (!HdfSbufWriteUint16(data, devClass)) {
        HDF_LOGE("Add service failed, failed to write devClass");
        return ret;
    }

    struct HdfDeviceNode *devNode =
        HDF_SLIST_CONTAINER_OF(struct HdfDeviceObject, service, struct HdfDeviceNode, deviceObject);
    struct DeviceServiceStub *deviceFullService = (struct DeviceServiceStub *)devNode;
    if (deviceFullService->remote == NULL) {
        HDF_LOGE("%{public}s: device service is broken", __func__);
        return ret;
    }

    if (HdfSbufWriteRemoteService(data, deviceFullService->remote) != HDF_SUCCESS) {
        HDF_LOGE("Add service failed, failed to write remote object");
        return ret;
    }
    const char *info = servInfo != NULL ? servInfo : "";
    if (!HdfSbufWriteString(data, info)) {
        HDF_LOGE("Add service failed, failed to write serv info");
        return HDF_FAILURE;
    }

    return HDF_SUCCESS;
}

static int DevSvcManagerProxyAddService(struct IDevSvcManager *inst, const char *svcName, uint16_t devClass,
    struct HdfDeviceObject *service, const char *servInfo)
{
    struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;
    if (service == NULL || svcName == NULL) {
        HDF_LOGE("%{public}s:service or name is null", __func__);
        return HDF_ERR_INVALID_PARAM;
    }
    if ((serviceProxy == NULL) || (serviceProxy->remote == NULL)) {
        HDF_LOGE("Add service failed, serviceProxy is invalid");
        return HDF_ERR_INVALID_PARAM;
    }

    if (devClass >= DEVICE_CLASS_MAX) {
        HDF_LOGE("Add service failed, devClass is invalid");
        return HDF_ERR_INVALID_PARAM;
    }

    int status = HDF_FAILURE;
    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
    do {
        if (data == NULL || reply == NULL) {
            HDF_LOGE("Add service failed, failed to obtain sbuf");
            break;
        }
        if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) ||
            WriteServiceInfo(data, svcName, devClass, service, servInfo) != HDF_SUCCESS) {
            break;
        }
        status =
            serviceProxy->remote->dispatcher->Dispatch(serviceProxy->remote, DEVSVC_MANAGER_ADD_SERVICE, data, reply);
        HDF_LOGI("servmgr add service %{public}s, result is %{public}d", svcName, status);
    } while (0);

    if (reply != NULL) {
        HdfSbufRecycle(reply);
    }
    if (data != NULL) {
        HdfSbufRecycle(data);
    }
    return status;
}

static int DevSvcManagerProxyUpdateService(struct IDevSvcManager *inst, const char *svcName, uint16_t devClass,
    struct HdfDeviceObject *service, const char *servInfo)
{
    struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;
    if (service == NULL || svcName == NULL) {
        HDF_LOGE("%{public}s:service or name is null", __func__);
        return HDF_ERR_INVALID_PARAM;
    }
    if ((serviceProxy == NULL) || (serviceProxy->remote == NULL)) {
        HDF_LOGE("Add service failed, serviceProxy is invalid");
        return HDF_ERR_INVALID_PARAM;
    }

    if (devClass >= DEVICE_CLASS_MAX) {
        HDF_LOGE("Add service failed, devClass is invalid");
        return HDF_ERR_INVALID_PARAM;
    }

    int status = HDF_FAILURE;
    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
    do {
        if (data == NULL || reply == NULL) {
            HDF_LOGE("Add service failed, failed to obtain sbuf");
            break;
        }
        if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) ||
            WriteServiceInfo(data, svcName, devClass, service, servInfo) != HDF_SUCCESS) {
            break;
        }
        status = serviceProxy->remote->dispatcher->Dispatch(
            serviceProxy->remote, DEVSVC_MANAGER_UPDATE_SERVICE, data, reply);
        HDF_LOGI("servmgr update service %{public}s, result is %{public}d", svcName, status);
    } while (0);

    if (reply != NULL) {
        HdfSbufRecycle(reply);
    }
    if (data != NULL) {
        HdfSbufRecycle(data);
    }
    return status;
}

struct HdfObject *DevSvcManagerProxyGetService(struct IDevSvcManager *inst, const char *svcName)
{
    int status = HDF_FAILURE;
    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
    struct HdfRemoteDispatcher *dispatcher = NULL;
    struct HdfRemoteService *remoteService = NULL;
    struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;
    do {
        if ((serviceProxy->remote == NULL) || (data == NULL) || (reply == NULL)) {
            HDF_LOGE("Get service failed, serviceProxy->remote or data or reply is null");
            break;
        }
        dispatcher = serviceProxy->remote->dispatcher;
        if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) || !HdfSbufWriteString(data, svcName)) {
            break;
        }
        status = dispatcher->Dispatch(serviceProxy->remote, DEVSVC_MANAGER_GET_SERVICE, data, reply);
        if (status == HDF_SUCCESS) {
            remoteService = HdfSbufReadRemoteService(reply);
        }
    } while (0);

    if (reply != NULL) {
        HdfSbufRecycle(reply);
    }
    if (data != NULL) {
        HdfSbufRecycle(data);
    }
    HDF_LOGI("DevSvcManagerProxyGetService finish, and status is %{public}d", status);
    return (remoteService == NULL) ? NULL : &remoteService->object_;
}

void DevSvcManagerProxyRemoveService(struct IDevSvcManager *inst, const char *svcName)
{
    if (inst == NULL || svcName == NULL) {
        return;
    }
    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
    struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
    struct HdfRemoteDispatcher *dispatcher = NULL;
    struct HdfRemoteService *remoteService = NULL;
    struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;

    do {
        if ((serviceProxy->remote == NULL) || (data == NULL) || (reply == NULL)) {
            HDF_LOGE("Remove service failed, serviceProxy->remote or data or reply is null");
            break;
        }
        remoteService = serviceProxy->remote;
        dispatcher = remoteService->dispatcher;
        if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) || !HdfSbufWriteString(data, svcName)) {
            break;
        }
        int status = dispatcher->Dispatch(remoteService, DEVSVC_MANAGER_REMOVE_SERVICE, data, reply);
        HDF_LOGW("Device service manager proxy remove service status is %{public}d", status);
    } while (0);

    if (reply != NULL) {
        HdfSbufRecycle(reply);
    }
    if (data != NULL) {
        HdfSbufRecycle(data);
    }
}

static void DevSvcManagerProxyOnRemoteDied(struct HdfDeathRecipient *recipient, struct HdfRemoteService *service)
{
    struct IDevHostService *instance = DevHostServiceNewInstance(0, NULL);

    if (recipient == NULL || service == NULL || instance == NULL) {
        HDF_LOGE("%{public}s parameter is null", __func__);
        return;
    }

    struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
    struct HdfMessageLooper *looper = &fullService->looper;
    HDF_LOGW("%{public}s: DevSvcManager dead, host %{public}d stop", __func__, fullService->super.hostId);
    if ((looper != NULL) && (looper->Stop != NULL)) {
        looper->Stop(looper);
    }
}

void DevSvcManagerProxyConstruct(struct DevSvcManagerProxy *inst, struct HdfRemoteService *remote)
{
    inst->pvtbl.AddService = DevSvcManagerProxyAddService;
    inst->pvtbl.UpdateService = DevSvcManagerProxyUpdateService;
    inst->pvtbl.GetService = DevSvcManagerProxyGetService;
    inst->pvtbl.RemoveService = DevSvcManagerProxyRemoveService;
    inst->remote = remote;
    inst->recipient.OnRemoteDied = DevSvcManagerProxyOnRemoteDied;
    HdfRemoteServiceAddDeathRecipient(remote, &inst->recipient);
}

static struct IDevSvcManager *DevSvcManagerProxyObtain(struct HdfRemoteService *remote)
{
    struct DevSvcManagerProxy *instance = (struct DevSvcManagerProxy *)OsalMemCalloc(sizeof(struct DevSvcManagerProxy));
    if (instance != NULL) {
        DevSvcManagerProxyConstruct(instance, remote);
    }
    return (struct IDevSvcManager *)instance;
}

struct HdfObject *DevSvcManagerProxyCreate()
{
    static struct IDevSvcManager *instance = NULL;
    if (instance == NULL) {
        struct HdfRemoteService *remote = HdfRemoteServiceGet(DEVICE_SERVICE_MANAGER_SA_ID);
        if (remote != NULL) {
            if (!HdfRemoteServiceSetInterfaceDesc(remote, "HDI.IServiceManager.V1_0")) {
                HDF_LOGE("%{public}s: failed to init interface desc", __func__);
                HdfRemoteServiceRecycle(remote);
                return NULL;
            }
            instance = DevSvcManagerProxyObtain(remote);
        }
    }
    return (struct HdfObject *)instance;
}

void DevSvcManagerProxyRelease(struct HdfObject *object)
{
    struct DevSvcManagerProxy *instance = (struct DevSvcManagerProxy *)object;
    if (instance != NULL) {
        if (instance->remote != NULL) {
            HdfRemoteServiceRecycle(instance->remote);
            instance->remote = NULL;
        }
        OsalMemFree(instance);
    }
}