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