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