• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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