1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "devsvc_manager_proxy.h"
17 #include "devhost_service.h"
18 #include "devhost_service_full.h"
19 #include "device_service_stub.h"
20 #include "devsvc_manager_stub.h"
21 #include "hdf_base.h"
22 #include "hdf_log.h"
23 #include "hdf_sbuf.h"
24 #include "osal_mem.h"
25 #include <unistd.h>
26 
27 #define HDF_LOG_TAG devsvc_manager_proxy
28 
WriteServiceInfo(struct HdfSBuf * data,struct HdfDeviceObject * service,const struct HdfServiceInfo * servInfo)29 static int WriteServiceInfo(
30     struct HdfSBuf *data, struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)
31 {
32     int ret = HDF_FAILURE;
33     if (!HdfSbufWriteString(data, servInfo->servName)) {
34         HDF_LOGE("Add service failed, failed to write service name");
35         return ret;
36     }
37 
38     if (!HdfSbufWriteUint16(data, servInfo->devClass)) {
39         HDF_LOGE("Add service failed, failed to write devClass");
40         return ret;
41     }
42     if (!HdfSbufWriteUint32(data, servInfo->devId)) {
43         HDF_LOGE("Add service failed, failed to write devId");
44         return ret;
45     }
46     struct HdfDeviceNode *devNode =
47         HDF_SLIST_CONTAINER_OF(struct HdfDeviceObject, service, struct HdfDeviceNode, deviceObject);
48     struct DeviceServiceStub *deviceFullService = (struct DeviceServiceStub *)devNode;
49     if (deviceFullService->remote == NULL) {
50         HDF_LOGE("%{public}s: device service is broken", __func__);
51         return ret;
52     }
53 
54     if (HdfSbufWriteRemoteService(data, deviceFullService->remote) != HDF_SUCCESS) {
55         HDF_LOGE("Add service failed, failed to write remote object");
56         return ret;
57     }
58     const char *info = servInfo->servInfo != NULL ? servInfo->servInfo : "";
59     if (!HdfSbufWriteString(data, info)) {
60         HDF_LOGE("Add service failed, failed to write serv info");
61         return HDF_FAILURE;
62     }
63     const char *interfaceDesc = servInfo->interfaceDesc != NULL ? servInfo->interfaceDesc : "";
64     if (!HdfSbufWriteString(data, interfaceDesc)) {
65         HDF_LOGE("Add service failed, failed to write interfaceDesc");
66         return HDF_FAILURE;
67     }
68 
69     return HDF_SUCCESS;
70 }
71 
DevSvcManagerProxyAddService(struct IDevSvcManager * inst,struct HdfDeviceObject * service,const struct HdfServiceInfo * servInfo)72 static int DevSvcManagerProxyAddService(
73     struct IDevSvcManager *inst, struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)
74 {
75     struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;
76     if (service == NULL || servInfo == NULL || servInfo->servName == NULL) {
77         HDF_LOGE("%{public}s:service or name is null", __func__);
78         return HDF_ERR_INVALID_PARAM;
79     }
80     if ((serviceProxy == NULL) || (serviceProxy->remote == NULL)) {
81         HDF_LOGE("Add service failed, serviceProxy is invalid");
82         return HDF_ERR_INVALID_PARAM;
83     }
84 
85     if (servInfo->devClass >= DEVICE_CLASS_MAX) {
86         HDF_LOGE("Add service failed, devClass is invalid");
87         return HDF_ERR_INVALID_PARAM;
88     }
89 
90     int status = HDF_FAILURE;
91     struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
92     struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
93     do {
94         if (data == NULL || reply == NULL) {
95             HDF_LOGE("Add service failed, failed to obtain sbuf");
96             break;
97         }
98         if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) ||
99             WriteServiceInfo(data, service, servInfo) != HDF_SUCCESS) {
100             break;
101         }
102         status =
103             serviceProxy->remote->dispatcher->Dispatch(serviceProxy->remote, DEVSVC_MANAGER_ADD_SERVICE, data, reply);
104         HDF_LOGI("servmgr add service %{public}s, result is %{public}d", servInfo->servName, status);
105     } while (0);
106 
107     HdfSbufRecycle(reply);
108     HdfSbufRecycle(data);
109     return status;
110 }
111 
DevSvcManagerProxyUpdateService(struct IDevSvcManager * inst,struct HdfDeviceObject * service,const struct HdfServiceInfo * servInfo)112 static int DevSvcManagerProxyUpdateService(struct IDevSvcManager *inst,
113     struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)
114 {
115     struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;
116     if (service == NULL || servInfo == NULL || servInfo->servName == NULL) {
117         HDF_LOGE("%{public}s:service or name is null", __func__);
118         return HDF_ERR_INVALID_PARAM;
119     }
120     if ((serviceProxy == NULL) || (serviceProxy->remote == NULL)) {
121         HDF_LOGE("update service failed, serviceProxy is invalid");
122         return HDF_ERR_INVALID_PARAM;
123     }
124 
125     if (servInfo->devClass >= DEVICE_CLASS_MAX) {
126         HDF_LOGE("update service failed, devClass is invalid");
127         return HDF_ERR_INVALID_PARAM;
128     }
129 
130     int status = HDF_FAILURE;
131     struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
132     struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
133     do {
134         if (data == NULL || reply == NULL) {
135             HDF_LOGE("update service failed, failed to obtain sbuf");
136             break;
137         }
138         if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) ||
139             WriteServiceInfo(data, service, servInfo) != HDF_SUCCESS) {
140             break;
141         }
142         status = serviceProxy->remote->dispatcher->Dispatch(
143             serviceProxy->remote, DEVSVC_MANAGER_UPDATE_SERVICE, data, reply);
144         HDF_LOGI("servmgr update service %{public}s, result is %{public}d", servInfo->servName, status);
145     } while (0);
146 
147     HdfSbufRecycle(reply);
148     HdfSbufRecycle(data);
149     return status;
150 }
151 
DevSvcManagerProxyGetService(struct IDevSvcManager * inst,const char * svcName)152 struct HdfObject *DevSvcManagerProxyGetService(struct IDevSvcManager *inst, const char *svcName)
153 {
154     int status = HDF_FAILURE;
155     struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
156     struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
157     struct HdfRemoteDispatcher *dispatcher = NULL;
158     struct HdfRemoteService *remoteService = NULL;
159     struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;
160     do {
161         if ((serviceProxy->remote == NULL) || (data == NULL) || (reply == NULL)) {
162             HDF_LOGE("Get service failed, serviceProxy->remote or data or reply is null");
163             break;
164         }
165         dispatcher = serviceProxy->remote->dispatcher;
166         if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) || !HdfSbufWriteString(data, svcName)) {
167             break;
168         }
169         status = dispatcher->Dispatch(serviceProxy->remote, DEVSVC_MANAGER_GET_SERVICE, data, reply);
170         if (status == HDF_SUCCESS) {
171             remoteService = HdfSbufReadRemoteService(reply);
172         }
173     } while (0);
174 
175     HdfSbufRecycle(reply);
176     HdfSbufRecycle(data);
177     HDF_LOGI("DevSvcManagerProxyGetService finish, and status is %{public}d", status);
178     return (remoteService == NULL) ? NULL : &remoteService->object;
179 }
180 
DevSvcManagerProxyRemoveService(struct IDevSvcManager * inst,const char * svcName,const struct HdfDeviceObject * devObj)181 void DevSvcManagerProxyRemoveService(struct IDevSvcManager *inst, const char *svcName,
182     const struct HdfDeviceObject *devObj)
183 {
184     (void)devObj;
185     if (inst == NULL || svcName == NULL) {
186         return;
187     }
188     struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
189     struct HdfSBuf *reply = HdfSbufTypedObtain(SBUF_IPC);
190     struct HdfRemoteDispatcher *dispatcher = NULL;
191     struct HdfRemoteService *remoteService = NULL;
192     struct DevSvcManagerProxy *serviceProxy = (struct DevSvcManagerProxy *)inst;
193 
194     do {
195         if ((serviceProxy->remote == NULL) || (data == NULL) || (reply == NULL)) {
196             HDF_LOGE("Remove service failed, serviceProxy->remote or data or reply is null");
197             break;
198         }
199         remoteService = serviceProxy->remote;
200         dispatcher = remoteService->dispatcher;
201         if (!HdfRemoteServiceWriteInterfaceToken(serviceProxy->remote, data) || !HdfSbufWriteString(data, svcName)) {
202             break;
203         }
204         int status = dispatcher->Dispatch(remoteService, DEVSVC_MANAGER_REMOVE_SERVICE, data, reply);
205         HDF_LOGW("Device service manager proxy remove service status is %{public}d", status);
206     } while (0);
207 
208     HdfSbufRecycle(reply);
209     HdfSbufRecycle(data);
210 }
211 
DevSvcManagerProxyOnRemoteDied(struct HdfDeathRecipient * recipient,struct HdfRemoteService * service)212 static void DevSvcManagerProxyOnRemoteDied(struct HdfDeathRecipient *recipient, struct HdfRemoteService *service)
213 {
214     struct IDevHostService *instance = DevHostServiceNewInstance(0, NULL);
215 
216     if (recipient == NULL || service == NULL || instance == NULL) {
217         HDF_LOGE("%{public}s parameter is null", __func__);
218         return;
219     }
220     (void)recipient;
221     struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
222     struct HdfMessageLooper *looper = &fullService->looper;
223     HDF_LOGW("%{public}s: DevSvcManager dead, host %{public}d stop", __func__, fullService->super.hostId);
224     if ((looper != NULL) && (looper->Stop != NULL)) {
225         looper->Stop(looper);
226     }
227     _exit(0);
228 }
229 
DevSvcManagerProxyConstruct(struct DevSvcManagerProxy * inst,struct HdfRemoteService * remote)230 void DevSvcManagerProxyConstruct(struct DevSvcManagerProxy *inst, struct HdfRemoteService *remote)
231 {
232     inst->pvtbl.AddService = DevSvcManagerProxyAddService;
233     inst->pvtbl.UpdateService = DevSvcManagerProxyUpdateService;
234     inst->pvtbl.GetService = DevSvcManagerProxyGetService;
235     inst->pvtbl.RemoveService = DevSvcManagerProxyRemoveService;
236     inst->remote = remote;
237     inst->recipient.OnRemoteDied = DevSvcManagerProxyOnRemoteDied;
238     HdfRemoteServiceAddDeathRecipient(remote, &inst->recipient);
239 }
240 
DevSvcManagerProxyObtain(struct HdfRemoteService * remote)241 static struct IDevSvcManager *DevSvcManagerProxyObtain(struct HdfRemoteService *remote)
242 {
243     struct DevSvcManagerProxy *instance = (struct DevSvcManagerProxy *)OsalMemCalloc(sizeof(struct DevSvcManagerProxy));
244     if (instance != NULL) {
245         DevSvcManagerProxyConstruct(instance, remote);
246     }
247     return (struct IDevSvcManager *)instance;
248 }
249 
DevSvcManagerProxyCreate(void)250 struct HdfObject *DevSvcManagerProxyCreate(void)
251 {
252     static struct IDevSvcManager *instance = NULL;
253     if (instance == NULL) {
254         struct HdfRemoteService *remote = HdfRemoteServiceGet(DEVICE_SERVICE_MANAGER_SA_ID);
255         if (remote != NULL) {
256             if (!HdfRemoteServiceSetInterfaceDesc(remote, "HDI.IServiceManager.V1_0")) {
257                 HDF_LOGE("%{public}s: failed to init interface desc", __func__);
258                 HdfRemoteServiceRecycle(remote);
259                 return NULL;
260             }
261             instance = DevSvcManagerProxyObtain(remote);
262         }
263     }
264     return (struct HdfObject *)instance;
265 }
266 
DevSvcManagerProxyRelease(struct HdfObject * object)267 void DevSvcManagerProxyRelease(struct HdfObject *object)
268 {
269     struct DevSvcManagerProxy *instance = (struct DevSvcManagerProxy *)object;
270     if (instance != NULL) {
271         if (instance->remote != NULL) {
272             HdfRemoteServiceRecycle(instance->remote);
273             instance->remote = NULL;
274         }
275         OsalMemFree(instance);
276     }
277 }
278