1 /*
2 * Copyright (c) 2021 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_map.h"
23 #include "hdf_message_looper.h"
24 #include "osal_message.h"
25
26 #define HDF_LOG_TAG devmgr_service_full
27 #define INVALID_PID (-1)
28
29 static Map g_hostMap = {0};
30 #define HOST_INIT_DIE_NUM 1
31 #define HOST_MAX_DIE_NUM 3
32
CleanupDiedHostResources(struct DevHostServiceClnt * hostClnt,struct HdfRemoteService * service)33 static void CleanupDiedHostResources(struct DevHostServiceClnt *hostClnt, struct HdfRemoteService *service)
34 {
35 OsalMutexLock(&hostClnt->hostLock);
36 struct DevHostServiceProxy *hostProxy = (struct DevHostServiceProxy *)hostClnt->hostService;
37 if (hostProxy != NULL) {
38 if ((hostProxy->remote != NULL) && ((uintptr_t)hostProxy->remote == (uintptr_t)service)) {
39 HDF_LOGI("%{public}s hostId: %{public}u remove current hostService", __func__, hostClnt->hostId);
40 hostClnt->hostPid = INVALID_PID;
41 DevHostServiceProxyRecycle(hostProxy);
42 hostClnt->hostService = NULL;
43 HdfSListFlush(&hostClnt->devices, DeviceTokenClntDelete);
44 } else {
45 hostProxy = (struct DevHostServiceProxy *)service->target;
46 HDF_LOGI("%{public}s hostId: %{public}u remove old hostService", __func__, hostClnt->hostId);
47 DevHostServiceProxyRecycle(hostProxy);
48 }
49 } else {
50 hostProxy = (struct DevHostServiceProxy *)service->target;
51 HDF_LOGI("%{public}s hostId: %{public}u remove old hostService, and current hostService is null",
52 __func__, hostClnt->hostId);
53 DevHostServiceProxyRecycle(hostProxy);
54 }
55
56 OsalMutexUnlock(&hostClnt->hostLock);
57 }
58
DevmgrServiceFullHandleDeviceHostDied(struct DevHostServiceClnt * hostClnt,struct HdfRemoteService * service)59 static int32_t DevmgrServiceFullHandleDeviceHostDied(struct DevHostServiceClnt *hostClnt,
60 struct HdfRemoteService *service)
61 {
62 bool isHostEmpty = HdfSListIsEmpty(&hostClnt->devices);
63
64 CleanupDiedHostResources(hostClnt, service);
65 if (isHostEmpty || hostClnt->stopFlag) {
66 return 0;
67 }
68
69 if (g_hostMap.nodeSize == 0) {
70 MapInit(&g_hostMap);
71 }
72 // host is started at init phase by init module, and it respawn by init module
73 if (!HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {
74 return 0;
75 }
76 int *hostDieValue = (int *)MapGet(&g_hostMap, hostClnt->hostName);
77 if (hostDieValue == NULL) {
78 int hostDieNum = HOST_INIT_DIE_NUM;
79 MapSet(&g_hostMap, hostClnt->hostName, &hostDieNum, sizeof(int));
80 } else {
81 if (*hostDieValue > HOST_MAX_DIE_NUM) {
82 HDF_LOGE("host %{public}s die 4 times, remove it", hostClnt->hostName);
83 *hostDieValue = 0;
84 hostClnt->stopFlag = false;
85 return INVALID_PID;
86 }
87 (*hostDieValue)++;
88 }
89 HDF_LOGI("%{public}s:%{public}d", __func__, __LINE__);
90 struct IDriverInstaller *installer = DriverInstallerGetInstance();
91 if (installer != NULL && installer->StartDeviceHost != NULL) {
92 HDF_LOGI("%{public}s:%{public}d", __func__, __LINE__);
93 int pid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName, true);
94 OsalMutexLock(&hostClnt->hostLock);
95 hostClnt->hostPid = pid;
96 OsalMutexUnlock(&hostClnt->hostLock);
97 return hostClnt->hostPid;
98 }
99 return INVALID_PID;
100 }
101
DevmgrServiceFullOnDeviceHostDied(struct DevmgrServiceFull * inst,uint32_t hostId,struct HdfRemoteService * service)102 static void DevmgrServiceFullOnDeviceHostDied(struct DevmgrServiceFull *inst, uint32_t hostId,
103 struct HdfRemoteService *service)
104 {
105 (void)hostId;
106 struct DevHostServiceClnt *hostClnt = NULL;
107 struct DevHostServiceClnt *hostClntTmp = NULL;
108 if (inst == NULL) {
109 return;
110 }
111 OsalMutexLock(&inst->super.devMgrMutex);
112 DLIST_FOR_EACH_ENTRY_SAFE(hostClnt, hostClntTmp, &inst->super.hosts, struct DevHostServiceClnt, node) {
113 if (hostClnt->hostId == hostId) {
114 int32_t ret = DevmgrServiceFullHandleDeviceHostDied(hostClnt, service);
115 if (ret == INVALID_PID) {
116 HDF_LOGE("%{public}s: failed to respawn host %{public}s", __func__, hostClnt->hostName);
117 }
118 break;
119 }
120 }
121 OsalMutexUnlock(&inst->super.devMgrMutex);
122 }
123
DevmgrServiceFullDispatchMessage(struct HdfMessageTask * task,struct HdfMessage * msg)124 int32_t DevmgrServiceFullDispatchMessage(struct HdfMessageTask *task, struct HdfMessage *msg)
125 {
126 (void)task;
127 struct DevmgrServiceFull *fullService = (struct DevmgrServiceFull *)DevmgrServiceGetInstance();
128 if (msg == NULL) {
129 HDF_LOGE("Input msg is null");
130 return HDF_ERR_INVALID_PARAM;
131 }
132 switch (msg->messageId) {
133 case DEVMGR_MESSAGE_DEVHOST_DIED: {
134 int hostId = (int)(uintptr_t)msg->data[0];
135 struct HdfRemoteService *service = (struct HdfRemoteService *)msg->data[1];
136 DevmgrServiceFullOnDeviceHostDied(fullService, hostId, service);
137 break;
138 }
139 default: {
140 HDF_LOGE("wrong message(%{public}u)", msg->messageId);
141 }
142 }
143
144 return HDF_SUCCESS;
145 }
146
DevmgrServiceFullGetMessageTask(void)147 struct HdfMessageTask *DevmgrServiceFullGetMessageTask(void)
148 {
149 struct DevmgrServiceFull *fullService = (struct DevmgrServiceFull *)DevmgrServiceGetInstance();
150 if (fullService != NULL) {
151 return &fullService->task;
152 }
153 HDF_LOGE("Get message task failed, fullService is null");
154 return NULL;
155 }
156
DevmgrServiceFullConstruct(struct DevmgrServiceFull * inst)157 void DevmgrServiceFullConstruct(struct DevmgrServiceFull *inst)
158 {
159 static struct IHdfMessageHandler handler = {.Dispatch = DevmgrServiceFullDispatchMessage};
160 if (inst != NULL) {
161 HdfMessageLooperConstruct(&inst->looper);
162 DevmgrServiceConstruct(&inst->super);
163 HdfMessageTaskConstruct(&inst->task, &inst->looper, &handler);
164 }
165 }
166
DevmgrServiceFullCreate(void)167 struct HdfObject *DevmgrServiceFullCreate(void)
168 {
169 static struct DevmgrServiceFull *instance = NULL;
170 if (instance == NULL) {
171 static struct DevmgrServiceFull fullInstance;
172 DevmgrServiceFullConstruct(&fullInstance);
173 instance = &fullInstance;
174 }
175 return (struct HdfObject *)instance;
176 }
177
DeviceManagerIsQuickLoad(void)178 int DeviceManagerIsQuickLoad(void)
179 {
180 return false;
181 }
182