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
16 #include "codec_callback_type_stub.h"
17 #include <dlfcn.h>
18 #include <hdf_base.h>
19 #include <hdf_dlist.h>
20 #include <hdf_remote_service.h>
21 #include <osal_mem.h>
22 #include <securec.h>
23 #include "codec_callback_type_service.h"
24 #include "codec_internal.h"
25 #include "codec_log_wrapper.h"
26 #include "codec_types.h"
27
28 #define CODEC_CALLBACK_SO_PATH "libcodec_hdi_omx_callback_type_service_impl.z.so"
29
30 typedef void (*SERVICE_CONSTRUCT_FUNC)(struct CodecCallbackType *);
31
32 struct CodecCallbackTypeStub {
33 struct CodecCallbackType service;
34 struct HdfRemoteDispatcher dispatcher;
35 void *dlHandler;
36 };
37
FreeMem(int8_t * mem,uint32_t memLen)38 static void FreeMem(int8_t *mem, uint32_t memLen)
39 {
40 if (memLen > 0 && mem != NULL) {
41 OsalMemFree(mem);
42 }
43 }
44
ReadArray(struct HdfSBuf * data,int8_t ** array,uint32_t * arrayLen)45 static int32_t ReadArray(struct HdfSBuf *data, int8_t **array, uint32_t *arrayLen)
46 {
47 int8_t *buffer = NULL;
48 uint32_t bufferLen = 0;
49 if (!HdfSbufReadUint32(data, &bufferLen)) {
50 CODEC_LOGE("read buffer size failed!");
51 return HDF_ERR_INVALID_PARAM;
52 }
53
54 if (bufferLen == 0) {
55 *arrayLen = bufferLen;
56 return HDF_SUCCESS;
57 }
58
59 buffer = (int8_t*)OsalMemCalloc(sizeof(int8_t) * bufferLen);
60 if (buffer == NULL) {
61 return HDF_ERR_MALLOC_FAIL;
62 }
63
64 for (uint32_t i = 0; i < bufferLen; i++) {
65 if (!HdfSbufReadInt8(data, &buffer[i])) {
66 CODEC_LOGE("read &buffer[i] failed!");
67 OsalMemFree(buffer);
68 return HDF_ERR_INVALID_PARAM;
69 }
70 }
71
72 *array = buffer;
73 *arrayLen = bufferLen;
74 return HDF_SUCCESS;
75 }
76
ReadEventInfo(struct HdfSBuf * data,struct EventInfo * info)77 static int32_t ReadEventInfo(struct HdfSBuf *data, struct EventInfo *info)
78 {
79 if (info == NULL) {
80 CODEC_LOGE("invalid parameter");
81 return HDF_ERR_INVALID_PARAM;
82 }
83 int32_t ret;
84 if (!HdfSbufReadInt64(data, &info->appData)) {
85 CODEC_LOGE("read appData failed!");
86 return HDF_ERR_INVALID_PARAM;
87 }
88
89 if (!HdfSbufReadUint32(data, &info->data1)) {
90 CODEC_LOGE("read &data1 failed!");
91 return HDF_ERR_INVALID_PARAM;
92 }
93
94 if (!HdfSbufReadUint32(data, &info->data2)) {
95 CODEC_LOGE("read &data2 failed!");
96 return HDF_ERR_INVALID_PARAM;
97 }
98
99 ret = ReadArray(data, &info->eventData, &info->eventDataLen);
100 if (ret != HDF_SUCCESS) {
101 CODEC_LOGE("read eventData failed!");
102 }
103 return ret;
104 }
105
ReleaseEventInfo(struct EventInfo * info)106 static void ReleaseEventInfo(struct EventInfo *info)
107 {
108 if (info == NULL) {
109 CODEC_LOGE("can not free info");
110 return;
111 }
112 FreeMem(info->eventData, info->eventDataLen);
113 }
114
SerStubEventHandler(struct CodecCallbackType * serviceImpl,struct HdfSBuf * data,struct HdfSBuf * reply)115 static int32_t SerStubEventHandler(struct CodecCallbackType *serviceImpl,
116 struct HdfSBuf *data, struct HdfSBuf *reply)
117 {
118 if (serviceImpl == NULL) {
119 CODEC_LOGE("invalid parameter");
120 return HDF_ERR_INVALID_PARAM;
121 }
122 int32_t ret;
123 enum OMX_EVENTTYPE event;
124 struct EventInfo info = {0};
125
126 if (!HdfSbufReadUint32(data, (uint32_t*)&event)) {
127 CODEC_LOGE("read &event failed!");
128 return HDF_ERR_INVALID_PARAM;
129 }
130
131 ret = ReadEventInfo(data, &info);
132 if (ret != HDF_SUCCESS) {
133 CODEC_LOGE("read &info failed!");
134 return HDF_ERR_INVALID_PARAM;
135 }
136
137 ret = serviceImpl->EventHandler(serviceImpl, event, &info);
138 if (ret != HDF_SUCCESS) {
139 CODEC_LOGE("call EventHandler function failed!");
140 }
141 ReleaseEventInfo(&info);
142 return ret;
143 }
144
SerStubEmptyBufferDone(struct CodecCallbackType * serviceImpl,struct HdfSBuf * data,struct HdfSBuf * reply)145 static int32_t SerStubEmptyBufferDone(struct CodecCallbackType *serviceImpl,
146 struct HdfSBuf *data, struct HdfSBuf *reply)
147 {
148 if (serviceImpl == NULL) {
149 CODEC_LOGE("invalid parameter");
150 return HDF_ERR_INVALID_PARAM;
151 }
152 int32_t ret;
153 int64_t appData = 0;
154 struct OmxCodecBuffer buffer;
155 InitOmxCodecBuffer(&buffer);
156
157 if (!HdfSbufReadInt64(data, &appData)) {
158 CODEC_LOGE("read appData size failed!");
159 return HDF_ERR_INVALID_PARAM;
160 }
161
162 if (!OmxCodecBufferBlockUnmarshalling(data, &buffer)) {
163 CODEC_LOGE("read buffer failed!");
164 ReleaseOmxCodecBuffer(&buffer);
165 return HDF_ERR_INVALID_PARAM;
166 }
167
168 ret = serviceImpl->EmptyBufferDone(serviceImpl, appData, &buffer);
169 if (ret != HDF_SUCCESS) {
170 CODEC_LOGE("call EmptyBufferDone function failed!");
171 ReleaseOmxCodecBuffer(&buffer);
172 return ret;
173 }
174
175 ReleaseOmxCodecBuffer(&buffer);
176 return ret;
177 }
178
SerStubFillBufferDone(struct CodecCallbackType * serviceImpl,struct HdfSBuf * data,struct HdfSBuf * reply)179 static int32_t SerStubFillBufferDone(struct CodecCallbackType *serviceImpl,
180 struct HdfSBuf *data, struct HdfSBuf *reply)
181 {
182 if (serviceImpl == NULL) {
183 CODEC_LOGE("invalid parameter");
184 return HDF_ERR_INVALID_PARAM;
185 }
186 int32_t ret;
187 int64_t appData = 0;
188 struct OmxCodecBuffer buffer;
189 InitOmxCodecBuffer(&buffer);
190 if (!HdfSbufReadInt64(data, &appData)) {
191 CODEC_LOGE("read appData size failed!");
192 return HDF_ERR_INVALID_PARAM;
193 }
194
195 if (!OmxCodecBufferBlockUnmarshalling(data, &buffer)) {
196 CODEC_LOGE("read buffer failed!");
197 return HDF_ERR_INVALID_PARAM;
198 }
199
200 ret = serviceImpl->FillBufferDone(serviceImpl, appData, &buffer);
201 if (ret != HDF_SUCCESS) {
202 CODEC_LOGE("call FillBufferDone function failed!");
203 ReleaseOmxCodecBuffer(&buffer);
204 return ret;
205 }
206
207 ReleaseOmxCodecBuffer(&buffer);
208 return ret;
209 }
210
CodecCallbackTypeServiceOnRemoteRequest(struct HdfRemoteService * service,int32_t code,struct HdfSBuf * data,struct HdfSBuf * reply)211 static int32_t CodecCallbackTypeServiceOnRemoteRequest(struct HdfRemoteService *service, int32_t code,
212 struct HdfSBuf *data, struct HdfSBuf *reply)
213 {
214 struct CodecCallbackType *serviceImpl = (struct CodecCallbackType*)service;
215 if (serviceImpl == NULL) {
216 CODEC_LOGE("invalid parameter");
217 return HDF_ERR_INVALID_PARAM;
218 }
219 if (!HdfRemoteServiceCheckInterfaceToken(serviceImpl->remote, data)) {
220 CODEC_LOGE("check interface token failed");
221 return HDF_ERR_INVALID_PARAM;
222 }
223
224 switch (code) {
225 case CMD_EVENT_HANDLER:
226 return SerStubEventHandler(serviceImpl, data, reply);
227 case CMD_EMPTY_BUFFER_DONE:
228 return SerStubEmptyBufferDone(serviceImpl, data, reply);
229 case CMD_FILL_BUFFER_DONE:
230 return SerStubFillBufferDone(serviceImpl, data, reply);
231 default: {
232 CODEC_LOGE("not support cmd %{public}d", code);
233 return HDF_ERR_INVALID_PARAM;
234 }
235 }
236 }
237
LoadServiceHandler(void)238 static void *LoadServiceHandler(void)
239 {
240 void *handler = NULL;
241 handler = dlopen(CODEC_CALLBACK_SO_PATH, RTLD_LAZY);
242 if (handler == NULL) {
243 CODEC_LOGE("dlopen failed %{public}s", dlerror());
244 return NULL;
245 }
246
247 return handler;
248 }
249
CodecCallbackTypeStubGetInstance(void)250 struct CodecCallbackType *CodecCallbackTypeStubGetInstance(void)
251 {
252 SERVICE_CONSTRUCT_FUNC serviceConstructFunc = NULL;
253 struct CodecCallbackTypeStub *stub
254 = (struct CodecCallbackTypeStub *)OsalMemAlloc(sizeof(struct CodecCallbackTypeStub));
255 if (stub == NULL) {
256 CODEC_LOGE("OsalMemAlloc obj failed!");
257 return NULL;
258 }
259
260 stub->dispatcher.Dispatch = CodecCallbackTypeServiceOnRemoteRequest;
261 stub->service.remote = HdfRemoteServiceObtain((struct HdfObject*)stub, &(stub->dispatcher));
262 if (stub->service.remote == NULL) {
263 CODEC_LOGE("stub->service.remote is null");
264 OsalMemFree(stub);
265 return NULL;
266 }
267
268 if (!HdfRemoteServiceSetInterfaceDesc(stub->service.remote, "ohos.hdi.codec_service")) {
269 CODEC_LOGE("failed to init interface desc");
270 OsalMemFree(stub);
271 return NULL;
272 }
273
274 stub->dlHandler = LoadServiceHandler();
275 if (stub->dlHandler == NULL) {
276 CODEC_LOGE("stub->dlHanlder is null");
277 OsalMemFree(stub);
278 return NULL;
279 }
280
281 serviceConstructFunc = (SERVICE_CONSTRUCT_FUNC)dlsym(stub->dlHandler, "CodecCallbackTypeServiceConstruct");
282 if (serviceConstructFunc == NULL) {
283 CODEC_LOGE("dlsym failed %{public}s", dlerror());
284 dlclose(stub->dlHandler);
285 OsalMemFree(stub);
286 return NULL;
287 }
288
289 serviceConstructFunc(&stub->service);
290 return &stub->service;
291 }
292
CodecCallbackTypeStubRelease(struct CodecCallbackType * instance)293 void CodecCallbackTypeStubRelease(struct CodecCallbackType *instance)
294 {
295 if (instance == NULL) {
296 CODEC_LOGE("instance is null");
297 return;
298 }
299 struct CodecCallbackTypeStub *stub = CONTAINER_OF(instance, struct CodecCallbackTypeStub, service);
300 dlclose(stub->dlHandler);
301 if (stub->service.remote != NULL) {
302 HdfRemoteServiceRecycle(stub->service.remote);
303 stub->service.remote = NULL;
304 }
305 OsalMemFree(stub);
306 }
CodecCallbackTypeGet(struct HdfRemoteService * remote)307 struct CodecCallbackType *CodecCallbackTypeGet(struct HdfRemoteService *remote)
308 {
309 (void)remote;
310 return CodecCallbackTypeStubGetInstance();
311 }
312
CodecCallbackTypeRelease(struct CodecCallbackType * instance)313 void CodecCallbackTypeRelease(struct CodecCallbackType *instance)
314 {
315 return CodecCallbackTypeStubRelease(instance);
316 }
317