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