1 /*
2  * Copyright (c) 2022-2023 Shenzhen Kaihong DID 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 #include "codec_component_manager_service.h"
16 #include <hdf_base.h>
17 #include <osal_mem.h>
18 #include <securec.h>
19 #include <unistd.h>
20 #include "codec_adapter_interface.h"
21 #include "codec_component_capability_config.h"
22 #include "codec_component_manager_stub.h"
23 #include "codec_component_type_service.h"
24 #include "codec_death_recipient.h"
25 #include "codec_log_wrapper.h"
26 
27 #define MAX_COMPONENT_SIZE 32
28 struct CodecComponentManagerSerivce *g_service = NULL;
29 uint32_t g_componentId = 0;
30 
OnRemoteServiceDied(struct HdfDeathRecipient * deathRecipient,struct HdfRemoteService * remote)31 static void OnRemoteServiceDied(struct HdfDeathRecipient *deathRecipient, struct HdfRemoteService *remote)
32 {
33     CleanRemoteServiceResource(deathRecipient, remote);
34 }
35 
36 static struct RemoteServiceDeathRecipient g_deathRecipient = {
37     .recipient = {
38         .OnRemoteDied = OnRemoteServiceDied,
39     }
40 };
41 
AddDeathRecipientForService(struct CodecCallbackType * callbacks,uint32_t componentId,struct CodecComponentNode * codecNode)42 static void AddDeathRecipientForService(struct CodecCallbackType *callbacks, uint32_t componentId,
43                                         struct CodecComponentNode *codecNode)
44 {
45     if (callbacks == NULL) {
46         CODEC_LOGE("invalid parameter");
47         return;
48     }
49     bool needAdd = RegisterService(callbacks, componentId, codecNode);
50     if (needAdd) {
51         CODEC_LOGI("add deathRecipient for remoteService!");
52         HdfRemoteServiceAddDeathRecipient(callbacks->remote, &g_deathRecipient.recipient);
53     }
54 }
55 
GetNextComponentId()56 static uint32_t GetNextComponentId()
57 {
58     uint32_t tempId = 0;
59     if (g_service == NULL) {
60         return tempId;
61     }
62     struct ComponentTypeNode *pos = NULL;
63     struct ComponentTypeNode *next = NULL;
64     bool find = false;
65 
66     do {
67         tempId = ++g_componentId;
68         find = false;
69         DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &g_service->head, struct ComponentTypeNode, node)
70         {
71             if (pos != NULL && tempId == pos->componentId) {
72                 find = true;
73                 break;
74             }
75         }
76     } while (find);
77     return tempId;
78 }
79 
OmxManagerGetComponentNum()80 static int32_t OmxManagerGetComponentNum()
81 {
82     int32_t num = 0;
83     if (GetComponentNum(&num) != HDF_SUCCESS) {
84         CODEC_LOGE("GetComponentNum error!");
85     }
86     return num;
87 }
88 
OmxManagerGetComponentCapabilityList(CodecCompCapability * capList,int32_t count)89 static int32_t OmxManagerGetComponentCapabilityList(CodecCompCapability *capList, int32_t count)
90 {
91     int32_t err = GetComponentCapabilityList(capList, count);
92     if (err != HDF_SUCCESS) {
93         CODEC_LOGE("GetComponentNum error!");
94     }
95     return err;
96 }
97 
OmxManagerDestroyComponent(uint32_t componentId)98 static int32_t OmxManagerDestroyComponent(uint32_t componentId)
99 {
100     CODEC_LOGI("service impl, %{public}d!", componentId);
101     if (g_service == NULL) {
102         CODEC_LOGE("g_service is not init!");
103         return HDF_ERR_INVALID_PARAM;
104     }
105 
106     struct ComponentTypeNode *pos = NULL;
107     struct ComponentTypeNode *next = NULL;
108     int32_t err = HDF_SUCCESS;
109     pthread_mutex_lock(&g_service->listMute);
110 
111     DLIST_FOR_EACH_ENTRY_SAFE(pos, next, &g_service->head, struct ComponentTypeNode, node)
112     {
113         if (pos == NULL || componentId != pos->componentId) {
114             continue;
115         }
116 
117         struct CodecComponentNode *codecNode = CodecComponentTypeServiceGetCodecNode(pos->service);
118         if (codecNode != NULL) {
119             err = OmxAdapterDestroyComponent(codecNode);
120             if (err != HDF_SUCCESS) {
121                 CODEC_LOGE("OmxAdapterDestroyComponent ret err[%{public}d]!", err);
122                 break;
123             }
124             RemoveDestoryedComponent(componentId);
125         }
126 
127         DListRemove(&pos->node);
128         CodecComponentTypeServiceRelease(pos->service);
129         OsalMemFree(pos);
130         pos = NULL;
131         break;
132     }
133 
134     pthread_mutex_unlock(&g_service->listMute);
135     return err;
136 }
137 
OmxManagerCreateComponent(struct CodecComponentType ** component,uint32_t * componentId,char * compName,int64_t appData,struct CodecCallbackType * callbacks)138 static int32_t OmxManagerCreateComponent(struct CodecComponentType **component, uint32_t *componentId, char *compName,
139                                          int64_t appData, struct CodecCallbackType *callbacks)
140 {
141     CODEC_LOGI("service impl!");
142     if (g_service == NULL) {
143         CODEC_LOGE("g_service is not init!");
144         return HDF_ERR_INVALID_PARAM;
145     }
146 
147     struct CodecComponentType *comp = CodecComponentTypeServiceGet();
148     if (comp == NULL) {
149         CODEC_LOGE("CodecComponentTypeServiceGet ret null!");
150         return HDF_ERR_INVALID_PARAM;
151     }
152 
153     struct ComponentTypeNode *node = (struct ComponentTypeNode *)OsalMemCalloc(sizeof(struct ComponentTypeNode));
154     if (node == NULL) {
155         CODEC_LOGE("CodecComponentTypeServiceGet ret null!");
156         CodecComponentTypeServiceRelease(comp);
157         return HDF_ERR_INVALID_PARAM;
158     }
159 
160     struct CodecComponentNode *codecNode = NULL;
161     int32_t err = OMXAdapterCreateComponent(&codecNode, compName, appData, callbacks);
162     if (err != HDF_SUCCESS) {
163         CODEC_LOGE("OMXAdapterCreateComponent err [%{public}x]", err);
164         CodecComponentTypeServiceRelease(comp);
165         OsalMemFree(node);
166         return HDF_ERR_INVALID_PARAM;
167     }
168 #ifdef SUPPORT_ROLE
169     err = OmxAdapterSetComponentRole(codecNode, compName);
170     if (err != HDF_SUCCESS) {
171         CODEC_LOGE("OMXAdapterSetComponentRole err [%{public}x]", err);
172         OmxManagerDestroyComponent(*componentId);
173         CodecComponentTypeServiceRelease(comp);
174         OsalMemFree(node);
175         return HDF_ERR_INVALID_PARAM;
176     }
177 #endif
178     *component = comp;
179     pthread_mutex_lock(&g_service->listMute);
180     *componentId = GetNextComponentId();
181     CodecComponentTypeServiceSetCodecNode(comp, codecNode);
182     DListInsertTail(&node->node, &g_service->head);
183     pthread_mutex_unlock(&g_service->listMute);
184 
185     node->componentId = *componentId;
186     node->service = comp;
187     CODEC_LOGI("componentId:%{public}d", node->componentId);
188     AddDeathRecipientForService(callbacks, *componentId, codecNode);
189     return err;
190 }
191 
CodecComponentManagerServiceConstruct(struct CodecComponentManager * manager)192 static void CodecComponentManagerServiceConstruct(struct CodecComponentManager *manager)
193 {
194     if (manager != NULL) {
195         manager->GetComponentNum = OmxManagerGetComponentNum;
196         manager->GetComponentCapabilityList = OmxManagerGetComponentCapabilityList;
197         manager->CreateComponent = OmxManagerCreateComponent;
198         manager->DestroyComponent = OmxManagerDestroyComponent;
199     }
200 }
201 
CodecComponentManagerSerivceGet(void)202 struct CodecComponentManagerSerivce *CodecComponentManagerSerivceGet(void)
203 {
204     if (g_service == NULL) {
205         g_service = (struct CodecComponentManagerSerivce *)OsalMemCalloc(sizeof(struct CodecComponentManagerSerivce));
206         if (g_service == NULL) {
207             CODEC_LOGE("malloc OmxComponentManagerService obj failed!");
208             return NULL;
209         }
210         DListHeadInit(&g_service->head);
211         if (!CodecComponentManagerStubConstruct(&g_service->stub)) {
212             CODEC_LOGE("construct SampleStub obj failed!");
213             OmxComponentManagerSeriveRelease(g_service);
214             g_service = NULL;
215         }
216         CodecComponentManagerServiceConstruct(&g_service->stub.interface);
217     }
218     return g_service;
219 }
220 
OmxComponentManagerSeriveRelease(struct CodecComponentManagerSerivce * instance)221 void OmxComponentManagerSeriveRelease(struct CodecComponentManagerSerivce *instance)
222 {
223     if (instance == NULL) {
224         return;
225     }
226     if (g_service == instance) {
227         g_service = NULL;
228     }
229     OsalMemFree(instance);
230 }
231 
CleanRemoteServiceResource(struct HdfDeathRecipient * deathRecipient,struct HdfRemoteService * remote)232 void CleanRemoteServiceResource(struct HdfDeathRecipient *deathRecipient, struct HdfRemoteService *remote)
233 {
234     uint32_t compIds[MAX_COMPONENT_SIZE];
235     uint32_t size = 0;
236     int32_t ret = CleanMapperOfDiedService(remote, compIds, &size);
237     if (ret != HDF_SUCCESS) {
238         CODEC_LOGE("clearn remote resource error!");
239         return;
240     }
241 
242     if (size == 0) {
243         CODEC_LOGE("remoteService no componment resource need to be release!");
244         return;
245     }
246     for (uint32_t i = 0; i < size; i++) {
247         OmxManagerDestroyComponent(compIds[i]);
248         CODEC_LOGI("destroyComponent done, compId=[%{public}d]", compIds[i]);
249     }
250 
251     CODEC_LOGI("remote service died , clean resource success!");
252 }