1 /*
2 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "devsvc_manager.h"
10 #include "devmgr_service.h"
11 #include "hdf_base.h"
12 #include "hdf_cstring.h"
13 #include "hdf_device_node.h"
14 #include "hdf_core_log.h"
15 #include "hdf_object_manager.h"
16 #include "hdf_service_record.h"
17 #include "osal_mem.h"
18
19 #define HDF_LOG_TAG devsvc_manager
20 #define SERVICE_LIST_MAX 16
21
DevSvcManagerSearchServiceLocked(struct IDevSvcManager * inst,uint32_t serviceKey)22 static struct DevSvcRecord *DevSvcManagerSearchServiceLocked(struct IDevSvcManager *inst, uint32_t serviceKey)
23 {
24 struct DevSvcRecord *record = NULL;
25 struct DevSvcRecord *searchResult = NULL;
26 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
27 if (devSvcManager == NULL) {
28 HDF_LOGE("failed to search service, devSvcManager is null");
29 return NULL;
30 }
31
32 DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
33 if (record->key == serviceKey) {
34 searchResult = record;
35 break;
36 }
37 }
38 return searchResult;
39 }
40
NotifyServiceStatusLocked(struct DevSvcManager * devSvcManager,const struct DevSvcRecord * record,uint32_t status)41 static void NotifyServiceStatusLocked(
42 struct DevSvcManager *devSvcManager, const struct DevSvcRecord *record, uint32_t status)
43 {
44 struct ServStatListenerHolder *holder = NULL;
45 struct ServStatListenerHolder *tmp = NULL;
46 struct ServiceStatus svcstat = {
47 .deviceClass = record->devClass,
48 .serviceName = record->servName,
49 .status = status,
50 .info = record->servInfo,
51 };
52 HDF_LOGI("notify service status %{public}s, %{public}d", svcstat.serviceName, svcstat.status);
53 DLIST_FOR_EACH_ENTRY_SAFE(holder, tmp, &devSvcManager->svcstatListeners, struct ServStatListenerHolder, node) {
54 if ((holder->listenClass & record->devClass) && holder->NotifyStatus != NULL) {
55 if (holder->NotifyStatus(holder, &svcstat) == HDF_FAILURE) {
56 DListRemove(&holder->node);
57 if (holder->Recycle != NULL) {
58 holder->Recycle(holder);
59 }
60 }
61 }
62 }
63 }
64
NotifyServiceStatusOnRegisterLocked(const struct DevSvcManager * devSvcManager,struct ServStatListenerHolder * listenerHolder)65 static void NotifyServiceStatusOnRegisterLocked(
66 const struct DevSvcManager *devSvcManager, struct ServStatListenerHolder *listenerHolder)
67 {
68 struct DevSvcRecord *record = NULL;
69 DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
70 if ((listenerHolder->listenClass & record->devClass) == 0) {
71 continue;
72 }
73 struct ServiceStatus svcstat = {
74 .deviceClass = record->devClass,
75 .serviceName = record->servName,
76 .status = SERVIE_STATUS_START,
77 .info = record->servInfo,
78 };
79 if (listenerHolder->NotifyStatus != NULL) {
80 listenerHolder->NotifyStatus(listenerHolder, &svcstat);
81 }
82 }
83 }
84
DevSvcManagerAddService(struct IDevSvcManager * inst,struct HdfDeviceObject * service,const struct HdfServiceInfo * servInfo)85 int DevSvcManagerAddService(struct IDevSvcManager *inst,
86 struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)
87 {
88 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
89 struct DevSvcRecord *record = NULL;
90 if (devSvcManager == NULL || service == NULL || servInfo == NULL || servInfo->servName == NULL) {
91 HDF_LOGE("failed to add service, input param is null");
92 return HDF_FAILURE;
93 }
94 OsalMutexLock(&devSvcManager->mutex);
95 record = DevSvcManagerSearchServiceLocked(inst, HdfStringMakeHashKey(servInfo->servName, 0));
96 if (record != NULL) {
97 // on service died will release old service object
98 record->value = service;
99 OsalMutexUnlock(&devSvcManager->mutex);
100 HDF_LOGI("%{public}s:add service %{public}s exist, only update value", __func__, servInfo->servName);
101 return HDF_SUCCESS;
102 }
103 OsalMutexUnlock(&devSvcManager->mutex);
104 record = DevSvcRecordNewInstance();
105 if (record == NULL) {
106 HDF_LOGE("failed to add service , record is null");
107 return HDF_FAILURE;
108 }
109
110 record->key = HdfStringMakeHashKey(servInfo->servName, 0);
111 record->value = service;
112 record->devClass = servInfo->devClass;
113 record->devId = servInfo->devId;
114 record->servName = HdfStringCopy(servInfo->servName);
115 record->servInfo = HdfStringCopy(servInfo->servInfo);
116
117 if (servInfo->interfaceDesc != NULL && strcmp(servInfo->interfaceDesc, "") != 0) {
118 record->interfaceDesc = HdfStringCopy(servInfo->interfaceDesc);
119 }
120 if (record->servName == NULL) {
121 DevSvcRecordFreeInstance(record);
122 return HDF_ERR_MALLOC_FAIL;
123 }
124 OsalMutexLock(&devSvcManager->mutex);
125 DListInsertTail(&record->entry, &devSvcManager->services);
126 NotifyServiceStatusLocked(devSvcManager, record, SERVIE_STATUS_START);
127 OsalMutexUnlock(&devSvcManager->mutex);
128 return HDF_SUCCESS;
129 }
130
DevSvcManagerUpdateService(struct IDevSvcManager * inst,struct HdfDeviceObject * service,const struct HdfServiceInfo * servInfo)131 int DevSvcManagerUpdateService(struct IDevSvcManager *inst,
132 struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)
133 {
134 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
135 struct DevSvcRecord *record = NULL;
136 char *servInfoStr = NULL;
137 if (devSvcManager == NULL || service == NULL || servInfo == NULL || servInfo->servName == NULL) {
138 HDF_LOGE("failed to update service, invalid param");
139 return HDF_FAILURE;
140 }
141 OsalMutexLock(&devSvcManager->mutex);
142 record = DevSvcManagerSearchServiceLocked(inst, HdfStringMakeHashKey(servInfo->servName, 0));
143 if (record == NULL) {
144 OsalMutexUnlock(&devSvcManager->mutex);
145 return HDF_DEV_ERR_NO_DEVICE;
146 }
147
148 if (servInfo->servInfo != NULL) {
149 servInfoStr = HdfStringCopy(servInfo->servInfo);
150 if (servInfoStr == NULL) {
151 OsalMutexUnlock(&devSvcManager->mutex);
152 return HDF_ERR_MALLOC_FAIL;
153 }
154 OsalMemFree((char *)record->servInfo);
155 record->servInfo = servInfoStr;
156 }
157
158 record->value = service;
159 record->devClass = servInfo->devClass;
160 record->devId = servInfo->devId;
161 NotifyServiceStatusLocked(devSvcManager, record, SERVIE_STATUS_CHANGE);
162 OsalMutexUnlock(&devSvcManager->mutex);
163 return HDF_SUCCESS;
164 }
165
DevSvcManagerSubscribeService(struct IDevSvcManager * inst,const char * svcName,struct SubscriberCallback callBack)166 int DevSvcManagerSubscribeService(struct IDevSvcManager *inst, const char *svcName, struct SubscriberCallback callBack)
167 {
168 struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
169 struct HdfObject *deviceService = NULL;
170 if (inst == NULL || svcName == NULL || devMgrSvc == NULL) {
171 return HDF_FAILURE;
172 }
173
174 deviceService = DevSvcManagerGetService(inst, svcName);
175 if (deviceService != NULL) {
176 if (callBack.OnServiceConnected != NULL) {
177 callBack.OnServiceConnected(callBack.deviceObject, deviceService);
178 }
179 return HDF_SUCCESS;
180 }
181
182 return devMgrSvc->super.LoadDevice(&devMgrSvc->super, svcName);
183 }
184
DevSvcManagerRemoveService(struct IDevSvcManager * inst,const char * svcName,const struct HdfDeviceObject * devObj)185 void DevSvcManagerRemoveService(struct IDevSvcManager *inst, const char *svcName, const struct HdfDeviceObject *devObj)
186 {
187 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
188 struct DevSvcRecord *serviceRecord = NULL;
189 uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0);
190 bool removeFlag = false;
191
192 if (svcName == NULL || devSvcManager == NULL) {
193 return;
194 }
195 OsalMutexLock(&devSvcManager->mutex);
196 serviceRecord = DevSvcManagerSearchServiceLocked(inst, serviceKey);
197 if (serviceRecord == NULL) {
198 OsalMutexUnlock(&devSvcManager->mutex);
199 return;
200 }
201 if (devObj == NULL || (uintptr_t)devObj == (uintptr_t)serviceRecord->value) {
202 NotifyServiceStatusLocked(devSvcManager, serviceRecord, SERVIE_STATUS_STOP);
203 DListRemove(&serviceRecord->entry);
204 removeFlag = true;
205 }
206 OsalMutexUnlock(&devSvcManager->mutex);
207
208 if (removeFlag) {
209 DevSvcRecordFreeInstance(serviceRecord);
210 } else {
211 HDF_LOGI("%{public}s %{public}s device object is out of date", __func__, svcName);
212 }
213 }
214
DevSvcManagerGetObject(struct IDevSvcManager * inst,const char * svcName)215 struct HdfDeviceObject *DevSvcManagerGetObject(struct IDevSvcManager *inst, const char *svcName)
216 {
217 uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0);
218 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
219 struct DevSvcRecord *serviceRecord = NULL;
220 struct HdfDeviceObject *deviceObject = NULL;
221 if (svcName == NULL) {
222 HDF_LOGE("Get service failed, svcName is null");
223 return NULL;
224 }
225 OsalMutexLock(&devSvcManager->mutex);
226 serviceRecord = DevSvcManagerSearchServiceLocked(inst, serviceKey);
227 if (serviceRecord != NULL) {
228 deviceObject = serviceRecord->value;
229 OsalMutexUnlock(&devSvcManager->mutex);
230 return deviceObject;
231 }
232 OsalMutexUnlock(&devSvcManager->mutex);
233 return NULL;
234 }
235
236 // only use for kernel space
DevSvcManagerListService(struct HdfSBuf * serviceNameSet,DeviceClass deviceClass)237 void DevSvcManagerListService(struct HdfSBuf *serviceNameSet, DeviceClass deviceClass)
238 {
239 struct DevSvcRecord *record = NULL;
240 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)DevSvcManagerGetInstance();
241 if (devSvcManager == NULL) {
242 HDF_LOGE("failed to list service, devSvcManager is null");
243 return;
244 }
245
246 OsalMutexLock(&devSvcManager->mutex);
247 DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
248 if (record->devClass == deviceClass) {
249 HdfSbufWriteString(serviceNameSet, record->servName);
250 }
251 }
252 OsalMutexUnlock(&devSvcManager->mutex);
253 }
254
DevSvcManagerGetService(struct IDevSvcManager * inst,const char * svcName)255 struct HdfObject *DevSvcManagerGetService(struct IDevSvcManager *inst, const char *svcName)
256 {
257 struct HdfDeviceObject *deviceObject = DevSvcManagerGetObject(inst, svcName);
258 if (deviceObject == NULL) {
259 return NULL;
260 }
261 return (struct HdfObject *)deviceObject->service;
262 }
263
DevSvcManagerListAllService(struct IDevSvcManager * inst,struct HdfSBuf * reply)264 void DevSvcManagerListAllService(struct IDevSvcManager *inst, struct HdfSBuf *reply)
265 {
266 struct DevSvcRecord *record = NULL;
267 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
268 if (devSvcManager == NULL || reply == NULL) {
269 HDF_LOGE("failed to list all service info, parameter is null");
270 return;
271 }
272 OsalMutexLock(&devSvcManager->mutex);
273 DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
274 HdfSbufWriteString(reply, record->servName);
275 HdfSbufWriteUint16(reply, record->devClass);
276 HdfSbufWriteUint32(reply, record->devId);
277 HDF_LOGD("%{public}s 0x%{public}x %{public}d", record->servName, record->devId, record->devClass);
278 }
279 OsalMutexUnlock(&devSvcManager->mutex);
280 HDF_LOGI("%{public}s end ", __func__);
281 }
282
DevSvcManagerListServiceByInterfaceDesc(struct IDevSvcManager * inst,const char * interfaceDesc,struct HdfSBuf * reply)283 int DevSvcManagerListServiceByInterfaceDesc(
284 struct IDevSvcManager *inst, const char *interfaceDesc, struct HdfSBuf *reply)
285 {
286 struct DevSvcRecord *record = NULL;
287 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
288 int status = HDF_SUCCESS;
289 if (devSvcManager == NULL || reply == NULL) {
290 HDF_LOGE("failed to list service collection info, parameter is null");
291 return HDF_ERR_INVALID_PARAM;
292 }
293 const char *serviceNames[SERVICE_LIST_MAX];
294 uint32_t serviceNum = 0;
295 uint32_t i;
296 OsalMutexLock(&devSvcManager->mutex);
297 DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
298 if (record->interfaceDesc == NULL) {
299 HDF_LOGD("%{public}s interfacedesc is null", record->servName);
300 continue;
301 }
302 if (serviceNum >= SERVICE_LIST_MAX) {
303 status = HDF_ERR_OUT_OF_RANGE;
304 HDF_LOGE(
305 "%{public}s: More than %{public}d services are found, but up to %{public}d services can be returned",
306 interfaceDesc, SERVICE_LIST_MAX, SERVICE_LIST_MAX);
307 break;
308 }
309 if (strcmp(record->interfaceDesc, interfaceDesc) == 0) {
310 serviceNames[serviceNum] = record->servName;
311 serviceNum = serviceNum + 1;
312 }
313 }
314 OsalMutexUnlock(&devSvcManager->mutex);
315 HDF_LOGD("find %{public}u services interfacedesc is %{public}s", serviceNum, interfaceDesc);
316 if (!HdfSbufWriteUint32(reply, serviceNum)) {
317 HDF_LOGE("failed to write serviceNum to buffer, interfacedesc is %{public}s, serviceNum is %{public}d",
318 interfaceDesc, serviceNum);
319 return HDF_FAILURE;
320 }
321 for (i = 0; i < serviceNum; i++) {
322 HdfSbufWriteString(reply, serviceNames[i]);
323 }
324 return status;
325 }
326
DevSvcManagerRegsterServListener(struct IDevSvcManager * inst,struct ServStatListenerHolder * listenerHolder)327 int DevSvcManagerRegsterServListener(struct IDevSvcManager *inst, struct ServStatListenerHolder *listenerHolder)
328 {
329 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
330 if (devSvcManager == NULL || listenerHolder == NULL) {
331 return HDF_ERR_INVALID_PARAM;
332 }
333
334 OsalMutexLock(&devSvcManager->mutex);
335 DListInsertTail(&listenerHolder->node, &devSvcManager->svcstatListeners);
336 NotifyServiceStatusOnRegisterLocked(devSvcManager, listenerHolder);
337 OsalMutexUnlock(&devSvcManager->mutex);
338
339 return HDF_SUCCESS;
340 }
341
DevSvcManagerUnregsterServListener(struct IDevSvcManager * inst,struct ServStatListenerHolder * listenerHolder)342 void DevSvcManagerUnregsterServListener(struct IDevSvcManager *inst, struct ServStatListenerHolder *listenerHolder)
343 {
344 struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
345 if (devSvcManager == NULL || listenerHolder == NULL) {
346 return;
347 }
348
349 OsalMutexLock(&devSvcManager->mutex);
350 DListRemove(&listenerHolder->node);
351 OsalMutexUnlock(&devSvcManager->mutex);
352 }
353
DevSvcManagerConstruct(struct DevSvcManager * inst)354 bool DevSvcManagerConstruct(struct DevSvcManager *inst)
355 {
356 struct IDevSvcManager *devSvcMgrIf = NULL;
357 if (inst == NULL) {
358 HDF_LOGE("%{public}s: inst is null!", __func__);
359 return false;
360 }
361 devSvcMgrIf = &inst->super;
362 devSvcMgrIf->AddService = DevSvcManagerAddService;
363 devSvcMgrIf->UpdateService = DevSvcManagerUpdateService;
364 devSvcMgrIf->SubscribeService = DevSvcManagerSubscribeService;
365 devSvcMgrIf->UnsubscribeService = NULL;
366 devSvcMgrIf->RemoveService = DevSvcManagerRemoveService;
367 devSvcMgrIf->GetService = DevSvcManagerGetService;
368 devSvcMgrIf->ListAllService = DevSvcManagerListAllService;
369 devSvcMgrIf->GetObject = DevSvcManagerGetObject;
370 devSvcMgrIf->RegsterServListener = DevSvcManagerRegsterServListener;
371 devSvcMgrIf->UnregsterServListener = DevSvcManagerUnregsterServListener;
372 devSvcMgrIf->ListServiceByInterfaceDesc = DevSvcManagerListServiceByInterfaceDesc;
373 if (OsalMutexInit(&inst->mutex) != HDF_SUCCESS) {
374 HDF_LOGE("failed to create device service manager mutex");
375 return false;
376 }
377 DListHeadInit(&inst->services);
378 DListHeadInit(&inst->svcstatListeners);
379 return true;
380 }
381
DevSvcManagerStartService(void)382 int DevSvcManagerStartService(void)
383 {
384 int ret;
385 struct IDevSvcManager *svcmgr = DevSvcManagerGetInstance();
386
387 if (svcmgr == NULL) {
388 return HDF_ERR_INVALID_OBJECT;
389 }
390 if (svcmgr->StartService == NULL) {
391 return HDF_SUCCESS;
392 }
393
394 ret = svcmgr->StartService(svcmgr);
395 if (ret != HDF_SUCCESS) {
396 HDF_LOGE("failed to start service manager");
397 }
398
399 return ret;
400 }
401
DevSvcManagerCreate(void)402 struct HdfObject *DevSvcManagerCreate(void)
403 {
404 static bool isDevSvcManagerInit = false;
405 static struct DevSvcManager devSvcManagerInstance;
406 if (!isDevSvcManagerInit) {
407 if (!DevSvcManagerConstruct(&devSvcManagerInstance)) {
408 return NULL;
409 }
410 isDevSvcManagerInit = true;
411 }
412 return (struct HdfObject *)&devSvcManagerInstance;
413 }
414
DevSvcManagerRelease(struct IDevSvcManager * inst)415 void DevSvcManagerRelease(struct IDevSvcManager *inst)
416 {
417 struct DevSvcManager *devSvcManager = CONTAINER_OF(inst, struct DevSvcManager, super);
418 if (inst == NULL) {
419 return;
420 }
421 struct DevSvcRecord *record = NULL;
422 struct DevSvcRecord *tmp = NULL;
423 DLIST_FOR_EACH_ENTRY_SAFE(record, tmp, &devSvcManager->services, struct DevSvcRecord, entry) {
424 DevSvcRecordFreeInstance(record);
425 }
426 OsalMutexDestroy(&devSvcManager->mutex);
427 }
428
DevSvcManagerGetInstance(void)429 struct IDevSvcManager *DevSvcManagerGetInstance(void)
430 {
431 static struct IDevSvcManager *instance = NULL;
432 if (instance == NULL) {
433 instance = (struct IDevSvcManager *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVSVC_MANAGER);
434 }
435 return instance;
436 }
437