1 /*
2 * Copyright (c) 2021-2023 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 "devmgr_service_full.h"
17 #include "devhost_service_clnt.h"
18 #include "devhost_service_proxy.h"
19 #include "device_token_clnt.h"
20 #include "hdf_driver_installer.h"
21 #include "hdf_log.h"
22 #include "hdf_message_looper.h"
23 #include "osal_message.h"
24
25 #define HDF_LOG_TAG devmgr_service_full
26 #define INVALID_PID (-1)
27
CleanupDiedHostResources(struct DevHostServiceClnt * hostClnt,struct HdfRemoteService * service)28 static void CleanupDiedHostResources(struct DevHostServiceClnt *hostClnt, struct HdfRemoteService *service)
29 {
30 OsalMutexLock(&hostClnt->hostLock);
31 struct DevHostServiceProxy *hostProxy = (struct DevHostServiceProxy *)hostClnt->hostService;
32 if (hostProxy != NULL) {
33 if ((hostProxy->remote != NULL) && ((uintptr_t)hostProxy->remote == (uintptr_t)service)) {
34 HDF_LOGI("%{public}s hostId: %{public}u remove current hostService", __func__, hostClnt->hostId);
35 hostClnt->hostPid = INVALID_PID;
36 DevHostServiceProxyRecycle(hostProxy);
37 hostClnt->hostService = NULL;
38 HdfSListFlush(&hostClnt->devices, DeviceTokenClntDelete);
39 } else {
40 hostProxy = (struct DevHostServiceProxy *)service->target;
41 HDF_LOGI("%{public}s hostId: %{public}u remove old hostService", __func__, hostClnt->hostId);
42 DevHostServiceProxyRecycle(hostProxy);
43 }
44 } else {
45 hostProxy = (struct DevHostServiceProxy *)service->target;
46 HDF_LOGI("%{public}s hostId: %{public}u remove old hostService, and current hostService is null",
47 __func__, hostClnt->hostId);
48 DevHostServiceProxyRecycle(hostProxy);
49 }
50
51 OsalMutexUnlock(&hostClnt->hostLock);
52 }
53
DevmgrServiceFullHandleDeviceHostDied(struct DevHostServiceClnt * hostClnt,struct HdfRemoteService * service)54 static int32_t DevmgrServiceFullHandleDeviceHostDied(struct DevHostServiceClnt *hostClnt,
55 struct HdfRemoteService *service)
56 {
57 // the host will be restart by init module if there are default loaded devices in it.
58 // the on-demand loaded device needs to be loaded by calling 'LoadDevice' interface.
59 CleanupDiedHostResources(hostClnt, service);
60 return 0;
61 }
62
DevmgrServiceFullOnDeviceHostDied(struct DevmgrServiceFull * inst,uint32_t hostId,struct HdfRemoteService * service)63 static void DevmgrServiceFullOnDeviceHostDied(struct DevmgrServiceFull *inst, uint32_t hostId,
64 struct HdfRemoteService *service)
65 {
66 struct DevHostServiceClnt *hostClnt = NULL;
67 struct DevHostServiceClnt *hostClntTmp = NULL;
68 if (inst == NULL) {
69 return;
70 }
71 OsalMutexLock(&inst->super.devMgrMutex);
72 DLIST_FOR_EACH_ENTRY_SAFE(hostClnt, hostClntTmp, &inst->super.hosts, struct DevHostServiceClnt, node) {
73 if (hostClnt->hostId == hostId) {
74 int32_t ret = DevmgrServiceFullHandleDeviceHostDied(hostClnt, service);
75 if (ret == INVALID_PID) {
76 HDF_LOGE("%{public}s: failed to respawn host %{public}s", __func__, hostClnt->hostName);
77 }
78 break;
79 }
80 }
81 OsalMutexUnlock(&inst->super.devMgrMutex);
82 }
83
DevmgrServiceFullDispatchMessage(struct HdfMessageTask * task,struct HdfMessage * msg)84 int32_t DevmgrServiceFullDispatchMessage(struct HdfMessageTask *task, struct HdfMessage *msg)
85 {
86 (void)task;
87 struct DevmgrServiceFull *fullService = (struct DevmgrServiceFull *)DevmgrServiceGetInstance();
88 if (msg == NULL) {
89 HDF_LOGE("Input msg is null");
90 return HDF_ERR_INVALID_PARAM;
91 }
92
93 if (msg->messageId == DEVMGR_MESSAGE_DEVHOST_DIED) {
94 int hostId = (int)(uintptr_t)msg->data[0];
95 struct HdfRemoteService *service = (struct HdfRemoteService *)msg->data[1];
96 DevmgrServiceFullOnDeviceHostDied(fullService, hostId, service);
97 } else {
98 HDF_LOGE("wrong message(%{public}u)", msg->messageId);
99 }
100
101 return HDF_SUCCESS;
102 }
103
DevmgrServiceFullGetMessageTask(void)104 struct HdfMessageTask *DevmgrServiceFullGetMessageTask(void)
105 {
106 struct DevmgrServiceFull *fullService = (struct DevmgrServiceFull *)DevmgrServiceGetInstance();
107 if (fullService != NULL) {
108 return &fullService->task;
109 }
110 HDF_LOGE("Get message task failed, fullService is null");
111 return NULL;
112 }
113
DevmgrServiceFullConstruct(struct DevmgrServiceFull * inst)114 void DevmgrServiceFullConstruct(struct DevmgrServiceFull *inst)
115 {
116 static struct IHdfMessageHandler handler = {.Dispatch = DevmgrServiceFullDispatchMessage};
117 if (inst != NULL) {
118 HdfMessageLooperConstruct(&inst->looper);
119 DevmgrServiceConstruct(&inst->super);
120 HdfMessageTaskConstruct(&inst->task, &inst->looper, &handler);
121 }
122 }
123
DevmgrServiceFullCreate(void)124 struct HdfObject *DevmgrServiceFullCreate(void)
125 {
126 static struct DevmgrServiceFull *instance = NULL;
127 if (instance == NULL) {
128 static struct DevmgrServiceFull fullInstance;
129 DevmgrServiceFullConstruct(&fullInstance);
130 instance = &fullInstance;
131 }
132 return (struct HdfObject *)instance;
133 }
134
DeviceManagerIsQuickLoad(void)135 int DeviceManagerIsQuickLoad(void)
136 {
137 return false;
138 }
139