1 /*
2 * Copyright (c) 2020 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 "liteipc_adapter.h"
17 #include <fcntl.h>
18 #include <pthread.h>
19 #include <sched.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/ioctl.h>
23 #include <sys/mman.h>
24 #include <sys/types.h>
25 #include <signal.h>
26 #include <time.h>
27 #include <unistd.h>
28 #include "liteipc.h"
29 #include "securec.h"
30 #include "sys_binder.h"
31 #include "utils_list.h"
32
33 #define ALIGN_SZ 4
34 #define IPC_IO_ALIGN(sz) (((sz) + ALIGN_SZ - 1) & (~(ALIGN_SZ - 1)))
35 #define SET_MAX_THREADS 4
36 #define BINDER_DRIVER "/dev/binder"
37 #define IPC_IO_DATA_TEMP 200
38 #define READ_BUFFER_SIZE 32
39
40 #define NS_PER_MS 1000000ULL
41 #define NS_PER_SEC 1000000000ULL
42 static UTILS_DL_LIST *g_tempHandles = NULL;
43 static UTILS_DL_LIST *g_funcPairs = NULL;
44 static pthread_mutex_t g_funcPairsMutex = PTHREAD_MUTEX_INITIALIZER;
45 static uint32_t g_samgrId = 0;
46 static uint32_t g_handle = 0;
47 static bool g_isStartLoop = false;
48 __thread const IpcContext *g_tlsContext = NULL;
49 __thread IpcIo **g_tlsReply = NULL;
50 __thread uint8_t g_tlsReplyData[IPC_IO_DATA_MAX] = {0};
51 bool g_init = 0;
52 struct TransactData {
53 uint32_t cmd;
54 struct binder_transaction_data btd;
55 }__attribute__((packed));
56
57 struct FreeData {
58 uint32_t cmd;
59 binder_uintptr_t buffer;
60 }__attribute__((packed));
61
62 static void RemoveDeathCallback(uint32_t handle);
63 typedef struct {
64 pthread_mutex_t mutex;
65 int32_t handleId;
66 bool threadWorking;
67 UTILS_DL_LIST apis;
68 UTILS_DL_LIST testaments;
69 } IpcCallbackCb;
70
71 IpcCallbackCb g_ipcCallbackCb = {
72 .mutex = PTHREAD_MUTEX_INITIALIZER,
73 .handleId = -1,
74 .threadWorking = false
75 };
76
77 typedef struct {
78 bool usedFlag;
79 IpcMsgHandler hdler;
80 void* arg;
81 } IpcMsgHandlerPair;
82
83 typedef struct {
84 UTILS_DL_LIST list;
85 uint32_t handle;
86 IpcMsgHandlerPair hdlerPairs[MAX_DEATHCB_PER_SVC];
87 size_t size;
88 bool isCallbackRuning;
89 } Testament;
90
91 typedef struct {
92 UTILS_DL_LIST list;
93 uint32_t token;
94 IpcMsgHandlerPair hdlerPair;
95 } AnonymousApi;
96
97 typedef struct {
98 uint32_t num;
99 void* msg;
100 IpcIo io;
101 IpcMsgHandlerPair* cbs;
102 const IpcContext* context;
103 } HdlerArg;
104
105 struct BinderDeath {
106 IpcMsgHandler func;
107 uint32_t token;
108 };
109
110 struct FuncPair {
111 UTILS_DL_LIST list;
112 pthread_t tid;
113 IpcMsgHandler func;
114 void* argv;
115 };
116
117 struct BinderThreadDesc {
118 const IpcContext* context;
119 IpcMsgHandler func;
120 void* argv;
121 };
122
123 #define LOG(level, format, ...) \
124 do { \
125 printf("[%s : %d]", __FUNCTION__, __LINE__); \
126 printf(format, ##__VA_ARGS__); \
127 printf("\n"); \
128 } while (0)
129
130 #define RETURN_IF_IPC_IOCTL_FAILED(retVal) \
131 do { \
132 if (ret < 0) { \
133 LOG(ERROR, "Liteipc driver ioctl failed."); \
134 return (retVal); \
135 } \
136 } while (0)
137
InitCallbackCb()138 static inline void InitCallbackCb()
139 {
140 UtilsListInit(&g_ipcCallbackCb.apis);
141 UtilsListInit(&g_ipcCallbackCb.testaments);
142 g_init = 1;
143 }
144
145 static int32_t StartCallbackDispatch(const IpcContext *context);
146
SaveFuncPair(const struct FuncPair * func)147 static void SaveFuncPair(const struct FuncPair* func)
148 {
149 if (g_funcPairs == NULL) {
150 return;
151 }
152 struct FuncPair* node = NULL;
153 struct FuncPair* next = NULL;
154 if (pthread_mutex_lock(&g_funcPairsMutex) != 0) {
155 LOG(ERROR, "Get save fun pair mutex failed.");
156 return;
157 }
158 uint32_t curTid = (uint32_t)pthread_self();
159 UTILS_DL_LIST_FOR_EACH_ENTRY_SAFE(node, next, g_funcPairs, struct FuncPair, list)
160 {
161 if (node->tid != curTid) {
162 continue;
163 }
164 node->func = func->func;
165 node->argv = func->argv;
166 (void)pthread_mutex_unlock(&g_funcPairsMutex);
167 return;
168 }
169
170 node = calloc(1, sizeof(struct FuncPair));
171 if (node == NULL) {
172 (void)pthread_mutex_unlock(&g_funcPairsMutex);
173 return;
174 }
175 node->func = func->func;
176 node->argv = func->argv;
177 node->tid = curTid;
178 UtilsListAdd(g_funcPairs, &node->list);
179 (void)pthread_mutex_unlock(&g_funcPairsMutex);
180 }
181
GetFuncPair(struct FuncPair * func,uint32_t target)182 static bool GetFuncPair(struct FuncPair* func, uint32_t target)
183 {
184 if (g_funcPairs == NULL) {
185 return false;
186 }
187 struct FuncPair* node = NULL;
188 struct FuncPair* next = NULL;
189 if (pthread_mutex_lock(&g_funcPairsMutex) != 0) {
190 LOG(ERROR, "Get callback mutex failed.");
191 return false;
192 }
193 UTILS_DL_LIST_FOR_EACH_ENTRY_SAFE(node, next, g_funcPairs, struct FuncPair, list)
194 {
195 if (node->tid != target) {
196 continue;
197 }
198 func->func = node->func;
199 func->argv = node->argv;
200 (void)pthread_mutex_unlock(&g_funcPairsMutex);
201 return true;
202 }
203 (void)pthread_mutex_unlock(&g_funcPairsMutex);
204 return false;
205 }
206
CheckIpcIo(IpcIo * data)207 static int32_t CheckIpcIo(IpcIo* data)
208 {
209 uint32_t totalSize;
210 /* It's OK if data is null */
211 if (data == NULL) {
212 return LITEIPC_OK;
213 }
214 if ((IpcIoAvailable(data) == false) ||
215 (data->bufferCur == NULL) ||
216 (data->bufferBase == NULL) ||
217 (data->offsetsCur == NULL) ||
218 (data->offsetsBase == NULL)) {
219 return LITEIPC_EINVAL;
220 }
221 totalSize = data->bufferCur- data->bufferBase + ((char*)data->offsetsCur - (char*)data->offsetsBase);
222 if (totalSize > IPC_IO_DATA_MAX) {
223 LOG(ERROR, "IpcIo data too big, please use IpcIoPushDataBuff to push big data.");
224 return LITEIPC_EINVAL;
225 }
226 return LITEIPC_OK;
227 }
228
BinderSetMaxthreads(const IpcContext * context,int threads)229 static int BinderSetMaxthreads(const IpcContext* context, int threads)
230 {
231 if (context == NULL) {
232 return LITEIPC_EINTNL;
233 }
234 int ret = ioctl(context->fd, BINDER_SET_MAX_THREADS, &threads);
235 return ret;
236 }
237
OpenLiteIpc(size_t mmapSize)238 IpcContext* OpenLiteIpc(size_t mmapSize)
239 {
240 if ((mmapSize == 0) || (mmapSize > MMAP_MAX_SIZE)) {
241 LOG(ERROR, "MmapSize not available");
242 return NULL;
243 }
244 IpcContext* context = (IpcContext *)malloc(sizeof(IpcContext));
245 if (context == NULL) {
246 return NULL;
247 }
248 context->fd = open(BINDER_DRIVER, O_RDONLY);
249 if (context->fd < 0) {
250 LOG(ERROR, "Open liteipc driver failed error %s.", strerror(errno));
251 goto OPEN_ERR;
252 }
253
254 context->mmapAddr = mmap(NULL, mmapSize, PROT_READ, MAP_PRIVATE, context->fd, 0);
255 if (context->mmapAddr == MAP_FAILED) {
256 LOG(ERROR, "Mmap failed.(size=%zu)", mmapSize);
257 goto MMAP_ERR;
258 }
259
260 context->mmapSize = mmapSize;
261 InitCallbackCb();
262 if (BinderSetMaxthreads(context, SET_MAX_THREADS) != LITEIPC_OK) {
263 LOG(ERROR, "set max threads failed");
264 goto MALLOC_ERR;
265 }
266 return context;
267
268 MALLOC_ERR:
269 munmap(context->mmapAddr, mmapSize);
270 MMAP_ERR:
271 close(context->fd);
272 OPEN_ERR:
273 free(context);
274 return NULL;
275 }
276
ResetLiteIpc()277 void ResetLiteIpc()
278 {
279 g_tempHandles = NULL;
280 g_funcPairs = NULL;
281 pthread_mutex_init(&(g_funcPairsMutex), NULL);
282 g_samgrId = 0;
283 g_handle = 0;
284 g_isStartLoop = false;
285 g_tlsContext = NULL;
286 g_tlsReply = NULL;
287 pthread_mutex_init(&(g_ipcCallbackCb.mutex), NULL);
288 g_ipcCallbackCb.handleId = -1;
289 g_ipcCallbackCb.threadWorking = false;
290 InitCallbackCb();
291 }
292
CloseLiteIpc(IpcContext * context)293 void CloseLiteIpc(IpcContext* context)
294 {
295 if (context == NULL) {
296 return;
297 }
298 munmap(context->mmapAddr, context->mmapSize);
299 close(context->fd);
300 free(context);
301 }
302
SetSaManager(const IpcContext * context,size_t maxMsgSize)303 int32_t SetSaManager(const IpcContext* context, size_t maxMsgSize)
304 {
305 if (context == NULL) {
306 LOG(ERROR, "Invalid parameter, null pointer.");
307 return LITEIPC_EINTNL;
308 }
309 int ret = ioctl(context->fd, BINDER_SET_CONTEXT_MGR, 0);
310 if (ret == LITEIPC_OK) {
311 g_samgrId = (uint32_t)pthread_self();
312 g_tempHandles = calloc(1, sizeof(UTILS_DL_LIST));
313 if (g_tempHandles == NULL) {
314 LOG(ERROR, "calloc failed.");
315 return LITEIPC_EINTNL;
316 }
317 UtilsListInit(g_tempHandles);
318 }
319 return ret;
320 }
321
AddServiceAccess(SvcIdentity sid,pid_t pid)322 int32_t AddServiceAccess(SvcIdentity sid, pid_t pid)
323 {
324 (void)sid;
325 (void)pid;
326 return LITEIPC_OK;
327 }
328
GetCode(const void * ipcMsg,uint32_t * code)329 int32_t GetCode(const void* ipcMsg, uint32_t* code)
330 {
331 if ((ipcMsg == NULL) || (code == NULL)) {
332 LOG(ERROR, "Invalid parameter, null pointer.");
333 return LITEIPC_EINVAL;
334 }
335
336 const IpcMsg* in = (const IpcMsg*)ipcMsg;
337 *code = in->code;
338 return LITEIPC_OK;
339 }
340
GetCallingTid(const void * ipcMsg)341 pid_t GetCallingTid(const void* ipcMsg)
342 {
343 if (ipcMsg == NULL) {
344 LOG(ERROR, "Invalid parameter, null pointer.");
345 return LITEIPC_EINVAL;
346 }
347
348 const IpcMsg* in = (const IpcMsg*)ipcMsg;
349 return (pid_t)in->taskID;
350 }
351
BinderWrite(const IpcContext * context,void * data,size_t len)352 static int BinderWrite(const IpcContext *context, void *data, size_t len)
353 {
354 struct binder_write_read bwr = {0};
355 int res;
356
357 bwr.write_size = len;
358 bwr.write_consumed = 0;
359 bwr.write_buffer = (uintptr_t)data;
360 bwr.read_size = 0;
361 bwr.read_consumed = 0;
362 bwr.read_buffer = 0;
363 res = ioctl(context->fd, BINDER_WRITE_READ, &bwr);
364 if (res < 0) {
365 LOG(ERROR, "ioctl failed ret = %d", res);
366 }
367 return res;
368 }
369
370 static void* BinderThreadRoutine(void *argv);
371
TxnToIpc(const struct binder_transaction_data * txn,IpcMsg * data)372 static void TxnToIpc(const struct binder_transaction_data *txn, IpcMsg* data)
373 {
374 data->target.handle = txn->target.handle;
375 data->target.token = txn->target.handle;
376 data->code = txn->code;
377 data->flag = txn->flags;
378 data->processID = txn->sender_pid;
379 data->userID = txn->sender_euid;
380 data->dataSz = txn->data_size;
381 data->data = (void *)txn->data.ptr.buffer;
382 data->freeData = (void *)txn->data.ptr.buffer;
383 data->offsets = (void *)txn->data.ptr.offsets;
384 data->spObjNum = txn->offsets_size / sizeof(size_t);
385 }
386
387 static void TryCallBack(const IpcContext* context, void* msg, IpcIo* data, void* arg);
388 static void GetIpcCallback(IpcMsg* msg, HdlerArg* arg);
389
IsValidCB(IpcMsg * ipcMsg)390 static bool IsValidCB(IpcMsg* ipcMsg)
391 {
392 HdlerArg tArg = {0};
393 GetIpcCallback(ipcMsg, &tArg);
394 if (tArg.num == 0) {
395 return false;
396 }
397 return true;
398 }
399
HandleSpawnLooper(const IpcContext * context,const struct FuncPair * funcPair)400 static void HandleSpawnLooper(const IpcContext *context, const struct FuncPair *funcPair)
401 {
402 pthread_t thread;
403 struct BinderThreadDesc *btd = (struct BinderThreadDesc *)malloc(sizeof(struct BinderThreadDesc));
404 if (btd == NULL) {
405 return;
406 }
407 (void)memset_s(btd, sizeof(struct BinderThreadDesc), 0, sizeof(struct BinderThreadDesc));
408
409 btd->context = context;
410 btd->func = funcPair->func;
411 btd->argv = funcPair->argv;
412 int ret = pthread_create(&thread, NULL, BinderThreadRoutine, btd);
413 if (ret != 0) {
414 free(btd);
415 btd = NULL;
416 }
417 }
418
HandleTransaction(const IpcContext * context,const struct binder_transaction_data * txn)419 static void HandleTransaction(const IpcContext *context, const struct binder_transaction_data *txn)
420 {
421 IpcMsg *data = (IpcMsg*)calloc(1, sizeof(IpcMsg));
422 if (data == NULL) {
423 LOG(ERROR, "HandleTransaction calloc failed!");
424 return;
425 }
426 data->type = MT_REQUEST;
427 TxnToIpc(txn, data);
428 IpcIo io = {0};
429 IpcIoInitFromMsg(&io, data);
430 uint32_t token = IpcIoPopUint32(&io);
431 SvcIdentity *remote = IpcIoPopSvc(&io);
432 if (remote == NULL) {
433 LOG(ERROR, "HandleTransaction remote NULL!");
434 return;
435 }
436 g_handle = remote->handle;
437 data->data = io.bufferCur;
438 data->offsets = io.offsetsCur;
439 data->dataSz = io.bufferLeft;
440 data->spObjNum = io.offsetsLeft;
441 if (IsValidCB(data)) {
442 TryCallBack(context, data, &io, NULL);
443 free(remote);
444 return;
445 }
446 data->target.token = token;
447 struct FuncPair pair;
448 if (GetFuncPair(&pair, txn->cookie)) {
449 pair.func(context, data, &io, pair.argv);
450 } else if (GetFuncPair(&pair, g_samgrId)) {
451 data->target.handle = remote->handle;
452 pair.func(context, data, &io, pair.argv);
453 } else {
454 LOG(ERROR, "BR_TRANSACTION should not happen!");
455 }
456 free(remote);
457 }
458
HandleReply(IpcIo * bio,const struct binder_transaction_data * txn,uintptr_t * buffer)459 static void HandleReply(IpcIo* bio, const struct binder_transaction_data *txn, uintptr_t* buffer)
460 {
461 if (bio == NULL) {
462 *buffer = 0;
463 return;
464 }
465 IpcMsg *data = (IpcMsg*)calloc(1, sizeof(IpcMsg));
466 if (data == NULL) {
467 LOG(ERROR, "HandleReply calloc failed!");
468 *buffer = 0;
469 return;
470 }
471
472 TxnToIpc(txn, data);
473 IpcIoInitFromMsg(bio, data);
474 IpcIoPopUint32(bio);
475 SvcIdentity *sid = IpcIoPopSvc(bio);
476 if (sid != NULL) {
477 free(sid);
478 sid = NULL;
479 }
480 if (buffer != NULL) {
481 *buffer = (uintptr_t)data;
482 }
483 }
484
HandleDeadBinder(const IpcContext * context,uintptr_t ptr)485 static void HandleDeadBinder(const IpcContext *context, uintptr_t ptr)
486 {
487 struct BinderDeath *death = (struct BinderDeath *)(uintptr_t) *(binder_uintptr_t *)ptr;
488 IpcMsg data = {0};
489 data.type = MT_DEATH_NOTIFY;
490 data.target.token = death->token;
491 data.target.handle = death->token;
492 death->func(context, &data, NULL, NULL);
493 }
494
BinderRefDone(const IpcContext * context,const struct binder_ptr_cookie * ptrCookie,enum binder_driver_command_protocol cmd)495 static void BinderRefDone(const IpcContext *context, const struct binder_ptr_cookie *ptrCookie,
496 enum binder_driver_command_protocol cmd)
497 {
498 struct {
499 uint32_t cmd;
500 struct binder_ptr_cookie payload;
501 } __attribute__((packed)) data;
502
503 data.cmd = cmd;
504 data.payload.ptr = ptrCookie->ptr;
505 data.payload.cookie = ptrCookie->cookie;
506 BinderWrite(context, &data, sizeof(data));
507 }
508
BinderParse(const IpcContext * context,void * bio,uintptr_t ptr,size_t size,struct FuncPair * funcPair,uintptr_t * buffer)509 static int BinderParse(const IpcContext *context, void *bio, uintptr_t ptr,
510 size_t size, struct FuncPair *funcPair, uintptr_t* buffer)
511 {
512 int ret = 1;
513 g_tlsContext = context;
514 uintptr_t end = ptr + (uintptr_t) size;
515 while (ptr < end) {
516 uint32_t cmd = *(uint32_t *) ptr;
517 ptr += sizeof(uint32_t);
518 switch (cmd) {
519 case BR_NOOP:
520 break;
521 case BR_TRANSACTION_COMPLETE:
522 break;
523 case BR_ACQUIRE: {
524 struct binder_ptr_cookie *ptrCookie = (struct binder_ptr_cookie *) ptr;
525 if ((end - ptr) < sizeof(*ptrCookie)) {
526 return -1;
527 }
528 BinderRefDone(context, ptrCookie, BC_ACQUIRE_DONE);
529 ptr += sizeof(*ptrCookie);
530 break;
531 }
532 case BR_INCREFS: {
533 struct binder_ptr_cookie *ptrCookie = (struct binder_ptr_cookie *) ptr;
534 if ((end - ptr) < sizeof(*ptrCookie)) {
535 return -1;
536 }
537 BinderRefDone(context, ptrCookie, BC_INCREFS_DONE);
538 ptr += sizeof(*ptrCookie);
539 break;
540 }
541 case BR_RELEASE:
542 case BR_DECREFS:
543 ptr += sizeof(struct binder_ptr_cookie);
544 break;
545 case BR_SPAWN_LOOPER: {
546 HandleSpawnLooper(context, funcPair);
547 break;
548 }
549 case BR_TRANSACTION: {
550 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
551 if ((end - ptr) < sizeof(*txn)) {
552 return -1;
553 }
554 HandleTransaction(context, txn);
555 ptr += sizeof(*txn);
556 break;
557 }
558 case BR_REPLY: {
559 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
560 if ((end - ptr) < sizeof(*txn)) {
561 return -1;
562 }
563 HandleReply(bio, txn, buffer);
564 ptr += sizeof(*txn);
565 ret = 0;
566 break;
567 }
568 case BR_DEAD_BINDER: {
569 HandleDeadBinder(context, ptr);
570 ptr += sizeof(binder_uintptr_t);
571 break;
572 }
573 case BR_FAILED_REPLY:
574 ret = -1;
575 break;
576 case BR_DEAD_REPLY:
577 ret = LITEIPC_DEAD_OBJECT;
578 break;
579 default:
580 ret = -1;
581 }
582 }
583 return ret;
584 }
585
StartLoop(const IpcContext * context,IpcMsgHandler func,void * arg)586 int32_t StartLoop(const IpcContext* context, IpcMsgHandler func, void* arg)
587 {
588 if (context == NULL) {
589 LOG(ERROR, "Invalid parameter, null pointer.");
590 return LITEIPC_EINVAL;
591 }
592 if (g_funcPairs == NULL) {
593 g_funcPairs = calloc(1, sizeof(UTILS_DL_LIST));
594 if (g_funcPairs == NULL) {
595 LOG(ERROR, "Invalid parameter, null pointer.");
596 return LITEIPC_EINVAL;
597 }
598 UtilsListInit(g_funcPairs);
599 }
600 struct binder_write_read bwr = {0};
601 uint32_t readbuf[READ_BUFFER_SIZE] = {0};
602 struct FuncPair funcPair = {0};
603 funcPair.func = func;
604 funcPair.argv = arg;
605 SaveFuncPair(&funcPair);
606
607 readbuf[0] = BC_ENTER_LOOPER;
608 BinderWrite(context, readbuf, sizeof(uint32_t));
609 for (;;) {
610 bwr.read_size = sizeof(readbuf);
611 bwr.read_consumed = 0;
612 bwr.read_buffer = (uintptr_t) readbuf;
613 int ret = ioctl(context->fd, BINDER_WRITE_READ, &bwr);
614
615 if (ret < 0) {
616 LOG(ERROR, "ioctl failed ret = %d", ret);
617 break;
618 }
619 ret = BinderParse(context, 0, (uintptr_t)readbuf, bwr.read_consumed, &funcPair, NULL);
620 if (ret == 0) {
621 LOG(ERROR, "reply failed!");
622 break;
623 }
624 if (ret < 0) {
625 LOG(ERROR, "io error %d", ret);
626 break;
627 }
628 }
629
630 return LITEIPC_OK;
631 }
632
BinderThreadLoop(const IpcContext * context,IpcMsgHandler func,void * arg)633 static void BinderThreadLoop(const IpcContext* context, IpcMsgHandler func, void* arg)
634 {
635 struct binder_write_read bwr = {0};
636 uint32_t readbuf[READ_BUFFER_SIZE] = {0};
637 struct FuncPair funcPair = {0};
638 funcPair.func = func;
639 funcPair.argv = arg;
640
641 readbuf[0] = BC_REGISTER_LOOPER;
642
643 BinderWrite(context, readbuf, sizeof(uint32_t));
644 for (;;) {
645 bwr.read_size = sizeof(readbuf);
646 bwr.read_consumed = 0;
647 bwr.read_buffer = (uintptr_t) readbuf;
648 int ret = ioctl(context->fd, BINDER_WRITE_READ, &bwr);
649
650 if (ret < 0) {
651 LOG(ERROR, "ioctl failed ret = %d", ret);
652 break;
653 }
654 ret = BinderParse(context, 0, (uintptr_t)readbuf, bwr.read_consumed, &funcPair, NULL);
655 if (ret == 0) {
656 LOG(ERROR, "reply failed");
657 break;
658 }
659 if (ret < 0) {
660 LOG(ERROR, "io error ret = %d", ret);
661 break;
662 }
663 }
664 }
665
BinderThreadRoutine(void * argv)666 static void* BinderThreadRoutine(void *argv)
667 {
668 struct BinderThreadDesc *btd = (struct BinderThreadDesc *)argv;
669 BinderThreadLoop(btd->context, btd->func, btd->argv);
670 free(argv);
671 argv = NULL;
672 return NULL;
673 }
674
ToTransData(SvcIdentity sid,uint32_t code,IpcIo * data,IpcFlag flag,struct TransactData * buf)675 static void ToTransData(SvcIdentity sid, uint32_t code, IpcIo* data, IpcFlag flag, struct TransactData *buf)
676 {
677 buf->btd.target.ptr = 0;
678 buf->btd.target.handle = sid.handle;
679 buf->btd.code = code;
680 buf->btd.flags = flag;
681 buf->btd.cookie = 0;
682 buf->btd.sender_pid = getpid();
683 buf->btd.sender_euid = getuid();
684 if ((data != NULL) && (data->bufferBase != NULL)) {
685 (data->bufferBase)[0] = sid.token;
686 }
687 buf->btd.data_size = (data == NULL) ? 0 : (data->bufferCur - data->bufferBase);
688 buf->btd.data.ptr.buffer = (data == NULL) ? 0 : (binder_uintptr_t)data->bufferBase;
689 buf->btd.offsets_size = (data == NULL) ? 0 : ((char*)data->offsetsCur - (char*)data->offsetsBase);
690 buf->btd.offsets_size = IPC_IO_ALIGN(buf->btd.offsets_size);
691 buf->btd.data.ptr.offsets = (data == NULL) ? 0 : (binder_uintptr_t)data->offsetsBase;
692 }
693
GetIpcContext(const IpcContext * context,const IpcContext * tlsContext)694 static IpcContext* GetIpcContext(const IpcContext* context, const IpcContext* tlsContext)
695 {
696 const IpcContext *tmpContext = NULL;
697 if (tlsContext != NULL) {
698 tmpContext = tlsContext;
699 } else if (context != NULL) {
700 tmpContext = context;
701 }
702 return (IpcContext*)tmpContext;
703 }
704
HandleInternelRequest(const IpcContext * context,SvcIdentity sid,uint32_t code,IpcIo * data,IpcIo * reply,IpcFlag flag)705 static int32_t HandleInternelRequest(const IpcContext *context, SvcIdentity sid, uint32_t code,
706 IpcIo* data, IpcIo* reply, IpcFlag flag)
707 {
708 AnonymousApi* node = (AnonymousApi*)sid.token;
709 if (node == NULL) {
710 LOG(ERROR, "Invalid parameter, node null pointer.");
711 return LITEIPC_EINVAL;
712 }
713 IpcMsg msg = {
714 .type = MT_REQUEST,
715 .target = sid,
716 .code = code,
717 .flag = flag,
718 .dataSz = (data == NULL) ? 0 : (data->bufferCur - data->bufferBase),
719 .data = (data == NULL) ? NULL : data->bufferBase,
720 .offsets = (data == NULL) ? NULL : data->offsetsBase,
721 .spObjNum = (data == NULL) ? 0 : ((char*)data->offsetsCur - (char*)data->offsetsBase) / sizeof(size_t)
722 };
723 IpcIo tmp;
724 IpcIoInitFromMsg(&tmp, &msg);
725 IpcIoPopUint32(&tmp);
726 SvcIdentity *sidTmp = IpcIoPopSvc(&tmp);
727 if (sidTmp != NULL) {
728 free(sidTmp);
729 sidTmp = NULL;
730 }
731 msg.data = tmp.bufferCur;
732 msg.offsets = tmp.offsetsCur;
733 msg.dataSz = tmp.bufferLeft;
734 msg.spObjNum = tmp.offsetsLeft;
735 if (reply != NULL) {
736 g_tlsReply = &reply;
737 }
738 node->hdlerPair.hdler(context, &msg, &tmp, node->hdlerPair.arg);
739 return LITEIPC_OK;
740 }
741
SendRequest(const IpcContext * context,SvcIdentity sid,uint32_t code,IpcIo * data,IpcIo * reply,IpcFlag flag,uintptr_t * buffer)742 int32_t SendRequest(const IpcContext *context, SvcIdentity sid, uint32_t code,
743 IpcIo* data, IpcIo* reply, IpcFlag flag, uintptr_t* buffer)
744 {
745 const IpcContext *tmpContext = GetIpcContext(context, sid.ipcContext);
746 if (tmpContext == NULL) {
747 LOG(ERROR, "Invalid parameter, null pointer.");
748 return LITEIPC_EINVAL;
749 }
750 if ((flag > LITEIPC_FLAG_ONEWAY) || ((flag == LITEIPC_FLAG_DEFAULT) && (buffer == NULL))) {
751 LOG(ERROR, "Invalid parameter, null pointer.");
752 return LITEIPC_EINVAL;
753 }
754
755 if (sid.handle == MIN_BINDER_HANDLE) {
756 return HandleInternelRequest(tmpContext, sid, code, data, reply, flag);
757 }
758 int ret;
759 if (!g_isStartLoop) {
760 ret = StartCallbackDispatch(tmpContext);
761 if (ret != LITEIPC_OK) {
762 LOG(ERROR, "StartCallbackDispatch failed.");
763 }
764 }
765 struct TransactData buf;
766 struct binder_write_read bwr;
767 ret = CheckIpcIo(data);
768 if (ret != LITEIPC_OK) {
769 LOG(ERROR, "CheckIpcIo failed.");
770 return ret;
771 }
772 buf.cmd = BC_TRANSACTION;
773 IpcIo tempIo;
774 if (data == NULL) {
775 data = &tempIo;
776 uint8_t tmpData[IPC_IO_DATA_TEMP];
777 IpcIoInit(data, tmpData, IPC_IO_DATA_TEMP, 0);
778 }
779 ToTransData(sid, code, data, flag, &buf);
780 bwr.write_size = sizeof(buf);
781 bwr.write_consumed = 0;
782 bwr.write_buffer = (uintptr_t)&buf;
783 uint32_t readbuf[READ_BUFFER_SIZE] = {0};
784 if (flag != LITEIPC_FLAG_ONEWAY) {
785 while (1) {
786 bwr.read_size = sizeof(readbuf);
787 bwr.read_consumed = 0;
788 bwr.read_buffer = (uintptr_t)readbuf;
789 ioctl(tmpContext->fd, BINDER_WRITE_READ, &bwr);
790 ret = BinderParse(tmpContext, reply, (uintptr_t)readbuf, bwr.read_consumed, NULL, buffer);
791 if (ret == 0) {
792 break;
793 }
794 }
795 } else {
796 bwr.read_size = sizeof(readbuf);
797 bwr.read_consumed = 0;
798 bwr.read_buffer = (uintptr_t)readbuf;
799 ioctl(tmpContext->fd, BINDER_WRITE_READ, &bwr);
800 ret = BinderParse(tmpContext, reply, (uintptr_t)readbuf, bwr.read_consumed, NULL, NULL);
801 if (ret == 1) {
802 ret = 0;
803 }
804 }
805 return ret;
806 }
807
SendReply(const IpcContext * context,void * ipcMsg,IpcIo * reply)808 int32_t SendReply(const IpcContext* context, void* ipcMsg, IpcIo* reply)
809 {
810 const IpcContext *tmpContext = NULL;
811 if (context != NULL) {
812 tmpContext = context;
813 } else if (g_tlsContext != NULL) {
814 tmpContext = g_tlsContext;
815 } else {
816 LOG(ERROR, "Invalid parameter, null pointer.");
817 return LITEIPC_EINVAL;
818 }
819 (void)FreeBuffer(tmpContext, ipcMsg);
820
821 int32_t ret = CheckIpcIo(reply);
822 if (ret != LITEIPC_OK) {
823 LOG(ERROR, "CheckIpcIo failed.");
824 return ret;
825 }
826
827 if (g_tlsReply != NULL && *g_tlsReply != NULL) {
828 IpcIo tmp;
829 IpcMsg msg = {
830 .dataSz = (reply == NULL) ? 0 : (reply->bufferCur - reply->bufferBase),
831 .data = (reply == NULL) ? NULL : (void*)reply->bufferBase,
832 .offsets = (reply == NULL) ? NULL : reply->offsetsBase,
833 .spObjNum = (reply == NULL) ? 0 : ((char*)reply->offsetsCur - (char*)reply->offsetsBase) / sizeof(size_t)
834 };
835 IpcIoInitFromMsg(&tmp, &msg);
836
837 size_t objectsSize = tmp.offsetsLeft * sizeof(size_t);
838 (*g_tlsReply)->bufferCur = (*g_tlsReply)->bufferBase = (char*)g_tlsReplyData + objectsSize;
839 (*g_tlsReply)->offsetsCur = (*g_tlsReply)->offsetsBase = (size_t*)g_tlsReplyData;
840 memcpy_s((*g_tlsReply)->bufferBase, IPC_IO_DATA_MAX, tmp.bufferBase, tmp.bufferLeft);
841 memcpy_s((*g_tlsReply)->offsetsBase, objectsSize, tmp.offsetsBase, objectsSize);
842 (*g_tlsReply)->bufferLeft = tmp.bufferLeft;
843 (*g_tlsReply)->offsetsLeft = tmp.offsetsLeft;
844 (*g_tlsReply)->flag = reply->flag;
845
846 IpcIoPopUint32(*g_tlsReply);
847 SvcIdentity *sid = IpcIoPopSvc(*g_tlsReply);
848 if (sid != NULL) {
849 free(sid);
850 sid = NULL;
851 }
852 g_tlsReply = NULL;
853 return LITEIPC_OK;
854 }
855
856 struct TransactData buf = {0};
857 buf.cmd = BC_REPLY;
858 SvcIdentity sid = {0};
859 IpcIo tempIo;
860 if (reply == NULL) {
861 reply = &tempIo;
862 uint8_t tmpData[IPC_IO_DATA_TEMP];
863 IpcIoInit(reply, tmpData, IPC_IO_DATA_TEMP, 0);
864 }
865 ToTransData(sid, 0, reply, 0, &buf);
866 ret = BinderWrite(tmpContext, &buf, sizeof(buf));
867 return ret;
868 }
869
CallbackBatchHandler(void * arg)870 static void CallbackBatchHandler(void* arg)
871 {
872 HdlerArg* hdlerArg = (HdlerArg*)arg;
873 IpcMsg* msg = hdlerArg->msg;
874 uint32_t i;
875
876 for (i = 0; i < hdlerArg->num; i++) {
877 if (hdlerArg->cbs[i].usedFlag == true) {
878 (hdlerArg->cbs[i].hdler)(hdlerArg->context, hdlerArg->msg, &hdlerArg->io, hdlerArg->cbs[i].arg);
879 }
880 }
881 if (msg->type == MT_DEATH_NOTIFY) {
882 RemoveDeathCallback(msg->target.token);
883 FreeBuffer(NULL, msg);
884 }
885 free(arg);
886 return;
887 }
888
GetIpcCallback(IpcMsg * msg,HdlerArg * arg)889 static void GetIpcCallback(IpcMsg* msg, HdlerArg* arg)
890 {
891 if (pthread_mutex_lock(&g_ipcCallbackCb.mutex) != 0) {
892 LOG(ERROR, "Get callback mutex failed.");
893 return;
894 }
895 IpcIoInitFromMsg(&arg->io, msg);
896 arg->msg = msg;
897
898 AnonymousApi* node = NULL;
899 UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_ipcCallbackCb.apis, AnonymousApi, list)
900 {
901 if (node->token == msg->target.token) {
902 arg->num = 1;
903 arg->cbs = &node->hdlerPair;
904 (void)pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
905 return;
906 }
907 }
908 arg->num = 0;
909 arg->cbs = NULL;
910 (void)pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
911 }
912
GetDeathCallback(IpcMsg * msg,HdlerArg * arg)913 static void GetDeathCallback(IpcMsg* msg, HdlerArg* arg)
914 {
915 if (pthread_mutex_lock(&g_ipcCallbackCb.mutex) != 0) {
916 LOG(ERROR, "Get callback mutex failed.");
917 return;
918 }
919 IpcIoInitFromMsg(&arg->io, msg);
920 arg->msg = msg;
921
922 Testament* node = NULL;
923 UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_ipcCallbackCb.testaments, Testament, list)
924 {
925 if (node->handle == msg->target.token) {
926 node->isCallbackRuning = true;
927 arg->num = MAX_DEATHCB_PER_SVC;
928 arg->cbs = node->hdlerPairs;
929 (void)pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
930 return;
931 }
932 }
933 arg->num = 0;
934 arg->cbs = NULL;
935 (void)pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
936 }
937
TryCallBack(const IpcContext * context,void * msg,IpcIo * data,void * arg)938 static void TryCallBack(const IpcContext* context, void* msg, IpcIo* data, void* arg)
939 {
940 IpcMsg* ipcMsg = (IpcMsg *)msg;
941 HdlerArg* tArg = (HdlerArg*)malloc(sizeof(HdlerArg));
942 if (tArg == NULL) {
943 goto ERROR_MALLOC;
944 }
945
946 switch (ipcMsg->type) {
947 case MT_DEATH_NOTIFY:
948 GetDeathCallback(ipcMsg, tArg);
949 break;
950 case MT_REQUEST:
951 GetIpcCallback(ipcMsg, tArg);
952 break;
953 default:
954 LOG(ERROR, "Callback thread received an unrecognized message.(type=%d)", ipcMsg->type);
955 goto ERROR_MSG;
956 }
957
958 if (tArg->num == 0) {
959 goto ERROR_MSG;
960 }
961 tArg->context = context;
962 CallbackBatchHandler(tArg);
963 return;
964 ERROR_MSG:
965 free(tArg);
966 ERROR_MALLOC:
967 if ((ipcMsg->type == MT_REQUEST) && (ipcMsg->flag == LITEIPC_FLAG_DEFAULT)) {
968 SendReply(context, ipcMsg, data);
969 } else {
970 (void)FreeBuffer(context, ipcMsg);
971 }
972 }
973
CallbackDispatch(void * arg)974 static void* CallbackDispatch(void* arg)
975 {
976 IpcContext *ipcContext = (IpcContext*)arg;
977 if (ipcContext == NULL) {
978 return (void*)(intptr_t)LITEIPC_EINTNL;
979 }
980 g_ipcCallbackCb.threadWorking = true;
981 StartLoop(ipcContext, (IpcMsgHandler)TryCallBack, NULL);
982 return (void*)(intptr_t)LITEIPC_OK;
983 }
984
StartCallbackDispatch(const IpcContext * context)985 static int32_t StartCallbackDispatch(const IpcContext *context)
986 {
987 g_isStartLoop = true;
988 pthread_attr_t threadAttr;
989 pthread_attr_init(&threadAttr);
990 pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
991 pthread_t tid;
992 int32_t ret = pthread_create(&tid, &threadAttr, CallbackDispatch, (void *)context);
993 if (ret != 0) {
994 LOG(ERROR, "Create callback dispatch thread failed.");
995 g_isStartLoop = false;
996 return LITEIPC_EINTNL;
997 }
998 struct timespec spark, now;
999 clock_gettime(CLOCK_REALTIME, &spark);
1000 sched_yield();
1001 while (!g_ipcCallbackCb.threadWorking) {
1002 clock_gettime(CLOCK_REALTIME, &now);
1003 if (now.tv_sec - spark.tv_sec > 1) {
1004 LOG(ERROR, "Wait callback thread starting timeout.");
1005 return LITEIPC_EINTNL;
1006 }
1007 sched_yield();
1008 }
1009 return LITEIPC_OK;
1010 }
1011
RegisterIpcCallback(IpcMsgHandler func,uint32_t mode,uint32_t timeoutMs,SvcIdentity * sid,void * arg)1012 int32_t RegisterIpcCallback(IpcMsgHandler func, uint32_t mode, uint32_t timeoutMs, SvcIdentity* sid, void* arg)
1013 {
1014 if (g_init == 0) {
1015 InitCallbackCb();
1016 }
1017 if ((func == NULL) || (sid == NULL) || (mode > RESET_AFTER_USE) || (timeoutMs < IPC_TIMEOUT_MIN)) {
1018 return LITEIPC_EINVAL;
1019 }
1020
1021 if (pthread_mutex_lock(&g_ipcCallbackCb.mutex) != 0) {
1022 LOG(ERROR, "Get callback mutex failed.");
1023 return LITEIPC_EINTNL;
1024 }
1025
1026 int ret = LITEIPC_OK;
1027 AnonymousApi* node = (AnonymousApi*)malloc(sizeof(AnonymousApi));
1028 if (node == NULL) {
1029 LOG(ERROR, "Malloc failed.(size=%zu)", sizeof(AnonymousApi));
1030 ret = LITEIPC_EINTNL;
1031 goto ERROR;
1032 }
1033 (void)memset_s(node, sizeof(AnonymousApi), 0, sizeof(AnonymousApi));
1034
1035 node->token = (uint32_t)(uintptr_t)node;
1036 node->hdlerPair.usedFlag = true;
1037 node->hdlerPair.hdler = func;
1038 node->hdlerPair.arg = arg;
1039 UtilsListAdd(&g_ipcCallbackCb.apis, &node->list);
1040 sid->token = node->token;
1041 sid->handle = 0;
1042 sid->cookie = node->token;
1043 ERROR:
1044 pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
1045 return ret;
1046 }
1047
UnregisterIpcCallback(SvcIdentity sid)1048 int32_t UnregisterIpcCallback(SvcIdentity sid)
1049 {
1050 if (pthread_mutex_lock(&g_ipcCallbackCb.mutex) != 0) {
1051 LOG(ERROR, "Get callback mutex failed.");
1052 return LITEIPC_EINTNL;
1053 }
1054
1055 AnonymousApi* node = NULL;
1056 AnonymousApi* next = NULL;
1057 UTILS_DL_LIST_FOR_EACH_ENTRY_SAFE(node, next, &g_ipcCallbackCb.apis, AnonymousApi, list)
1058 {
1059 if (node->token == sid.token) {
1060 UtilsListDelete(&node->list);
1061 free(node);
1062 pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
1063 return LITEIPC_OK;
1064 }
1065 }
1066
1067 LOG(ERROR, "Input sid not exist.");
1068 pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
1069
1070 return LITEIPC_OK;
1071 }
1072
SetDeathHandlerPair(Testament * node,uint32_t index,IpcMsgHandler func,void * arg)1073 static inline uint32_t SetDeathHandlerPair(Testament* node, uint32_t index, IpcMsgHandler func, void* arg)
1074 {
1075 node->hdlerPairs[index].usedFlag = true;
1076 node->hdlerPairs[index].hdler = func;
1077 node->hdlerPairs[index].arg = arg;
1078 return index;
1079 }
1080
BinderLinkToDeath(const SvcIdentity * sid,IpcMsgHandler callback,const IpcContext * context)1081 static void BinderLinkToDeath(const SvcIdentity *sid, IpcMsgHandler callback, const IpcContext* context)
1082 {
1083 struct BinderDeath *bd;
1084 struct {
1085 uint32_t cmd;
1086 struct binder_handle_cookie payload;
1087 } __attribute__((packed)) data;
1088 bd = calloc(1, sizeof(struct BinderDeath));
1089 if (bd == NULL) {
1090 return;
1091 }
1092 bd->func = (void *)callback;
1093 bd->token = sid->handle;
1094 data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
1095 data.payload.handle = sid->handle;
1096 data.payload.cookie = (binder_uintptr_t)bd;
1097 BinderWrite(context, &data, sizeof(data));
1098 }
1099
RegisterDeathCallback(const IpcContext * context,SvcIdentity sid,IpcMsgHandler func,void * arg,uint32_t * cbId)1100 int32_t RegisterDeathCallback(const IpcContext* context, SvcIdentity sid, IpcMsgHandler func, void* arg, uint32_t* cbId)
1101 {
1102 int ret = LITEIPC_OK;
1103 Testament* node = NULL;
1104
1105 if ((func == NULL) || (cbId == NULL)) {
1106 return LITEIPC_EINVAL;
1107 }
1108
1109 const IpcContext *tmpContext = GetIpcContext(context, sid.ipcContext);
1110 if (tmpContext == NULL) {
1111 LOG(ERROR, "Invalid parameter, null pointer.");
1112 return LITEIPC_EINVAL;
1113 }
1114
1115 if (pthread_mutex_lock(&g_ipcCallbackCb.mutex) != 0) {
1116 LOG(ERROR, "Get callback mutex failed.");
1117 return LITEIPC_EINTNL;
1118 }
1119
1120 UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_ipcCallbackCb.testaments, Testament, list)
1121 {
1122 if (node->handle != sid.handle) {
1123 continue;
1124 }
1125
1126 if (node->size == MAX_DEATHCB_PER_SVC) {
1127 LOG(ERROR, "Reach max num on this svc:%d", sid.handle);
1128 ret = LITEIPC_EINTNL;
1129 goto UNLOCK_RETURN;
1130 }
1131 for (int i = 0; i < MAX_DEATHCB_PER_SVC; i++) {
1132 if (node->hdlerPairs[i].usedFlag == false) {
1133 node->size++;
1134 *cbId = SetDeathHandlerPair(node, i, func, arg);
1135 break;
1136 }
1137 }
1138 goto UNLOCK_RETURN;
1139 }
1140 node = (Testament*)malloc(sizeof(Testament));
1141 if (node == NULL) {
1142 LOG(ERROR, "Malloc failed.(size=%zu)", sizeof(Testament));
1143 ret = LITEIPC_ENOMEM;
1144 goto UNLOCK_RETURN;
1145 }
1146 (void)memset_s(node, sizeof(Testament), 0, sizeof(Testament));
1147 node->handle = sid.handle;
1148 node->size = 1;
1149 *cbId = SetDeathHandlerPair(node, 0, func, arg);
1150 UtilsListAdd(&g_ipcCallbackCb.testaments, &node->list);
1151 BinderLinkToDeath(&sid, (IpcMsgHandler)TryCallBack, tmpContext);
1152
1153 UNLOCK_RETURN:
1154 pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
1155 return ret;
1156 }
1157
UnregisterDeathCallback(SvcIdentity sid,uint32_t cbId)1158 int32_t UnregisterDeathCallback(SvcIdentity sid, uint32_t cbId)
1159 {
1160 Testament* node = NULL;
1161 Testament* next = NULL;
1162 if (cbId >= MAX_DEATHCB_PER_SVC) {
1163 LOG(ERROR, "Wrong cbId:%d.", cbId);
1164 return LITEIPC_EINVAL;
1165 }
1166 if (pthread_mutex_lock(&g_ipcCallbackCb.mutex) != 0) {
1167 LOG(ERROR, "Get callback mutex failed.");
1168 return LITEIPC_EINTNL;
1169 }
1170 UTILS_DL_LIST_FOR_EACH_ENTRY_SAFE(node, next, &g_ipcCallbackCb.testaments, Testament, list)
1171 {
1172 if (node->handle == sid.handle) {
1173 if ((node->isCallbackRuning == false) && (node->hdlerPairs[cbId].usedFlag == true)) {
1174 node->hdlerPairs[cbId].usedFlag = false;
1175 node->size--;
1176 if (node->size == 0) {
1177 UtilsListDelete(&node->list);
1178 free(node);
1179 }
1180 }
1181 pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
1182 return LITEIPC_OK;
1183 }
1184 }
1185 LOG(ERROR, "Input sid not exist.");
1186 pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
1187
1188 return LITEIPC_OK;
1189 }
1190
RemoveDeathCallback(uint32_t handle)1191 static void RemoveDeathCallback(uint32_t handle)
1192 {
1193 Testament* node = NULL;
1194 Testament* next = NULL;
1195
1196 if (pthread_mutex_lock(&g_ipcCallbackCb.mutex) != 0) {
1197 LOG(ERROR, "Get callback mutex failed.");
1198 return;
1199 }
1200 UTILS_DL_LIST_FOR_EACH_ENTRY_SAFE(node, next, &g_ipcCallbackCb.testaments, Testament, list)
1201 {
1202 if (node->handle == handle) {
1203 UtilsListDelete(&node->list);
1204 free(node);
1205 break;
1206 }
1207 }
1208 pthread_mutex_unlock(&g_ipcCallbackCb.mutex);
1209 }
1210
GetToken(const void * ipcMsg,uint32_t * token)1211 int32_t GetToken(const void* ipcMsg, uint32_t* token)
1212 {
1213 if ((ipcMsg == NULL) || (token == NULL)) {
1214 LOG(ERROR, "Invalid parameter, null pointer.");
1215 return LITEIPC_EINVAL;
1216 }
1217
1218 const IpcMsg* in = (const IpcMsg*)ipcMsg;
1219 *token = in->target.token;
1220 return LITEIPC_OK;
1221 }
1222
GetFlag(const void * ipcMsg,uint32_t * flag)1223 int32_t GetFlag(const void* ipcMsg, uint32_t* flag)
1224 {
1225 if ((ipcMsg == NULL) || (flag == NULL)) {
1226 LOG(ERROR, "Invalid parameter, null pointer.");
1227 return LITEIPC_EINVAL;
1228 }
1229
1230 const IpcMsg* in = (const IpcMsg*)ipcMsg;
1231 *flag = in->flag;
1232 return LITEIPC_OK;
1233 }
1234
GetCallingPid(const void * ipcMsg)1235 pid_t GetCallingPid(const void* ipcMsg)
1236 {
1237 if (ipcMsg == NULL) {
1238 LOG(ERROR, "Invalid parameter, null pointer.");
1239 return LITEIPC_EINVAL;
1240 }
1241
1242 const IpcMsg* in = (const IpcMsg*)ipcMsg;
1243 return (pid_t)in->processID;
1244 }
1245
GetCallingUid(const void * ipcMsg)1246 pid_t GetCallingUid(const void* ipcMsg)
1247 {
1248 if (ipcMsg == NULL) {
1249 LOG(ERROR, "Invalid parameter, null pointer.");
1250 return LITEIPC_EINVAL;
1251 }
1252
1253 const IpcMsg* in = (const IpcMsg*)ipcMsg;
1254 return (pid_t)in->userID;
1255 }
1256
GetCallingGid(const void * ipcMsg)1257 pid_t GetCallingGid(const void* ipcMsg)
1258 {
1259 if (ipcMsg == NULL) {
1260 LOG(ERROR, "Invalid parameter, null pointer.");
1261 return LITEIPC_EINVAL;
1262 }
1263
1264 const IpcMsg* in = (const IpcMsg*)ipcMsg;
1265 return (pid_t)in->gid;
1266 }
1267
FreeBuffer(const IpcContext * context,void * ptr)1268 int32_t FreeBuffer(const IpcContext* context, void* ptr)
1269 {
1270 if (ptr == NULL) {
1271 return LITEIPC_OK;
1272 }
1273
1274 IpcMsg* ipcMsg = (IpcMsg*)ptr;
1275 if (ipcMsg->freeData == NULL) {
1276 return LITEIPC_OK;
1277 }
1278
1279 const IpcContext *tmpContext = GetIpcContext(context, g_tlsContext);
1280 if (tmpContext == NULL) {
1281 LOG(ERROR, "Invalid parameter, null pointer.");
1282 free(ptr);
1283 ptr = NULL;
1284 return LITEIPC_EINTNL;
1285 }
1286 struct FreeData data = {0};
1287 data.cmd = BC_FREE_BUFFER;
1288 data.buffer = (binder_uintptr_t)ipcMsg->freeData;
1289 int ret = BinderWrite(tmpContext, &data, sizeof(data));
1290 free(ptr);
1291 ptr = NULL;
1292 RETURN_IF_IPC_IOCTL_FAILED(LITEIPC_EBADF);
1293 return ret;
1294 }
1295
GenServiceHandle(SvcIdentity * sid,pid_t tid)1296 int32_t GenServiceHandle(SvcIdentity* sid, pid_t tid)
1297 {
1298 if (g_tempHandles == NULL || sid == NULL) {
1299 return LITEIPC_EINVAL;
1300 }
1301 sid->handle = g_handle;
1302 return LITEIPC_OK;
1303 }
1304
BinderAcquire(const IpcContext * context,uint32_t handle)1305 int32_t BinderAcquire(const IpcContext* context, uint32_t handle)
1306 {
1307 if (context == NULL) {
1308 return LITEIPC_EINVAL;
1309 }
1310 uint32_t cmd[2];
1311 cmd[0] = BC_ACQUIRE;
1312 cmd[1] = handle;
1313 int ret;
1314 ret = BinderWrite(context, &cmd, sizeof(cmd));
1315 return ret;
1316 }
1317
BinderRelease(const IpcContext * context,uint32_t handle)1318 int32_t BinderRelease(const IpcContext* context, uint32_t handle)
1319 {
1320 if (context == NULL) {
1321 return LITEIPC_EINVAL;
1322 }
1323 uint32_t cmd[2];
1324 cmd[0] = BC_RELEASE;
1325 cmd[1] = handle;
1326 int ret;
1327 ret = BinderWrite(context, &cmd, sizeof(cmd));
1328 return ret;
1329 }
1330