Compare commits
398 Commits
1.0.19
...
ubports/fo
| Author | SHA1 | Date | |
|---|---|---|---|
| 2778ec3a88 | |||
| 6697470380 | |||
|
|
a9dfd6e453 | ||
|
|
2439ff878d | ||
|
|
8c65520173 | ||
|
|
e3764d7002 | ||
|
|
624bfa843d | ||
|
|
6d71a0649c | ||
|
|
c31cd7e964 | ||
|
|
c1db86e734 | ||
|
|
bfb95f2bf5 | ||
|
|
6f4c69d58a | ||
|
|
c6b09a10d4 | ||
|
|
545f5bc28d | ||
|
|
78e006f1cf | ||
|
|
3c9cc1711a | ||
|
|
71aa3acc08 | ||
|
|
eee26c5e98 | ||
|
|
736a29aa4c | ||
|
|
0d7105edbe | ||
|
|
4420c7b2ae | ||
|
|
52726a07b0 | ||
|
|
12b9fd49ad | ||
|
|
e75959e389 | ||
|
|
9d35ca22fb | ||
|
|
3e0d0005ce | ||
|
|
29718f921f | ||
|
|
99b2dd85c1 | ||
|
|
cf5417d5db | ||
|
|
03f214eb24 | ||
|
|
6508a73dcd | ||
|
|
1100d8ede1 | ||
|
|
f89469b1a5 | ||
|
|
fcf2ef0ea4 | ||
|
|
f9202cab37 | ||
|
|
49729d95c9 | ||
|
|
11765cd80d | ||
|
|
4820b2971f | ||
|
|
0623fb85db | ||
|
|
e655d8992a | ||
|
|
44e57ea98d | ||
|
|
e3f705c4cc | ||
|
|
6f0e8a693d | ||
|
|
c7fab6373b | ||
|
|
9aded94555 | ||
|
|
b5bab2431e | ||
|
|
509faccba0 | ||
|
|
a89dcd2702 | ||
|
|
62b9b30865 | ||
|
|
4a913590d9 | ||
|
|
1ee872aaf2 | ||
|
|
00e9d8ac6f | ||
|
|
b032e151a2 | ||
|
|
b8edc9221a | ||
|
|
05634757d7 | ||
|
|
03ef78c9fd | ||
|
|
84efc32ac0 | ||
|
|
88388de696 | ||
|
|
daa062d981 | ||
|
|
85db18f663 | ||
|
|
af796828a4 | ||
|
|
885d27c12c | ||
|
|
38f156a8ba | ||
|
|
d7eacd455f | ||
|
|
b1a3dc5c64 | ||
|
|
98ad09e803 | ||
|
|
c94ccbd8bf | ||
|
|
5874c88559 | ||
|
|
b0c3b6017f | ||
|
|
4f82e82081 | ||
|
|
51eefbf566 | ||
|
|
ec76cb3930 | ||
|
|
9a0d0a7894 | ||
|
|
32b3d4455a | ||
|
|
09e9a9d5c1 | ||
|
|
83b04757c6 | ||
|
|
c636814500 | ||
|
|
2592ea60ce | ||
|
|
f04e21b462 | ||
|
|
d739912faa | ||
|
|
c2263874ec | ||
|
|
aa23e44677 | ||
|
|
ca38c15d3c | ||
|
|
6f9220aedb | ||
|
|
eafec68ff8 | ||
|
|
0dc84b0748 | ||
|
|
f227ae4291 | ||
|
|
b14b68717f | ||
|
|
8bf0d63960 | ||
|
|
c22eafe49e | ||
|
|
66122a2ce6 | ||
|
|
c1ff25f6ae | ||
|
|
af3c23a18f | ||
|
|
5a14796c4c | ||
|
|
3bb8a38f5f | ||
|
|
f29f0b5a1b | ||
|
|
2da1c7b5ca | ||
|
|
8348bc76bd | ||
|
|
a97a153c94 | ||
|
|
94ddc9f0e5 | ||
|
|
370d2dedb3 | ||
|
|
58c9a7fe93 | ||
|
|
3742e2ca8e | ||
|
|
ede15da9e2 | ||
|
|
771444a8ac | ||
|
|
956fa90cbf | ||
|
|
17ff87510c | ||
|
|
552fc4f172 | ||
|
|
4b179477ad | ||
|
|
8419a53f23 | ||
|
|
865a29d1dd | ||
|
|
93fbb5b238 | ||
|
|
1a9408f65c | ||
|
|
14399b112f | ||
|
|
754fa5bcda | ||
|
|
0b43f88700 | ||
|
|
5822a40c39 | ||
|
|
ca5f3ad0be | ||
|
|
3398afd701 | ||
|
|
3c828b453a | ||
|
|
9d95a622f4 | ||
|
|
78dd0563e6 | ||
|
|
5fd5b423c1 | ||
|
|
2acec3f7ce | ||
|
|
59dee397f0 | ||
|
|
e196c66264 | ||
|
|
8f62f4d65c | ||
|
|
8583a72d11 | ||
|
|
381446eb4f | ||
|
|
eabf5683f4 | ||
|
|
f4712be3b5 | ||
|
|
08f701c96b | ||
|
|
8c5618aaab | ||
|
|
1bc2efd724 | ||
|
|
066464f3af | ||
|
|
f5b399d775 | ||
|
|
6e127bd184 | ||
|
|
95277d1b3d | ||
|
|
e0c56c1226 | ||
|
|
5e3df46da9 | ||
|
|
393006f051 | ||
|
|
e10e3df1eb | ||
|
|
86ba34dc67 | ||
|
|
b0b5595f20 | ||
|
|
757908cd6c | ||
|
|
e6ca4b50ec | ||
|
|
97831a65da | ||
|
|
5798434ead | ||
|
|
54b1149a75 | ||
|
|
e9f873b3a4 | ||
|
|
8b621fe7d3 | ||
|
|
e5542027c2 | ||
|
|
8539f6e944 | ||
|
|
fa53d0cf70 | ||
|
|
d6c3ddb4e3 | ||
|
|
fd081601a3 | ||
|
|
7b319ba822 | ||
|
|
d439bd467a | ||
|
|
c99df04daf | ||
|
|
81b6b7f087 | ||
|
|
91bc5253e4 | ||
|
|
ddf67e83eb | ||
|
|
fc257ec23c | ||
|
|
8148f03ae6 | ||
|
|
a1616163e7 | ||
|
|
7f12f1a476 | ||
|
|
f3cf738265 | ||
|
|
f8916148a9 | ||
|
|
fe2d441e25 | ||
|
|
85c7d8f311 | ||
|
|
597fb84367 | ||
|
|
30242d7124 | ||
|
|
14327ed5f1 | ||
|
|
36e1fed889 | ||
|
|
cecdea76bc | ||
|
|
7f72021075 | ||
|
|
846037073b | ||
|
|
f0b55886b2 | ||
|
|
165d386436 | ||
|
|
a07e0f2a99 | ||
|
|
bc172346e0 | ||
|
|
5801ed4f15 | ||
|
|
e8c5a0c0bb | ||
|
|
94b74ee948 | ||
|
|
1bfacab88d | ||
|
|
704e7d011c | ||
|
|
3a4ae9a716 | ||
|
|
5ddc9d94d6 | ||
|
|
159708d829 | ||
|
|
5753cdab1a | ||
|
|
d4ea1261eb | ||
|
|
7e3ac0a761 | ||
|
|
76494c3e3d | ||
|
|
dfbc8acd9e | ||
|
|
158d33db5a | ||
|
|
4b11769895 | ||
|
|
4da96dd0b5 | ||
|
|
d9bfb9e200 | ||
|
|
f088e6d1bb | ||
|
|
ca665ad3d1 | ||
|
|
6ed9082e69 | ||
|
|
5332dd3482 | ||
|
|
a15f63621e | ||
|
|
e4b5f081bd | ||
|
|
5fab0bcdaa | ||
|
|
5c1b23f30e | ||
|
|
8f720e11de | ||
|
|
3c2cd5d599 | ||
|
|
8df1e70c0b | ||
|
|
3833a36693 | ||
|
|
38fd1e6dcb | ||
|
|
5fa4cd03de | ||
|
|
d6c0cdd231 | ||
|
|
c38843d9c9 | ||
|
|
a6a5df963f | ||
|
|
b60960d955 | ||
|
|
0adb80a9ed | ||
|
|
f591433118 | ||
|
|
5a897a34c2 | ||
|
|
138423de4a | ||
|
|
1d9f9c4487 | ||
|
|
82f71a6c91 | ||
|
|
0c85299efc | ||
|
|
50195aae1d | ||
|
|
586425bc2d | ||
|
|
b0bde6b652 | ||
|
|
be2369c64c | ||
|
|
c2cf68cab6 | ||
|
|
f7d1863615 | ||
|
|
0bb0aee6cb | ||
|
|
b392e019f3 | ||
|
|
8eb5fa7394 | ||
|
|
c5c04db81a | ||
|
|
4056cfaa15 | ||
|
|
ba8b226d89 | ||
|
|
88df2edb95 | ||
|
|
b856cf2141 | ||
|
|
f4a2429a13 | ||
|
|
7d1f8ad4e7 | ||
|
|
82656db49d | ||
|
|
d6dac912dd | ||
|
|
207f9398b4 | ||
|
|
7b51a82de8 | ||
|
|
66f08bf0db | ||
|
|
90384e921f | ||
|
|
1ae7c2697c | ||
|
|
536143c1d7 | ||
|
|
6025950aab | ||
|
|
4d69940b96 | ||
|
|
b1f49cae13 | ||
|
|
80e9be5343 | ||
|
|
d6d6b76fa5 | ||
|
|
d18a352a82 | ||
|
|
5fbaabb47e | ||
|
|
83cc13b817 | ||
|
|
1679cda4c5 | ||
|
|
e5f11aafc1 | ||
|
|
f262c77b17 | ||
|
|
3ef00effc5 | ||
|
|
1ce13bea91 | ||
|
|
eaab366dcb | ||
|
|
784f06c415 | ||
|
|
4b07e80a8f | ||
|
|
9f7fac407d | ||
|
|
47b6668876 | ||
|
|
951977961b | ||
|
|
f069c3a595 | ||
|
|
b84194e8c7 | ||
|
|
e06e989aa5 | ||
|
|
ab75505437 | ||
|
|
e97663b58e | ||
|
|
a92f57a30c | ||
|
|
ebb9381e46 | ||
|
|
5fb441fb81 | ||
|
|
f3a00fe8a2 | ||
|
|
573494570c | ||
|
|
92392f5c9a | ||
|
|
8a634a0d95 | ||
|
|
23c5d48b5d | ||
|
|
f000b344dd | ||
|
|
42177e1ff2 | ||
|
|
091ca483e7 | ||
|
|
42ce4f8821 | ||
|
|
9a1781765b | ||
|
|
544b8181e5 | ||
|
|
82ea37ead9 | ||
|
|
882ef93084 | ||
|
|
881469ab7f | ||
|
|
d7834650ae | ||
|
|
20bf183a10 | ||
|
|
c990ac66da | ||
|
|
0964163a35 | ||
|
|
fc980b1bc9 | ||
|
|
e76c8a3ba7 | ||
|
|
5805290369 | ||
|
|
7dd9623929 | ||
|
|
95ac07e4de | ||
|
|
92cd463b34 | ||
|
|
6832546dca | ||
|
|
049042b134 | ||
|
|
6d2f2efe31 | ||
|
|
bcce4831e3 | ||
|
|
7fb3053135 | ||
|
|
00359a0fc8 | ||
|
|
ccf3e1237c | ||
|
|
e02f00fd41 | ||
|
|
e45e640f3c | ||
|
|
75e8015c43 | ||
|
|
2c52fcc156 | ||
|
|
dc5b51a41f | ||
|
|
d12cee4690 | ||
|
|
a74c4ac148 | ||
|
|
53e50a8107 | ||
|
|
e896ba94cc | ||
|
|
87ff990c73 | ||
|
|
e406162be2 | ||
|
|
2de4120f25 | ||
|
|
d8dc58a133 | ||
|
|
8684bffe97 | ||
|
|
a08513ade0 | ||
|
|
1a57e01e07 | ||
|
|
6d4faf19b8 | ||
|
|
96e6845e16 | ||
|
|
b33adeb708 | ||
|
|
ea0e294a74 | ||
|
|
2d878c2391 | ||
|
|
6dec867cd3 | ||
|
|
d8bd7b9366 | ||
|
|
b52e4c6dee | ||
|
|
21046af42f | ||
|
|
3cbe1d6ac8 | ||
|
|
b4b1a99a27 | ||
|
|
f5a2d481e3 | ||
|
|
da57a15852 | ||
|
|
9d0ac624c5 | ||
|
|
b8ccc80b87 | ||
|
|
27e2dac22e | ||
|
|
a4ec4e382d | ||
|
|
30df5faf64 | ||
|
|
0aa29d8a91 | ||
|
|
3ace986e4a | ||
|
|
064ab48eee | ||
|
|
12c1725ab1 | ||
|
|
ba2ddf4163 | ||
|
|
3d16384acd | ||
|
|
0f73626025 | ||
|
|
84fb44e519 | ||
|
|
aafe23396a | ||
|
|
51f270df67 | ||
|
|
e9c404de92 | ||
|
|
141bda151b | ||
|
|
e952380ce6 | ||
|
|
721f5dc469 | ||
|
|
434b17eefe | ||
|
|
af6a1c84ef | ||
|
|
a0ce447a1f | ||
|
|
f24145f407 | ||
|
|
11c173b2e4 | ||
|
|
aff816d10c | ||
|
|
e1acaa3bdb | ||
|
|
c63743ac51 | ||
|
|
6832d9bf46 | ||
|
|
4c3ccbc06f | ||
|
|
f82596c372 | ||
|
|
4921a6ab8d | ||
|
|
ef9c242a59 | ||
|
|
a83c9937a5 | ||
|
|
cfa3ad4d9e | ||
|
|
ffc9638ebb | ||
|
|
000534654d | ||
|
|
68e9358d02 | ||
|
|
37e3859f8f | ||
|
|
e79b940b0d | ||
|
|
d8dfe3f289 | ||
|
|
394c286ee5 | ||
|
|
307bd6942c | ||
|
|
148b53e862 | ||
|
|
5c8cb0a013 | ||
|
|
4d644e0584 | ||
|
|
dce9c8b3d1 | ||
|
|
b117ee6404 | ||
|
|
c3f783bf7e | ||
|
|
4c65a6eded | ||
|
|
c382cab922 | ||
|
|
199fd4ed61 | ||
|
|
f86d62fbf8 | ||
|
|
3ea82dc384 | ||
|
|
03ae5834ee | ||
|
|
e39b5c20ee | ||
|
|
d6e131eb6e | ||
|
|
1c36b5f142 | ||
|
|
827bd0b59f | ||
|
|
2dab057652 | ||
|
|
488fbc5b63 | ||
|
|
17f511d7a3 | ||
|
|
63e633c0ec | ||
|
|
f46448c236 | ||
|
|
43023be32d |
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,13 +1,13 @@
|
||||
*~
|
||||
debian/files
|
||||
debian/libgbinder-dev.debhelper.log
|
||||
debian/libgbinder-dev.substvars
|
||||
debian/libgbinder-dev
|
||||
debian/libgbinder.debhelper.log
|
||||
debian/libgbinder.postinst.debhelper
|
||||
debian/libgbinder.postrm.debhelper
|
||||
debian/libgbinder.substvars
|
||||
debian/libgbinder
|
||||
debian/libgbinder-dev
|
||||
debian/libgbinder-tools
|
||||
debian/*.debhelper.log
|
||||
debian/*.debhelper
|
||||
debian/*.substvars
|
||||
debian/libgbinder.install
|
||||
debian/libgbinder-dev.install
|
||||
debian/tmp
|
||||
documentation.list
|
||||
installroot
|
||||
|
||||
11
AUTHORS
11
AUTHORS
@@ -1,4 +1,13 @@
|
||||
Slava Monich <slava.monich@jolla.com>
|
||||
Slava Monich <slava@monich.com>
|
||||
Matti Lehtimäki <matti.lehtimaki@gmail.com>
|
||||
Franz-Josef Haider <franz.haider@jolla.com>
|
||||
Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
Andrew Branson <andrew.branson@jolla.com>
|
||||
Rinigus <rinigus.git@gmail.com>
|
||||
George Hopkins <george-hopkins@null.net>
|
||||
Bart Ribbers <bribbers@disroot.org>
|
||||
Gary Wang <gary.wang@canonical.com>
|
||||
Eugenio Paolantonio <me@medesimo.eu>
|
||||
Alessandro Astone <ales.astone@gmail.com>
|
||||
Martin Kampas <martin.kampas@seafarix.com>
|
||||
Nikita Ukhrenkov <nikita.ukhrenkov@seafarix.com>
|
||||
|
||||
12
LICENSE
12
LICENSE
@@ -1,7 +1,5 @@
|
||||
Copyright (C) 2018 Jolla Ltd.
|
||||
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
|
||||
You may use this file under the terms of BSD license as follows:
|
||||
Copyright (C) 2018-2024 Jolla Ltd.
|
||||
Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@@ -12,9 +10,9 @@ are met:
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
3. Neither the names of the copyright holders nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
156
Makefile
156
Makefile
@@ -1,16 +1,25 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
#
|
||||
# LIBGLIBUTIL_PATH can be defined to point to libglibutil root directory
|
||||
# for side-by-side build.
|
||||
#
|
||||
|
||||
.PHONY: clean all debug release test
|
||||
.PHONY: print_debug_so print_release_so
|
||||
.PHONY: print_debug_lib print_release_lib
|
||||
.PHONY: print_debug_lib print_release_lib print_coverage_lib
|
||||
.PHONY: print_debug_link print_release_link
|
||||
.PHONY: print_debug_path print_release_path
|
||||
|
||||
#
|
||||
# Required packages
|
||||
# Library version
|
||||
#
|
||||
|
||||
PKGS = libglibutil glib-2.0 gobject-2.0
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 1
|
||||
VERSION_RELEASE = 40
|
||||
|
||||
# Version for pkg-config
|
||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
|
||||
#
|
||||
# Default target
|
||||
@@ -19,15 +28,34 @@ PKGS = libglibutil glib-2.0 gobject-2.0
|
||||
all: debug release pkgconfig
|
||||
|
||||
#
|
||||
# Library version
|
||||
# Required packages
|
||||
#
|
||||
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 0
|
||||
VERSION_RELEASE = 19
|
||||
PKGS = glib-2.0 gobject-2.0
|
||||
|
||||
# Version for pkg-config
|
||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
ifeq ($(LIBGLIBUTIL_PATH),)
|
||||
|
||||
# Assume that libglibutil devel package is installed
|
||||
PKGS += libglibutil
|
||||
|
||||
else
|
||||
|
||||
# Side-by-side build
|
||||
INCLUDES += -I$(LIBGLIBUTIL_PATH)/include
|
||||
DEBUG_LIBS = -L$(LIBGLIBUTIL_PATH)/build/debug -lglibutil
|
||||
RELEASE_LIBS = -L$(LIBGLIBUTIL_PATH)/build/release -lglibutil
|
||||
DEBUG_DEPS = libglibutil_debug
|
||||
RELEASE_DEPS = libglibutil_release
|
||||
|
||||
.PHONY: libglibutil_debug libglibutil_release
|
||||
|
||||
libglibutil_debug:
|
||||
$(MAKE) -C $(LIBGLIBUTIL_PATH) debug
|
||||
|
||||
libglibutil_release:
|
||||
$(MAKE) -C $(LIBGLIBUTIL_PATH) release
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# Library name
|
||||
@@ -47,28 +75,38 @@ LIB = $(LIB_NAME).a
|
||||
#
|
||||
|
||||
SRC = \
|
||||
gbinder_bridge.c \
|
||||
gbinder_buffer.c \
|
||||
gbinder_cleanup.c \
|
||||
gbinder_client.c \
|
||||
gbinder_config.c \
|
||||
gbinder_driver.c \
|
||||
gbinder_eventloop.c \
|
||||
gbinder_fmq.c \
|
||||
gbinder_io_32.c \
|
||||
gbinder_io_64.c \
|
||||
gbinder_ipc.c \
|
||||
gbinder_local_object.c \
|
||||
gbinder_local_reply.c \
|
||||
gbinder_local_request.c \
|
||||
gbinder_log.c \
|
||||
gbinder_proxy_object.c \
|
||||
gbinder_reader.c \
|
||||
gbinder_remote_object.c \
|
||||
gbinder_remote_reply.c \
|
||||
gbinder_remote_request.c \
|
||||
gbinder_rpc_protocol.c \
|
||||
gbinder_servicename.c \
|
||||
gbinder_servicepoll.c \
|
||||
gbinder_writer.c
|
||||
|
||||
SRC += \
|
||||
gbinder_defaultservicemanager.c \
|
||||
gbinder_hwservicemanager.c \
|
||||
gbinder_servicemanager.c
|
||||
gbinder_servicemanager.c \
|
||||
gbinder_servicemanager_aidl.c \
|
||||
gbinder_servicemanager_aidl2.c \
|
||||
gbinder_servicemanager_aidl3.c \
|
||||
gbinder_servicemanager_aidl4.c \
|
||||
gbinder_servicemanager_hidl.c
|
||||
|
||||
SRC += \
|
||||
gbinder_system.c
|
||||
@@ -88,29 +126,30 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
PKG_CONFIG ?= pkg-config
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
STRIP ?= strip
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
|
||||
INCLUDES = -I$(INCLUDE_DIR)
|
||||
DEFINES += -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \
|
||||
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED
|
||||
INCLUDES += -I$(INCLUDE_DIR)
|
||||
BASE_FLAGS = -fPIC
|
||||
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
|
||||
-MMD -MP $(shell pkg-config --cflags $(PKGS))
|
||||
-MMD -MP $(shell $(PKG_CONFIG) --cflags $(PKGS))
|
||||
FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \
|
||||
$(shell pkg-config --libs $(PKGS)) -lpthread
|
||||
$(shell $(PKG_CONFIG) --libs $(PKGS)) -lpthread
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
COVERAGE_FLAGS = -g
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
KEEP_SYMBOLS ?= 0
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_LIBS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_LIBS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
|
||||
@@ -124,6 +163,16 @@ DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
COVERAGE_OBJS = $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o)
|
||||
|
||||
DEBUG_SO = $(DEBUG_BUILD_DIR)/$(LIB_SO)
|
||||
RELEASE_SO = $(RELEASE_BUILD_DIR)/$(LIB_SO)
|
||||
DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1)
|
||||
RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1)
|
||||
DEBUG_DEV_LINK = $(DEBUG_BUILD_DIR)/$(LIB_DEV_SYMLINK)
|
||||
RELEASE_DEV_LINK = $(RELEASE_BUILD_DIR)/$(LIB_DEV_SYMLINK)
|
||||
DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
|
||||
RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
|
||||
COVERAGE_LIB = $(COVERAGE_BUILD_DIR)/$(LIB)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
@@ -136,25 +185,22 @@ endif
|
||||
endif
|
||||
|
||||
$(PKGCONFIG): | $(BUILD_DIR)
|
||||
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR)
|
||||
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR) $(DEBUG_DEPS)
|
||||
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR) $(RELEASE_DEPS)
|
||||
$(COVERAGE_OBJS) $(COVERAGE_LIB): | $(COVERAGE_BUILD_DIR)
|
||||
|
||||
$(DEBUG_LINK): | $(DEBUG_LIB)
|
||||
$(RELEASE_LINK): | $(RELEASE_LIB)
|
||||
$(DEBUG_DEV_LINK): | $(DEBUG_LINK)
|
||||
$(RELEASE_DEV_LINK): | $(RELEASE_LINK)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_SO = $(DEBUG_BUILD_DIR)/$(LIB_SO)
|
||||
RELEASE_SO = $(RELEASE_BUILD_DIR)/$(LIB_SO)
|
||||
DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1)
|
||||
RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1)
|
||||
DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
|
||||
RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
|
||||
COVERAGE_LIB = $(COVERAGE_BUILD_DIR)/$(LIB)
|
||||
debug: $(DEBUG_SO) $(DEBUG_LINK) $(DEBUG_DEV_LINK)
|
||||
|
||||
debug: $(DEBUG_SO)
|
||||
|
||||
release: $(RELEASE_SO)
|
||||
release: $(RELEASE_SO) $(RELEASE_LINK) $(RELEASE_DEV_LINK)
|
||||
|
||||
debug_lib: $(DEBUG_LIB)
|
||||
|
||||
@@ -192,17 +238,18 @@ print_release_path:
|
||||
@echo $(RELEASE_BUILD_DIR)
|
||||
|
||||
clean:
|
||||
make -C test clean
|
||||
make -C unit clean
|
||||
$(MAKE) -C test clean
|
||||
$(MAKE) -C unit clean
|
||||
rm -fr test/coverage/results test/coverage/*.gcov
|
||||
rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
|
||||
rm -fr $(BUILD_DIR) RPMS installroot
|
||||
rm -fr debian/tmp debian/libgbinder debian/libgbinder-dev
|
||||
rm -f documentation.list debian/files debian/*.substvars
|
||||
rm -f debian/*.debhelper.log debian/*.debhelper debian/*~
|
||||
rm -f debian/libgbinder.install debian/libgbinder-dev.install
|
||||
|
||||
test:
|
||||
make -C unit test
|
||||
$(MAKE) -C unit test
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
@@ -227,13 +274,11 @@ $(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
|
||||
$(DEBUG_SO): $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@
|
||||
ln -sf $(LIB_SO) $(DEBUG_LINK)
|
||||
|
||||
$(RELEASE_SO): $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@
|
||||
ln -sf $(LIB_SO) $(RELEASE_LINK)
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
$(DEBUG_LIB): $(DEBUG_OBJS)
|
||||
@@ -244,12 +289,35 @@ $(RELEASE_LIB): $(RELEASE_OBJS)
|
||||
$(AR) rc $@ $?
|
||||
ranlib $@
|
||||
|
||||
$(DEBUG_LINK):
|
||||
ln -sf $(LIB_SO) $@
|
||||
|
||||
$(RELEASE_LINK):
|
||||
ln -sf $(LIB_SO) $@
|
||||
|
||||
$(DEBUG_DEV_LINK):
|
||||
ln -sf $(LIB_SYMLINK1) $@
|
||||
|
||||
$(RELEASE_DEV_LINK):
|
||||
ln -sf $(LIB_SYMLINK1) $@
|
||||
|
||||
$(COVERAGE_LIB): $(COVERAGE_OBJS)
|
||||
$(AR) rc $@ $?
|
||||
ranlib $@
|
||||
|
||||
#
|
||||
# LIBDIR usually gets substituted with arch specific dir.
|
||||
# It's relative in deb build and can be whatever in rpm build.
|
||||
#
|
||||
|
||||
LIBDIR ?= usr/lib
|
||||
ABS_LIBDIR := $(shell echo /$(LIBDIR) | sed -r 's|/+|/|g')
|
||||
|
||||
$(PKGCONFIG): $(LIB_NAME).pc.in Makefile
|
||||
sed -e 's/\[version\]/'$(PCVERSION)/g $< > $@
|
||||
sed -e 's|@version@|$(PCVERSION)|g' -e 's|@libdir@|$(ABS_LIBDIR)|g' $< > $@
|
||||
|
||||
debian/%.install: debian/%.install.in
|
||||
sed 's|@LIBDIR@|$(LIBDIR)|g' $< > $@
|
||||
|
||||
#
|
||||
# Install
|
||||
@@ -261,12 +329,12 @@ INSTALL = install
|
||||
INSTALL_DIRS = $(INSTALL) -d
|
||||
INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM)
|
||||
|
||||
INSTALL_LIB_DIR = $(DESTDIR)/usr/lib
|
||||
INSTALL_LIB_DIR = $(DESTDIR)$(ABS_LIBDIR)
|
||||
INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/$(NAME)
|
||||
INSTALL_PKGCONFIG_DIR = $(DESTDIR)/usr/lib/pkgconfig
|
||||
INSTALL_PKGCONFIG_DIR = $(DESTDIR)$(ABS_LIBDIR)/pkgconfig
|
||||
|
||||
install: $(INSTALL_LIB_DIR)
|
||||
$(INSTALL_FILES) $(RELEASE_SO) $(INSTALL_LIB_DIR)
|
||||
$(INSTALL) -m 755 $(RELEASE_SO) $(INSTALL_LIB_DIR)
|
||||
ln -sf $(LIB_SO) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2)
|
||||
ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1)
|
||||
|
||||
|
||||
41
README
41
README
@@ -1,7 +1,46 @@
|
||||
GLib-style interface to binder (Android IPC mechanism)
|
||||
|
||||
Provides:
|
||||
Key features:
|
||||
|
||||
1. Integration with GLib event loop
|
||||
2. Detection of 32 vs 64 bit kernel at runtime
|
||||
3. Asynchronous transactions that don't block the event thread
|
||||
4. Stable service manager and low-level transaction APIs
|
||||
|
||||
Android keeps changing both low-level RPC and service manager
|
||||
protocols from version to version. To counter that, libgbinder
|
||||
implements configirable backends for different variants of those,
|
||||
and yet keeping its own API unchanged.
|
||||
|
||||
Configuration is loaded from [Protocol] and [ServiceManager] sections
|
||||
of /etc/gbinder.conf file. The keys are binder device names or the
|
||||
special Default value, the value is the identifier of the protocol
|
||||
or service manager variant, respectively.
|
||||
|
||||
In addition to reading /etc/gbinder.conf if it exists, /etc/gbinder.d
|
||||
directory is scanned for .conf files, the file list is sorted, files are
|
||||
loaded one by one, overwriting the entries loaded from /etc/gbinder.conf
|
||||
or from the previously processed file.
|
||||
|
||||
Known protocol and service manager variants are aidl, aidl2, aidl3 and
|
||||
hidl. This list is expected to expand further in the future. The default
|
||||
configuration is as follows:
|
||||
|
||||
[Protocol]
|
||||
Default = aidl
|
||||
/dev/binder = aidl
|
||||
/dev/hwbinder = hidl
|
||||
|
||||
[ServiceManager]
|
||||
Default = aidl
|
||||
/dev/binder = aidl
|
||||
/dev/hwbinder = hidl
|
||||
|
||||
Alternatively and preferably, one can specify the desired Android API
|
||||
level:
|
||||
|
||||
[General]
|
||||
ApiLevel = 29
|
||||
|
||||
and let libgbinder pick the appropriate preset. Full list of presets can
|
||||
be found in src/gbinder_config.c
|
||||
|
||||
10
debian/Jenkinsfile
vendored
Normal file
10
debian/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
@Library('ubports-build-tools') _
|
||||
|
||||
buildAndProvideDebianPackage()
|
||||
|
||||
// Or if the package consists entirely of arch-independent packages:
|
||||
// (optional optimization, will confuse BlueOcean's live view at build stage)
|
||||
// buildAndProvideDebianPackage(/* isArchIndependent */ true)
|
||||
|
||||
// Optionally, to skip building on some architectures (amd64 is always built):
|
||||
// buildAndProvideDebianPackage(false, /* ignoredArchs */ ['arm64'])
|
||||
450
debian/changelog
vendored
450
debian/changelog
vendored
@@ -1,3 +1,453 @@
|
||||
libgbinder (1.1.40-0ubports1) UNRELEASED; urgency=medium
|
||||
|
||||
* Upstream release v1.1.40
|
||||
|
||||
-- TheKit <thekit@disroot.org> Thu, 15 Aug 2024 15:56:51 +0300
|
||||
|
||||
libgbinder (1.1.35-0ubports1) UNRELEASED; urgency=unknown
|
||||
|
||||
* New upstream release v1.1.35
|
||||
|
||||
-- UBports package upgrader bot <dev@ubports.com> Thu, 23 Nov 2023 23:02:23 +0000
|
||||
|
||||
libgbinder (1.1.34-0ubports1) focal; urgency=medium
|
||||
|
||||
* New upstream release v1.1.34
|
||||
|
||||
-- Marius Gripsgard <mariogrip@debian.org> Thu, 31 Aug 2023 12:09:35 +0200
|
||||
|
||||
libgbinder (1.1.30-0ubports1) focal; urgency=medium
|
||||
|
||||
* Upstream release v1.1.30
|
||||
|
||||
-- Jami Kettunen <jami.kettunen@protonmail.com> Wed, 07 Dec 2022 00:58:38 +0200
|
||||
|
||||
libgbinder (1.1.30) unstable; urgency=low
|
||||
|
||||
* Fixed BC_ACQUIRE_DONE encoding
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sun, 04 Dec 2022 19:50:10 +0200
|
||||
|
||||
libgbinder (1.1.29) unstable; urgency=low
|
||||
|
||||
* Added gbinder_writer_append_struct_vec
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 25 Nov 2022 00:01:41 +0200
|
||||
|
||||
libgbinder (1.1.28) unstable; urgency=low
|
||||
|
||||
* Allow to pass negative number as a parameter to binder-call
|
||||
* Compile tools as PIE
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 22 Nov 2022 18:21:29 +0200
|
||||
|
||||
libgbinder (1.1.27) unstable; urgency=low
|
||||
|
||||
* Added gbinder_writer_append_struct()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 17 Nov 2022 03:25:37 +0200
|
||||
|
||||
libgbinder (1.1.26) unstable; urgency=low
|
||||
|
||||
* Use BINDER_TYPE_HANDLE for NULL binders
|
||||
* Fixed binder object encoding in aidl3 protocol
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 14 Oct 2022 16:48:29 +0300
|
||||
|
||||
libgbinder (1.1.25) unstable; urgency=low
|
||||
|
||||
* Handle RPC protocol change at run time
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 19 Jul 2022 02:02:41 +0300
|
||||
|
||||
libgbinder (1.1.24) unstable; urgency=low
|
||||
|
||||
* Bumped debhelper compat level to 7
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 14 Jul 2022 01:32:11 +0300
|
||||
|
||||
libgbinder (1.1.23) unstable; urgency=low
|
||||
|
||||
* Fixed Debian build dependencies
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 23 Jun 2022 20:09:35 +0300
|
||||
|
||||
libgbinder (1.1.22) unstable; urgency=low
|
||||
|
||||
* Added support for Android 12 (API level 31)
|
||||
* Made binder device configurable for binder-dump
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 22 Jun 2022 17:02:20 +0300
|
||||
|
||||
libgbinder (1.1.21) unstable; urgency=low
|
||||
|
||||
* Properly finalize GBinderIpc and GBinderServicePoll
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 20 Jun 2022 18:53:26 +0300
|
||||
|
||||
libgbinder (1.1.20) unstable; urgency=low
|
||||
|
||||
* Made RPC protocol selectable at runtime
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sat, 11 Jun 2022 02:49:49 +0300
|
||||
|
||||
libgbinder (1.1.19-0ubports1) xenial; urgency=medium
|
||||
|
||||
* New upstream version 1.1.19.
|
||||
* debian/ubports.source_location: update the location for 1.1.19
|
||||
* debian/*: bring in upstream Debian packaging changes where appropriate
|
||||
* debian/rules: pass KEEP_SYMBOLS to let dh do the strip (& auto dbgsym)
|
||||
* debian/libgbinder-tools.install: add the missing .install file
|
||||
|
||||
-- Ratchanan Srirattanamet <ratchanan@ubports.com> Thu, 21 Apr 2022 17:22:20 +0700
|
||||
|
||||
libgbinder (1.1.19) unstable; urgency=low
|
||||
|
||||
* Added reader and writer for aidl parcelables
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sun, 20 Feb 2022 03:26:24 +0200
|
||||
|
||||
libgbinder (1.1.18) unstable; urgency=low
|
||||
|
||||
* Disassociate auto-created proxies to stop them from piling up
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sat, 08 Jan 2022 15:35:56 +0200
|
||||
|
||||
libgbinder (1.1.17) unstable; urgency=low
|
||||
|
||||
* Don't release remote proxy handle too early (sometimes hever)
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 07 Jan 2022 14:43:51 +0200
|
||||
|
||||
libgbinder (1.1.16) unstable; urgency=low
|
||||
|
||||
* Make sure stale object pointers don't hang around
|
||||
* Properly shut down remote object inside the proxy
|
||||
* Read ref_count from GObject atomically
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 03 Jan 2022 13:58:44 +0200
|
||||
|
||||
libgbinder (1.1.15) unstable; urgency=low
|
||||
|
||||
* Added readers and writers for int8 and int16
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 27 Dec 2021 15:13:23 +0200
|
||||
|
||||
libgbinder (1.1.14) unstable; urgency=low
|
||||
|
||||
* Support for FMQ (Fast Message Queues)
|
||||
* Support for Android 11 (API level 30)
|
||||
* Made GBinderReader API slightly more NULL tolerant
|
||||
* Added gbinder_client_rpc_header()
|
||||
* Added gbinder_reader_get_data()
|
||||
* Added gbinder_writer_get_data()
|
||||
* Added gbinder_servicemanager_device()
|
||||
* Added gbinder_local_reply_append_fd()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 24 Nov 2021 17:15:48 +0200
|
||||
|
||||
libgbinder (1.1.13) unstable; urgency=low
|
||||
|
||||
* Added gbinder_writer_strdup()
|
||||
* Added gbinder_writer_append_hidl_string_copy()
|
||||
* Dropped pkgconfig requirement for devel package
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 28 Oct 2021 14:31:01 +0300
|
||||
|
||||
libgbinder (1.1.12) unstable; urgency=low
|
||||
|
||||
* Added binder-call test tool
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 24 Sep 2021 16:46:05 +0300
|
||||
|
||||
libgbinder (1.1.11) unstable; urgency=low
|
||||
|
||||
* Fix potential deadlock in gbinder_ipc_looper_free()
|
||||
* Fix occasional crashes in pthread_setname_np()
|
||||
* Fix unit tests on some musl-based systems
|
||||
* Make unit tests comptible with glib < 2.36
|
||||
* Bump libglibutil requirement for debian build
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 02 Sep 2021 12:32:39 +0300
|
||||
|
||||
libgbinder (1.1.10) unstable; urgency=low
|
||||
|
||||
* Release dead binder nodes
|
||||
* Use gutil_memdup() instead of g_memdup()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 10 May 2021 02:36:43 +0300
|
||||
|
||||
libgbinder (1.1.9) unstable; urgency=low
|
||||
|
||||
* Include definition of _IOC_SIZE
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 20 Apr 2021 12:52:41 +0300
|
||||
|
||||
libgbinder (1.1.8) unstable; urgency=low
|
||||
|
||||
* Handle out-of-range transaction codes
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 16 Apr 2021 19:11:14 +0300
|
||||
|
||||
libgbinder (1.1.7) unstable; urgency=low
|
||||
|
||||
* Dropped use of g_main_context_invoke_full()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 31 Mar 2021 23:10:37 +0300
|
||||
|
||||
libgbinder (1.1.6-0ubports1) xenial; urgency=medium
|
||||
|
||||
* Import v1.1.6 to ubports
|
||||
|
||||
-- Marius Gripsgard <marius@ubports.com> Fri, 05 Mar 2021 01:02:27 +0100
|
||||
|
||||
libgbinder (1.1.6) unstable; urgency=low
|
||||
|
||||
* Implemented support for passing object over the bridge
|
||||
* Retry service name registration
|
||||
* Wait for completion of the reply
|
||||
* Fixed death handling by GBinderBridge
|
||||
* Added gbinder_bridge_new2()
|
||||
* Added -s option to binder-bridge
|
||||
* Fixed invalid slice deallocation
|
||||
* Made unit tests more reliable
|
||||
* Make sure that libgbinder doesn't block on exit
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 02 Mar 2021 18:18:03 +0200
|
||||
|
||||
libgbinder (1.1.5) unstable; urgency=low
|
||||
|
||||
* Fixed gbinder_remote_reply_copy_to_local() for empty replies
|
||||
* Improved binder simulation
|
||||
* Added GBinderBridge object
|
||||
* Added proxy_object and bridge unit tests
|
||||
* Added binder-bridge to libgbinder-tools package
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 29 Jan 2021 04:00:09 +0200
|
||||
|
||||
libgbinder (1.1.4) unstable; urgency=low
|
||||
|
||||
* Fixed a threading issue
|
||||
* Decode NULL object reference
|
||||
* Added new basic HIDL types
|
||||
* Set TF_ACCEPT_FDS transaction flag
|
||||
* Added servicemanager_hidl unit test
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 21 Jan 2021 03:34:45 +0200
|
||||
|
||||
libgbinder (1.1.3) unstable; urgency=low
|
||||
|
||||
* Improved unit test coverage
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 23 Dec 2020 21:48:27 +0200
|
||||
|
||||
libgbinder (1.1.2) unstable; urgency=low
|
||||
|
||||
* Fixed random unit text failures
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 23 Dec 2020 12:39:22 +0200
|
||||
|
||||
libgbinder (1.1.1) unstable; urgency=low
|
||||
|
||||
* Handle corner cases for abandoned loopers
|
||||
* Pass 0x0f priority to aidl2 service list request.
|
||||
* Improved binder simulation for unit tests
|
||||
* Added servicemanager_aidl unit test
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 22 Dec 2020 15:15:10 +0200
|
||||
|
||||
libgbinder (1.1.0) unstable; urgency=low
|
||||
|
||||
* Made RPC protocol configurable per binder device
|
||||
* Made service managers configurable per binder device
|
||||
* Added support for multiple config files
|
||||
* Added "aidl2" variant of service manager
|
||||
* Added "aidl2" variant of RPC protocol
|
||||
* Added support for API level presets
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 04 Dec 2020 13:47:26 +0200
|
||||
|
||||
libgbinder (1.0.47) unstable; urgency=low
|
||||
|
||||
* Make library executable on RPM based systems
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sat, 19 Sep 2020 20:14:20 +0300
|
||||
|
||||
libgbinder (1.0.46) unstable; urgency=low
|
||||
|
||||
* Make sure we drop fds that are going to be closed
|
||||
* Better diagnostics for polling failures
|
||||
* Package binder-list and binder-ping utilities
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 31 Jul 2020 02:04:38 +0300
|
||||
|
||||
libgbinder (1.0.45) unstable; urgency=low
|
||||
|
||||
* Always provide data buffer for hidl vector
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 27 Jul 2020 23:19:25 +0300
|
||||
|
||||
libgbinder (1.0.44) unstable; urgency=low
|
||||
|
||||
* Never drop valid incoming transactions
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 29 Jun 2020 17:05:22 +0300
|
||||
|
||||
libgbinder (1.0.43) unstable; urgency=low
|
||||
|
||||
* Hide internal symbols
|
||||
* Respect arch specific lib dir
|
||||
* Allow strip command to be replaced via environment variable
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 03 Jun 2020 15:15:40 +0300
|
||||
|
||||
libgbinder (1.0.42) unstable; urgency=low
|
||||
|
||||
* Allow GBinderClient to use multiple interfaces
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 05 May 2020 19:56:39 +0300
|
||||
|
||||
libgbinder (1.0.41) unstable; urgency=low
|
||||
|
||||
* Stop using GUtilIdlePool
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 14 Apr 2020 12:36:54 +0300
|
||||
|
||||
libgbinder (1.0.40) unstable; urgency=low
|
||||
|
||||
* Support integration with non-glib event loops
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 09 Apr 2020 17:22:12 +0300
|
||||
|
||||
libgbinder (1.0.39) unstable; urgency=low
|
||||
|
||||
* Adapted to side-by-side linking
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 02 Apr 2020 18:07:16 +0300
|
||||
|
||||
libgbinder (1.0.38) unstable; urgency=low
|
||||
|
||||
* Allow to configure log level via environment
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 02 Apr 2020 00:12:01 +0300
|
||||
|
||||
libgbinder (1.0.37) unstable; urgency=low
|
||||
|
||||
* Allow side-by-side linking with libglibutil
|
||||
* Fixed compilation warnings
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 17 Mar 2020 20:15:11 +0200
|
||||
|
||||
libgbinder (1.0.36) unstable; urgency=low
|
||||
|
||||
* Allow overwriting CC
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 16 Mar 2020 16:15:24 +0200
|
||||
|
||||
libgbinder (1.0.35) unstable; urgency=low
|
||||
|
||||
* Added binder-ping example
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 25 Feb 2020 13:58:19 +0200
|
||||
|
||||
libgbinder (1.0.34) unstable; urgency=low
|
||||
|
||||
* Better cleanup on unload to prevent crashes on exit
|
||||
* Fixed rare memory leak in GBinderServiceManager
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 16 Dec 2019 12:25:56 +0200
|
||||
|
||||
libgbinder (1.0.33) unstable; urgency=low
|
||||
|
||||
* Reuse loopers
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 13 Sep 2019 15:57:47 +0300
|
||||
|
||||
libgbinder (1.0.32) unstable; urgency=low
|
||||
|
||||
* Refuse to perform transactions with dead objects
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 17 May 2019 15:57:30 +0300
|
||||
|
||||
libgbinder (1.0.31) unstable; urgency=low
|
||||
|
||||
* Invalidate handle when remote object dies
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 13 May 2019 18:05:35 +0300
|
||||
|
||||
libgbinder (1.0.30) unstable; urgency=low
|
||||
|
||||
* Added gbinder_local_object_new()
|
||||
* Added gbinder_remote_object_ipc()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 20 Feb 2019 11:59:08 +0200
|
||||
|
||||
libgbinder (1.0.29) unstable; urgency=low
|
||||
|
||||
* Added gbinder_servicemanager_new_local_object2()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 14 Feb 2019 18:17:53 +0300
|
||||
|
||||
libgbinder (1.0.28) unstable; urgency=low
|
||||
|
||||
* Set type for local nulls to BINDER_TYPE_WEAK_BINDER
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 29 Jan 2019 02:49:10 +0200
|
||||
|
||||
libgbinder (1.0.27) unstable; urgency=low
|
||||
|
||||
* Fixed outgoing oneway transactions
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 24 Jan 2019 18:55:16 +0200
|
||||
|
||||
libgbinder (1.0.26) unstable; urgency=low
|
||||
|
||||
* Implement PING and INTERFACE transactions
|
||||
* Add GBinderServiceName API
|
||||
* Added gbinder_reader_read_string16_utf16()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 23 Jan 2019 17:43:41 +0200
|
||||
|
||||
libgbinder (1.0.25) unstable; urgency=low
|
||||
|
||||
* Added ServiceManager presence API
|
||||
|
||||
gbinder_servicemanager_wait()
|
||||
gbinder_servicemanager_is_present()
|
||||
gbinder_servicemanager_add_presence_handler()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 22 Jan 2019 16:03:57 +0200
|
||||
|
||||
libgbinder (1.0.24) unstable; urgency=low
|
||||
|
||||
* Revert "Make sure NULL objects are passed as BINDER_TYPE_WEAK_HANDLE"
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 18 Jan 2019 21:36:32 +0200
|
||||
|
||||
libgbinder (1.0.23) unstable; urgency=low
|
||||
|
||||
* Added gbinder_reader_read_hidl_string_c()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 15 Jan 2019 15:16:41 +0200
|
||||
|
||||
libgbinder (1.0.22) unstable; urgency=low
|
||||
|
||||
* Added gbinder_client_interface()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 10 Jan 2019 14:09:44 +0300
|
||||
|
||||
libgbinder (1.0.21) unstable; urgency=low
|
||||
|
||||
* Added API to overwrite prefix length
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 18 Dec 2018 14:05:14 +0200
|
||||
|
||||
libgbinder (1.0.20) unstable; urgency=low
|
||||
|
||||
* Added API to block incoming requests
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 17 Dec 2018 16:06:43 +0200
|
||||
|
||||
libgbinder (1.0.19) unstable; urgency=low
|
||||
|
||||
* Added GBinderWriter memory allocation and cleanup API
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
5
|
||||
7
|
||||
|
||||
12
debian/control
vendored
12
debian/control
vendored
@@ -2,17 +2,23 @@ Source: libgbinder
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Maintainer: Slava Monich <slava.monich@jolla.com>
|
||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.34)
|
||||
Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.0), libglibutil-dev (>= 1.0.52), flex, bison
|
||||
Standards-Version: 3.8.4
|
||||
|
||||
Package: libgbinder
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Depends: libglibutil (>= 1.0.34), ${shlibs:Depends}, ${misc:Depends}
|
||||
Depends: libglibutil (>= 1.0.52), ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Binder client library
|
||||
|
||||
Package: libgbinder-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: libgbinder (= ${binary:Version}), ${misc:Depends}
|
||||
Depends: libgbinder (= ${binary:Version}), libglibutil-dev (>= 1.0.52), ${misc:Depends}
|
||||
Description: Development files for libgbinder
|
||||
|
||||
Package: libgbinder-tools
|
||||
Section: utils
|
||||
Architecture: any
|
||||
Depends: libgbinder, ${misc:Depends}
|
||||
Description: Binder command line utilities
|
||||
|
||||
10
debian/copyright
vendored
10
debian/copyright
vendored
@@ -1,5 +1,5 @@
|
||||
Copyright (C) 2018 Jolla Ltd.
|
||||
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
Copyright (C) 2018-2022 Jolla Ltd.
|
||||
Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
|
||||
You may use this file under the terms of BSD license as follows:
|
||||
|
||||
@@ -12,9 +12,9 @@ are met:
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
3. Neither the names of the copyright holders nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
37
debian/gbinder.conf
vendored
Normal file
37
debian/gbinder.conf
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# Android keeps changing both low-level RPC and service manager
|
||||
# protocols from version to version. To counter that, libgbinder
|
||||
# implements configirable backends for different variants of those,
|
||||
# and yet keeping its own API unchanged.
|
||||
|
||||
# Configuration is loaded from [Protocol] and [ServiceManager] sections
|
||||
# of /etc/gbinder.conf file. The keys are binder device names or the
|
||||
# special Default value, the value is the identifier of the protocol
|
||||
# or service manager variant, respectively.
|
||||
|
||||
# In addition to reading /etc/gbinder.conf if it exists, /etc/gbinder.d
|
||||
# directory is scanned for .conf files, the file list is sorted, files are
|
||||
# loaded one by one, overwriting the entries loaded from /etc/gbinder.conf
|
||||
# or from the previously processed file.
|
||||
|
||||
# Known protocol and service manager variants are aidl, aidl2, aidl3 and
|
||||
# hidl. This list is expected to expand further in the future. The default
|
||||
# configuration is as follows:
|
||||
|
||||
# [Protocol]
|
||||
# Default = aidl
|
||||
# /dev/binder = aidl
|
||||
# /dev/hwbinder = hidl
|
||||
|
||||
# [ServiceManager]
|
||||
# Default = aidl
|
||||
# /dev/binder = aidl
|
||||
# /dev/hwbinder = hidl
|
||||
|
||||
# Alternatively and preferably, one can specify the desired Android API
|
||||
# level:
|
||||
|
||||
# [General]
|
||||
# ApiLevel = 29
|
||||
|
||||
# and let libgbinder pick the appropriate preset. Full list of presets can
|
||||
# be found in src/gbinder_config.c
|
||||
3
debian/libgbinder-dev.install
vendored
3
debian/libgbinder-dev.install
vendored
@@ -1,3 +0,0 @@
|
||||
debian/tmp/usr/lib/libgbinder.so usr/lib
|
||||
include/*.h usr/include/gbinder
|
||||
build/libgbinder.pc usr/lib/pkgconfig
|
||||
3
debian/libgbinder-dev.install.in
vendored
Normal file
3
debian/libgbinder-dev.install.in
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
debian/tmp/@LIBDIR@/libgbinder.so @LIBDIR@
|
||||
debian/tmp/@LIBDIR@/pkgconfig/libgbinder.pc @LIBDIR@/pkgconfig
|
||||
debian/tmp/usr/include/* usr/include
|
||||
1
debian/libgbinder-tools.install
vendored
Normal file
1
debian/libgbinder-tools.install
vendored
Normal file
@@ -0,0 +1 @@
|
||||
debian/tmp/usr/bin/* usr/bin/
|
||||
1
debian/libgbinder.dirs
vendored
Normal file
1
debian/libgbinder.dirs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/etc/gbinder.d/
|
||||
1
debian/libgbinder.install
vendored
1
debian/libgbinder.install
vendored
@@ -1 +0,0 @@
|
||||
debian/tmp/usr/lib/libgbinder.so.* usr/lib
|
||||
2
debian/libgbinder.install.in
vendored
Normal file
2
debian/libgbinder.install.in
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
debian/tmp/@LIBDIR@/libgbinder.so.* @LIBDIR@
|
||||
debian/gbinder.conf /etc/
|
||||
15
debian/rules
vendored
15
debian/rules
vendored
@@ -4,8 +4,21 @@
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
LIBDIR=usr/lib/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
|
||||
|
||||
override_dh_auto_build:
|
||||
dh_auto_build -- LIBDIR=$(LIBDIR) KEEP_SYMBOLS=1 release pkgconfig debian/libgbinder.install debian/libgbinder-dev.install
|
||||
dh_auto_build -- -C test/binder-bridge release
|
||||
dh_auto_build -- -C test/binder-call release
|
||||
dh_auto_build -- -C test/binder-list release
|
||||
dh_auto_build -- -C test/binder-ping release
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install -- install-dev
|
||||
dh_auto_install -- LIBDIR=$(LIBDIR) install-dev
|
||||
dh_auto_install -- -C test/binder-bridge
|
||||
dh_auto_install -- -C test/binder-call
|
||||
dh_auto_install -- -C test/binder-list
|
||||
dh_auto_install -- -C test/binder-ping
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -35,8 +35,10 @@
|
||||
|
||||
/* Convenience header to pull in everything at once */
|
||||
|
||||
#include "gbinder_bridge.h"
|
||||
#include "gbinder_buffer.h"
|
||||
#include "gbinder_client.h"
|
||||
#include "gbinder_fmq.h"
|
||||
#include "gbinder_local_object.h"
|
||||
#include "gbinder_local_reply.h"
|
||||
#include "gbinder_local_request.h"
|
||||
@@ -44,6 +46,7 @@
|
||||
#include "gbinder_remote_object.h"
|
||||
#include "gbinder_remote_reply.h"
|
||||
#include "gbinder_remote_request.h"
|
||||
#include "gbinder_servicename.h"
|
||||
#include "gbinder_servicemanager.h"
|
||||
#include "gbinder_writer.h"
|
||||
|
||||
|
||||
89
include/gbinder_bridge.h
Normal file
89
include/gbinder_bridge.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_BRIDGE_H
|
||||
#define GBINDER_BRIDGE_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
/* Since 1.1.5 */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* A binder bridge object.
|
||||
*
|
||||
* For example, bridging "foobar" with interfaces ["example@1.0::IFoo",
|
||||
* "example@1.0::IBar"] would:
|
||||
*
|
||||
* 1. Watch "example@1.0::IFoo/foobar" and "example@1.0::IBar/foobar" on dest
|
||||
* 2. When those names appears, register objects with the same name on src
|
||||
* 3. Pass calls coming from src to the dest objects and replies in the
|
||||
* opposite direction
|
||||
* 4. When dest objects disappear, remove the corresponding bridging objects
|
||||
* from src
|
||||
*
|
||||
* and so on.
|
||||
*/
|
||||
|
||||
GBinderBridge*
|
||||
gbinder_bridge_new(
|
||||
const char* name,
|
||||
const char* const* ifaces,
|
||||
GBinderServiceManager* src,
|
||||
GBinderServiceManager* dest) /* Since 1.1.5 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderBridge*
|
||||
gbinder_bridge_new2(
|
||||
const char* src_name,
|
||||
const char* dest_name,
|
||||
const char* const* ifaces,
|
||||
GBinderServiceManager* src,
|
||||
GBinderServiceManager* dest) /* Since 1.1.6 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
void
|
||||
gbinder_bridge_free(
|
||||
GBinderBridge* bridge); /* Since 1.1.5 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_BRIDGE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -37,6 +37,11 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct gbinder_client_iface_info {
|
||||
const char* iface;
|
||||
guint32 last_code;
|
||||
} GBinderClientIfaceInfo;
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderClientReplyFunc)(
|
||||
@@ -50,6 +55,12 @@ gbinder_client_new(
|
||||
GBinderRemoteObject* object,
|
||||
const char* iface);
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_new2(
|
||||
GBinderRemoteObject* object,
|
||||
const GBinderClientIfaceInfo* ifaces,
|
||||
gsize count); /* since 1.0.42 */
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_ref(
|
||||
GBinderClient* client);
|
||||
@@ -58,10 +69,29 @@ void
|
||||
gbinder_client_unref(
|
||||
GBinderClient* client);
|
||||
|
||||
const char*
|
||||
gbinder_client_interface(
|
||||
GBinderClient* client); /* since 1.0.22 */
|
||||
|
||||
const char*
|
||||
gbinder_client_interface2(
|
||||
GBinderClient* client,
|
||||
guint32 code); /* since 1.0.42 */
|
||||
|
||||
GBytes*
|
||||
gbinder_client_rpc_header(
|
||||
GBinderClient* client,
|
||||
guint32 code); /* since 1.1.14 */
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_client_new_request(
|
||||
GBinderClient* client);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_client_new_request2(
|
||||
GBinderClient* client,
|
||||
guint32 code); /* since 1.0.42 */
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_client_transact_sync_reply(
|
||||
GBinderClient* client,
|
||||
|
||||
194
include/gbinder_eventloop.h
Normal file
194
include/gbinder_eventloop.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Jolla Ltd.
|
||||
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_EVENTLOOP_H
|
||||
#define GBINDER_EVENTLOOP_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Since 1.0.40 */
|
||||
|
||||
typedef struct gbinder_eventloop_integration GBinderEventLoopIntegration;
|
||||
typedef void (*GBinderEventLoopCallbackFunc)(gpointer data);
|
||||
|
||||
typedef struct gbinder_eventloop_timeout {
|
||||
const GBinderEventLoopIntegration* eventloop;
|
||||
} GBinderEventLoopTimeout;
|
||||
|
||||
typedef struct gbinder_eventloop_callback {
|
||||
const GBinderEventLoopIntegration* eventloop;
|
||||
} GBinderEventLoopCallback;
|
||||
|
||||
/**
|
||||
* Main event loop integration. There is only one main event loop in the
|
||||
* process (by definition).
|
||||
*
|
||||
* By default, GLib event loop is being used for callbacks and timeouts.
|
||||
*
|
||||
* It may be necessary to replace it with e.g. Qt event loop. Quite often
|
||||
* Qt event loop is implemented by QEventDispatcherGlib which is sitting
|
||||
* on top of GLib event and therefore works with the default implementation.
|
||||
* But it won't work with e.g. QEventDispatcherUNIX.
|
||||
*
|
||||
* For Qt programs that use QEventDispatcherUNIX, it needs to be replaced
|
||||
* with the one provided by libqbinder.
|
||||
*/
|
||||
typedef struct gbinder_eventloop_integration {
|
||||
|
||||
/**
|
||||
* timeout_add
|
||||
*
|
||||
* Sets a function to be called at regular intervals (in milliseconds).
|
||||
* If the function returns G_SOURCE_REMOVE, timeout is automatically
|
||||
* destroyed (you must not call timeout_remove in this case). If the
|
||||
* function returns G_SOURCE_CONTINUE, it will be called again after
|
||||
* the same interval.
|
||||
*/
|
||||
GBinderEventLoopTimeout* (*timeout_add)(guint millis, GSourceFunc func,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* timeout_remove
|
||||
*
|
||||
* Removes a pending timeout and destroys it. The caller makes sure that
|
||||
* argument is not NULL. Note that timeout is automatically destroyed if
|
||||
* the callback function returns G_SOURCE_REMOVE.
|
||||
*/
|
||||
void (*timeout_remove)(GBinderEventLoopTimeout* timeout);
|
||||
|
||||
/**
|
||||
* callback_new
|
||||
*
|
||||
* Creates a callback object. It returns you a reference, you must
|
||||
* eventually pass the returned object to callback_unref to drop
|
||||
* this reference.
|
||||
*
|
||||
* Note that it doesn't automatically schedule the callback. You
|
||||
* must explicitly call callback_schedule to actually schedule it.
|
||||
* The finalize function is invoked regardless of whether callback
|
||||
* was cancelled or not.
|
||||
*/
|
||||
GBinderEventLoopCallback* (*callback_new)(GBinderEventLoopCallbackFunc fun,
|
||||
gpointer data, GDestroyNotify finalize);
|
||||
|
||||
/**
|
||||
* callback_ref
|
||||
*
|
||||
* Increments the reference count. That prevents the object from being
|
||||
* deleted before you drop this reference. The caller makes sure that
|
||||
* argument is not NULL.
|
||||
*/
|
||||
void (*callback_ref)(GBinderEventLoopCallback* cb);
|
||||
|
||||
/**
|
||||
* callback_unref
|
||||
*
|
||||
* Decrements the reference count (drops the reference). When reference
|
||||
* count reaches zero, the object gets deleted. The caller makes sure
|
||||
* that argument is not NULL.
|
||||
*
|
||||
* Note that calling callback_schedule temporarily adds an internal
|
||||
* reference until the callback is invoked or callback_cancel is called,
|
||||
* whichever happens first.
|
||||
*/
|
||||
void (*callback_unref)(GBinderEventLoopCallback* cb);
|
||||
|
||||
/**
|
||||
* callback_schedule
|
||||
*
|
||||
* Schedules the callback to be invoked in the main loop at some point
|
||||
* in the future (but as soon as possible). The caller makes sure that
|
||||
* argument is not NULL.
|
||||
*
|
||||
* This adds an internal reference to the GBinderEventLoopCallback object
|
||||
* until the callback is invoked or callback_cancel is called, whichever
|
||||
* happens first.
|
||||
*/
|
||||
void (*callback_schedule)(GBinderEventLoopCallback* cb);
|
||||
|
||||
/**
|
||||
* callback_cancel
|
||||
*
|
||||
* Makes sure that callback won't be invoked (if it hasn't been
|
||||
* invoked yet) and drops the internal reference. Does nothing
|
||||
* if the callback has already been invoked. The caller makes sure that
|
||||
* argument is not NULL.
|
||||
*/
|
||||
void (*callback_cancel)(GBinderEventLoopCallback* cb);
|
||||
|
||||
/**
|
||||
* cleanup
|
||||
*
|
||||
* This function is called when event loop integration is being replaced
|
||||
* with a different one, or libgbinder is being unloaded.
|
||||
*/
|
||||
void (*cleanup)(void);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_reserved1)(void);
|
||||
void (*_reserved2)(void);
|
||||
void (*_reserved3)(void);
|
||||
void (*_reserved4)(void);
|
||||
void (*_reserved5)(void);
|
||||
void (*_reserved6)(void);
|
||||
void (*_reserved7)(void);
|
||||
void (*_reserved8)(void);
|
||||
void (*_reserved9)(void);
|
||||
|
||||
/*
|
||||
* api_level will remain zero (and ignored) until we run out of
|
||||
* the above placeholders. Hopefully, forever.
|
||||
*/
|
||||
int api_level;
|
||||
} GBinderEventLoopIntegration;
|
||||
|
||||
/**
|
||||
* gbinder_eventloop_set should be called before libgbinder creates any of
|
||||
* its internal threads. And it must be done from the main thread.
|
||||
*/
|
||||
void
|
||||
gbinder_eventloop_set(
|
||||
const GBinderEventLoopIntegration* loop);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_EVENTLOOP_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
154
include/gbinder_fmq.h
Normal file
154
include/gbinder_fmq.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_FMQ_H
|
||||
#define GBINDER_FMQ_H
|
||||
|
||||
#include <gbinder_types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Since 1.1.14 */
|
||||
|
||||
typedef enum gbinder_fmq_type {
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE = 1,
|
||||
GBINDER_FMQ_TYPE_UNSYNC_WRITE
|
||||
} GBINDER_FMQ_TYPE;
|
||||
|
||||
typedef enum gbinder_fmq_flags {
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG = 0x1,
|
||||
GBINDER_FMQ_FLAG_NO_RESET_POINTERS = 0x2
|
||||
} GBINDER_FMQ_FLAGS;
|
||||
|
||||
GBinderFmq*
|
||||
gbinder_fmq_new(
|
||||
gsize item_size,
|
||||
gsize max_num_items,
|
||||
GBINDER_FMQ_TYPE type,
|
||||
GBINDER_FMQ_FLAGS flags,
|
||||
gint fd,
|
||||
gsize buffer_size);
|
||||
|
||||
GBinderFmq*
|
||||
gbinder_fmq_ref(
|
||||
GBinderFmq* fmq);
|
||||
|
||||
void
|
||||
gbinder_fmq_unref(
|
||||
GBinderFmq* fmq);
|
||||
|
||||
/* Functions for checking how many items are available in queue */
|
||||
gsize
|
||||
gbinder_fmq_available_to_read(
|
||||
GBinderFmq* fmq);
|
||||
|
||||
gsize
|
||||
gbinder_fmq_available_to_write(
|
||||
GBinderFmq* fmq);
|
||||
|
||||
gsize
|
||||
gbinder_fmq_available_to_read_contiguous(
|
||||
GBinderFmq* fmq);
|
||||
|
||||
gsize
|
||||
gbinder_fmq_available_to_write_contiguous(
|
||||
GBinderFmq* fmq);
|
||||
|
||||
/* Functions for obtaining data pointer for zero copy read/write */
|
||||
const void*
|
||||
gbinder_fmq_begin_read(
|
||||
GBinderFmq* fmq,
|
||||
gsize items);
|
||||
|
||||
void*
|
||||
gbinder_fmq_begin_write(
|
||||
GBinderFmq* fmq,
|
||||
gsize items);
|
||||
|
||||
/* Functions for ending zero copy read/write
|
||||
* The number of items must match the value provided to gbinder_fmq_begin_read
|
||||
* or gbinder_fmq_begin_write */
|
||||
void
|
||||
gbinder_fmq_end_read(
|
||||
GBinderFmq* fmq,
|
||||
gsize items);
|
||||
|
||||
void
|
||||
gbinder_fmq_end_write(
|
||||
GBinderFmq* fmq,
|
||||
gsize items);
|
||||
|
||||
/* Regular read/write functions (non-zero-copy) */
|
||||
gboolean
|
||||
gbinder_fmq_read(
|
||||
GBinderFmq* fmq,
|
||||
void* data,
|
||||
gsize items);
|
||||
|
||||
gboolean
|
||||
gbinder_fmq_write(
|
||||
GBinderFmq* fmq,
|
||||
const void* data,
|
||||
gsize items);
|
||||
|
||||
/*
|
||||
* Functions for waiting and waking message queue.
|
||||
* Requires configured event flag in message queue.
|
||||
*/
|
||||
int
|
||||
gbinder_fmq_wait_timeout(
|
||||
GBinderFmq* fmq,
|
||||
guint32 bit_mask,
|
||||
guint32* state,
|
||||
int timeout_ms);
|
||||
|
||||
#define gbinder_fmq_try_wait(fmq, mask, state) \
|
||||
gbinder_fmq_wait_timeout(fmq, mask, state, 0)
|
||||
|
||||
#define gbinder_fmq_wait(fmq, mask, state) \
|
||||
gbinder_fmq_wait_timeout(fmq, mask, state, -1)
|
||||
|
||||
int
|
||||
gbinder_fmq_wake(
|
||||
GBinderFmq* fmq,
|
||||
guint32 bit_mask);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_FMQ_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2019 Jolla Ltd.
|
||||
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -37,6 +37,14 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_new(
|
||||
GBinderIpc* ipc,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc handler,
|
||||
void* user_data) /* Since 1.0.30 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_ref(
|
||||
GBinderLocalObject* obj);
|
||||
@@ -53,6 +61,11 @@ GBinderLocalReply*
|
||||
gbinder_local_object_new_reply(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_local_object_set_stability(
|
||||
GBinderLocalObject* self,
|
||||
GBINDER_STABILITY_LEVEL stability); /* Since 1.1.40 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_LOCAL_OBJECT_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -112,6 +112,11 @@ gbinder_local_reply_append_remote_object(
|
||||
GBinderLocalReply* reply,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_fd(
|
||||
GBinderLocalReply* reply,
|
||||
int fd); /* Since 1.1.14 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_LOCAL_OBJECT_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -65,6 +65,26 @@ gbinder_reader_read_bool(
|
||||
GBinderReader* reader,
|
||||
gboolean* value);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int8(
|
||||
GBinderReader* reader,
|
||||
gint8* value); /* Since 1.1.15 */
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint8(
|
||||
GBinderReader* reader,
|
||||
guint8* value); /* Since 1.1.15 */
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int16(
|
||||
GBinderReader* reader,
|
||||
gint16* value); /* Since 1.1.15 */
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint16(
|
||||
GBinderReader* reader,
|
||||
guint16* value); /* Since 1.1.15 */
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int32(
|
||||
GBinderReader* reader,
|
||||
@@ -122,10 +142,15 @@ gbinder_reader_read_buffer(
|
||||
GBinderReader* reader)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
const void*
|
||||
gbinder_reader_read_parcelable(
|
||||
GBinderReader* reader,
|
||||
gsize* size); /* Since 1.1.19 */
|
||||
|
||||
const void*
|
||||
gbinder_reader_read_hidl_struct1(
|
||||
GBinderReader* reader,
|
||||
gsize size); /* since 1.0.9 */
|
||||
gsize size); /* Since 1.0.9 */
|
||||
|
||||
#define gbinder_reader_read_hidl_struct(reader,type) \
|
||||
((const type*)gbinder_reader_read_hidl_struct1(reader, sizeof(type)))
|
||||
@@ -140,7 +165,7 @@ const void*
|
||||
gbinder_reader_read_hidl_vec1(
|
||||
GBinderReader* reader,
|
||||
gsize* count,
|
||||
guint expected_elemsize); /* since 1.0.9 */
|
||||
guint expected_elemsize); /* Since 1.0.9 */
|
||||
|
||||
#define gbinder_reader_read_hidl_type_vec(reader,type,count) \
|
||||
((const type*)gbinder_reader_read_hidl_vec1(reader, count, sizeof(type)))
|
||||
@@ -152,6 +177,13 @@ gbinder_reader_read_hidl_string(
|
||||
GBinderReader* reader)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
const char*
|
||||
gbinder_reader_read_hidl_string_c(
|
||||
GBinderReader* reader); /* Since 1.0.23 */
|
||||
|
||||
#define gbinder_reader_skip_hidl_string(reader) \
|
||||
(gbinder_reader_read_hidl_string_c(reader) != NULL)
|
||||
|
||||
char**
|
||||
gbinder_reader_read_hidl_string_vec(
|
||||
GBinderReader* reader);
|
||||
@@ -177,8 +209,13 @@ gbinder_reader_read_nullable_string16(
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_string16_utf16(
|
||||
GBinderReader* reader,
|
||||
gunichar2** out,
|
||||
gsize* len); /* since 1.0.17 */
|
||||
const gunichar2** out,
|
||||
gsize* len); /* Since 1.0.17 */
|
||||
|
||||
const gunichar2*
|
||||
gbinder_reader_read_string16_utf16(
|
||||
GBinderReader* reader,
|
||||
gsize* len); /* Since 1.0.26 */
|
||||
|
||||
gboolean
|
||||
gbinder_reader_skip_string16(
|
||||
@@ -187,7 +224,12 @@ gbinder_reader_skip_string16(
|
||||
const void*
|
||||
gbinder_reader_read_byte_array(
|
||||
GBinderReader* reader,
|
||||
gsize* len); /* since 1.0.12 */
|
||||
gsize* len); /* Since 1.0.12 */
|
||||
|
||||
const void*
|
||||
gbinder_reader_get_data(
|
||||
const GBinderReader* reader,
|
||||
gsize* size); /* Since 1.1.14 */
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_read(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2019 Jolla Ltd.
|
||||
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -51,6 +51,10 @@ void
|
||||
gbinder_remote_object_unref(
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_remote_object_ipc(
|
||||
GBinderRemoteObject* obj); /* Since 1.0.30 */
|
||||
|
||||
gboolean
|
||||
gbinder_remote_object_is_dead(
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
@@ -67,6 +67,16 @@ gbinder_remote_request_copy_to_local(
|
||||
GBinderRemoteRequest* req) /* since 1.0.6 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
void
|
||||
gbinder_remote_request_block(
|
||||
GBinderRemoteRequest* req); /* Since 1.0.20 */
|
||||
|
||||
void
|
||||
gbinder_remote_request_complete(
|
||||
GBinderRemoteRequest* req,
|
||||
GBinderLocalReply* reply,
|
||||
int status); /* Since 1.0.20 */
|
||||
|
||||
/* Convenience function to decode requests with just one data item */
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -37,6 +37,12 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderServiceManagerFunc)(
|
||||
GBinderServiceManager* sm,
|
||||
void* user_data);
|
||||
|
||||
/* GBinderServiceManagerListFunc callback returns TRUE to keep the services
|
||||
* list, otherwise the caller will deallocate it. */
|
||||
typedef
|
||||
@@ -70,22 +76,41 @@ void
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new(
|
||||
const char* dev);
|
||||
const char* dev)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new2(
|
||||
const char* dev,
|
||||
const char* sm_protocol,
|
||||
const char* rpc_protocol) /* Since 1.1.20 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_defaultservicemanager_new(
|
||||
const char* dev);
|
||||
const char* dev)
|
||||
G_DEPRECATED_FOR(gbinder_servicemanager_new);
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
const char* dev);
|
||||
const char* dev)
|
||||
G_DEPRECATED_FOR(gbinder_servicemanager_new);
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_servicemanager_new_local_object(
|
||||
GBinderServiceManager* sm,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc handler,
|
||||
void* user_data);
|
||||
void* user_data)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_servicemanager_new_local_object2(
|
||||
GBinderServiceManager* sm,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc handler,
|
||||
void* user_data) /* Since 1.0.29 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_ref(
|
||||
@@ -95,6 +120,19 @@ void
|
||||
gbinder_servicemanager_unref(
|
||||
GBinderServiceManager* sm);
|
||||
|
||||
const char*
|
||||
gbinder_servicemanager_device(
|
||||
GBinderServiceManager* sm); /* Since 1.1.14 */
|
||||
|
||||
gboolean
|
||||
gbinder_servicemanager_is_present(
|
||||
GBinderServiceManager* sm); /* Since 1.0.25 */
|
||||
|
||||
gboolean
|
||||
gbinder_servicemanager_wait(
|
||||
GBinderServiceManager* sm,
|
||||
long max_wait_ms); /* Since 1.0.25 */
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_list(
|
||||
GBinderServiceManager* sm,
|
||||
@@ -103,7 +141,9 @@ gbinder_servicemanager_list(
|
||||
|
||||
char**
|
||||
gbinder_servicemanager_list_sync(
|
||||
GBinderServiceManager* sm);
|
||||
GBinderServiceManager* sm)
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
G_GNUC_MALLOC;
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_get_service(
|
||||
@@ -137,6 +177,12 @@ gbinder_servicemanager_cancel(
|
||||
GBinderServiceManager* sm,
|
||||
gulong id);
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_presence_handler(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderServiceManagerFunc func,
|
||||
void* user_data); /* Since 1.0.25 */
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_registration_handler(
|
||||
GBinderServiceManager* sm,
|
||||
@@ -149,6 +195,15 @@ gbinder_servicemanager_remove_handler(
|
||||
GBinderServiceManager* sm,
|
||||
gulong id); /* Since 1.0.13 */
|
||||
|
||||
void
|
||||
gbinder_servicemanager_remove_handlers(
|
||||
GBinderServiceManager* sm,
|
||||
gulong* ids,
|
||||
guint count); /* Since 1.0.25 */
|
||||
|
||||
#define gbinder_servicemanager_remove_all_handlers(sm,ids) \
|
||||
gbinder_servicemanager_remove_handlers(sm, ids, G_N_ELEMENTS(ids))
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_H */
|
||||
|
||||
70
include/gbinder_servicename.h
Normal file
70
include/gbinder_servicename.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Jolla Ltd.
|
||||
* Copyright (C) 2019 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_SERVICENAME_H
|
||||
#define GBINDER_SERVICENAME_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Since 1.0.26 */
|
||||
|
||||
struct gbinder_servicename {
|
||||
const char* name;
|
||||
};
|
||||
|
||||
GBinderServiceName*
|
||||
gbinder_servicename_new(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderLocalObject* object,
|
||||
const char* name);
|
||||
|
||||
GBinderServiceName*
|
||||
gbinder_servicename_ref(
|
||||
GBinderServiceName* name);
|
||||
|
||||
void
|
||||
gbinder_servicename_unref(
|
||||
GBinderServiceName* name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_SERVICENAME_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -59,8 +59,11 @@ G_BEGIN_DECLS
|
||||
* 6. Reader parses the data coming with RemoteRequest and RemoteReply
|
||||
*/
|
||||
|
||||
typedef struct gbinder_bridge GBinderBridge; /* Since 1.1.5 */
|
||||
typedef struct gbinder_buffer GBinderBuffer;
|
||||
typedef struct gbinder_client GBinderClient;
|
||||
typedef struct gbinder_fmq GBinderFmq; /* Since 1.1.14 */
|
||||
typedef struct gbinder_ipc GBinderIpc;
|
||||
typedef struct gbinder_local_object GBinderLocalObject;
|
||||
typedef struct gbinder_local_reply GBinderLocalReply;
|
||||
typedef struct gbinder_local_request GBinderLocalRequest;
|
||||
@@ -68,22 +71,27 @@ typedef struct gbinder_reader GBinderReader;
|
||||
typedef struct gbinder_remote_object GBinderRemoteObject;
|
||||
typedef struct gbinder_remote_reply GBinderRemoteReply;
|
||||
typedef struct gbinder_remote_request GBinderRemoteRequest;
|
||||
typedef struct gbinder_servicename GBinderServiceName;
|
||||
typedef struct gbinder_servicemanager GBinderServiceManager;
|
||||
typedef struct gbinder_writer GBinderWriter;
|
||||
typedef struct gbinder_parent GBinderParent;
|
||||
|
||||
/* Basic HIDL types */
|
||||
|
||||
#define GBINDER_ALIGNED(x) __attribute__ ((aligned(x)))
|
||||
|
||||
typedef struct gbinder_hidl_vec {
|
||||
union {
|
||||
guint64 value;
|
||||
const void* ptr;
|
||||
} data;
|
||||
guint32 count;
|
||||
guint32 owns_buffer;
|
||||
guint8 owns_buffer;
|
||||
guint8 pad[3];
|
||||
} GBinderHidlVec;
|
||||
|
||||
#define GBINDER_HIDL_VEC_BUFFER_OFFSET (0)
|
||||
G_STATIC_ASSERT(sizeof(GBinderHidlVec) == 16);
|
||||
|
||||
typedef struct gbinder_hidl_string {
|
||||
union {
|
||||
@@ -91,10 +99,51 @@ typedef struct gbinder_hidl_string {
|
||||
const char* str;
|
||||
} data;
|
||||
guint32 len;
|
||||
guint32 owns_buffer;
|
||||
guint8 owns_buffer;
|
||||
guint8 pad[3];
|
||||
} GBinderHidlString;
|
||||
|
||||
#define GBINDER_HIDL_STRING_BUFFER_OFFSET (0)
|
||||
G_STATIC_ASSERT(sizeof(GBinderHidlString) == 16);
|
||||
|
||||
typedef struct gbinder_fds {
|
||||
guint32 version GBINDER_ALIGNED(4);
|
||||
guint32 num_fds GBINDER_ALIGNED(4);
|
||||
guint32 num_ints GBINDER_ALIGNED(4);
|
||||
} GBINDER_ALIGNED(4) GBinderFds; /* Since 1.1.4 */
|
||||
|
||||
/* Actual fds immediately follow GBinderFds: */
|
||||
#define gbinder_fds_get_fd(fds,i) (((const int*)((fds) + 1))[i])
|
||||
|
||||
#define GBINDER_HIDL_FDS_VERSION (12)
|
||||
G_STATIC_ASSERT(sizeof(GBinderFds) == GBINDER_HIDL_FDS_VERSION);
|
||||
|
||||
typedef struct gbinder_hidl_handle {
|
||||
union {
|
||||
guint64 value;
|
||||
const GBinderFds* fds;
|
||||
} data;
|
||||
guint8 owns_handle;
|
||||
guint8 pad[7];
|
||||
} GBinderHidlHandle; /* Since 1.1.4 */
|
||||
|
||||
#define GBINDER_HIDL_HANDLE_VALUE_OFFSET (0)
|
||||
G_STATIC_ASSERT(sizeof(GBinderHidlHandle) == 16);
|
||||
|
||||
typedef struct gbinder_hidl_memory {
|
||||
union {
|
||||
guint64 value;
|
||||
const GBinderFds* fds;
|
||||
} data;
|
||||
guint8 owns_buffer;
|
||||
guint8 pad[7];
|
||||
guint64 size;
|
||||
GBinderHidlString name;
|
||||
} GBinderHidlMemory; /* Since 1.1.4 */
|
||||
|
||||
#define GBINDER_HIDL_MEMORY_PTR_OFFSET (0)
|
||||
#define GBINDER_HIDL_MEMORY_NAME_OFFSET (24)
|
||||
G_STATIC_ASSERT(sizeof(GBinderHidlMemory) == 40);
|
||||
|
||||
/*
|
||||
* Each RPC call is identified by the interface name returned
|
||||
@@ -124,6 +173,13 @@ typedef enum gbinder_status {
|
||||
GBINDER_STATUS_DEAD_OBJECT
|
||||
} GBINDER_STATUS;
|
||||
|
||||
typedef enum gbinder_stability_level {
|
||||
GBINDER_STABILITY_UNDECLARED = 0,
|
||||
GBINDER_STABILITY_VENDOR = 0x03,
|
||||
GBINDER_STABILITY_SYSTEM = 0x0c,
|
||||
GBINDER_STABILITY_VINTF = 0x3f
|
||||
} GBINDER_STABILITY_LEVEL; /* Since 1.1.40 */
|
||||
|
||||
#define GBINDER_FOURCC(c1,c2,c3,c4) \
|
||||
(((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -55,6 +55,119 @@ struct gbinder_parent {
|
||||
guint32 offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that gbinder_writer_append_struct() doesn't copy the data, it writes
|
||||
* buffer objects pointing to whatever was passed in. The caller must make
|
||||
* sure that those pointers outlive the transaction. That's most commonly
|
||||
* done with by using gbinder_writer_malloc() and friends for allocating
|
||||
* memory for the transaction.
|
||||
*
|
||||
* Below is an example of initializing GBinderWriterType which can then
|
||||
* be passed to gbinder_writer_append_struct(). Fields have to be listed
|
||||
* in the order in which they appear in the structure.
|
||||
*
|
||||
* typedef struct data {
|
||||
* int x;
|
||||
* } Data;
|
||||
*
|
||||
* typedef struct data2 {
|
||||
* int y;
|
||||
* GBinderHidlString str;
|
||||
* GBinderHidlVec vec; // vec<Data>
|
||||
* } Data2;
|
||||
*
|
||||
* static const GBinderWriterType data_t = {
|
||||
* GBINDER_WRITER_STRUCT_NAME_AND_SIZE(Data), NULL
|
||||
* };
|
||||
*
|
||||
* static const GBinderWriterField data2_f[] = {
|
||||
* GBINDER_WRITER_FIELD_HIDL_STRING(Data2,str),
|
||||
* GBINDER_WRITER_FIELD_HIDL_VEC(Data2, vec, &data_t),
|
||||
* GBINDER_WRITER_FIELD_END()
|
||||
* };
|
||||
*
|
||||
* static const GBinderWriterType data2_t = {
|
||||
* GBINDER_WRITER_STRUCT_NAME_AND_SIZE(Data2), data2_f
|
||||
* };
|
||||
*/
|
||||
|
||||
typedef struct gbinder_writer_type {
|
||||
const char* name;
|
||||
gsize size;
|
||||
const struct gbinder_writer_field* fields;
|
||||
} GBinderWriterType; /* Since 1.1.27 */
|
||||
|
||||
typedef struct gbinder_writer_field {
|
||||
const char* name;
|
||||
gsize offset;
|
||||
const GBinderWriterType* type;
|
||||
void (*write_buf)(GBinderWriter* writer, const void* ptr,
|
||||
const struct gbinder_writer_field* field, const GBinderParent* parent);
|
||||
gpointer reserved;
|
||||
} GBinderWriterField; /* Since 1.1.27 */
|
||||
|
||||
#define GBINDER_WRITER_STRUCT_NAME_AND_SIZE(type) \
|
||||
#type, sizeof(type)
|
||||
#define GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field) \
|
||||
#type "." #field, G_STRUCT_OFFSET(type,field)
|
||||
#define GBINDER_WRITER_FIELD_POINTER(type,field,field_type) { \
|
||||
GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field), field_type, NULL, NULL }
|
||||
#define GBINDER_WRITER_FIELD_HIDL_VEC(type,field,elem) { \
|
||||
GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field), elem, \
|
||||
gbinder_writer_field_hidl_vec_write_buf, NULL }
|
||||
#define GBINDER_WRITER_FIELD_HIDL_VEC_INT32(type,field) \
|
||||
GBINDER_WRITER_FIELD_HIDL_VEC(type,field, &gbinder_writer_type_int32)
|
||||
#define GBINDER_WRITER_FIELD_HIDL_VEC_BYTE(type,field) \
|
||||
GBINDER_WRITER_FIELD_HIDL_VEC(type,field, &gbinder_writer_type_byte)
|
||||
#define GBINDER_WRITER_FIELD_HIDL_VEC_STRING(type,field) \
|
||||
GBINDER_WRITER_FIELD_HIDL_VEC(type,field, &gbinder_writer_type_hidl_string)
|
||||
#define GBINDER_WRITER_FIELD_HIDL_STRING(type,field) { \
|
||||
GBINDER_WRITER_FIELD_NAME_AND_OFFSET(type,field), NULL, \
|
||||
gbinder_writer_field_hidl_string_write_buf, NULL }
|
||||
#define GBINDER_WRITER_FIELD_END() { NULL, 0, NULL, NULL, NULL }
|
||||
|
||||
extern const GBinderWriterType gbinder_writer_type_byte; /* Since 1.1.27 */
|
||||
extern const GBinderWriterType gbinder_writer_type_int32; /* Since 1.1.27 */
|
||||
extern const GBinderWriterType gbinder_writer_type_hidl_string; /* 1.1.27 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_struct(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
const GBinderWriterType* type,
|
||||
const GBinderParent* parent); /* Since 1.1.27 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_struct_vec(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
guint count,
|
||||
const GBinderWriterType* type); /* Since 1.1.29 */
|
||||
|
||||
void
|
||||
gbinder_writer_field_hidl_vec_write_buf(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
const GBinderWriterField* field,
|
||||
const GBinderParent* parent); /* Since 1.1.27 */
|
||||
|
||||
void
|
||||
gbinder_writer_field_hidl_string_write_buf(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
const GBinderWriterField* field,
|
||||
const GBinderParent* parent); /* Since 1.1.27 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_int8(
|
||||
GBinderWriter* writer,
|
||||
guint8 value); /* Since 1.1.15 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_int16(
|
||||
GBinderWriter* writer,
|
||||
guint16 value); /* Since 1.1.15 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_int32(
|
||||
GBinderWriter* writer,
|
||||
@@ -119,6 +232,12 @@ gbinder_writer_append_fd(
|
||||
GBinderWriter* writer,
|
||||
int fd); /* Since 1.0.18 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_fds(
|
||||
GBinderWriter* writer,
|
||||
const GBinderFds* fds,
|
||||
const GBinderParent* parent); /* Since 1.1.14 */
|
||||
|
||||
guint
|
||||
gbinder_writer_append_buffer_object_with_parent(
|
||||
GBinderWriter* writer,
|
||||
@@ -132,18 +251,29 @@ gbinder_writer_append_buffer_object(
|
||||
const void* buf,
|
||||
gsize len);
|
||||
|
||||
void
|
||||
gbinder_writer_append_parcelable(
|
||||
GBinderWriter* writer,
|
||||
const void* buf,
|
||||
gsize len); /* Since 1.1.19 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_vec(
|
||||
GBinderWriter* writer,
|
||||
const void* base,
|
||||
guint count,
|
||||
guint elemsize); /* since 1.0.8 */
|
||||
guint elemsize); /* Since 1.0.8 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string(
|
||||
GBinderWriter* writer,
|
||||
const char* str);
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string_copy(
|
||||
GBinderWriter* writer,
|
||||
const char* str); /* Since 1.1.13 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string_vec(
|
||||
GBinderWriter* writer,
|
||||
@@ -164,17 +294,39 @@ void
|
||||
gbinder_writer_append_byte_array(
|
||||
GBinderWriter* writer,
|
||||
const void* byte_array,
|
||||
gint32 len); /* since 1.0.12 */
|
||||
gint32 len); /* Since 1.0.12 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_fmq_descriptor(
|
||||
GBinderWriter* writer,
|
||||
const GBinderFmq* queue); /* since 1.1.14 */
|
||||
|
||||
const void*
|
||||
gbinder_writer_get_data(
|
||||
GBinderWriter* writer,
|
||||
gsize* size); /* Since 1.1.14 */
|
||||
|
||||
gsize
|
||||
gbinder_writer_bytes_written(
|
||||
GBinderWriter* writer); /* Since 1.0.21 */
|
||||
|
||||
void
|
||||
gbinder_writer_overwrite_int32(
|
||||
GBinderWriter* writer,
|
||||
gsize offset,
|
||||
gint32 value); /* Since 1.0.21 */
|
||||
|
||||
/* Note: memory allocated by GBinderWriter is owned by GBinderWriter */
|
||||
|
||||
void*
|
||||
gbinder_writer_malloc(
|
||||
GBinderWriter* writer,
|
||||
gsize size); /* since 1.0.19 */
|
||||
gsize size); /* Since 1.0.19 */
|
||||
|
||||
void*
|
||||
gbinder_writer_malloc0(
|
||||
GBinderWriter* writer,
|
||||
gsize size); /* since 1.0.19 */
|
||||
gsize size); /* Since 1.0.19 */
|
||||
|
||||
#define gbinder_writer_new(writer,type) \
|
||||
((type*) gbinder_writer_malloc(writer, sizeof(type)))
|
||||
@@ -182,17 +334,22 @@ gbinder_writer_malloc0(
|
||||
#define gbinder_writer_new0(writer,type) \
|
||||
((type*) gbinder_writer_malloc0(writer, sizeof(type)))
|
||||
|
||||
void*
|
||||
gbinder_writer_memdup(
|
||||
GBinderWriter* writer,
|
||||
const void* buf,
|
||||
gsize size); /* since 1.0.19 */
|
||||
|
||||
void
|
||||
gbinder_writer_add_cleanup(
|
||||
GBinderWriter* writer,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data); /* since 1.0.19 */
|
||||
gpointer data); /* Since 1.0.19 */
|
||||
|
||||
void*
|
||||
gbinder_writer_memdup(
|
||||
GBinderWriter* writer,
|
||||
const void* buf,
|
||||
gsize size); /* Since 1.0.19 */
|
||||
|
||||
char*
|
||||
gbinder_writer_strdup(
|
||||
GBinderWriter* writer,
|
||||
const char* str); /* Since 1.1.13 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
name=gbinder
|
||||
libdir=/usr/lib
|
||||
libdir=@libdir@
|
||||
includedir=/usr/include
|
||||
|
||||
Name: libgbinder
|
||||
Description: Binder client library
|
||||
Version: [version]
|
||||
Requires: glib-2.0 libglibutil
|
||||
Version: @version@
|
||||
Requires.private: glib-2.0 libglibutil
|
||||
Libs: -L${libdir} -l${name}
|
||||
Cflags: -I${includedir} -I${includedir}/${name}
|
||||
|
||||
8
misc/coverity_model.c
Normal file
8
misc/coverity_model.c
Normal file
@@ -0,0 +1,8 @@
|
||||
typedef struct gbinder_remote_request GBinderRemoteRequest;
|
||||
|
||||
void
|
||||
gbinder_remote_request_unref(
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
__coverity_free__(req);
|
||||
}
|
||||
@@ -1,14 +1,30 @@
|
||||
Name: libgbinder
|
||||
Version: 1.0.19
|
||||
|
||||
Version: 1.1.40
|
||||
Release: 0
|
||||
Summary: Binder client library
|
||||
Group: Development/Libraries
|
||||
License: BSD
|
||||
URL: https://github.com/mer-hybris/libgbinder
|
||||
Source: %{name}-%{version}.tar.bz2
|
||||
Requires: libglibutil >= 1.0.34
|
||||
BuildRequires: pkgconfig(glib-2.0)
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.34
|
||||
|
||||
%define glib_version 2.32
|
||||
%define libglibutil_version 1.0.52
|
||||
|
||||
BuildRequires: pkgconfig(glib-2.0) >= %{glib_version}
|
||||
BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}
|
||||
BuildRequires: pkgconfig
|
||||
BuildRequires: bison
|
||||
BuildRequires: flex
|
||||
|
||||
# license macro requires rpm >= 4.11
|
||||
BuildRequires: pkgconfig(rpm)
|
||||
%define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?)
|
||||
|
||||
# make_build macro appeared in rpm 4.12
|
||||
%{!?make_build:%define make_build make %{_smp_mflags}}
|
||||
|
||||
Requires: glib2 >= %{glib_version}
|
||||
Requires: libglibutil >= %{libglibutil_version}
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
|
||||
@@ -18,7 +34,7 @@ C interfaces for Android binder
|
||||
%package devel
|
||||
Summary: Development library for %{name}
|
||||
Requires: %{name} = %{version}
|
||||
Requires: pkgconfig
|
||||
Requires: pkgconfig(glib-2.0) >= %{glib_version}
|
||||
|
||||
%description devel
|
||||
This package contains the development library for %{name}.
|
||||
@@ -27,11 +43,18 @@ This package contains the development library for %{name}.
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
make KEEP_SYMBOLS=1 release pkgconfig
|
||||
%make_build LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
|
||||
%make_build -C test/binder-bridge -j1 KEEP_SYMBOLS=1 release
|
||||
%make_build -C test/binder-list -j1 KEEP_SYMBOLS=1 release
|
||||
%make_build -C test/binder-ping -j1 KEEP_SYMBOLS=1 release
|
||||
%make_build -C test/binder-call -j1 KEEP_SYMBOLS=1 release
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
make install-dev DESTDIR=%{buildroot}
|
||||
make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev
|
||||
make -C test/binder-bridge DESTDIR=%{buildroot} install
|
||||
make -C test/binder-list DESTDIR=%{buildroot} install
|
||||
make -C test/binder-ping DESTDIR=%{buildroot} install
|
||||
make -C test/binder-call DESTDIR=%{buildroot} install
|
||||
|
||||
%check
|
||||
make -C unit test
|
||||
@@ -43,9 +66,29 @@ make -C unit test
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/%{name}.so.*
|
||||
%if %{license_support} == 0
|
||||
%license LICENSE
|
||||
%endif
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{_includedir}/gbinder
|
||||
%{_libdir}/pkgconfig/*.pc
|
||||
%{_libdir}/%{name}.so
|
||||
%{_includedir}/gbinder/*.h
|
||||
|
||||
# Tools
|
||||
|
||||
%package tools
|
||||
Summary: Binder tools
|
||||
Requires: %{name} >= %{version}
|
||||
|
||||
%description tools
|
||||
Binder command line utilities
|
||||
|
||||
%files tools
|
||||
%defattr(-,root,root,-)
|
||||
%{_bindir}/binder-bridge
|
||||
%{_bindir}/binder-list
|
||||
%{_bindir}/binder-ping
|
||||
%{_bindir}/binder-call
|
||||
|
||||
272
src/gbinder_bridge.c
Normal file
272
src/gbinder_bridge.c
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_local_request.h"
|
||||
#include "gbinder_local_reply.h"
|
||||
#include "gbinder_proxy_object.h"
|
||||
#include "gbinder_remote_request_p.h"
|
||||
#include "gbinder_remote_reply.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_servicename.h"
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_bridge.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct gbinder_bridge_interface {
|
||||
GBinderBridge* bridge;
|
||||
char* iface;
|
||||
char* fqname;
|
||||
char* src_name;
|
||||
char* dest_name;
|
||||
gulong dest_watch_id;
|
||||
gulong dest_death_id;
|
||||
GBinderRemoteObject* dest_obj;
|
||||
GBinderServiceName* src_service;
|
||||
GBinderProxyObject* proxy;
|
||||
} GBinderBridgeInterface;
|
||||
|
||||
struct gbinder_bridge {
|
||||
GBinderBridgeInterface** ifaces;
|
||||
GBinderServiceManager* src;
|
||||
GBinderServiceManager* dest;
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_bridge_dest_drop_remote_object(
|
||||
GBinderBridgeInterface* bi)
|
||||
{
|
||||
if (bi->dest_obj) {
|
||||
GDEBUG("Detached from %s", bi->fqname);
|
||||
gbinder_remote_object_remove_handler(bi->dest_obj, bi->dest_death_id);
|
||||
gbinder_remote_object_unref(bi->dest_obj);
|
||||
bi->dest_death_id = 0;
|
||||
bi->dest_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_bridge_interface_deactivate(
|
||||
GBinderBridgeInterface* bi)
|
||||
{
|
||||
gbinder_bridge_dest_drop_remote_object(bi);
|
||||
if (bi->proxy) {
|
||||
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(bi->proxy));
|
||||
bi->proxy = NULL;
|
||||
}
|
||||
if (bi->src_service) {
|
||||
gbinder_servicename_unref(bi->src_service);
|
||||
bi->src_service = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_bridge_interface_free(
|
||||
GBinderBridgeInterface* bi)
|
||||
{
|
||||
GBinderBridge* bridge = bi->bridge;
|
||||
|
||||
gbinder_bridge_interface_deactivate(bi);
|
||||
gbinder_servicemanager_remove_handler(bridge->dest, bi->dest_watch_id);
|
||||
g_free(bi->iface);
|
||||
g_free(bi->fqname);
|
||||
g_free(bi->src_name);
|
||||
g_free(bi->dest_name);
|
||||
gutil_slice_free(bi);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_bridge_dest_death_proc(
|
||||
GBinderRemoteObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderBridgeInterface* bi = user_data;
|
||||
|
||||
GDEBUG("%s has died", bi->fqname);
|
||||
gbinder_bridge_interface_deactivate(bi);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_bridge_interface_activate(
|
||||
GBinderBridgeInterface* bi)
|
||||
{
|
||||
GBinderBridge* bridge = bi->bridge;
|
||||
GBinderServiceManager* src = bridge->src;
|
||||
GBinderServiceManager* dest = bridge->dest;
|
||||
|
||||
if (bi->dest_obj && bi->dest_obj->dead) {
|
||||
gbinder_bridge_dest_drop_remote_object(bi);
|
||||
}
|
||||
if (!bi->dest_obj) {
|
||||
bi->dest_obj = gbinder_servicemanager_get_service_sync(dest,
|
||||
bi->fqname, NULL);
|
||||
if (bi->dest_obj) {
|
||||
GDEBUG("Attached to %s", bi->fqname);
|
||||
gbinder_remote_object_ref(bi->dest_obj);
|
||||
bi->dest_death_id = gbinder_remote_object_add_death_handler
|
||||
(bi->dest_obj, gbinder_bridge_dest_death_proc, bi);
|
||||
}
|
||||
}
|
||||
if (bi->dest_obj && !bi->proxy) {
|
||||
bi->proxy = gbinder_proxy_object_new(gbinder_servicemanager_ipc(src),
|
||||
bi->dest_obj);
|
||||
}
|
||||
if (bi->proxy && !bi->src_service) {
|
||||
bi->src_service = gbinder_servicename_new(src,
|
||||
GBINDER_LOCAL_OBJECT(bi->proxy), bi->src_name);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_bridge_dest_registration_proc(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderBridgeInterface* bi = user_data;
|
||||
|
||||
if (!g_strcmp0(name, bi->fqname)) {
|
||||
GDEBUG("%s has been registered", bi->fqname);
|
||||
gbinder_bridge_interface_activate(bi);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderBridgeInterface*
|
||||
gbinder_bridge_interface_new(
|
||||
GBinderBridge* self,
|
||||
const char* src_name,
|
||||
const char* dest_name,
|
||||
const char* iface)
|
||||
{
|
||||
GBinderBridgeInterface* bi = g_slice_new0(GBinderBridgeInterface);
|
||||
|
||||
bi->bridge = self;
|
||||
bi->iface = g_strdup(iface);
|
||||
bi->fqname = g_strconcat(iface, "/", dest_name, NULL);
|
||||
bi->src_name = g_strdup(src_name);
|
||||
bi->dest_name = g_strdup(dest_name);
|
||||
bi->dest_watch_id = gbinder_servicemanager_add_registration_handler
|
||||
(self->dest, bi->fqname, gbinder_bridge_dest_registration_proc, bi);
|
||||
|
||||
/* Try to activate at startup */
|
||||
gbinder_bridge_interface_activate(bi);
|
||||
return bi;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderBridge*
|
||||
gbinder_bridge_new(
|
||||
const char* name,
|
||||
const char* const* ifaces,
|
||||
GBinderServiceManager* src,
|
||||
GBinderServiceManager* dest) /* Since 1.1.5 */
|
||||
{
|
||||
return gbinder_bridge_new2(name, NULL, ifaces, src, dest);
|
||||
}
|
||||
|
||||
GBinderBridge*
|
||||
gbinder_bridge_new2(
|
||||
const char* src_name,
|
||||
const char* dest_name,
|
||||
const char* const* ifaces,
|
||||
GBinderServiceManager* src,
|
||||
GBinderServiceManager* dest) /* Since 1.1.6 */
|
||||
{
|
||||
const guint n = gutil_strv_length((const GStrV*)ifaces);
|
||||
|
||||
if (!src_name) {
|
||||
src_name = dest_name;
|
||||
} else if (!dest_name) {
|
||||
dest_name = src_name;
|
||||
}
|
||||
if (G_LIKELY(src_name) && G_LIKELY(n) && G_LIKELY(src) && G_LIKELY(dest)) {
|
||||
GBinderBridge* self = g_slice_new0(GBinderBridge);
|
||||
guint i;
|
||||
|
||||
self->src = gbinder_servicemanager_ref(src);
|
||||
self->dest = gbinder_servicemanager_ref(dest);
|
||||
self->ifaces = g_new(GBinderBridgeInterface*, n + 1);
|
||||
for (i = 0; i < n; i++) {
|
||||
self->ifaces[i] = gbinder_bridge_interface_new(self,
|
||||
src_name, dest_name, ifaces[i]);
|
||||
}
|
||||
self->ifaces[i] = NULL;
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_bridge_free(
|
||||
GBinderBridge* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderBridgeInterface** bi = self->ifaces;
|
||||
|
||||
while (*bi) {
|
||||
gbinder_bridge_interface_free(*bi);
|
||||
bi++;
|
||||
}
|
||||
gbinder_servicemanager_unref(self->src);
|
||||
gbinder_servicemanager_unref(self->dest);
|
||||
g_free(self->ifaces);
|
||||
gutil_slice_free(self);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -112,6 +112,47 @@ gbinder_buffer_contents_unref(
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* GBinderBufferContentsList
|
||||
* It's actually a GSList containing GBinderBufferContents refs.
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderBufferContentsList*
|
||||
gbinder_buffer_contents_list_add(
|
||||
GBinderBufferContentsList* list,
|
||||
GBinderBufferContents* contents)
|
||||
{
|
||||
/* Prepend rather than append for better efficiency */
|
||||
return contents ? (GBinderBufferContentsList*) g_slist_prepend((GSList*)
|
||||
list, gbinder_buffer_contents_ref(contents)) : list;
|
||||
}
|
||||
|
||||
GBinderBufferContentsList*
|
||||
gbinder_buffer_contents_list_dup(
|
||||
GBinderBufferContentsList* list)
|
||||
{
|
||||
GSList* out = NULL;
|
||||
|
||||
if (list) {
|
||||
GSList* l = (GSList*) list;
|
||||
|
||||
/* The order gets reversed but it doesn't matter */
|
||||
while (l) {
|
||||
out = g_slist_prepend(out, gbinder_buffer_contents_ref(l->data));
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
return (GBinderBufferContentsList*) out;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_buffer_contents_list_free(
|
||||
GBinderBufferContentsList* list)
|
||||
{
|
||||
g_slist_free_full((GSList*) list, (GDestroyNotify)
|
||||
gbinder_buffer_contents_unref);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* GBinderBuffer
|
||||
*==========================================================================*/
|
||||
@@ -210,6 +251,15 @@ gbinder_buffer_io(
|
||||
return driver ? gbinder_driver_io(driver) : NULL;
|
||||
}
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_buffer_protocol(
|
||||
GBinderBuffer* buf)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_buffer_driver(buf);
|
||||
|
||||
return driver ? gbinder_driver_protocol(driver) : NULL;
|
||||
}
|
||||
|
||||
void**
|
||||
gbinder_buffer_objects(
|
||||
GBinderBuffer* self)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -42,42 +42,72 @@ gbinder_buffer_new(
|
||||
GBinderDriver* driver,
|
||||
void* data,
|
||||
gsize size,
|
||||
void** objects);
|
||||
void** objects)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderBuffer*
|
||||
gbinder_buffer_new_with_parent(
|
||||
GBinderBuffer* parent,
|
||||
void* data,
|
||||
gsize size);
|
||||
gsize size)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_buffer_driver(
|
||||
GBinderBuffer* buf);
|
||||
GBinderBuffer* buf)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderBufferContents*
|
||||
gbinder_buffer_contents(
|
||||
GBinderBuffer* buf);
|
||||
GBinderBuffer* buf)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gconstpointer
|
||||
gbinder_buffer_data(
|
||||
GBinderBuffer* buf,
|
||||
gsize* size);
|
||||
gsize* size)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const GBinderIo*
|
||||
gbinder_buffer_io(
|
||||
GBinderBuffer* buf);
|
||||
GBinderBuffer* buf)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_buffer_protocol(
|
||||
GBinderBuffer* buf)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void**
|
||||
gbinder_buffer_objects(
|
||||
GBinderBuffer* buffer);
|
||||
GBinderBuffer* buffer)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderBufferContents*
|
||||
gbinder_buffer_contents_ref(
|
||||
GBinderBufferContents* contents);
|
||||
GBinderBufferContents* contents)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_buffer_contents_unref(
|
||||
GBinderBufferContents* contents);
|
||||
GBinderBufferContents* contents)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderBufferContentsList*
|
||||
gbinder_buffer_contents_list_add(
|
||||
GBinderBufferContentsList* list,
|
||||
GBinderBufferContents* contents)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderBufferContentsList*
|
||||
gbinder_buffer_contents_list_dup(
|
||||
GBinderBufferContentsList* list)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_buffer_contents_list_free(
|
||||
GBinderBufferContentsList* list)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_BUFFER_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -37,17 +37,20 @@
|
||||
|
||||
void
|
||||
gbinder_cleanup_free(
|
||||
GBinderCleanup* cleanup);
|
||||
GBinderCleanup* cleanup)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_cleanup_reset(
|
||||
GBinderCleanup* cleanup);
|
||||
GBinderCleanup* cleanup)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderCleanup*
|
||||
gbinder_cleanup_add(
|
||||
GBinderCleanup* cleanup,
|
||||
GDestroyNotify destroy,
|
||||
gpointer pointer);
|
||||
gpointer pointer)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_CLEANUP_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -41,14 +41,22 @@
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
typedef struct gbinder_client_iface_range {
|
||||
char* iface;
|
||||
GBytes* rpc_header;
|
||||
GBinderLocalRequest* basic_req;
|
||||
guint32 last_code;
|
||||
} GBinderClientIfaceRange;
|
||||
|
||||
typedef struct gbinder_client_priv {
|
||||
GBinderClient pub;
|
||||
guint32 refcount;
|
||||
char* iface;
|
||||
GBytes* rpc_header;
|
||||
GBinderLocalRequest* basic_req;
|
||||
GBinderClientIfaceRange* ranges;
|
||||
guint nr;
|
||||
} GBinderClientPriv;
|
||||
|
||||
typedef struct gbinder_client_tx {
|
||||
@@ -65,19 +73,79 @@ static inline GBinderClientPriv* gbinder_client_cast(GBinderClient* client)
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
const GBinderClientIfaceRange*
|
||||
gbinder_client_find_range(
|
||||
GBinderClientPriv* priv,
|
||||
guint32 code)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < priv->nr; i++) {
|
||||
const GBinderClientIfaceRange* r = priv->ranges + i;
|
||||
|
||||
if (r->last_code >= code) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates basic request (without additional parameters) for the
|
||||
* specified interface and pulls header data out of it. The basic
|
||||
* request can be reused for those transactions which have no
|
||||
* additional parameters. The header data are needed for building
|
||||
* non-trivial requests.
|
||||
*/
|
||||
static
|
||||
void
|
||||
gbinder_client_init_range(
|
||||
GBinderClientIfaceRange* r,
|
||||
GBinderDriver* driver,
|
||||
const GBinderClientIfaceInfo* info)
|
||||
{
|
||||
GBinderOutputData* hdr;
|
||||
|
||||
r->basic_req = gbinder_driver_local_request_new(driver, info->iface);
|
||||
hdr = gbinder_local_request_data(r->basic_req);
|
||||
r->rpc_header = g_bytes_new(hdr->bytes->data, hdr->bytes->len);
|
||||
r->iface = g_strdup(info->iface);
|
||||
r->last_code = info->last_code;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
gbinder_client_sort_ranges(
|
||||
const void* p1,
|
||||
const void* p2)
|
||||
{
|
||||
const GBinderClientIfaceRange* r1 = p1;
|
||||
const GBinderClientIfaceRange* r2 = p2;
|
||||
|
||||
return (r1->last_code < r2->last_code) ? (-1) :
|
||||
(r1->last_code > r2->last_code) ? 1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_client_free(
|
||||
GBinderClientPriv* priv)
|
||||
{
|
||||
GBinderClient* self = &priv->pub;
|
||||
guint i;
|
||||
|
||||
gbinder_remote_object_unref(self->remote);
|
||||
gbinder_local_request_unref(priv->basic_req);
|
||||
g_free(priv->iface);
|
||||
if (priv->rpc_header) {
|
||||
g_bytes_unref(priv->rpc_header);
|
||||
for (i = 0; i < priv->nr; i++) {
|
||||
GBinderClientIfaceRange* r = priv->ranges + i;
|
||||
|
||||
gbinder_local_request_unref(r->basic_req);
|
||||
g_free(r->iface);
|
||||
if (r->rpc_header) {
|
||||
g_bytes_unref(r->rpc_header);
|
||||
}
|
||||
}
|
||||
g_free(priv->ranges);
|
||||
gbinder_remote_object_unref(self->remote);
|
||||
g_slice_free(GBinderClientPriv, priv);
|
||||
}
|
||||
|
||||
@@ -110,14 +178,86 @@ gbinder_client_transact_destroy(
|
||||
g_slice_free(GBinderClientTx, tx);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internal interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_client_transact_sync_reply2(
|
||||
GBinderClient* self,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
int* status,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
|
||||
if (G_LIKELY(!obj->dead)) {
|
||||
if (!req) {
|
||||
const GBinderClientIfaceRange* r = gbinder_client_find_range
|
||||
(gbinder_client_cast(self), code);
|
||||
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
if (r) {
|
||||
req = r->basic_req;
|
||||
}
|
||||
}
|
||||
if (req) {
|
||||
return api->sync_reply(obj->ipc, obj->handle, code, req,
|
||||
status);
|
||||
} else {
|
||||
GWARN("Unable to build empty request for tx code %u", code);
|
||||
}
|
||||
} else {
|
||||
GDEBUG("Refusing to perform transaction with a dead object");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_client_transact_sync_oneway2(
|
||||
GBinderClient* self,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
|
||||
if (G_LIKELY(!obj->dead)) {
|
||||
if (!req) {
|
||||
const GBinderClientIfaceRange* r = gbinder_client_find_range
|
||||
(gbinder_client_cast(self), code);
|
||||
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
if (r) {
|
||||
req = r->basic_req;
|
||||
}
|
||||
}
|
||||
if (req) {
|
||||
return api->sync_oneway(obj->ipc, obj->handle, code, req);
|
||||
} else {
|
||||
GWARN("Unable to build empty request for tx code %u", code);
|
||||
}
|
||||
} else {
|
||||
GDEBUG("Refusing to perform transaction with a dead object");
|
||||
return (-ESTALE);
|
||||
}
|
||||
}
|
||||
return (-EINVAL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_new(
|
||||
gbinder_client_new2(
|
||||
GBinderRemoteObject* remote,
|
||||
const char* iface)
|
||||
const GBinderClientIfaceInfo* ifaces,
|
||||
gsize count)
|
||||
{
|
||||
if (G_LIKELY(remote)) {
|
||||
GBinderClientPriv* priv = g_slice_new0(GBinderClientPriv);
|
||||
@@ -126,29 +266,42 @@ gbinder_client_new(
|
||||
|
||||
g_atomic_int_set(&priv->refcount, 1);
|
||||
self->remote = gbinder_remote_object_ref(remote);
|
||||
if (count > 0) {
|
||||
gsize i;
|
||||
|
||||
/*
|
||||
* Generate basic request (without additional parameters) and pull
|
||||
* header data out of it. The basic request can be reused for those
|
||||
* transactions which has no additional parameters. The header data
|
||||
* are needed for building non-trivial requests.
|
||||
*/
|
||||
if (iface) {
|
||||
GBinderOutputData* hdr;
|
||||
|
||||
priv->basic_req = gbinder_driver_local_request_new(driver, iface);
|
||||
hdr = gbinder_local_request_data(priv->basic_req);
|
||||
priv->rpc_header = g_bytes_new(hdr->bytes->data, hdr->bytes->len);
|
||||
self->iface = priv->iface = g_strdup(iface);
|
||||
priv->nr = count;
|
||||
priv->ranges = g_new(GBinderClientIfaceRange, priv->nr);
|
||||
for (i = 0; i < count; i++) {
|
||||
gbinder_client_init_range(priv->ranges + i, driver, ifaces + i);
|
||||
}
|
||||
qsort(priv->ranges, count, sizeof(GBinderClientIfaceRange),
|
||||
gbinder_client_sort_ranges);
|
||||
} else {
|
||||
priv->basic_req = gbinder_local_request_new
|
||||
(gbinder_driver_io(driver), NULL);
|
||||
/* No interface info */
|
||||
priv->nr = 1;
|
||||
priv->ranges = g_new0(GBinderClientIfaceRange, 1);
|
||||
priv->ranges[0].last_code = UINT_MAX;
|
||||
priv->ranges[0].basic_req = gbinder_local_request_new
|
||||
(gbinder_driver_io(driver), gbinder_driver_protocol(driver),
|
||||
NULL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_new(
|
||||
GBinderRemoteObject* remote,
|
||||
const char* iface)
|
||||
{
|
||||
GBinderClientIfaceInfo info;
|
||||
|
||||
info.iface = iface;
|
||||
info.last_code = UINT_MAX;
|
||||
return gbinder_client_new2(remote, &info, 1);
|
||||
}
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_ref(
|
||||
GBinderClient* self)
|
||||
@@ -176,14 +329,75 @@ gbinder_client_unref(
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_client_interface(
|
||||
GBinderClient* self) /* since 1.0.22 */
|
||||
{
|
||||
return G_LIKELY(self) ? gbinder_client_cast(self)->ranges->iface : NULL;
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_client_interface2(
|
||||
GBinderClient* self,
|
||||
guint32 code) /* since 1.0.42 */
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
const GBinderClientIfaceRange* r =
|
||||
gbinder_client_find_range(gbinder_client_cast(self), code);
|
||||
|
||||
if (r) {
|
||||
return r->iface;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBytes*
|
||||
gbinder_client_rpc_header(
|
||||
GBinderClient* self,
|
||||
guint32 code) /* since 1.1.14 */
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
const GBinderClientIfaceRange* r =
|
||||
gbinder_client_find_range(gbinder_client_cast(self), code);
|
||||
|
||||
if (r) {
|
||||
return r->rpc_header;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_client_new_request(
|
||||
GBinderClient* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderClientPriv* priv = gbinder_client_cast(self);
|
||||
const GBinderIo* io = gbinder_driver_io(self->remote->ipc->driver);
|
||||
return gbinder_local_request_new(io, priv->rpc_header);
|
||||
GBinderDriver* driver = self->remote->ipc->driver;
|
||||
|
||||
return gbinder_local_request_new(gbinder_driver_io(driver),
|
||||
gbinder_driver_protocol(driver), priv->ranges->rpc_header);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_client_new_request2(
|
||||
GBinderClient* self,
|
||||
guint32 code) /* since 1.0.42 */
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderClientPriv* priv = gbinder_client_cast(self);
|
||||
const GBinderClientIfaceRange* range = gbinder_client_find_range
|
||||
(priv, code);
|
||||
|
||||
if (range) {
|
||||
GBinderDriver* driver = self->remote->ipc->driver;
|
||||
|
||||
return gbinder_local_request_new(gbinder_driver_io(driver),
|
||||
gbinder_driver_protocol(driver), range->rpc_header);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -195,17 +409,8 @@ gbinder_client_transact_sync_reply(
|
||||
GBinderLocalRequest* req,
|
||||
int* status)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
|
||||
if (!req) {
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
req = gbinder_client_cast(self)->basic_req;
|
||||
}
|
||||
return gbinder_ipc_transact_sync_reply(obj->ipc, obj->handle,
|
||||
code, req, status);
|
||||
}
|
||||
return NULL;
|
||||
return gbinder_client_transact_sync_reply2(self, code, req, status,
|
||||
&gbinder_ipc_sync_main);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -214,18 +419,8 @@ gbinder_client_transact_sync_oneway(
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
|
||||
if (!req) {
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
req = gbinder_client_cast(self)->basic_req;
|
||||
}
|
||||
return gbinder_ipc_transact_sync_oneway(obj->ipc, obj->handle,
|
||||
code, req);
|
||||
} else {
|
||||
return (-EINVAL);
|
||||
}
|
||||
return gbinder_client_transact_sync_oneway2(self, code, req,
|
||||
&gbinder_ipc_sync_main);
|
||||
}
|
||||
|
||||
gulong
|
||||
@@ -240,23 +435,35 @@ gbinder_client_transact(
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
GBinderClientTx* tx = g_slice_new0(GBinderClientTx);
|
||||
|
||||
tx->client = gbinder_client_ref(self);
|
||||
tx->reply = reply;
|
||||
tx->destroy = destroy;
|
||||
tx->user_data = user_data;
|
||||
if (G_LIKELY(!obj->dead)) {
|
||||
if (!req) {
|
||||
const GBinderClientIfaceRange* r = gbinder_client_find_range
|
||||
(gbinder_client_cast(self), code);
|
||||
|
||||
if (!req) {
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
req = gbinder_client_cast(self)->basic_req;
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
if (r) {
|
||||
req = r->basic_req;
|
||||
}
|
||||
}
|
||||
if (req) {
|
||||
GBinderClientTx* tx = g_slice_new0(GBinderClientTx);
|
||||
|
||||
tx->client = gbinder_client_ref(self);
|
||||
tx->reply = reply;
|
||||
tx->destroy = destroy;
|
||||
tx->user_data = user_data;
|
||||
return gbinder_ipc_transact(obj->ipc, obj->handle, code,
|
||||
flags, req, gbinder_client_transact_reply,
|
||||
gbinder_client_transact_destroy, tx);
|
||||
} else {
|
||||
GWARN("Unable to build empty request for tx code %u", code);
|
||||
}
|
||||
} else {
|
||||
GDEBUG("Refusing to perform transaction with a dead object");
|
||||
}
|
||||
|
||||
return gbinder_ipc_transact(obj->ipc, obj->handle, code, flags, req,
|
||||
gbinder_client_transact_reply, gbinder_client_transact_destroy, tx);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -38,10 +38,27 @@
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
struct gbinder_client {
|
||||
const char* iface;
|
||||
GBinderRemoteObject* remote;
|
||||
};
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_client_transact_sync_reply2(
|
||||
GBinderClient* self,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
int* status,
|
||||
const GBinderIpcSyncApi* api)
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_client_transact_sync_oneway2(
|
||||
GBinderClient* self,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
const GBinderIpcSyncApi* api)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#define gbinder_client_ipc(client) ((client)->remote->ipc)
|
||||
|
||||
#endif /* GBINDER_CLIENT_PRIVATE_H */
|
||||
|
||||
429
src/gbinder_config.c
Normal file
429
src/gbinder_config.c
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Jolla Ltd.
|
||||
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_eventloop_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* The contents of the config file is queried from (at least) two places,
|
||||
* and pretty much always this happens the same stack. Which means that
|
||||
* we can avoid reading the same file twice if we delay dereferencing of
|
||||
* GKeyFile until the next idle loop.
|
||||
*/
|
||||
|
||||
static GKeyFile* gbinder_config_keyfile = NULL;
|
||||
static GBinderEventLoopCallback* gbinder_config_autorelease = NULL;
|
||||
|
||||
static const char gbinder_config_suffix[] = ".conf";
|
||||
static const char gbinder_config_default_file[] = "/etc/gbinder.conf";
|
||||
static const char gbinder_config_default_dir[] = "/etc/gbinder.d";
|
||||
|
||||
const char* gbinder_config_file = gbinder_config_default_file;
|
||||
const char* gbinder_config_dir = gbinder_config_default_dir;
|
||||
|
||||
/*
|
||||
* Presets for particular API level can be chosen with ApiLevel
|
||||
* setting, e.g.
|
||||
*
|
||||
* [General]
|
||||
* ApiLevel=29
|
||||
*
|
||||
*/
|
||||
|
||||
static const char CONF_GENERAL[] = "General";
|
||||
static const char CONG_API_LEVEL[] = "ApiLevel";
|
||||
|
||||
typedef struct gbinder_config_preset_entry {
|
||||
const char* key;
|
||||
const char* value;
|
||||
} GBinderConfigPresetEntry;
|
||||
|
||||
typedef struct gbinder_config_preset_group {
|
||||
const char* name;
|
||||
const GBinderConfigPresetEntry* entries;
|
||||
} GBinderConfigPresetGroup;
|
||||
|
||||
typedef struct gbinder_config_preset {
|
||||
guint api_level;
|
||||
const GBinderConfigPresetGroup* groups;
|
||||
} GBinderConfigPreset;
|
||||
|
||||
/* API level 28 */
|
||||
|
||||
static const GBinderConfigPresetEntry gbinder_config_28_servicemanager[] = {
|
||||
{ "/dev/binder", "aidl2" },
|
||||
{ "/dev/vndbinder", "aidl2" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const GBinderConfigPresetGroup gbinder_config_28[] = {
|
||||
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_28_servicemanager },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* API level 29 */
|
||||
|
||||
static const GBinderConfigPresetEntry gbinder_config_29_protocol[] = {
|
||||
{ "/dev/binder", "aidl2" },
|
||||
{ "/dev/vndbinder", "aidl2" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
#define gbinder_config_29_servicemanager gbinder_config_28_servicemanager
|
||||
|
||||
static const GBinderConfigPresetGroup gbinder_config_29[] = {
|
||||
{ GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_29_protocol },
|
||||
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_29_servicemanager },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* API level 30 */
|
||||
|
||||
static const GBinderConfigPresetEntry gbinder_config_30_protocol[] = {
|
||||
{ "/dev/binder", "aidl3" },
|
||||
{ "/dev/vndbinder", "aidl3" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const GBinderConfigPresetEntry gbinder_config_30_servicemanager[] = {
|
||||
{ "/dev/binder", "aidl3" },
|
||||
{ "/dev/vndbinder", "aidl3" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const GBinderConfigPresetGroup gbinder_config_30[] = {
|
||||
{ GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
|
||||
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* API level 31 */
|
||||
|
||||
static const GBinderConfigPresetEntry gbinder_config_31_protocol[] = {
|
||||
{ "/dev/binder", "aidl4" },
|
||||
{ "/dev/vndbinder", "aidl4" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const GBinderConfigPresetGroup gbinder_config_31[] = {
|
||||
{ GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_31_protocol },
|
||||
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* API level 33 - reverts back to AIDL3 protocol */
|
||||
|
||||
static const GBinderConfigPresetGroup gbinder_config_33[] = {
|
||||
{ GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
|
||||
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_30_servicemanager },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Presets sorted by API level in descending order */
|
||||
|
||||
static const GBinderConfigPreset gbinder_config_presets[] = {
|
||||
{ 33, gbinder_config_33 },
|
||||
{ 31, gbinder_config_31 },
|
||||
{ 30, gbinder_config_30 },
|
||||
{ 29, gbinder_config_29 },
|
||||
{ 28, gbinder_config_28 }
|
||||
};
|
||||
|
||||
static
|
||||
char**
|
||||
gbinder_config_collect_files(
|
||||
const char* path,
|
||||
const char* suffix)
|
||||
{
|
||||
/*
|
||||
* Returns sorted list of regular files in the directory,
|
||||
* optionally having the specified suffix (e.g. ".conf").
|
||||
* Returns NULL if nothing appropriate has been found.
|
||||
*/
|
||||
char** files = NULL;
|
||||
|
||||
if (path) {
|
||||
GDir* dir = g_dir_open(path, 0, NULL);
|
||||
|
||||
if (dir) {
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
const gchar* name;
|
||||
|
||||
while ((name = g_dir_read_name(dir)) != NULL) {
|
||||
if (g_str_has_suffix(name, suffix)) {
|
||||
char* fullname = g_build_filename(path, name, NULL);
|
||||
struct stat st;
|
||||
|
||||
if (!stat(fullname, &st) && S_ISREG(st.st_mode)) {
|
||||
g_ptr_array_add(list, fullname);
|
||||
} else {
|
||||
g_free(fullname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list->len > 0) {
|
||||
g_ptr_array_add(list, NULL);
|
||||
files = (char**) g_ptr_array_free(list, FALSE);
|
||||
gutil_strv_sort(files, TRUE);
|
||||
} else {
|
||||
g_ptr_array_free(list, TRUE);
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
static
|
||||
GKeyFile*
|
||||
gbinder_config_merge_keyfiles(
|
||||
GKeyFile* dest,
|
||||
GKeyFile* src)
|
||||
{
|
||||
gsize i, ngroups;
|
||||
gchar** groups = g_key_file_get_groups(src, &ngroups);
|
||||
|
||||
for (i = 0; i < ngroups; i++) {
|
||||
gsize k, nkeys;
|
||||
const char* group = groups[i];
|
||||
char** keys = g_key_file_get_keys(src, group, &nkeys, NULL);
|
||||
|
||||
for (k = 0; k < nkeys; k++) {
|
||||
const char* key = keys[k];
|
||||
char* value = g_key_file_get_value(src, group, key, NULL);
|
||||
|
||||
g_key_file_set_value(dest, group, key, value);
|
||||
g_free(value);
|
||||
}
|
||||
|
||||
g_strfreev(keys);
|
||||
}
|
||||
|
||||
g_strfreev(groups);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_config_apply_presets(
|
||||
GKeyFile* config,
|
||||
const GBinderConfigPreset* preset)
|
||||
{
|
||||
const GBinderConfigPresetGroup* g;
|
||||
|
||||
GDEBUG("Applying presets for API level %d", preset->api_level);
|
||||
for (g = preset->groups; g->name; g++) {
|
||||
const GBinderConfigPresetEntry* e;
|
||||
|
||||
for (e = g->entries; e->key; e++) {
|
||||
if (!g_key_file_has_key(config, g->name, e->key, NULL)) {
|
||||
g_key_file_set_value(config, g->name, e->key, e->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GKeyFile*
|
||||
gbinder_config_load_files()
|
||||
{
|
||||
GError* error = NULL;
|
||||
GKeyFile* out = NULL;
|
||||
char** files = gbinder_config_collect_files(gbinder_config_dir,
|
||||
gbinder_config_suffix);
|
||||
|
||||
if (gbinder_config_file &&
|
||||
g_file_test(gbinder_config_file, G_FILE_TEST_EXISTS)) {
|
||||
out = g_key_file_new();
|
||||
if (g_key_file_load_from_file(out, gbinder_config_file,
|
||||
G_KEY_FILE_NONE, &error)) {
|
||||
GDEBUG("Loaded %s", gbinder_config_file);
|
||||
} else {
|
||||
GERR("Error loading %s: %s", gbinder_config_file, error->message);
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
gbinder_config_file = NULL; /* Don't retry */
|
||||
g_key_file_unref(out);
|
||||
out = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Files in the config directory overwrite /etc/gbinder.conf */
|
||||
if (files) {
|
||||
char** ptr;
|
||||
GKeyFile* override = NULL;
|
||||
|
||||
for (ptr = files; *ptr; ptr++) {
|
||||
const char* file = *ptr;
|
||||
|
||||
if (!override) {
|
||||
override = g_key_file_new();
|
||||
}
|
||||
if (g_key_file_load_from_file(override, file,
|
||||
G_KEY_FILE_NONE, &error)) {
|
||||
GDEBUG("Loaded %s", file);
|
||||
if (!out) {
|
||||
out = override;
|
||||
override = NULL;
|
||||
} else {
|
||||
out = gbinder_config_merge_keyfiles(out, override);
|
||||
}
|
||||
} else {
|
||||
GERR("Error loading %s: %s", file, error->message);
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev(files);
|
||||
if (override) {
|
||||
g_key_file_unref(override);
|
||||
}
|
||||
}
|
||||
|
||||
if (out) {
|
||||
/* Apply presets */
|
||||
const int api_level = g_key_file_get_integer(out,
|
||||
CONF_GENERAL, CONG_API_LEVEL, NULL);
|
||||
|
||||
if (api_level > 0) {
|
||||
int i;
|
||||
|
||||
GDEBUG("API level %d", api_level);
|
||||
for (i = 0; i < G_N_ELEMENTS(gbinder_config_presets); i++) {
|
||||
const GBinderConfigPreset* preset = gbinder_config_presets + i;
|
||||
|
||||
if (api_level >= preset->api_level) {
|
||||
gbinder_config_apply_presets(out, preset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_config_autorelease_cb(
|
||||
gpointer data)
|
||||
{
|
||||
GASSERT(gbinder_config_keyfile == data);
|
||||
gbinder_config_keyfile = NULL;
|
||||
g_key_file_unref(data);
|
||||
}
|
||||
|
||||
GKeyFile* /* autoreleased */
|
||||
gbinder_config_get()
|
||||
{
|
||||
if (!gbinder_config_keyfile &&
|
||||
(gbinder_config_file || gbinder_config_dir)) {
|
||||
gbinder_config_keyfile = gbinder_config_load_files();
|
||||
if (gbinder_config_keyfile) {
|
||||
/* See the comment at the top of the file why this is needed */
|
||||
gbinder_config_autorelease = gbinder_idle_callback_schedule_new
|
||||
(gbinder_config_autorelease_cb, gbinder_config_keyfile, NULL);
|
||||
}
|
||||
}
|
||||
return gbinder_config_keyfile;
|
||||
}
|
||||
|
||||
/* Helper for loading config group in device = ident format */
|
||||
GHashTable*
|
||||
gbinder_config_load(
|
||||
const char* group,
|
||||
GBinderConfigValueMapFunc mapper)
|
||||
{
|
||||
GKeyFile* k = gbinder_config_get();
|
||||
GHashTable* map = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
if (k) {
|
||||
gsize n;
|
||||
char** devs = g_key_file_get_keys(k, group, &n, NULL);
|
||||
|
||||
if (devs) {
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
char* dev = devs[i];
|
||||
char* sval = g_key_file_get_value(k, group, dev, NULL);
|
||||
gconstpointer val = mapper(sval);
|
||||
|
||||
if (val) {
|
||||
g_hash_table_replace(map, dev, (gpointer) val);
|
||||
} else {
|
||||
GWARN("Unknown gbinder config '%s' for %s in group [%s]",
|
||||
sval, dev, group);
|
||||
g_free(dev);
|
||||
}
|
||||
g_free(sval);
|
||||
}
|
||||
|
||||
/* Shallow delete (contents got stolen or freed) */
|
||||
g_free(devs);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_config_exit()
|
||||
{
|
||||
if (gbinder_config_autorelease) {
|
||||
gbinder_idle_callback_destroy(gbinder_config_autorelease);
|
||||
gbinder_config_autorelease = NULL;
|
||||
}
|
||||
if (gbinder_config_keyfile) {
|
||||
g_key_file_unref(gbinder_config_keyfile);
|
||||
gbinder_config_keyfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
78
src/gbinder_config.h
Normal file
78
src/gbinder_config.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Jolla Ltd.
|
||||
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_CONFIG_H
|
||||
#define GBINDER_CONFIG_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef
|
||||
gconstpointer
|
||||
(*GBinderConfigValueMapFunc)(
|
||||
const char* value);
|
||||
|
||||
GHashTable*
|
||||
gbinder_config_load(
|
||||
const char* group,
|
||||
GBinderConfigValueMapFunc map)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GKeyFile* /* autoreleased */
|
||||
gbinder_config_get(
|
||||
void)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* This one declared strictly for unit tests */
|
||||
void
|
||||
gbinder_config_exit(
|
||||
void)
|
||||
GBINDER_INTERNAL
|
||||
GBINDER_DESTRUCTOR;
|
||||
|
||||
/* And these too */
|
||||
extern const char* gbinder_config_file GBINDER_INTERNAL;
|
||||
extern const char* gbinder_config_dir GBINDER_INTERNAL;
|
||||
|
||||
/* Configuration groups and special value */
|
||||
#define GBINDER_CONFIG_GROUP_PROTOCOL "Protocol"
|
||||
#define GBINDER_CONFIG_GROUP_SERVICEMANAGER "ServiceManager"
|
||||
#define GBINDER_CONFIG_VALUE_DEFAULT "Default"
|
||||
|
||||
#endif /* GBINDER_CONFIG_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,325 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_servicepoll.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct gbinder_defaultservicemanager_watch {
|
||||
GBinderServicePoll* poll;
|
||||
char* name;
|
||||
gulong handler_id;
|
||||
guint notify_id;
|
||||
} GBinderDefaultServiceManagerWatch;
|
||||
|
||||
typedef GBinderServiceManagerClass GBinderDefaultServiceManagerClass;
|
||||
typedef struct gbinder_defaultservicemanager {
|
||||
GBinderServiceManager manager;
|
||||
GBinderServicePoll* poll;
|
||||
GHashTable* watch_table;
|
||||
} GBinderDefaultServiceManager;
|
||||
|
||||
G_DEFINE_TYPE(GBinderDefaultServiceManager,
|
||||
gbinder_defaultservicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define PARENT_CLASS gbinder_defaultservicemanager_parent_class
|
||||
#define GBINDER_TYPE_DEFAULTSERVICEMANAGER \
|
||||
gbinder_defaultservicemanager_get_type()
|
||||
#define GBINDER_DEFAULTSERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_DEFAULTSERVICEMANAGER, \
|
||||
GBinderDefaultServiceManager)
|
||||
|
||||
enum gbinder_defaultservicemanager_calls {
|
||||
GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
CHECK_SERVICE_TRANSACTION,
|
||||
ADD_SERVICE_TRANSACTION,
|
||||
LIST_SERVICES_TRANSACTION
|
||||
};
|
||||
|
||||
/* As a special case, ServiceManager's handle is zero */
|
||||
#define DEFAULTSERVICEMANAGER_HANDLE (0)
|
||||
#define DEFAULTSERVICEMANAGER_IFACE "android.os.IServiceManager"
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_defaultservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(GBINDER_TYPE_DEFAULTSERVICEMANAGER, dev);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_watch_proc(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name_added,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch = user_data;
|
||||
|
||||
if (!g_strcmp0(name_added, watch->name)) {
|
||||
GBinderServiceManager* manager =
|
||||
gbinder_servicepoll_manager(watch->poll);
|
||||
|
||||
if (watch->notify_id) {
|
||||
g_source_remove(watch->notify_id);
|
||||
watch->notify_id = 0;
|
||||
}
|
||||
gbinder_servicemanager_service_registered(manager, name_added);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_defaultservicemanager_watch_notify(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch = user_data;
|
||||
GBinderServiceManager* manager = gbinder_servicepoll_manager(watch->poll);
|
||||
char* name = g_strdup(watch->name);
|
||||
|
||||
GASSERT(watch->notify_id);
|
||||
watch->notify_id = 0;
|
||||
gbinder_servicemanager_service_registered(manager, name);
|
||||
g_free(name);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_watch_free(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch = user_data;
|
||||
|
||||
if (watch->notify_id) {
|
||||
g_source_remove(watch->notify_id);
|
||||
}
|
||||
gbinder_servicepoll_remove_handler(watch->poll, watch->handler_id);
|
||||
gbinder_servicepoll_unref(watch->poll);
|
||||
g_free(watch->name);
|
||||
g_slice_free(GBinderDefaultServiceManagerWatch, watch);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderDefaultServiceManagerWatch*
|
||||
gbinder_defaultservicemanager_watch_new(
|
||||
GBinderDefaultServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch =
|
||||
g_slice_new0(GBinderDefaultServiceManagerWatch);
|
||||
|
||||
watch->name = g_strdup(name);
|
||||
watch->poll = gbinder_servicepoll_new(&manager->manager, &manager->poll);
|
||||
watch->handler_id = gbinder_servicepoll_add_handler(watch->poll,
|
||||
gbinder_defaultservicemanager_watch_proc, watch);
|
||||
return watch;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_list_services_req(
|
||||
GBinderServiceManager* self,
|
||||
gint32 index)
|
||||
{
|
||||
return gbinder_local_request_append_int32
|
||||
(gbinder_client_new_request(self->client), index);
|
||||
}
|
||||
|
||||
static
|
||||
char**
|
||||
gbinder_defaultservicemanager_list(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
GBinderLocalRequest* req = gbinder_servicemanager_list_services_req(self,0);
|
||||
GBinderRemoteReply* reply;
|
||||
|
||||
while ((reply = gbinder_client_transact_sync_reply(self->client,
|
||||
LIST_SERVICES_TRANSACTION, req, NULL)) != NULL) {
|
||||
char* service = gbinder_remote_reply_read_string16(reply);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
if (service) {
|
||||
g_ptr_array_add(list, service);
|
||||
gbinder_local_request_unref(req);
|
||||
req = gbinder_servicemanager_list_services_req(self, list->len);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
g_ptr_array_add(list, NULL);
|
||||
return (char**)g_ptr_array_free(list, FALSE);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderRemoteObject*
|
||||
gbinder_defaultservicemanager_get_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
int* status)
|
||||
{
|
||||
GBinderRemoteObject* obj;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
CHECK_SERVICE_TRANSACTION, req, status);
|
||||
|
||||
obj = gbinder_remote_reply_read_object(reply);
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
gbinder_defaultservicemanager_add_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
int status;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
gbinder_local_request_append_int32(req, 0);
|
||||
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
ADD_SERVICE_TRANSACTION, req, &status);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
gbinder_defaultservicemanager_check_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
return GBINDER_SERVICEMANAGER_NAME_OK;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_defaultservicemanager_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderDefaultServiceManager* self = GBINDER_DEFAULTSERVICEMANAGER(manager);
|
||||
GBinderDefaultServiceManagerWatch* watch =
|
||||
gbinder_defaultservicemanager_watch_new(self, name);
|
||||
|
||||
g_hash_table_replace(self->watch_table, watch->name, watch);
|
||||
if (gbinder_servicepoll_is_known_name(watch->poll, name)) {
|
||||
watch->notify_id =
|
||||
g_idle_add(gbinder_defaultservicemanager_watch_notify, watch);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_unwatch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
g_hash_table_remove(GBINDER_DEFAULTSERVICEMANAGER(manager)->watch_table,
|
||||
name);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_init(
|
||||
GBinderDefaultServiceManager* self)
|
||||
{
|
||||
self->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
NULL, gbinder_defaultservicemanager_watch_free);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderDefaultServiceManager* self = GBINDER_DEFAULTSERVICEMANAGER(object);
|
||||
|
||||
g_hash_table_destroy(self->watch_table);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_class_init(
|
||||
GBinderDefaultServiceManagerClass* klass)
|
||||
{
|
||||
klass->handle = DEFAULTSERVICEMANAGER_HANDLE;
|
||||
klass->iface = DEFAULTSERVICEMANAGER_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_BINDER;
|
||||
klass->rpc_protocol = &gbinder_rpc_protocol_binder;
|
||||
|
||||
klass->list = gbinder_defaultservicemanager_list;
|
||||
klass->get_service = gbinder_defaultservicemanager_get_service;
|
||||
klass->add_service = gbinder_defaultservicemanager_add_service;
|
||||
klass->check_name = gbinder_defaultservicemanager_check_name;
|
||||
/* normalize_name is not needed */
|
||||
klass->watch = gbinder_defaultservicemanager_watch;
|
||||
klass->unwatch = gbinder_defaultservicemanager_unwatch;
|
||||
G_OBJECT_CLASS(klass)->finalize = gbinder_defaultservicemanager_finalize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -40,101 +40,149 @@ struct pollfd;
|
||||
GBinderDriver*
|
||||
gbinder_driver_new(
|
||||
const char* dev,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
const GBinderRpcProtocol* protocol)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_driver_ref(
|
||||
GBinderDriver* driver);
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_driver_unref(
|
||||
GBinderDriver* driver);
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_driver_close(
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_driver_fd(
|
||||
GBinderDriver* driver);
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_driver_poll(
|
||||
GBinderDriver* driver,
|
||||
struct pollfd* pollfd);
|
||||
struct pollfd* pollfd)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const char*
|
||||
gbinder_driver_dev(
|
||||
GBinderDriver* driver);
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const GBinderIo*
|
||||
gbinder_driver_io(
|
||||
GBinderDriver* driver);
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_driver_protocol(
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_acquire_done(
|
||||
GBinderDriver* driver,
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_dead_binder_done(
|
||||
GBinderDriver* driver,
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_request_death_notification(
|
||||
GBinderDriver* driver,
|
||||
GBinderRemoteObject* obj);
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_clear_death_notification(
|
||||
GBinderDriver* driver,
|
||||
GBinderRemoteObject* obj);
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_increfs(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
guint32 handle)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_decrefs(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
guint32 handle)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_acquire(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
guint32 handle)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_release(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
guint32 handle)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_driver_close_fds(
|
||||
GBinderDriver* self,
|
||||
GBinderDriver* driver,
|
||||
void** objects,
|
||||
const void* end);
|
||||
const void* end)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_driver_free_buffer(
|
||||
GBinderDriver* driver,
|
||||
void* buffer);
|
||||
void* buffer)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_enter_looper(
|
||||
GBinderDriver* driver);
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_driver_exit_looper(
|
||||
GBinderDriver* driver);
|
||||
GBinderDriver* driver)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_driver_read(
|
||||
GBinderDriver* driver,
|
||||
GBinderObjectRegistry* reg,
|
||||
GBinderHandler* handler);
|
||||
GBinderHandler* handler)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_driver_transact(
|
||||
GBinderDriver* driver,
|
||||
GBinderObjectRegistry* reg,
|
||||
GBinderHandler* handler,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* request,
|
||||
GBinderRemoteReply* reply);
|
||||
GBinderRemoteReply* reply)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_driver_local_request_new(
|
||||
GBinderDriver* self,
|
||||
const char* iface);
|
||||
GBinderDriver* driver,
|
||||
const char* iface)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_driver_local_request_new_ping(
|
||||
GBinderDriver* self)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_DRIVER_H */
|
||||
|
||||
|
||||
405
src/gbinder_eventloop.c
Normal file
405
src/gbinder_eventloop.c
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Jolla Ltd.
|
||||
* Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_eventloop_p.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
typedef struct gbinder_idle_callback_data {
|
||||
GBinderEventLoopCallback* cb;
|
||||
GBinderEventLoopCallbackFunc func;
|
||||
GDestroyNotify destroy;
|
||||
gpointer data;
|
||||
} GBinderIdleCallbackData;
|
||||
|
||||
#define GBINDER_DEFAULT_EVENTLOOP (&gbinder_eventloop_glib)
|
||||
|
||||
static const GBinderEventLoopIntegration gbinder_eventloop_glib;
|
||||
|
||||
/*==========================================================================*
|
||||
* GLib event loop integration
|
||||
*==========================================================================*/
|
||||
|
||||
typedef struct gbinder_eventloop_glib_timeout {
|
||||
GBinderEventLoopTimeout timeout;
|
||||
guint id;
|
||||
GSourceFunc func;
|
||||
gpointer data;
|
||||
} GBinderEventLoopTimeoutGLib;
|
||||
|
||||
typedef struct gbinder_eventloop_glib_callback {
|
||||
GSource source;
|
||||
GBinderEventLoopCallback callback;
|
||||
} GBinderEventLoopCallbackGLib;
|
||||
|
||||
static
|
||||
inline
|
||||
GBinderEventLoopTimeoutGLib*
|
||||
gbinder_eventloop_glib_timeout_cast(
|
||||
GBinderEventLoopTimeout* timeout)
|
||||
{
|
||||
return G_CAST(timeout,GBinderEventLoopTimeoutGLib,timeout);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
GSource*
|
||||
gbinder_eventloop_glib_callback_source(
|
||||
GBinderEventLoopCallback* callback)
|
||||
{
|
||||
return &(G_CAST(callback,GBinderEventLoopCallbackGLib,callback)->source);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_eventloop_glib_timeout_callback(
|
||||
gpointer data)
|
||||
{
|
||||
GBinderEventLoopTimeoutGLib* timeout = data;
|
||||
|
||||
return timeout->func(timeout->data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_eventloop_glib_timeout_finalize(
|
||||
gpointer data)
|
||||
{
|
||||
g_slice_free1(sizeof(GBinderEventLoopTimeoutGLib), data);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderEventLoopTimeout*
|
||||
gbinder_eventloop_glib_timeout_add(
|
||||
guint interval,
|
||||
GSourceFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
GBinderEventLoopTimeoutGLib* impl =
|
||||
g_slice_new(GBinderEventLoopTimeoutGLib);
|
||||
|
||||
impl->timeout.eventloop = &gbinder_eventloop_glib;
|
||||
impl->func = func;
|
||||
impl->data = data;
|
||||
impl->id = g_timeout_add_full(G_PRIORITY_DEFAULT, interval,
|
||||
gbinder_eventloop_glib_timeout_callback, impl,
|
||||
gbinder_eventloop_glib_timeout_finalize);
|
||||
return &impl->timeout;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_eventloop_glib_timeout_remove(
|
||||
GBinderEventLoopTimeout* timeout)
|
||||
{
|
||||
g_source_remove(gbinder_eventloop_glib_timeout_cast(timeout)->id);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_eventloop_glib_callback_prepare(
|
||||
GSource* source,
|
||||
gint* timeout)
|
||||
{
|
||||
*timeout = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_eventloop_glib_callback_check(
|
||||
GSource* source)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_eventloop_glib_callback_dispatch(
|
||||
GSource* source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
((GBinderEventLoopCallbackFunc)callback)(user_data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderEventLoopCallback*
|
||||
gbinder_eventloop_glib_callback_new(
|
||||
GBinderEventLoopCallbackFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify finalize)
|
||||
{
|
||||
static GSourceFuncs callback_funcs = {
|
||||
gbinder_eventloop_glib_callback_prepare,
|
||||
gbinder_eventloop_glib_callback_check,
|
||||
gbinder_eventloop_glib_callback_dispatch
|
||||
};
|
||||
|
||||
GBinderEventLoopCallbackGLib* impl = (GBinderEventLoopCallbackGLib*)
|
||||
g_source_new(&callback_funcs, sizeof(GBinderEventLoopCallbackGLib));
|
||||
|
||||
impl->callback.eventloop = &gbinder_eventloop_glib;
|
||||
g_source_set_callback(&impl->source, (GSourceFunc) func, data, finalize);
|
||||
return &impl->callback;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_eventloop_glib_callback_ref(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
g_source_ref(gbinder_eventloop_glib_callback_source(cb));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_eventloop_glib_callback_unref(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
g_source_unref(gbinder_eventloop_glib_callback_source(cb));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_eventloop_glib_callback_schedule(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
static GMainContext* context = NULL;
|
||||
|
||||
if (!context) context = g_main_context_default();
|
||||
g_source_attach(gbinder_eventloop_glib_callback_source(cb), context);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_eventloop_glib_callback_cancel(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
g_source_destroy(gbinder_eventloop_glib_callback_source(cb));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_eventloop_glib_cleanup(
|
||||
void)
|
||||
{
|
||||
}
|
||||
|
||||
static const GBinderEventLoopIntegration gbinder_eventloop_glib = {
|
||||
gbinder_eventloop_glib_timeout_add,
|
||||
gbinder_eventloop_glib_timeout_remove,
|
||||
gbinder_eventloop_glib_callback_new,
|
||||
gbinder_eventloop_glib_callback_ref,
|
||||
gbinder_eventloop_glib_callback_unref,
|
||||
gbinder_eventloop_glib_callback_schedule,
|
||||
gbinder_eventloop_glib_callback_cancel,
|
||||
gbinder_eventloop_glib_cleanup
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_idle_callback_invoke_proc(
|
||||
void* user_data)
|
||||
{
|
||||
GBinderIdleCallbackData* idle = user_data;
|
||||
|
||||
if (idle->func) {
|
||||
idle->func(idle->data);
|
||||
}
|
||||
gbinder_idle_callback_unref(idle->cb);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_idle_callback_invoke_done(
|
||||
void* user_data)
|
||||
{
|
||||
GBinderIdleCallbackData* idle = user_data;
|
||||
|
||||
if (idle->destroy) {
|
||||
idle->destroy(idle->data);
|
||||
}
|
||||
gutil_slice_free(idle);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internal interface
|
||||
*==========================================================================*/
|
||||
|
||||
static const GBinderEventLoopIntegration* gbinder_eventloop =
|
||||
GBINDER_DEFAULT_EVENTLOOP;
|
||||
|
||||
GBinderEventLoopTimeout*
|
||||
gbinder_timeout_add(
|
||||
guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data)
|
||||
{
|
||||
return gbinder_eventloop->timeout_add(interval, function, data);
|
||||
}
|
||||
|
||||
GBinderEventLoopTimeout*
|
||||
gbinder_idle_add(
|
||||
GSourceFunc function,
|
||||
gpointer data)
|
||||
{
|
||||
return gbinder_eventloop->timeout_add(0, function, data);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_timeout_remove(
|
||||
GBinderEventLoopTimeout* timeout)
|
||||
{
|
||||
if (timeout) {
|
||||
timeout->eventloop->timeout_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderEventLoopCallback*
|
||||
gbinder_idle_callback_new(
|
||||
GBinderEventLoopCallbackFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify finalize)
|
||||
{
|
||||
return gbinder_eventloop->callback_new(func, data, finalize);
|
||||
}
|
||||
|
||||
GBinderEventLoopCallback*
|
||||
gbinder_idle_callback_schedule_new(
|
||||
GBinderEventLoopCallbackFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify finalize)
|
||||
{
|
||||
GBinderEventLoopCallback* cb =
|
||||
gbinder_eventloop->callback_new(func, data, finalize);
|
||||
|
||||
gbinder_idle_callback_schedule(cb);
|
||||
return cb;
|
||||
}
|
||||
|
||||
GBinderEventLoopCallback*
|
||||
gbinder_idle_callback_ref(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
if (cb) {
|
||||
cb->eventloop->callback_ref(cb);
|
||||
return cb;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_idle_callback_unref(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
if (cb) {
|
||||
cb->eventloop->callback_unref(cb);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_idle_callback_schedule(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
if (cb) {
|
||||
cb->eventloop->callback_schedule(cb);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_idle_callback_cancel(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
if (cb) {
|
||||
cb->eventloop->callback_cancel(cb);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_idle_callback_destroy(
|
||||
GBinderEventLoopCallback* cb)
|
||||
{
|
||||
if (cb) {
|
||||
const GBinderEventLoopIntegration* eventloop = cb->eventloop;
|
||||
|
||||
eventloop->callback_cancel(cb);
|
||||
eventloop->callback_unref(cb);
|
||||
}
|
||||
}
|
||||
|
||||
/* Non-cancellable callback */
|
||||
void
|
||||
gbinder_idle_callback_invoke_later(
|
||||
GBinderEventLoopCallbackFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
GBinderIdleCallbackData* idle = g_slice_new(GBinderIdleCallbackData);
|
||||
|
||||
idle->func = func;
|
||||
idle->data = data;
|
||||
idle->destroy = destroy;
|
||||
idle->cb = gbinder_idle_callback_new(gbinder_idle_callback_invoke_proc,
|
||||
idle, gbinder_idle_callback_invoke_done);
|
||||
gbinder_idle_callback_schedule(idle->cb);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Public interface
|
||||
*==========================================================================*/
|
||||
|
||||
void
|
||||
gbinder_eventloop_set(
|
||||
const GBinderEventLoopIntegration* loop)
|
||||
{
|
||||
if (!loop) loop = GBINDER_DEFAULT_EVENTLOOP;
|
||||
if (gbinder_eventloop != loop) {
|
||||
const GBinderEventLoopIntegration* prev = gbinder_eventloop;
|
||||
|
||||
gbinder_eventloop = loop;
|
||||
prev->cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
115
src/gbinder_eventloop_p.h
Normal file
115
src/gbinder_eventloop_p.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Jolla Ltd.
|
||||
* Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_EVENTLOOP_PRIVATE_H
|
||||
#define GBINDER_EVENTLOOP_PRIVATE_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
#include "gbinder_eventloop.h"
|
||||
|
||||
GBinderEventLoopTimeout*
|
||||
gbinder_timeout_add(
|
||||
guint millis,
|
||||
GSourceFunc func,
|
||||
gpointer data)
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderEventLoopTimeout*
|
||||
gbinder_idle_add(
|
||||
GSourceFunc func,
|
||||
gpointer data)
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_timeout_remove(
|
||||
GBinderEventLoopTimeout* timeout)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderEventLoopCallback*
|
||||
gbinder_idle_callback_new(
|
||||
GBinderEventLoopCallbackFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy)
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderEventLoopCallback*
|
||||
gbinder_idle_callback_schedule_new(
|
||||
GBinderEventLoopCallbackFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy)
|
||||
G_GNUC_WARN_UNUSED_RESULT
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderEventLoopCallback*
|
||||
gbinder_idle_callback_ref(
|
||||
GBinderEventLoopCallback* cb)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_idle_callback_unref(
|
||||
GBinderEventLoopCallback* cb)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_idle_callback_schedule(
|
||||
GBinderEventLoopCallback* cb)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_idle_callback_cancel(
|
||||
GBinderEventLoopCallback* cb)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_idle_callback_destroy(
|
||||
GBinderEventLoopCallback* cb)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_idle_callback_invoke_later(
|
||||
GBinderEventLoopCallbackFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_EVENTLOOP_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
699
src/gbinder_fmq.c
Normal file
699
src/gbinder_fmq.c
Normal file
@@ -0,0 +1,699 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_fmq_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/futex.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if GBINDER_FMQ_SUPPORTED
|
||||
|
||||
/* Grantor data positions */
|
||||
enum {
|
||||
READ_PTR_POS = 0,
|
||||
WRITE_PTR_POS,
|
||||
DATA_PTR_POS,
|
||||
EVENT_FLAG_PTR_POS
|
||||
};
|
||||
|
||||
typedef struct gbinder_fmq {
|
||||
GBinderMQDescriptor* desc;
|
||||
guint8* ring;
|
||||
guint64* read_ptr;
|
||||
guint64* write_ptr;
|
||||
guint32* event_flag_ptr;
|
||||
guint32 refcount;
|
||||
} GBinderFmq;
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderFmqGrantorDescriptor*
|
||||
gbinder_fmq_get_grantor_descriptor(
|
||||
GBinderFmq* self,
|
||||
gint index)
|
||||
{
|
||||
return (GBinderFmqGrantorDescriptor*)(self->desc->grantors.data.ptr) +
|
||||
index;
|
||||
}
|
||||
|
||||
static
|
||||
gsize
|
||||
gbinder_fmq_available_to_read_bytes(
|
||||
GBinderFmq* self,
|
||||
gboolean contiguous)
|
||||
{
|
||||
const guint64 read_ptr = __atomic_load_n(self->read_ptr, __ATOMIC_ACQUIRE);
|
||||
const gsize available_total = __atomic_load_n(self->write_ptr,
|
||||
__ATOMIC_ACQUIRE) - read_ptr;
|
||||
|
||||
if (contiguous) {
|
||||
/*
|
||||
* The number of bytes that can be read contiguously from
|
||||
* read offset without wrapping around the ring buffer.
|
||||
*/
|
||||
const gsize size = gbinder_fmq_get_grantor_descriptor(self,
|
||||
DATA_PTR_POS)->extent;
|
||||
const gsize available_contiguous = size - (read_ptr % size);
|
||||
|
||||
return (available_contiguous < available_total) ?
|
||||
available_contiguous : available_total;
|
||||
} else {
|
||||
return available_total;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gsize
|
||||
gbinder_fmq_available_to_write_bytes(
|
||||
GBinderFmq* self,
|
||||
gboolean contiguous)
|
||||
{
|
||||
const guint32 size = gbinder_fmq_get_grantor_descriptor(self,
|
||||
DATA_PTR_POS)->extent;
|
||||
const gsize available_total = size -
|
||||
gbinder_fmq_available_to_read_bytes(self, FALSE);
|
||||
|
||||
if (contiguous) {
|
||||
/*
|
||||
* The number of bytes that can be written contiguously starting from
|
||||
* write_offset without wrapping around the ring buffer.
|
||||
*/
|
||||
const guint64 write_ptr = __atomic_load_n(self->write_ptr,
|
||||
__ATOMIC_RELAXED);
|
||||
const gsize available_contiguous = size - (write_ptr % size);
|
||||
|
||||
return (available_contiguous < available_total) ?
|
||||
available_contiguous : available_total;
|
||||
} else {
|
||||
return available_total;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderFmqGrantorDescriptor*
|
||||
gbinder_fmq_create_grantors(
|
||||
gsize queue_size_bytes,
|
||||
gsize num_fds,
|
||||
gboolean configure_event_flag)
|
||||
{
|
||||
const gsize num_grantors = configure_event_flag ?
|
||||
(EVENT_FLAG_PTR_POS + 1) : (DATA_PTR_POS + 1);
|
||||
GBinderFmqGrantorDescriptor* grantors =
|
||||
g_new0(GBinderFmqGrantorDescriptor, num_grantors);
|
||||
gsize pos, offset;
|
||||
gsize mem_sizes[] = {
|
||||
sizeof(guint64), /* read pointer counter */
|
||||
sizeof(guint64), /* write pointer counter */
|
||||
queue_size_bytes, /* data buffer */
|
||||
sizeof(guint32) /* event flag pointer */
|
||||
};
|
||||
|
||||
for (pos = 0, offset = 0; pos < num_grantors; pos++) {
|
||||
GBinderFmqGrantorDescriptor* grantor = grantors + pos;
|
||||
guint32 grantor_fd_index;
|
||||
gsize grantor_offset;
|
||||
|
||||
if (pos == DATA_PTR_POS && num_fds == 2) {
|
||||
grantor_fd_index = 1;
|
||||
grantor_offset = 0;
|
||||
} else {
|
||||
grantor_fd_index = 0;
|
||||
grantor_offset = offset;
|
||||
offset += mem_sizes[pos];
|
||||
}
|
||||
grantor->fd_index = grantor_fd_index;
|
||||
grantor->offset = (guint32)G_ALIGN8(grantor_offset);
|
||||
grantor->extent = mem_sizes[pos];
|
||||
}
|
||||
return grantors;
|
||||
}
|
||||
|
||||
static
|
||||
void*
|
||||
gbinder_fmq_map_grantor_descriptor(
|
||||
GBinderFmq* self,
|
||||
guint32 index)
|
||||
{
|
||||
if (index < self->desc->grantors.count) {
|
||||
const GBinderFmqGrantorDescriptor* desc =
|
||||
gbinder_fmq_get_grantor_descriptor(self, index);
|
||||
/* Offset for mmap must be a multiple of PAGE_SIZE */
|
||||
const guint32 map_offset = (desc->offset & ~(getpagesize()-1));
|
||||
const guint32 map_length = desc->offset - map_offset + desc->extent;
|
||||
const GBinderFds* fds = self->desc->data.fds;
|
||||
void* address = mmap(0, map_length, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
gbinder_fds_get_fd(fds, desc->fd_index), map_offset);
|
||||
|
||||
if (address != MAP_FAILED) {
|
||||
return (guint8*)address + (desc->offset - map_offset);
|
||||
} else {
|
||||
GWARN("mmap failed: %d", errno);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_fmq_unmap_grantor_descriptor(
|
||||
GBinderFmq* self,
|
||||
void* address,
|
||||
guint index)
|
||||
{
|
||||
if (index < self->desc->grantors.count && address) {
|
||||
const GBinderFmqGrantorDescriptor* desc =
|
||||
gbinder_fmq_get_grantor_descriptor(self, index);
|
||||
const gsize remainder = desc->offset & (getpagesize() - 1);
|
||||
|
||||
munmap((guint8*)address - remainder, remainder + desc->extent);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_fmq_free(
|
||||
GBinderFmq* self)
|
||||
{
|
||||
if (self->desc) {
|
||||
if (self->desc->flags == GBINDER_FMQ_TYPE_UNSYNC_WRITE) {
|
||||
g_free(self->read_ptr);
|
||||
} else {
|
||||
gbinder_fmq_unmap_grantor_descriptor(self, self->read_ptr,
|
||||
READ_PTR_POS);
|
||||
}
|
||||
gbinder_fmq_unmap_grantor_descriptor(self, self->write_ptr,
|
||||
WRITE_PTR_POS);
|
||||
gbinder_fmq_unmap_grantor_descriptor(self, self->ring,
|
||||
DATA_PTR_POS);
|
||||
gbinder_fmq_unmap_grantor_descriptor(self, self->event_flag_ptr,
|
||||
EVENT_FLAG_PTR_POS);
|
||||
|
||||
g_free((GBinderFmqGrantorDescriptor*)self->desc->grantors.data.ptr);
|
||||
g_free((GBinderFds*)self->desc->data.fds);
|
||||
|
||||
g_free(self->desc);
|
||||
}
|
||||
g_slice_free(GBinderFmq, self);
|
||||
}
|
||||
|
||||
/* Private API */
|
||||
|
||||
GBinderMQDescriptor*
|
||||
gbinder_fmq_get_descriptor(
|
||||
const GBinderFmq* self)
|
||||
{
|
||||
return self->desc;
|
||||
}
|
||||
|
||||
/* Public API */
|
||||
|
||||
GBinderFmq*
|
||||
gbinder_fmq_new(
|
||||
gsize item_size,
|
||||
gsize num_items,
|
||||
GBINDER_FMQ_TYPE type,
|
||||
GBINDER_FMQ_FLAGS flags,
|
||||
gint fd,
|
||||
gsize buffer_size)
|
||||
{
|
||||
if (item_size <= 0) {
|
||||
GWARN("Incorrect item size");
|
||||
} else if (num_items <= 0) {
|
||||
GWARN("Empty queue requested");
|
||||
} else if (num_items > SIZE_MAX / item_size) {
|
||||
GWARN("Requested message queue size too large");
|
||||
} else if (fd != -1 && num_items * item_size > buffer_size) {
|
||||
GWARN("The size needed for items (%"G_GSIZE_FORMAT") is larger "
|
||||
"than the supplied buffer size (%"G_GSIZE_FORMAT")",
|
||||
num_items * item_size, buffer_size);
|
||||
} else {
|
||||
GBinderFmq* self = g_slice_new0(GBinderFmq);
|
||||
gboolean configure_event_flag =
|
||||
(flags & GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG) != 0;
|
||||
gsize queue_size_bytes = num_items * item_size;
|
||||
gsize meta_data_size;
|
||||
gsize shmem_size;
|
||||
int shmem_fd;
|
||||
|
||||
meta_data_size = 2 * sizeof(guint64);
|
||||
if (configure_event_flag) {
|
||||
meta_data_size += sizeof(guint32);
|
||||
}
|
||||
|
||||
/* Allocate shared memory */
|
||||
if (fd != -1) {
|
||||
/* User-supplied ringbuffer memory provided,
|
||||
* allocating memory only for meta data */
|
||||
shmem_size = (meta_data_size + getpagesize() - 1) &
|
||||
~(getpagesize() - 1);
|
||||
} else {
|
||||
/* Allocate ringbuffer, read counter and write counter */
|
||||
shmem_size = (G_ALIGN8(queue_size_bytes) +
|
||||
meta_data_size + getpagesize() - 1) & ~(getpagesize() - 1);
|
||||
}
|
||||
|
||||
shmem_fd = syscall(__NR_memfd_create, "MessageQueue", MFD_CLOEXEC);
|
||||
|
||||
if (shmem_fd >= 0 && ftruncate(shmem_fd, shmem_size) == 0) {
|
||||
GBinderFmqGrantorDescriptor* grantors;
|
||||
gsize num_fds = (fd != -1) ? 2 : 1;
|
||||
gsize fds_size = sizeof(GBinderFds) + sizeof(int) * num_fds;
|
||||
GBinderFds* fds = (GBinderFds*)g_malloc0(fds_size);
|
||||
|
||||
fds->version = fds_size;
|
||||
fds->num_fds = num_fds;
|
||||
|
||||
(((int*)((fds) + 1))[0]) = shmem_fd;
|
||||
|
||||
if (fd != -1) {
|
||||
/* Use user-supplied file descriptor for fd_index 1 */
|
||||
(((int*)((fds) + 1))[1]) = fd;
|
||||
}
|
||||
grantors = gbinder_fmq_create_grantors(queue_size_bytes,
|
||||
num_fds, configure_event_flag);
|
||||
|
||||
/* Fill FMQ descriptor */
|
||||
self->desc = g_new0(GBinderMQDescriptor, 1);
|
||||
self->desc->data.fds = fds;
|
||||
self->desc->quantum = item_size;
|
||||
self->desc->flags = type;
|
||||
self->desc->grantors.data.ptr = grantors;
|
||||
self->desc->grantors.count = configure_event_flag ?
|
||||
(EVENT_FLAG_PTR_POS + 1) : (DATA_PTR_POS + 1);
|
||||
self->desc->grantors.owns_buffer = TRUE;
|
||||
|
||||
/* Initialize memory pointers */
|
||||
if (type == GBINDER_FMQ_TYPE_SYNC_READ_WRITE) {
|
||||
self->read_ptr = gbinder_fmq_map_grantor_descriptor(self,
|
||||
READ_PTR_POS);
|
||||
} else {
|
||||
/*
|
||||
* Unsynchronized write FMQs may have multiple readers and
|
||||
* each reader would have their own read pointer counter.
|
||||
*/
|
||||
self->read_ptr = g_new0(guint64, 1);
|
||||
}
|
||||
|
||||
if (!self->read_ptr) {
|
||||
GWARN("Read pointer is null");
|
||||
}
|
||||
|
||||
self->write_ptr = gbinder_fmq_map_grantor_descriptor(self,
|
||||
WRITE_PTR_POS);
|
||||
if (!self->write_ptr) {
|
||||
GWARN("Write pointer is null");
|
||||
}
|
||||
|
||||
if (!(flags & GBINDER_FMQ_FLAG_NO_RESET_POINTERS)) {
|
||||
__atomic_store_n(self->read_ptr, 0, __ATOMIC_RELEASE);
|
||||
__atomic_store_n(self->write_ptr, 0, __ATOMIC_RELEASE);
|
||||
} else if (type != GBINDER_FMQ_TYPE_SYNC_READ_WRITE) {
|
||||
/* Always reset the read pointer */
|
||||
__atomic_store_n(self->read_ptr, 0, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
self->ring = gbinder_fmq_map_grantor_descriptor(self,
|
||||
DATA_PTR_POS);
|
||||
if (!self->ring) {
|
||||
GWARN("Ring buffer pointer is null");
|
||||
}
|
||||
|
||||
if (self->desc->grantors.count > EVENT_FLAG_PTR_POS) {
|
||||
self->event_flag_ptr = gbinder_fmq_map_grantor_descriptor(self,
|
||||
EVENT_FLAG_PTR_POS);
|
||||
if (!self->event_flag_ptr) {
|
||||
GWARN("Event flag pointer is null");
|
||||
}
|
||||
}
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
return self;
|
||||
}
|
||||
|
||||
GWARN("Failed to allocate shared memory: %s", strerror(errno));
|
||||
gbinder_fmq_free(self);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderFmq*
|
||||
gbinder_fmq_ref(
|
||||
GBinderFmq* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
g_atomic_int_inc(&self->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_fmq_unref(
|
||||
GBinderFmq* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->refcount)) {
|
||||
gbinder_fmq_free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_fmq_available_to_read(
|
||||
GBinderFmq* self)
|
||||
{
|
||||
return G_LIKELY(self) ? (gbinder_fmq_available_to_read_bytes(self, FALSE) /
|
||||
self->desc->quantum) : 0;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_fmq_available_to_write(
|
||||
GBinderFmq* self)
|
||||
{
|
||||
return G_LIKELY(self) ? (gbinder_fmq_available_to_write_bytes(self, FALSE) /
|
||||
self->desc->quantum) : 0;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_fmq_available_to_read_contiguous(
|
||||
GBinderFmq* self)
|
||||
{
|
||||
return G_LIKELY(self) ? (gbinder_fmq_available_to_read_bytes(self, TRUE) /
|
||||
self->desc->quantum) : 0;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_fmq_available_to_write_contiguous(
|
||||
GBinderFmq* self)
|
||||
{
|
||||
return G_LIKELY(self) ? (gbinder_fmq_available_to_write_bytes(self, TRUE) /
|
||||
self->desc->quantum) : 0;
|
||||
}
|
||||
|
||||
const void*
|
||||
gbinder_fmq_begin_read(
|
||||
GBinderFmq* self,
|
||||
gsize items)
|
||||
{
|
||||
void* ptr = NULL;
|
||||
|
||||
if (G_LIKELY(self) && G_LIKELY(items > 0)) {
|
||||
gsize size = gbinder_fmq_get_grantor_descriptor(self,
|
||||
DATA_PTR_POS)->extent;
|
||||
gsize item_size = self->desc->quantum;
|
||||
gsize bytes_desired = items * item_size;
|
||||
guint64 write_ptr = __atomic_load_n(self->write_ptr, __ATOMIC_ACQUIRE);
|
||||
guint64 read_ptr = __atomic_load_n(self->read_ptr, __ATOMIC_RELAXED);
|
||||
|
||||
if ((write_ptr % item_size) || (read_ptr % item_size)) {
|
||||
GWARN("Unable to write data because of misaligned pointer");
|
||||
} else if (write_ptr - read_ptr > size) {
|
||||
__atomic_store_n(self->read_ptr, write_ptr, __ATOMIC_RELEASE);
|
||||
} else if (write_ptr - read_ptr < bytes_desired) {
|
||||
/* Not enough data to read in FMQ. */
|
||||
} else {
|
||||
ptr = self->ring + (read_ptr % size);
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void*
|
||||
gbinder_fmq_begin_write(
|
||||
GBinderFmq* self,
|
||||
gsize items)
|
||||
{
|
||||
void* ptr = NULL;
|
||||
if (G_LIKELY(self) && G_LIKELY(items > 0)) {
|
||||
const gsize item_size = self->desc->quantum;
|
||||
const gsize size = gbinder_fmq_get_grantor_descriptor(self,
|
||||
DATA_PTR_POS)->extent;
|
||||
|
||||
if ((self->desc->flags == GBINDER_FMQ_TYPE_SYNC_READ_WRITE &&
|
||||
(gbinder_fmq_available_to_write(self) < items)) ||
|
||||
items > size / item_size) {
|
||||
/* Incorrect parameters */
|
||||
} else {
|
||||
guint64 write_ptr = __atomic_load_n(self->write_ptr,
|
||||
__ATOMIC_RELAXED);
|
||||
|
||||
if (write_ptr % item_size) {
|
||||
GWARN("The write pointer has become misaligned.");
|
||||
} else {
|
||||
|
||||
ptr = self->ring + (write_ptr % size);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_fmq_end_read(
|
||||
GBinderFmq* self,
|
||||
gsize items)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(items > 0)) {
|
||||
gsize size = gbinder_fmq_get_grantor_descriptor(self,
|
||||
DATA_PTR_POS)->extent;
|
||||
guint64 read_ptr = __atomic_load_n(self->read_ptr, __ATOMIC_RELAXED);
|
||||
guint64 write_ptr = __atomic_load_n(self->write_ptr, __ATOMIC_ACQUIRE);
|
||||
|
||||
/*
|
||||
* If queue type is unsynchronized, it is possible that a write
|
||||
* overflow may have occurred.
|
||||
*/
|
||||
if (write_ptr - read_ptr > size) {
|
||||
__atomic_store_n(self->read_ptr, write_ptr, __ATOMIC_RELEASE);
|
||||
} else {
|
||||
read_ptr += items * self->desc->quantum;
|
||||
__atomic_store_n(self->read_ptr, read_ptr, __ATOMIC_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_fmq_end_write(
|
||||
GBinderFmq* self,
|
||||
gsize items)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(items > 0)) {
|
||||
guint64 write_ptr = __atomic_load_n(self->write_ptr, __ATOMIC_RELAXED);
|
||||
|
||||
write_ptr += items * self->desc->quantum;
|
||||
__atomic_store_n(self->write_ptr, write_ptr, __ATOMIC_RELEASE);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_fmq_read(
|
||||
GBinderFmq* self,
|
||||
void* data,
|
||||
gsize items)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(data) && G_LIKELY(items > 0)) {
|
||||
const void* in_data = gbinder_fmq_begin_read(self, items);
|
||||
|
||||
if (in_data) {
|
||||
/*
|
||||
* The number of messages that can be read contiguously without
|
||||
* wrapping around the ring buffer.
|
||||
*/
|
||||
const gsize contiguous_messages =
|
||||
gbinder_fmq_available_to_read_contiguous(self);
|
||||
const gsize item_size = self->desc->quantum;
|
||||
|
||||
if (contiguous_messages < items) {
|
||||
/* A wrap around is required */
|
||||
memcpy(data, in_data, contiguous_messages * item_size);
|
||||
memcpy((char*)data + contiguous_messages * item_size,
|
||||
self->ring, (items - contiguous_messages) * item_size);
|
||||
} else {
|
||||
/* A wrap around is not required */
|
||||
memcpy(data, in_data, items * item_size);
|
||||
}
|
||||
|
||||
gbinder_fmq_end_read(self, items);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_fmq_write(
|
||||
GBinderFmq* self,
|
||||
const void* data,
|
||||
gsize items)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(data) && G_LIKELY(items > 0)) {
|
||||
void *out_data = gbinder_fmq_begin_write(self, items);
|
||||
|
||||
if (out_data) {
|
||||
/*
|
||||
* The number of messages that can be written contiguously without
|
||||
* wrapping around the ring buffer.
|
||||
*/
|
||||
const gsize contiguous_messages =
|
||||
gbinder_fmq_available_to_write_contiguous(self);
|
||||
const gsize item_size = self->desc->quantum;
|
||||
|
||||
if (contiguous_messages < items) {
|
||||
/* A wrap around is required. */
|
||||
memcpy(out_data, data, contiguous_messages * item_size);
|
||||
memcpy(self->ring, (char *)data + contiguous_messages *
|
||||
item_size / sizeof(char),
|
||||
(items - contiguous_messages) * item_size);
|
||||
} else {
|
||||
/* A wrap around is not required to write items */
|
||||
memcpy(out_data, data, items * item_size);
|
||||
}
|
||||
|
||||
gbinder_fmq_end_write(self, items);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_fmq_wait_timeout(
|
||||
GBinderFmq* self,
|
||||
guint32 bit_mask,
|
||||
guint32* state,
|
||||
int timeout_ms)
|
||||
{
|
||||
if (G_UNLIKELY(!state) || G_UNLIKELY(!self)) {
|
||||
return (-EINVAL);
|
||||
} else if (!self->event_flag_ptr) {
|
||||
return (-ENOSYS);
|
||||
} else if (!bit_mask) {
|
||||
return (-EINVAL);
|
||||
} else {
|
||||
guint32 old_value = __atomic_fetch_and(self->event_flag_ptr, ~bit_mask,
|
||||
__ATOMIC_SEQ_CST);
|
||||
guint32 set_bits = old_value & bit_mask;
|
||||
|
||||
/* Check if any of the bits was already set */
|
||||
if (set_bits != 0) {
|
||||
*state = set_bits;
|
||||
return 0;
|
||||
} else if (!timeout_ms) {
|
||||
return (-ETIMEDOUT);
|
||||
} else {
|
||||
int ret;
|
||||
|
||||
if (timeout_ms > 0) {
|
||||
struct timespec deadline;
|
||||
const guint64 ms = 1000000;
|
||||
const guint64 sec = 1000 * ms;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &deadline);
|
||||
deadline.tv_sec += timeout_ms / 1000;
|
||||
deadline.tv_nsec += (timeout_ms % 1000) * ms;
|
||||
if (deadline.tv_nsec >= sec) {
|
||||
deadline.tv_sec++;
|
||||
deadline.tv_nsec -= sec;
|
||||
}
|
||||
|
||||
ret = syscall(__NR_futex, self->event_flag_ptr,
|
||||
FUTEX_WAIT_BITSET, old_value, &deadline, NULL, bit_mask);
|
||||
} else {
|
||||
ret = syscall(__NR_futex, self->event_flag_ptr,
|
||||
FUTEX_WAIT_BITSET, old_value, NULL, NULL, bit_mask);
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
return errno ? (-errno) : -EFAULT;
|
||||
} else {
|
||||
old_value = __atomic_fetch_and(self->event_flag_ptr, ~bit_mask,
|
||||
__ATOMIC_SEQ_CST);
|
||||
*state = old_value & bit_mask;
|
||||
return (*state) ? 0 : (-EAGAIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_fmq_wake(
|
||||
GBinderFmq* self,
|
||||
guint32 bit_mask)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
if (!self->event_flag_ptr) {
|
||||
/* Event flag is not configured */
|
||||
ret = -ENOSYS;
|
||||
} else if (!bit_mask) {
|
||||
/* Ignore zero bit mask */
|
||||
} else {
|
||||
/* Set bit mask only if needed */
|
||||
guint32 old_value = __atomic_fetch_or(self->event_flag_ptr,
|
||||
bit_mask, __ATOMIC_SEQ_CST);
|
||||
|
||||
if (~old_value & bit_mask) {
|
||||
ret = syscall(__NR_futex, self->event_flag_ptr,
|
||||
FUTEX_WAKE_BITSET, G_MAXUINT32, NULL, NULL, bit_mask);
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
/* Report error code */
|
||||
ret = -errno;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* !GBINDER_FMQ_SUPPORTED */
|
||||
#pragma message("Not compiling FMQ")
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
102
src/gbinder_fmq_p.h
Normal file
102
src/gbinder_fmq_p.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_FMQ_PRIVATE_H
|
||||
#define GBINDER_FMQ_PRIVATE_H
|
||||
|
||||
#include <gbinder_fmq.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
/* FMQ functionality requires __NR_memfd_create syscall */
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#ifdef __NR_memfd_create
|
||||
# define GBINDER_FMQ_SUPPORTED 1
|
||||
#else
|
||||
# define GBINDER_FMQ_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* From linux/memfd.h
|
||||
*/
|
||||
#ifndef MFD_CLOEXEC
|
||||
# define MFD_CLOEXEC 0x0001U
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FMQ types
|
||||
*/
|
||||
typedef struct gbinder_fmq_grantor_descriptor {
|
||||
guint32 flags GBINDER_ALIGNED(4);
|
||||
guint32 fd_index GBINDER_ALIGNED(4);
|
||||
guint32 offset GBINDER_ALIGNED(4);
|
||||
guint64 extent GBINDER_ALIGNED(8);
|
||||
} GBinderFmqGrantorDescriptor;
|
||||
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, flags) == 0);
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, fd_index) == 4);
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, offset) == 8);
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderFmqGrantorDescriptor, extent) == 16);
|
||||
G_STATIC_ASSERT(sizeof(GBinderFmqGrantorDescriptor) == 24);
|
||||
|
||||
typedef struct gbinder_mq_descriptor {
|
||||
GBinderHidlVec grantors;
|
||||
union {
|
||||
guint64 value;
|
||||
const GBinderFds* fds;
|
||||
} data;
|
||||
guint32 quantum;
|
||||
guint32 flags;
|
||||
} GBinderMQDescriptor;
|
||||
|
||||
#define GBINDER_MQ_DESCRIPTOR_GRANTORS_OFFSET (0)
|
||||
#define GBINDER_MQ_DESCRIPTOR_FDS_OFFSET (16)
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderMQDescriptor, grantors) ==
|
||||
GBINDER_MQ_DESCRIPTOR_GRANTORS_OFFSET);
|
||||
G_STATIC_ASSERT(G_STRUCT_OFFSET(GBinderMQDescriptor, data) ==
|
||||
GBINDER_MQ_DESCRIPTOR_FDS_OFFSET);
|
||||
G_STATIC_ASSERT(sizeof(GBinderMQDescriptor) == 32);
|
||||
|
||||
GBinderMQDescriptor*
|
||||
gbinder_fmq_get_descriptor(
|
||||
const GBinderFmq* self)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_FMQ_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef struct gbinder_handler_functions {
|
||||
gboolean (*can_loop)(GBinderHandler* handler);
|
||||
GBinderLocalReply* (*transact)(GBinderHandler* handler,
|
||||
GBinderLocalObject* obj, GBinderRemoteRequest* req, guint code,
|
||||
guint flags, int* status);
|
||||
@@ -47,6 +48,14 @@ struct gbinder_handler {
|
||||
|
||||
/* Inline wrappers */
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
gboolean
|
||||
gbinder_handler_can_loop(
|
||||
GBinderHandler* self)
|
||||
{
|
||||
return self && self->f->can_loop && self->f->can_loop(self);
|
||||
}
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderLocalReply*
|
||||
gbinder_handler_transact(
|
||||
|
||||
243
src/gbinder_io.c
243
src/gbinder_io.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_writer.h"
|
||||
#include "gbinder_system.h"
|
||||
#include "gbinder_log.h"
|
||||
@@ -90,19 +91,51 @@ GBINDER_IO_FN(write_read)(
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns size of the object */
|
||||
static
|
||||
gsize
|
||||
GBINDER_IO_FN(object_size)(
|
||||
const void* obj,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
if (obj) {
|
||||
const struct binder_object_header* hdr = obj;
|
||||
|
||||
switch (hdr->type) {
|
||||
case BINDER_TYPE_BINDER:
|
||||
case BINDER_TYPE_WEAK_BINDER:
|
||||
case BINDER_TYPE_HANDLE:
|
||||
case BINDER_TYPE_WEAK_HANDLE:
|
||||
return sizeof(struct flat_binder_object) +
|
||||
protocol->flat_binder_object_extra;
|
||||
case BINDER_TYPE_FD:
|
||||
return sizeof(struct binder_fd_object);
|
||||
case BINDER_TYPE_FDA:
|
||||
return sizeof(struct binder_fd_array_object);
|
||||
case BINDER_TYPE_PTR:
|
||||
return sizeof(struct binder_buffer_object);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns size of the object's extra data */
|
||||
static
|
||||
gsize
|
||||
GBINDER_IO_FN(object_data_size)(
|
||||
const void* obj)
|
||||
{
|
||||
const struct binder_buffer_object* buf = obj;
|
||||
if (obj) {
|
||||
const struct binder_object_header* hdr = obj;
|
||||
|
||||
if (buf && buf->hdr.type == BINDER_TYPE_PTR) {
|
||||
return buf->length;
|
||||
} else {
|
||||
return 0;
|
||||
switch (hdr->type) {
|
||||
case BINDER_TYPE_PTR:
|
||||
return ((struct binder_buffer_object*)obj)->length;
|
||||
case BINDER_TYPE_FDA:
|
||||
return ((struct binder_fd_array_object*)obj)->num_fds * 4;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Writes pointer to the buffer */
|
||||
@@ -118,20 +151,41 @@ GBINDER_IO_FN(encode_pointer)(
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Encodes flat_buffer_object */
|
||||
/* Writes cookie to the buffer */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_cookie)(
|
||||
void* out,
|
||||
guint64 cookie)
|
||||
{
|
||||
binder_uintptr_t* dest = out;
|
||||
|
||||
*dest = (uintptr_t)cookie;
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Encodes flat_binder_object */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_local_object)(
|
||||
void* out,
|
||||
GBinderLocalObject* obj)
|
||||
GBinderLocalObject* obj,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
struct flat_binder_object* dest = out;
|
||||
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
dest->hdr.type = obj ? BINDER_TYPE_BINDER : BINDER_TYPE_WEAK_HANDLE;
|
||||
dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->binder = (uintptr_t)obj;
|
||||
return sizeof(*dest);
|
||||
dest->hdr.type = BINDER_TYPE_BINDER;
|
||||
if (obj) {
|
||||
dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->binder = (uintptr_t)obj;
|
||||
}
|
||||
if (protocol->finish_flatten_binder) {
|
||||
protocol->finish_flatten_binder(dest + 1, obj);
|
||||
} else if (protocol->flat_binder_object_extra) {
|
||||
memset(dest + 1, 0, protocol->flat_binder_object_extra);
|
||||
}
|
||||
return sizeof(*dest) + protocol->flat_binder_object_extra;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -159,12 +213,29 @@ GBINDER_IO_FN(encode_fd_object)(
|
||||
void* out,
|
||||
int fd)
|
||||
{
|
||||
struct flat_binder_object* dest = out;
|
||||
struct binder_fd_object* dest = out;
|
||||
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
dest->hdr.type = BINDER_TYPE_FD;
|
||||
dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->handle = fd;
|
||||
dest->pad_flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->fd = fd;
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_fda_object)(
|
||||
void* out,
|
||||
const GBinderFds *fds,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
struct binder_fd_array_object* dest = out;
|
||||
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
dest->hdr.type = BINDER_TYPE_FDA;
|
||||
dest->num_fds = fds->num_fds;
|
||||
dest->parent = parent->index;
|
||||
dest->parent_offset = parent->offset;
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
@@ -193,7 +264,7 @@ GBINDER_IO_FN(encode_buffer_object)(
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_death_notification)(
|
||||
GBINDER_IO_FN(encode_handle_cookie)(
|
||||
void* out,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
@@ -205,7 +276,21 @@ GBINDER_IO_FN(encode_death_notification)(
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Encodes BC_TRANSACTION data */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_ptr_cookie)(
|
||||
void* out,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
struct binder_ptr_cookie* dest = out;
|
||||
|
||||
/* We never send these cookies and don't expect them back */
|
||||
dest->ptr = (uintptr_t)obj;
|
||||
dest->cookie = 0;
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Fills binder_transaction_data for BC_TRANSACTION/REPLY */
|
||||
static
|
||||
void
|
||||
GBINDER_IO_FN(fill_transaction_data)(
|
||||
@@ -213,7 +298,7 @@ GBINDER_IO_FN(fill_transaction_data)(
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* payload,
|
||||
guint flags,
|
||||
guint tx_flags,
|
||||
GUtilIntArray* offsets,
|
||||
void** offsets_buf)
|
||||
{
|
||||
@@ -222,9 +307,7 @@ GBINDER_IO_FN(fill_transaction_data)(
|
||||
tr->code = code;
|
||||
tr->data_size = payload->len;
|
||||
tr->data.ptr.buffer = (uintptr_t)payload->data;
|
||||
if (flags & GBINDER_TX_FLAG_ONEWAY) {
|
||||
tr->flags |= TF_ONE_WAY;
|
||||
}
|
||||
tr->flags = tx_flags;
|
||||
if (offsets && offsets->count) {
|
||||
guint i;
|
||||
binder_size_t* tx_offsets = g_new(binder_size_t, offsets->count);
|
||||
@@ -240,6 +323,7 @@ GBINDER_IO_FN(fill_transaction_data)(
|
||||
}
|
||||
}
|
||||
|
||||
/* Encodes BC_TRANSACTION data */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_transaction)(
|
||||
@@ -253,7 +337,8 @@ GBINDER_IO_FN(encode_transaction)(
|
||||
{
|
||||
struct binder_transaction_data* tr = out;
|
||||
|
||||
GBINDER_IO_FN(fill_transaction_data)(tr, handle, code, payload, flags,
|
||||
GBINDER_IO_FN(fill_transaction_data)(tr, handle, code, payload,
|
||||
(flags & GBINDER_TX_FLAG_ONEWAY) ? TF_ONE_WAY : TF_ACCEPT_FDS,
|
||||
offsets, offsets_buf);
|
||||
return sizeof(*tr);
|
||||
}
|
||||
@@ -274,13 +359,53 @@ GBINDER_IO_FN(encode_transaction_sg)(
|
||||
struct binder_transaction_data_sg* sg = out;
|
||||
|
||||
GBINDER_IO_FN(fill_transaction_data)(&sg->transaction_data, handle, code,
|
||||
payload, flags, offsets, offsets_buf);
|
||||
payload, (flags & GBINDER_TX_FLAG_ONEWAY) ? TF_ONE_WAY : TF_ACCEPT_FDS,
|
||||
offsets, offsets_buf);
|
||||
/* The driver seems to require buffers to be 8-byte aligned */
|
||||
sg->buffers_size = G_ALIGN8(buffers_size);
|
||||
return sizeof(*sg);
|
||||
}
|
||||
|
||||
/* Encode BC_REPLY */
|
||||
/* Encodes BC_REPLY data */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_reply)(
|
||||
void* out,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* payload,
|
||||
GUtilIntArray* offsets,
|
||||
void** offsets_buf)
|
||||
{
|
||||
struct binder_transaction_data* tr = out;
|
||||
|
||||
GBINDER_IO_FN(fill_transaction_data)(tr, handle, code, payload, 0,
|
||||
offsets, offsets_buf);
|
||||
return sizeof(*tr);
|
||||
}
|
||||
|
||||
/* Encodes BC_REPLY_SG data */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_reply_sg)(
|
||||
void* out,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* payload,
|
||||
GUtilIntArray* offsets,
|
||||
void** offsets_buf,
|
||||
gsize buffers_size)
|
||||
{
|
||||
struct binder_transaction_data_sg* sg = out;
|
||||
|
||||
GBINDER_IO_FN(fill_transaction_data)(&sg->transaction_data, handle, code,
|
||||
payload, 0, offsets, offsets_buf);
|
||||
/* The driver seems to require buffers to be 8-byte aligned */
|
||||
sg->buffers_size = G_ALIGN8(buffers_size);
|
||||
return sizeof(*sg);
|
||||
}
|
||||
|
||||
/* Encode BC_REPLY with just status */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_status_reply)(
|
||||
@@ -368,7 +493,7 @@ GBINDER_IO_FN(decode_cookie)(
|
||||
/* Decode struct binder_ptr_cookie */
|
||||
static
|
||||
void*
|
||||
GBINDER_IO_FN(decode_binder_ptr_cookie)(
|
||||
GBINDER_IO_FN(decode_ptr_cookie)(
|
||||
const void* data)
|
||||
{
|
||||
const struct binder_ptr_cookie* ptr = data;
|
||||
@@ -378,13 +503,33 @@ GBINDER_IO_FN(decode_binder_ptr_cookie)(
|
||||
return (void*)(uintptr_t)ptr->ptr;
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(decode_binder_handle)(
|
||||
const void* data,
|
||||
guint32* handle,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
const struct flat_binder_object* obj = data;
|
||||
|
||||
/* Caller guarantees that data points to an object */
|
||||
if (obj->hdr.type == BINDER_TYPE_HANDLE) {
|
||||
if (handle) {
|
||||
*handle = obj->handle;
|
||||
}
|
||||
return sizeof(*obj) + protocol->flat_binder_object_extra;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(decode_binder_object)(
|
||||
const void* data,
|
||||
gsize size,
|
||||
GBinderObjectRegistry* reg,
|
||||
GBinderRemoteObject** out)
|
||||
GBinderRemoteObject** out,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
const struct flat_binder_object* obj = data;
|
||||
|
||||
@@ -392,9 +537,22 @@ GBINDER_IO_FN(decode_binder_object)(
|
||||
switch (obj->hdr.type) {
|
||||
case BINDER_TYPE_HANDLE:
|
||||
if (out) {
|
||||
*out = gbinder_object_registry_get_remote(reg, obj->handle);
|
||||
*out = gbinder_object_registry_get_remote(reg, obj->handle,
|
||||
REMOTE_REGISTRY_CAN_CREATE_AND_ACQUIRE);
|
||||
if (*out && protocol->finish_unflatten_binder) {
|
||||
protocol->finish_unflatten_binder(obj + 1, *out);
|
||||
}
|
||||
}
|
||||
return sizeof(*obj);
|
||||
return sizeof(*obj) + protocol->flat_binder_object_extra;
|
||||
case BINDER_TYPE_BINDER:
|
||||
if (!obj->binder) {
|
||||
/* That's a NULL reference */
|
||||
if (out) {
|
||||
*out = NULL;
|
||||
}
|
||||
return sizeof(*obj) + protocol->flat_binder_object_extra;
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
GERR("Unsupported binder object type 0x%08x", obj->hdr.type);
|
||||
break;
|
||||
@@ -409,7 +567,7 @@ guint
|
||||
GBINDER_IO_FN(decode_buffer_object)(
|
||||
GBinderBuffer* buf,
|
||||
gsize offset,
|
||||
GBinderBuffer** out)
|
||||
GBinderIoBufferObject* out)
|
||||
{
|
||||
const void* data = (guint8*)buf->data + offset;
|
||||
const gsize size = (offset < buf->size) ? (buf->size - offset) : 0;
|
||||
@@ -417,12 +575,14 @@ GBINDER_IO_FN(decode_buffer_object)(
|
||||
|
||||
if (size >= sizeof(*flat) && flat->hdr.type == BINDER_TYPE_PTR) {
|
||||
if (out) {
|
||||
*out = gbinder_buffer_new_with_parent(buf,
|
||||
(void*)(uintptr_t)flat->buffer, flat->length);
|
||||
out->data = (void*)(uintptr_t)flat->buffer;
|
||||
out->size = (gsize)flat->length;
|
||||
out->parent_offset = (gsize)flat->parent_offset;
|
||||
out->has_parent = (flat->flags & BINDER_BUFFER_FLAG_HAS_PARENT) ?
|
||||
TRUE : FALSE;
|
||||
}
|
||||
return sizeof(*flat);
|
||||
}
|
||||
if (out) *out = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -497,23 +657,30 @@ const GBinderIo GBINDER_IO_PREFIX = {
|
||||
.failed_reply = BR_FAILED_REPLY
|
||||
},
|
||||
|
||||
.object_size = GBINDER_IO_FN(object_size),
|
||||
.object_data_size = GBINDER_IO_FN(object_data_size),
|
||||
|
||||
/* Encoders */
|
||||
.encode_pointer = GBINDER_IO_FN(encode_pointer),
|
||||
.encode_cookie = GBINDER_IO_FN(encode_cookie),
|
||||
.encode_local_object = GBINDER_IO_FN(encode_local_object),
|
||||
.encode_remote_object = GBINDER_IO_FN(encode_remote_object),
|
||||
.encode_fd_object = GBINDER_IO_FN(encode_fd_object),
|
||||
.encode_fda_object = GBINDER_IO_FN(encode_fda_object),
|
||||
.encode_buffer_object = GBINDER_IO_FN(encode_buffer_object),
|
||||
.encode_death_notification = GBINDER_IO_FN(encode_death_notification),
|
||||
.encode_handle_cookie = GBINDER_IO_FN(encode_handle_cookie),
|
||||
.encode_ptr_cookie = GBINDER_IO_FN(encode_ptr_cookie),
|
||||
.encode_transaction = GBINDER_IO_FN(encode_transaction),
|
||||
.encode_transaction_sg = GBINDER_IO_FN(encode_transaction_sg),
|
||||
.encode_reply = GBINDER_IO_FN(encode_reply),
|
||||
.encode_reply_sg = GBINDER_IO_FN(encode_reply_sg),
|
||||
.encode_status_reply = GBINDER_IO_FN(encode_status_reply),
|
||||
|
||||
/* Decoders */
|
||||
.decode_transaction_data = GBINDER_IO_FN(decode_transaction_data),
|
||||
.decode_cookie = GBINDER_IO_FN(decode_cookie),
|
||||
.decode_binder_ptr_cookie = GBINDER_IO_FN(decode_binder_ptr_cookie),
|
||||
.decode_ptr_cookie = GBINDER_IO_FN(decode_ptr_cookie),
|
||||
.decode_binder_handle = GBINDER_IO_FN(decode_binder_handle),
|
||||
.decode_binder_object = GBINDER_IO_FN(decode_binder_object),
|
||||
.decode_buffer_object = GBINDER_IO_FN(decode_buffer_object),
|
||||
.decode_fd_object = GBINDER_IO_FN(decode_fd_object),
|
||||
@@ -526,10 +693,14 @@ const GBinderIo GBINDER_IO_PREFIX = {
|
||||
G_STATIC_ASSERT(GBINDER_POINTER_SIZE <= GBINDER_MAX_POINTER_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct flat_binder_object) <=
|
||||
GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_fd_object) <=
|
||||
GBINDER_MAX_BUFFER_OBJECT_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_fd_array_object) <=
|
||||
GBINDER_MAX_BUFFER_OBJECT_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_buffer_object) <=
|
||||
GBINDER_MAX_BUFFER_OBJECT_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_handle_cookie) <=
|
||||
GBINDER_MAX_DEATH_NOTIFICATION_SIZE);
|
||||
GBINDER_MAX_HANDLE_COOKIE_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_transaction_data) <=
|
||||
GBINDER_MAX_BC_TRANSACTION_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_transaction_data_sg) <=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -43,6 +43,13 @@ typedef struct gbinder_io_buf {
|
||||
gsize consumed;
|
||||
} GBinderIoBuf;
|
||||
|
||||
typedef struct gbinder_io_buffer_object {
|
||||
void* data;
|
||||
gsize size;
|
||||
gsize parent_offset;
|
||||
gboolean has_parent;
|
||||
} GBinderIoBufferObject;
|
||||
|
||||
typedef struct gbinder_io_tx_data {
|
||||
int status;
|
||||
guint32 code;
|
||||
@@ -118,7 +125,8 @@ struct gbinder_io {
|
||||
guint failed_reply;
|
||||
} br;
|
||||
|
||||
/* Size of the object's extra data */
|
||||
/* Size of the object and its extra data */
|
||||
gsize (*object_size)(const void* obj, const GBinderRpcProtocol* protocol);
|
||||
gsize (*object_data_size)(const void* obj);
|
||||
|
||||
/* Writes pointer to the buffer. The destination buffer must have
|
||||
@@ -127,55 +135,76 @@ struct gbinder_io {
|
||||
#define GBINDER_MAX_POINTER_SIZE (8)
|
||||
guint (*encode_pointer)(void* out, const void* pointer);
|
||||
|
||||
/* Writes cookie to the buffer. The destination buffer must have
|
||||
* at least GBINDER_IO_MAX_COOKIE_SIZE bytes available. The
|
||||
* actual size is returned. */
|
||||
#define GBINDER_MAX_COOKIE_SIZE GBINDER_MAX_POINTER_SIZE
|
||||
guint (*encode_cookie)(void* out, guint64 cookie);
|
||||
|
||||
/* Encode flat_buffer_object */
|
||||
#define GBINDER_MAX_BINDER_OBJECT_SIZE (24)
|
||||
guint (*encode_local_object)(void* out, GBinderLocalObject* obj);
|
||||
#define GBINDER_MAX_BINDER_OBJECT_SIZE (28)
|
||||
guint (*encode_local_object)(void* out, GBinderLocalObject* obj,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
guint (*encode_remote_object)(void* out, GBinderRemoteObject* obj);
|
||||
guint (*encode_fd_object)(void* out, int fd);
|
||||
guint (*encode_fda_object)(void* out, const GBinderFds *fds,
|
||||
const GBinderParent* parent);
|
||||
|
||||
/* Encode binder_buffer_object */
|
||||
#define GBINDER_MAX_BUFFER_OBJECT_SIZE (40)
|
||||
guint (*encode_buffer_object)(void* out, const void* data, gsize size,
|
||||
const GBinderParent* parent);
|
||||
|
||||
/* Encode death notification */
|
||||
#define GBINDER_MAX_DEATH_NOTIFICATION_SIZE (12)
|
||||
guint (*encode_death_notification)(void* out, GBinderRemoteObject* obj);
|
||||
/* Encode binder_handle_cookie */
|
||||
#define GBINDER_MAX_HANDLE_COOKIE_SIZE (12)
|
||||
guint (*encode_handle_cookie)(void* out, GBinderRemoteObject* obj);
|
||||
|
||||
/* Encode BC_TRANSACTION/REPLY data */
|
||||
/* Encode binder_ptr_cookie */
|
||||
#define GBINDER_MAX_PTR_COOKIE_SIZE (16)
|
||||
guint (*encode_ptr_cookie)(void* out, GBinderLocalObject* obj);
|
||||
|
||||
/* Encode BC_TRANSACTION/BC_TRANSACTION_SG data */
|
||||
#define GBINDER_MAX_BC_TRANSACTION_SIZE (64)
|
||||
guint (*encode_transaction)(void* out, guint32 handle, guint32 code,
|
||||
const GByteArray* data, guint flags /* See below */,
|
||||
GUtilIntArray* offsets, void** offsets_buf);
|
||||
|
||||
/* Encode BC_TRANSACTION_SG/REPLY_SG data */
|
||||
#define GBINDER_MAX_BC_TRANSACTION_SG_SIZE (72)
|
||||
guint (*encode_transaction_sg)(void* out, guint32 handle, guint32 code,
|
||||
const GByteArray* data, guint flags /* GBINDER_TX_FLAG_xxx */,
|
||||
GUtilIntArray* offsets, void** offsets_buf,
|
||||
gsize buffers_size);
|
||||
|
||||
/* Encode BC_REPLY/REPLY_SG data */
|
||||
#define GBINDER_MAX_BC_REPLY_SIZE GBINDER_MAX_BC_TRANSACTION_SIZE
|
||||
guint (*encode_reply)(void* out, guint32 handle, guint32 code,
|
||||
const GByteArray* data, GUtilIntArray* offsets, void** offsets_buf);
|
||||
#define GBINDER_MAX_BC_REPLY_SG_SIZE GBINDER_MAX_BC_TRANSACTION_SG_SIZE
|
||||
guint (*encode_reply_sg)(void* out, guint32 handle, guint32 code,
|
||||
const GByteArray* data, GUtilIntArray* offsets, void** offsets_buf,
|
||||
gsize buffers_size);
|
||||
|
||||
/* Encode BC_REPLY */
|
||||
guint (*encode_status_reply)(void* out, gint32* status);
|
||||
|
||||
/* Decoders */
|
||||
void (*decode_transaction_data)(const void* data, GBinderIoTxData* tx);
|
||||
|
||||
#define GBINDER_MAX_PTR_COOKIE_SIZE (16)
|
||||
void* (*decode_binder_ptr_cookie)(const void* data);
|
||||
void* (*decode_ptr_cookie)(const void* data);
|
||||
guint (*decode_cookie)(const void* data, guint64* cookie);
|
||||
guint (*decode_binder_handle)(const void* obj, guint32* handle,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
guint (*decode_binder_object)(const void* data, gsize size,
|
||||
GBinderObjectRegistry* reg, GBinderRemoteObject** obj);
|
||||
GBinderObjectRegistry* reg, GBinderRemoteObject** obj,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
guint (*decode_buffer_object)(GBinderBuffer* buf, gsize offset,
|
||||
GBinderBuffer** out);
|
||||
GBinderIoBufferObject* out);
|
||||
guint (*decode_fd_object)(const void* data, gsize size, int* fd);
|
||||
|
||||
/* ioctl wrappers */
|
||||
int (*write_read)(int fd, GBinderIoBuf* write, GBinderIoBuf* read);
|
||||
};
|
||||
|
||||
extern const GBinderIo gbinder_io_32;
|
||||
extern const GBinderIo gbinder_io_64;
|
||||
extern const GBinderIo gbinder_io_32 GBINDER_INTERNAL;
|
||||
extern const GBinderIo gbinder_io_64 GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_IO_H */
|
||||
|
||||
|
||||
1657
src/gbinder_ipc.c
1657
src/gbinder_ipc.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -42,7 +42,6 @@ struct gbinder_ipc {
|
||||
GObject object;
|
||||
GBinderIpcPriv* priv;
|
||||
GBinderDriver* driver;
|
||||
GUtilIdlePool* pool;
|
||||
const char* dev;
|
||||
};
|
||||
|
||||
@@ -60,6 +59,12 @@ struct gbinder_ipc_tx {
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
typedef
|
||||
gboolean
|
||||
(*GBinderIpcLocalObjectCheckFunc)(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data);
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderIpcReplyFunc)(
|
||||
@@ -68,54 +73,105 @@ void
|
||||
int status,
|
||||
void* user_data);
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_new(
|
||||
const char* dev,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_ref(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
void
|
||||
gbinder_ipc_unref(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
void
|
||||
gbinder_ipc_looper_check(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
GBinderObjectRegistry*
|
||||
gbinder_ipc_object_registry(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_ipc_new_local_object(
|
||||
GBinderIpc* ipc,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* data);
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_ipc_get_remote_object(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle);
|
||||
|
||||
typedef
|
||||
GBinderRemoteReply*
|
||||
gbinder_ipc_transact_sync_reply(
|
||||
(*GBinderIpcSyncReplyFunc)(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
int* status);
|
||||
|
||||
typedef
|
||||
int
|
||||
gbinder_ipc_transact_sync_oneway(
|
||||
(*GBinderIpcSyncOnewayFunc)(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req);
|
||||
|
||||
struct gbinder_ipc_sync_api {
|
||||
GBinderIpcSyncReplyFunc sync_reply;
|
||||
GBinderIpcSyncOnewayFunc sync_oneway;
|
||||
};
|
||||
|
||||
extern const GBinderIpcSyncApi gbinder_ipc_sync_main GBINDER_INTERNAL;
|
||||
extern const GBinderIpcSyncApi gbinder_ipc_sync_worker GBINDER_INTERNAL;
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_new(
|
||||
const char* dev,
|
||||
const char* protocol)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_ref(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_ipc_unref(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const char*
|
||||
gbinder_ipc_name(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_ipc_looper_check(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderObjectRegistry*
|
||||
gbinder_ipc_object_registry(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const GBinderIo*
|
||||
gbinder_ipc_io(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_ipc_protocol(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_ipc_find_local_object(
|
||||
GBinderIpc* ipc,
|
||||
GBinderIpcLocalObjectCheckFunc func,
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
void
|
||||
gbinder_ipc_register_local_object(
|
||||
GBinderIpc* ipc,
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_ipc_get_service_manager(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
void
|
||||
gbinder_ipc_invalidate_remote_handle(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_ipc_ping_sync(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle,
|
||||
const GBinderIpcSyncApi* api)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gulong
|
||||
gbinder_ipc_transact(
|
||||
GBinderIpc* ipc,
|
||||
@@ -125,7 +181,8 @@ gbinder_ipc_transact(
|
||||
GBinderLocalRequest* req,
|
||||
GBinderIpcReplyFunc func,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data);
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gulong
|
||||
gbinder_ipc_transact_custom(
|
||||
@@ -133,24 +190,48 @@ gbinder_ipc_transact_custom(
|
||||
GBinderIpcTxFunc exec,
|
||||
GBinderIpcTxFunc done,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data);
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_ipc_cancel(
|
||||
GBinderIpc* ipc,
|
||||
gulong id);
|
||||
gulong id)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Internal for GBinderLocalObject */
|
||||
void
|
||||
gbinder_ipc_local_object_disposed(
|
||||
GBinderIpc* self,
|
||||
GBinderLocalObject* obj);
|
||||
GBinderIpc* ipc,
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_ipc_invalidate_local_object(
|
||||
GBinderIpc* ipc,
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Internal for GBinderRemoteObject */
|
||||
void
|
||||
gbinder_ipc_remote_object_disposed(
|
||||
GBinderIpc* self,
|
||||
GBinderRemoteObject* obj);
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Needed by unit tests */
|
||||
gboolean
|
||||
gbinder_ipc_set_max_threads(
|
||||
GBinderIpc* ipc,
|
||||
gint max_threads)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Declared for unit tests */
|
||||
void
|
||||
gbinder_ipc_exit(
|
||||
void)
|
||||
GBINDER_INTERNAL
|
||||
GBINDER_DESTRUCTOR;
|
||||
|
||||
#endif /* GBINDER_IPC_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -32,27 +32,44 @@
|
||||
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_remote_request.h"
|
||||
#include "gbinder_eventloop_p.h"
|
||||
#include "gbinder_writer.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
struct gbinder_local_object_priv {
|
||||
GMainContext* context;
|
||||
char* iface;
|
||||
char** ifaces;
|
||||
GBinderLocalTransactFunc txproc;
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
typedef struct gbinder_local_object_acquire_data {
|
||||
GBinderLocalObject* object;
|
||||
GBinderBufferContentsList* bufs;
|
||||
} GBinderLocalObjectAcquireData;
|
||||
|
||||
G_DEFINE_TYPE(GBinderLocalObject, gbinder_local_object, G_TYPE_OBJECT)
|
||||
|
||||
#define PARENT_CLASS gbinder_local_object_parent_class
|
||||
#define GBINDER_LOCAL_OBJECT_GET_CLASS(obj) \
|
||||
G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_LOCAL_OBJECT, \
|
||||
GBinderLocalObjectClass)
|
||||
|
||||
typedef
|
||||
GBinderLocalReply*
|
||||
(*GBinderLocalObjectTxHandler)(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
int* status);
|
||||
|
||||
enum gbinder_local_object_signal {
|
||||
SIGNAL_WEAK_REFS_CHANGED,
|
||||
SIGNAL_STRONG_REFS_CHANGED,
|
||||
@@ -70,6 +87,15 @@ static const char hidl_base_interface[] = "android.hidl.base@1.0::IBase";
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_create_reply(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
return gbinder_local_reply_new(gbinder_local_object_io(self),
|
||||
gbinder_local_object_protocol(self));
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
gbinder_local_object_default_can_handle_transaction(
|
||||
@@ -78,6 +104,9 @@ gbinder_local_object_default_can_handle_transaction(
|
||||
guint code)
|
||||
{
|
||||
switch (code) {
|
||||
case GBINDER_PING_TRANSACTION:
|
||||
case GBINDER_INTERFACE_TRANSACTION:
|
||||
return GBINDER_LOCAL_TRANSACTION_LOOPER;
|
||||
case HIDL_PING_TRANSACTION:
|
||||
case HIDL_GET_DESCRIPTOR_TRANSACTION:
|
||||
case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
|
||||
@@ -110,6 +139,37 @@ gbinder_local_object_default_handle_transaction(
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_ping_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
int* status)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
|
||||
GVERBOSE(" PING_TRANSACTION");
|
||||
gbinder_local_reply_append_int32(reply, GBINDER_STATUS_OK);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_interface_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
int* status)
|
||||
{
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
|
||||
GVERBOSE(" INTERFACE_TRANSACTION");
|
||||
gbinder_local_reply_append_string16(reply, priv->ifaces[0]);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_hidl_ping_transaction(
|
||||
@@ -118,14 +178,11 @@ gbinder_local_object_hidl_ping_transaction(
|
||||
int* status)
|
||||
{
|
||||
/*android.hidl.base@1.0::IBase interfaceDescriptor() */
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderWriter writer;
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
|
||||
GVERBOSE(" HIDL_PING_TRANSACTION \"%s\"",
|
||||
gbinder_remote_request_interface(req));
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_local_reply_append_int32(reply, GBINDER_STATUS_OK);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
@@ -138,16 +195,15 @@ gbinder_local_object_hidl_get_descriptor_transaction(
|
||||
int* status)
|
||||
{
|
||||
/*android.hidl.base@1.0::IBase interfaceDescriptor() */
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
GBinderWriter writer;
|
||||
|
||||
GVERBOSE(" HIDL_GET_DESCRIPTOR_TRANSACTION \"%s\"",
|
||||
gbinder_remote_request_interface(req));
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_hidl_string(&writer, self->iface ? self->iface :
|
||||
hidl_base_interface);
|
||||
gbinder_writer_append_hidl_string(&writer, priv->ifaces[0]);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
@@ -160,20 +216,16 @@ gbinder_local_object_hidl_descriptor_chain_transaction(
|
||||
int* status)
|
||||
{
|
||||
/*android.hidl.base@1.0::IBase interfaceChain() */
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
GBinderWriter writer;
|
||||
const char* chain[2];
|
||||
int n = 0;
|
||||
|
||||
GVERBOSE(" HIDL_DESCRIPTOR_CHAIN_TRANSACTION \"%s\"",
|
||||
gbinder_remote_request_interface(req));
|
||||
if (self->iface) chain[n++] = self->iface;
|
||||
chain[n++] = hidl_base_interface;
|
||||
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_hidl_string_vec(&writer, chain, n);
|
||||
gbinder_writer_append_hidl_string_vec(&writer, (const char**)
|
||||
self->ifaces, -1);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
@@ -187,92 +239,142 @@ gbinder_local_object_default_handle_looper_transaction(
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
GBinderLocalObjectTxHandler handler = NULL;
|
||||
|
||||
switch (code) {
|
||||
case GBINDER_PING_TRANSACTION:
|
||||
handler = gbinder_local_object_ping_transaction;
|
||||
break;
|
||||
case GBINDER_INTERFACE_TRANSACTION:
|
||||
handler = gbinder_local_object_interface_transaction;
|
||||
break;
|
||||
case HIDL_PING_TRANSACTION:
|
||||
GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
|
||||
return gbinder_local_object_hidl_ping_transaction
|
||||
(self, req, status);
|
||||
handler = gbinder_local_object_hidl_ping_transaction;
|
||||
break;
|
||||
case HIDL_GET_DESCRIPTOR_TRANSACTION:
|
||||
GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
|
||||
return gbinder_local_object_hidl_get_descriptor_transaction
|
||||
(self, req, status);
|
||||
handler = gbinder_local_object_hidl_get_descriptor_transaction;
|
||||
break;
|
||||
case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
|
||||
GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
|
||||
return gbinder_local_object_hidl_descriptor_chain_transaction
|
||||
(self, req, status);
|
||||
handler = gbinder_local_object_hidl_descriptor_chain_transaction;
|
||||
break;
|
||||
default:
|
||||
if (status) *status = (-EBADMSG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
|
||||
return handler(self, req, status);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_default_drop(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
/* Clear the transaction callback */
|
||||
priv->txproc = NULL;
|
||||
priv->user_data = NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_handle_later(
|
||||
GBinderLocalObject* self,
|
||||
GSourceFunc function)
|
||||
GBinderEventLoopCallbackFunc function)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
g_main_context_invoke_full(priv->context, G_PRIORITY_DEFAULT, function,
|
||||
gbinder_idle_callback_invoke_later(function,
|
||||
gbinder_local_object_ref(self), g_object_unref);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_increfs_proc(
|
||||
gpointer local)
|
||||
void
|
||||
gbinder_local_object_increfs_proc(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(user_data);
|
||||
|
||||
self->weak_refs++;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_WEAK_REFS_CHANGED], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_decrefs_proc(
|
||||
gpointer local)
|
||||
void
|
||||
gbinder_local_object_decrefs_proc(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(user_data);
|
||||
|
||||
GASSERT(self->weak_refs > 0);
|
||||
self->weak_refs--;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_WEAK_REFS_CHANGED], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_acquire_proc(
|
||||
gpointer local)
|
||||
void
|
||||
gbinder_local_object_default_acquire(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
|
||||
self->strong_refs++;
|
||||
gbinder_local_object_ref(self);
|
||||
GVERBOSE_("%p => %d", self, self->strong_refs);
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_STRONG_REFS_CHANGED], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_release_proc(
|
||||
gpointer local)
|
||||
void
|
||||
gbinder_local_object_acquire_proc(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
GBinderLocalObjectAcquireData* data = user_data;
|
||||
GBinderLocalObject* self = data->object;
|
||||
|
||||
GASSERT(self->strong_refs > 0);
|
||||
self->strong_refs--;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_STRONG_REFS_CHANGED], 0);
|
||||
GBINDER_LOCAL_OBJECT_GET_CLASS(self)->acquire(self);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_acquire_done(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderLocalObjectAcquireData* data = user_data;
|
||||
GBinderLocalObject* self = data->object;
|
||||
|
||||
gbinder_driver_acquire_done(self->ipc->driver, self);
|
||||
gbinder_local_object_unref(self);
|
||||
return G_SOURCE_REMOVE;
|
||||
gbinder_buffer_contents_list_free(data->bufs);
|
||||
return gutil_slice_free(data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_default_release(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
GASSERT(self->strong_refs > 0);
|
||||
if (self->strong_refs > 0) {
|
||||
self->strong_refs--;
|
||||
GVERBOSE_("%p => %d", self, self->strong_refs);
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_STRONG_REFS_CHANGED], 0);
|
||||
gbinder_local_object_unref(self);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_release_proc(
|
||||
gpointer obj)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(obj);
|
||||
|
||||
GBINDER_LOCAL_OBJECT_GET_CLASS(self)->release(self);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -282,23 +384,67 @@ gbinder_local_object_handle_release_proc(
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_new(
|
||||
GBinderIpc* ipc,
|
||||
const char* iface,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data) /* Since 1.0.30 */
|
||||
{
|
||||
return gbinder_local_object_new_with_type(GBINDER_TYPE_LOCAL_OBJECT,
|
||||
ipc, ifaces, txproc, user_data);
|
||||
}
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_new_with_type(
|
||||
GType type,
|
||||
GBinderIpc* ipc,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* arg)
|
||||
{
|
||||
if (G_LIKELY(ipc)) {
|
||||
GBinderLocalObject* obj = g_object_new(type, NULL);
|
||||
|
||||
gbinder_local_object_init_base(obj, ipc, ifaces, txproc, arg);
|
||||
gbinder_ipc_register_local_object(ipc, obj);
|
||||
return obj;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_init_base(
|
||||
GBinderLocalObject* self,
|
||||
GBinderIpc* ipc,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
{
|
||||
/* Should only be called from gbinder_ipc_new_local_local_object() */
|
||||
if (G_LIKELY(ipc)) {
|
||||
GBinderLocalObject* self = g_object_new
|
||||
(GBINDER_TYPE_LOCAL_OBJECT, NULL);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
guint i = 0, n = gutil_strv_length((char**)ifaces);
|
||||
gboolean append_base_interface;
|
||||
|
||||
self->ipc = gbinder_ipc_ref(ipc);
|
||||
self->iface = priv->iface = g_strdup(iface);
|
||||
priv->txproc = txproc;
|
||||
priv->user_data = user_data;
|
||||
return self;
|
||||
if (g_strcmp0(gutil_strv_last((char**)ifaces), hidl_base_interface)) {
|
||||
append_base_interface = TRUE;
|
||||
n++;
|
||||
} else {
|
||||
append_base_interface = FALSE;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
priv->ifaces = g_new(char*, n + 1);
|
||||
if (ifaces) {
|
||||
while (*ifaces) {
|
||||
priv->ifaces[i++] = g_strdup(*ifaces++);
|
||||
}
|
||||
}
|
||||
if (append_base_interface) {
|
||||
priv->ifaces[i++] = g_strdup(hidl_base_interface);
|
||||
}
|
||||
priv->ifaces[i] = NULL;
|
||||
|
||||
self->ipc = gbinder_ipc_ref(ipc);
|
||||
self->ifaces = (const char**)priv->ifaces;
|
||||
self->stability = GBINDER_STABILITY_SYSTEM;
|
||||
priv->txproc = txproc;
|
||||
priv->user_data = user_data;
|
||||
}
|
||||
|
||||
GBinderLocalObject*
|
||||
@@ -327,11 +473,7 @@ gbinder_local_object_drop(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
/* Clear the transaction callback */
|
||||
priv->txproc = NULL;
|
||||
priv->user_data = NULL;
|
||||
GBINDER_LOCAL_OBJECT_GET_CLASS(self)->drop(self);
|
||||
g_object_unref(GBINDER_LOCAL_OBJECT(self));
|
||||
}
|
||||
}
|
||||
@@ -341,7 +483,7 @@ gbinder_local_object_new_reply(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return gbinder_local_reply_new(gbinder_local_object_io(self));
|
||||
return gbinder_local_object_create_reply(self);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -425,33 +567,59 @@ void
|
||||
gbinder_local_object_handle_increfs(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_increfs_proc);
|
||||
gbinder_local_object_handle_later(self, gbinder_local_object_increfs_proc);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_decrefs(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_decrefs_proc);
|
||||
gbinder_local_object_handle_later(self, gbinder_local_object_decrefs_proc);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_acquire(
|
||||
GBinderLocalObject* self)
|
||||
GBinderLocalObject* self,
|
||||
GBinderBufferContentsList* bufs)
|
||||
{
|
||||
gbinder_local_object_ref(self);
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_acquire_proc);
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderLocalObjectAcquireData* data =
|
||||
g_slice_new(GBinderLocalObjectAcquireData);
|
||||
|
||||
/*
|
||||
* This is a bit complicated :)
|
||||
* GBinderProxyObject derived from GBinderLocalObject acquires a
|
||||
* reference to the remote object in addition to performing the
|
||||
* default GBinderLocalObject action later on the main thread.
|
||||
* We must ensure that remote object doesn't go away before we
|
||||
* acquire our reference to it. One of the references to that
|
||||
* remote object (possibly the last one) may be associated with
|
||||
* the transaction buffer contained in GBinderBufferContentsList.
|
||||
* We don't know exactly which one we need, so we keep all those
|
||||
* buffers alive until we are done with BR_ACQUIRE.
|
||||
*/
|
||||
data->object = gbinder_local_object_ref(self);
|
||||
data->bufs = gbinder_buffer_contents_list_dup(bufs);
|
||||
gbinder_idle_callback_invoke_later(gbinder_local_object_acquire_proc,
|
||||
data, gbinder_local_object_acquire_done);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_release(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_release_proc);
|
||||
gbinder_local_object_handle_later(self, gbinder_local_object_release_proc);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_set_stability(
|
||||
GBinderLocalObject* self,
|
||||
GBINDER_STABILITY_LEVEL stability) /* Since 1.1.40 */
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
self->stability = stability;
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -466,33 +634,33 @@ gbinder_local_object_init(
|
||||
GBinderLocalObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObjectPriv);
|
||||
|
||||
priv->context = g_main_context_default();
|
||||
self->priv = priv;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_dispose(
|
||||
GObject* local)
|
||||
GObject* object)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(object);
|
||||
|
||||
gbinder_ipc_local_object_disposed(self->ipc, self);
|
||||
G_OBJECT_CLASS(gbinder_local_object_parent_class)->dispose(local);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_finalize(
|
||||
GObject* local)
|
||||
GObject* object)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(object);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
GASSERT(!self->strong_refs);
|
||||
gbinder_ipc_invalidate_local_object(self->ipc, self);
|
||||
gbinder_ipc_unref(self->ipc);
|
||||
g_free(priv->iface);
|
||||
G_OBJECT_CLASS(gbinder_local_object_parent_class)->finalize(local);
|
||||
g_strfreev(priv->ifaces);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -512,6 +680,9 @@ gbinder_local_object_class_init(
|
||||
gbinder_local_object_default_handle_looper_transaction;
|
||||
klass->can_handle_transaction =
|
||||
gbinder_local_object_default_can_handle_transaction;
|
||||
klass->acquire = gbinder_local_object_default_acquire;
|
||||
klass->release = gbinder_local_object_default_release;
|
||||
klass->drop = gbinder_local_object_default_drop;
|
||||
|
||||
gbinder_local_object_signals[SIGNAL_WEAK_REFS_CHANGED] =
|
||||
g_signal_new(SIGNAL_WEAK_REFS_CHANGED_NAME,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -40,8 +40,9 @@
|
||||
#include <glib-object.h>
|
||||
|
||||
/*
|
||||
* Some if this stuff may become public if we decide to allow the clients
|
||||
* to derive their classes from GBinderLocalObject
|
||||
* Some of this stuff may become public if we decide to allow the clients
|
||||
* to derive their own classes from GBinderLocalObject. For now it's all
|
||||
* private.
|
||||
*/
|
||||
|
||||
typedef
|
||||
@@ -55,9 +56,10 @@ struct gbinder_local_object {
|
||||
GObject object;
|
||||
GBinderLocalObjectPriv* priv;
|
||||
GBinderIpc* ipc;
|
||||
const char* iface;
|
||||
const char* const* ifaces;
|
||||
gint weak_refs;
|
||||
gint strong_refs;
|
||||
GBINDER_STABILITY_LEVEL stability;
|
||||
};
|
||||
|
||||
typedef enum gbinder_local_transaction_support {
|
||||
@@ -76,47 +78,68 @@ typedef struct gbinder_local_object_class {
|
||||
GBinderLocalReply* (*handle_looper_transaction)
|
||||
(GBinderLocalObject* self, GBinderRemoteRequest* req, guint code,
|
||||
guint flags, int* status);
|
||||
void (*acquire)(GBinderLocalObject* self);
|
||||
void (*release)(GBinderLocalObject* self);
|
||||
void (*drop)(GBinderLocalObject* self);
|
||||
/* Need to add some placeholders if this class becomes public */
|
||||
} GBinderLocalObjectClass;
|
||||
|
||||
GType gbinder_local_object_get_type(void);
|
||||
GType gbinder_local_object_get_type(void) GBINDER_INTERNAL;
|
||||
#define GBINDER_TYPE_LOCAL_OBJECT (gbinder_local_object_get_type())
|
||||
#define GBINDER_LOCAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObject))
|
||||
#define GBINDER_LOCAL_OBJECT_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), \
|
||||
GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObjectClass)
|
||||
|
||||
#define gbinder_local_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
|
||||
#define gbinder_local_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
|
||||
#define gbinder_local_object_protocol(obj) \
|
||||
(gbinder_driver_protocol((obj)->ipc->driver))
|
||||
|
||||
/* Should only be called from gbinder_ipc_new_local_object() */
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_new(
|
||||
gbinder_local_object_new_with_type(
|
||||
GType type,
|
||||
GBinderIpc* ipc,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc handler,
|
||||
void* user_data);
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_local_object_init_base(
|
||||
GBinderLocalObject* self,
|
||||
GBinderIpc* ipc,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gulong
|
||||
gbinder_local_object_add_weak_refs_changed_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderLocalObjectFunc func,
|
||||
void* user_data);
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gulong
|
||||
gbinder_local_object_add_strong_refs_changed_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderLocalObjectFunc func,
|
||||
void* user_data);
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_local_object_remove_handler(
|
||||
GBinderLocalObject* obj,
|
||||
gulong id);
|
||||
gulong id)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
gbinder_local_object_can_handle_transaction(
|
||||
GBinderLocalObject* self,
|
||||
const char* iface,
|
||||
guint code);
|
||||
guint code)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_handle_transaction(
|
||||
@@ -124,7 +147,8 @@ gbinder_local_object_handle_transaction(
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status);
|
||||
int* status)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_handle_looper_transaction(
|
||||
@@ -132,23 +156,29 @@ gbinder_local_object_handle_looper_transaction(
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status);
|
||||
int* status)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_increfs(
|
||||
GBinderLocalObject* obj);
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_decrefs(
|
||||
GBinderLocalObject* obj);
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_acquire(
|
||||
GBinderLocalObject* obj);
|
||||
GBinderLocalObject* obj,
|
||||
GBinderBufferContentsList* bufs)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_release(
|
||||
GBinderLocalObject* obj);
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_LOCAL_OBJECT_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -43,6 +43,7 @@ struct gbinder_local_reply {
|
||||
gint refcount;
|
||||
GBinderWriterData data;
|
||||
GBinderOutputData out;
|
||||
GBinderBufferContents* contents;
|
||||
};
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
@@ -71,10 +72,12 @@ gbinder_local_reply_output_buffers_size(
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new(
|
||||
const GBinderIo* io)
|
||||
const GBinderIo* io,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
GASSERT(io);
|
||||
if (io) {
|
||||
GASSERT(protocol);
|
||||
if (io && protocol) {
|
||||
GBinderLocalReply* self = g_slice_new0(GBinderLocalReply);
|
||||
GBinderWriterData* data = &self->data;
|
||||
GBinderOutputData* out = &self->out;
|
||||
@@ -86,6 +89,7 @@ gbinder_local_reply_new(
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
data->io = io;
|
||||
data->protocol = protocol;
|
||||
out->bytes = data->bytes = g_byte_array_new();
|
||||
out->f = &local_reply_output_fn;
|
||||
return self;
|
||||
@@ -94,14 +98,16 @@ gbinder_local_reply_new(
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new_from_data(
|
||||
GBinderBuffer* buffer)
|
||||
gbinder_local_reply_set_contents(
|
||||
GBinderLocalReply* self,
|
||||
GBinderBuffer* buffer,
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
const GBinderIo* io = gbinder_buffer_io(buffer);
|
||||
GBinderLocalReply* self = gbinder_local_reply_new(io);
|
||||
|
||||
if (self) {
|
||||
gbinder_writer_data_set_contents(&self->data, buffer);
|
||||
gbinder_writer_data_set_contents(&self->data, buffer, convert);
|
||||
gbinder_buffer_contents_unref(self->contents);
|
||||
self->contents = gbinder_buffer_contents_ref
|
||||
(gbinder_buffer_contents(buffer));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -116,7 +122,8 @@ gbinder_local_reply_free(
|
||||
gutil_int_array_free(data->offsets, TRUE);
|
||||
g_byte_array_free(data->bytes, TRUE);
|
||||
gbinder_cleanup_free(data->cleanup);
|
||||
g_slice_free(GBinderLocalReply, self);
|
||||
gbinder_buffer_contents_unref(self->contents);
|
||||
gutil_slice_free(self);
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
@@ -149,6 +156,13 @@ gbinder_local_reply_data(
|
||||
return G_LIKELY(self) ? &self->out : NULL;
|
||||
}
|
||||
|
||||
GBinderBufferContents*
|
||||
gbinder_local_reply_contents(
|
||||
GBinderLocalReply* self)
|
||||
{
|
||||
return G_LIKELY(self) ? self->contents : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_reply_cleanup(
|
||||
GBinderLocalReply* self,
|
||||
@@ -296,6 +310,17 @@ gbinder_local_reply_append_remote_object(
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_fd(
|
||||
GBinderLocalReply* self,
|
||||
int fd) /* Since 1.1.14 */
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_fd(&self->data, fd);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -39,15 +39,26 @@
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new(
|
||||
const GBinderIo* io);
|
||||
const GBinderIo* io,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderOutputData*
|
||||
gbinder_local_reply_data(
|
||||
GBinderLocalReply* reply);
|
||||
GBinderLocalReply* reply)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderBufferContents*
|
||||
gbinder_local_reply_contents(
|
||||
GBinderLocalReply* reply)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new_from_data(
|
||||
GBinderBuffer* buffer);
|
||||
gbinder_local_reply_set_contents(
|
||||
GBinderLocalReply* reply,
|
||||
GBinderBuffer* buffer,
|
||||
GBinderObjectConverter* convert)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_LOCAL_REPLY_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_writer_p.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
@@ -73,10 +74,12 @@ gbinder_local_request_output_buffers_size(
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new(
|
||||
const GBinderIo* io,
|
||||
const GBinderRpcProtocol* protocol,
|
||||
GBytes* init)
|
||||
{
|
||||
GASSERT(io);
|
||||
if (io) {
|
||||
GASSERT(protocol);
|
||||
if (io && protocol) {
|
||||
GBinderLocalRequest* self = g_slice_new0(GBinderLocalRequest);
|
||||
GBinderWriterData* writer = &self->data;
|
||||
GBinderOutputData* out = &self->out;
|
||||
@@ -88,9 +91,11 @@ gbinder_local_request_new(
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
writer->io = io;
|
||||
writer->protocol = protocol;
|
||||
if (init) {
|
||||
gsize size;
|
||||
gconstpointer data = g_bytes_get_data(init, &size);
|
||||
|
||||
writer->bytes = g_byte_array_sized_new(size);
|
||||
g_byte_array_append(writer->bytes, data, size);
|
||||
} else {
|
||||
@@ -104,18 +109,49 @@ gbinder_local_request_new(
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new_from_data(
|
||||
GBinderBuffer* buffer)
|
||||
gbinder_local_request_new_iface(
|
||||
const GBinderIo* io,
|
||||
const GBinderRpcProtocol* protocol,
|
||||
const char* iface)
|
||||
{
|
||||
GBinderLocalRequest* self = gbinder_local_request_new
|
||||
(gbinder_buffer_io(buffer), NULL);
|
||||
GBinderLocalRequest* self = gbinder_local_request_new(io, protocol, NULL);
|
||||
|
||||
if (self) {
|
||||
gbinder_writer_data_set_contents(&self->data, buffer);
|
||||
/* gbinder_local_request_new() fails if protocol is NULL */
|
||||
if (self && G_LIKELY(iface)) {
|
||||
GBinderWriter writer;
|
||||
|
||||
gbinder_local_request_init_writer(self, &writer);
|
||||
protocol->write_rpc_header(&writer, iface);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new_from_data(
|
||||
GBinderBuffer* buffer,
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
GBinderLocalRequest* self = gbinder_local_request_new
|
||||
(gbinder_buffer_io(buffer), gbinder_buffer_protocol(buffer), NULL);
|
||||
|
||||
if (self) {
|
||||
gbinder_writer_data_append_contents(&self->data, buffer, 0, convert);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_request_append_contents(
|
||||
GBinderLocalRequest* self,
|
||||
GBinderBuffer* buffer,
|
||||
gsize off,
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
if (self) {
|
||||
gbinder_writer_data_append_contents(&self->data, buffer, off, convert);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_request_free(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -40,15 +40,35 @@
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new(
|
||||
const GBinderIo* io,
|
||||
GBytes* init);
|
||||
const GBinderRpcProtocol* protocol,
|
||||
GBytes* init)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderOutputData*
|
||||
gbinder_local_request_data(
|
||||
GBinderLocalRequest* req);
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new_iface(
|
||||
const GBinderIo* io,
|
||||
const GBinderRpcProtocol* protocol,
|
||||
const char* iface)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new_from_data(
|
||||
GBinderBuffer* buffer);
|
||||
GBinderBuffer* buffer,
|
||||
GBinderObjectConverter* convert)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderOutputData*
|
||||
gbinder_local_request_data(
|
||||
GBinderLocalRequest* req)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_local_request_append_contents(
|
||||
GBinderLocalRequest* req,
|
||||
GBinderBuffer* buffer,
|
||||
gsize offset,
|
||||
GBinderObjectConverter* convert)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
|
||||
|
||||
|
||||
62
src/gbinder_log.c
Normal file
62
src/gbinder_log.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Jolla Ltd.
|
||||
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Log module */
|
||||
GLOG_MODULE_DEFINE("gbinder");
|
||||
|
||||
/* Initializes the default log level at startup */
|
||||
void
|
||||
gbinder_log_init(
|
||||
void)
|
||||
{
|
||||
int level = GLOG_MODULE_NAME.level;
|
||||
|
||||
if (gutil_parse_int(getenv("GBINDER_DEFAULT_LOG_LEVEL"), 0, &level) &&
|
||||
level >= GLOG_LEVEL_INHERIT && level <= GLOG_LEVEL_VERBOSE) {
|
||||
GINFO("Log level %d", level);
|
||||
GLOG_MODULE_NAME.level = level;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -33,11 +33,21 @@
|
||||
#ifndef GBINDER_LOG_H
|
||||
#define GBINDER_LOG_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
#define GLOG_MODULE_NAME GBINDER_LOG_MODULE
|
||||
#include <gutil_log.h>
|
||||
|
||||
#define DBG(fmt, ...) \
|
||||
gutil_log(GLOG_MODULE_CURRENT, GLOG_LEVEL_ALWAYS, "gbinder:"fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Declared for unit tests */
|
||||
__attribute__((constructor))
|
||||
void
|
||||
gbinder_log_init(
|
||||
void)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_LOG_H */
|
||||
|
||||
/*
|
||||
|
||||
67
src/gbinder_object_converter.h
Normal file
67
src/gbinder_object_converter.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_OBJECT_CONVERTER_H
|
||||
#define GBINDER_OBJECT_CONVERTER_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef struct gbinder_object_converter_functions {
|
||||
GBinderLocalObject* (*handle_to_local)(GBinderObjectConverter*, guint32);
|
||||
} GBinderObjectConverterFunctions;
|
||||
|
||||
struct gbinder_object_converter {
|
||||
const GBinderObjectConverterFunctions* f;
|
||||
const GBinderIo* io;
|
||||
const GBinderRpcProtocol* protocol;
|
||||
};
|
||||
|
||||
/* Inline wrappers */
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderLocalObject*
|
||||
gbinder_object_converter_handle_to_local(
|
||||
GBinderObjectConverter* convert,
|
||||
guint32 handle)
|
||||
{
|
||||
return convert ? convert->f->handle_to_local(convert, handle) : NULL;
|
||||
}
|
||||
|
||||
#endif /* GBINDER_OBJECT_CONVERTER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -35,13 +35,19 @@
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef enum gbinder_remote_registry_create {
|
||||
REMOTE_REGISTRY_DONT_CREATE,
|
||||
REMOTE_REGISTRY_CAN_CREATE,
|
||||
REMOTE_REGISTRY_CAN_CREATE_AND_ACQUIRE
|
||||
} REMOTE_REGISTRY_CREATE;
|
||||
|
||||
typedef struct gbinder_object_registry_functions {
|
||||
void (*ref)(GBinderObjectRegistry* reg);
|
||||
void (*unref)(GBinderObjectRegistry* reg);
|
||||
GBinderLocalObject* (*get_local)(GBinderObjectRegistry* reg,
|
||||
void* pointer);
|
||||
GBinderRemoteObject* (*get_remote)(GBinderObjectRegistry* reg,
|
||||
guint32 handle);
|
||||
guint32 handle, REMOTE_REGISTRY_CREATE create);
|
||||
} GBinderObjectRegistryFunctions;
|
||||
|
||||
struct gbinder_object_registry {
|
||||
@@ -81,9 +87,10 @@ GBINDER_INLINE_FUNC
|
||||
GBinderRemoteObject*
|
||||
gbinder_object_registry_get_remote(
|
||||
GBinderObjectRegistry* reg,
|
||||
guint32 handle)
|
||||
guint32 handle,
|
||||
REMOTE_REGISTRY_CREATE create)
|
||||
{
|
||||
return reg ? reg->f->get_remote(reg, handle) : NULL;
|
||||
return reg ? reg->f->get_remote(reg, handle, create) : NULL;
|
||||
}
|
||||
|
||||
#endif /* GBINDER_OBJECT_REGISTRY_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
420
src/gbinder_proxy_object.c
Normal file
420
src/gbinder_proxy_object.c
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2023 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_proxy_object.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_local_request.h"
|
||||
#include "gbinder_local_reply.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_remote_request_p.h"
|
||||
#include "gbinder_remote_reply_p.h"
|
||||
#include "gbinder_object_converter.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
typedef GBinderLocalObjectClass GBinderProxyObjectClass;
|
||||
typedef struct gbinder_proxy_tx GBinderProxyTx;
|
||||
|
||||
struct gbinder_proxy_tx {
|
||||
GBinderProxyTx* next;
|
||||
GBinderRemoteRequest* req;
|
||||
GBinderProxyObject* proxy;
|
||||
gulong id;
|
||||
};
|
||||
|
||||
struct gbinder_proxy_object_priv {
|
||||
gboolean acquired;
|
||||
gboolean dropped;
|
||||
GBinderProxyTx* tx;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GBinderProxyObject, gbinder_proxy_object, \
|
||||
GBINDER_TYPE_LOCAL_OBJECT)
|
||||
#define GBINDER_IS_PROXY_OBJECT(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, \
|
||||
GBINDER_TYPE_PROXY_OBJECT)
|
||||
|
||||
#define THIS(obj) GBINDER_PROXY_OBJECT(obj)
|
||||
#define THIS_TYPE GBINDER_TYPE_PROXY_OBJECT
|
||||
#define PARENT_CLASS gbinder_proxy_object_parent_class
|
||||
|
||||
/*==========================================================================*
|
||||
* Converter
|
||||
*==========================================================================*/
|
||||
|
||||
typedef struct gbinder_proxy_object_converter {
|
||||
GBinderObjectConverter pub;
|
||||
GBinderIpc* remote;
|
||||
GBinderIpc* local;
|
||||
} GBinderProxyObjectConverter;
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderProxyObjectConverter*
|
||||
gbinder_proxy_object_converter_cast(
|
||||
GBinderObjectConverter* pub)
|
||||
{
|
||||
return G_CAST(pub, GBinderProxyObjectConverter, pub);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_proxy_object_converter_check(
|
||||
GBinderLocalObject* obj,
|
||||
void* remote)
|
||||
{
|
||||
if (GBINDER_IS_PROXY_OBJECT(obj) && THIS(obj)->remote == remote) {
|
||||
/* Found matching proxy object */
|
||||
return TRUE;
|
||||
}
|
||||
/* Keep looking */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalObject*
|
||||
gbinder_proxy_object_converter_handle_to_local(
|
||||
GBinderObjectConverter* pub,
|
||||
guint32 handle)
|
||||
{
|
||||
GBinderProxyObjectConverter* c = gbinder_proxy_object_converter_cast(pub);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(c->remote);
|
||||
GBinderRemoteObject* remote = gbinder_object_registry_get_remote(reg,
|
||||
handle, REMOTE_REGISTRY_CAN_CREATE /* but don't acquire */);
|
||||
GBinderLocalObject* local = gbinder_ipc_find_local_object(c->local,
|
||||
gbinder_proxy_object_converter_check, remote);
|
||||
|
||||
if (!local && !remote->dead) {
|
||||
/* GBinderProxyObject will reference GBinderRemoteObject */
|
||||
local = &gbinder_proxy_object_new(c->local, remote)->parent;
|
||||
}
|
||||
|
||||
/* Release the reference returned by gbinder_object_registry_get_remote */
|
||||
gbinder_remote_object_unref(remote);
|
||||
return local;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_converter_init(
|
||||
GBinderProxyObjectConverter* convert,
|
||||
GBinderProxyObject* proxy,
|
||||
GBinderIpc* remote,
|
||||
GBinderIpc* local)
|
||||
{
|
||||
static const GBinderObjectConverterFunctions gbinder_converter_fn = {
|
||||
.handle_to_local = gbinder_proxy_object_converter_handle_to_local
|
||||
};
|
||||
|
||||
GBinderObjectConverter* pub = &convert->pub;
|
||||
GBinderIpc* dest = proxy->parent.ipc;
|
||||
|
||||
memset(convert, 0, sizeof(*convert));
|
||||
convert->remote = remote;
|
||||
convert->local = local;
|
||||
pub->f = &gbinder_converter_fn;
|
||||
pub->io = gbinder_ipc_io(dest);
|
||||
pub->protocol = gbinder_ipc_protocol(dest);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_tx_dequeue(
|
||||
GBinderProxyTx* tx)
|
||||
{
|
||||
GBinderProxyObject* proxy = tx->proxy;
|
||||
|
||||
if (proxy) {
|
||||
GBinderProxyObjectPriv* priv = proxy->priv;
|
||||
|
||||
if (priv->tx) {
|
||||
if (priv->tx == tx) {
|
||||
priv->tx = tx->next;
|
||||
} else {
|
||||
GBinderProxyTx* prev = priv->tx;
|
||||
|
||||
while (prev->next) {
|
||||
if (prev->next == tx) {
|
||||
prev->next = tx->next;
|
||||
break;
|
||||
}
|
||||
prev = prev->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
tx->next = NULL;
|
||||
tx->proxy = NULL;
|
||||
g_object_unref(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_tx_reply(
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderProxyTx* tx = user_data;
|
||||
GBinderProxyObject* self = tx->proxy;
|
||||
GBinderProxyObjectConverter convert;
|
||||
GBinderLocalReply* fwd;
|
||||
|
||||
/*
|
||||
* For proxy objects auto-created by the reply, the remote side (the
|
||||
* one sent the reply) will be the remote GBinderIpc and this object's
|
||||
* GBinderIpc will be the local, i.e. those proxies will work in the
|
||||
* same direction as the top level object. The direction gets inverted
|
||||
* twice.
|
||||
*/
|
||||
gbinder_proxy_object_converter_init(&convert, self, ipc, self->parent.ipc);
|
||||
fwd = gbinder_remote_reply_convert_to_local(reply, &convert.pub);
|
||||
tx->id = 0;
|
||||
gbinder_proxy_tx_dequeue(tx);
|
||||
gbinder_remote_request_complete(tx->req, fwd,
|
||||
(status > 0) ? (-EFAULT) : status);
|
||||
if (status == GBINDER_STATUS_DEAD_OBJECT) {
|
||||
/*
|
||||
* Some kernels sometimes don't bother sending us death notifications.
|
||||
* Let's also interpret BR_DEAD_REPLY as an obituary to make sure that
|
||||
* we don't keep dead remote objects around.
|
||||
*/
|
||||
gbinder_remote_object_commit_suicide(self->remote);
|
||||
}
|
||||
gbinder_local_reply_unref(fwd);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_tx_destroy(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderProxyTx* tx = user_data;
|
||||
|
||||
gbinder_proxy_tx_dequeue(tx);
|
||||
gbinder_remote_request_unref(tx->req);
|
||||
gutil_slice_free(tx);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_proxy_object_handle_transaction(
|
||||
GBinderLocalObject* object,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
if (!priv->dropped && !remote->dead) {
|
||||
GBinderLocalRequest* fwd;
|
||||
GBinderProxyTx* tx = g_slice_new0(GBinderProxyTx);
|
||||
GBinderProxyObjectConverter convert;
|
||||
|
||||
g_object_ref(tx->proxy = self);
|
||||
tx->req = gbinder_remote_request_ref(req);
|
||||
tx->next = priv->tx;
|
||||
priv->tx = tx;
|
||||
|
||||
/* Mark the incoming request as pending */
|
||||
gbinder_remote_request_block(req);
|
||||
|
||||
/*
|
||||
* For auto-created proxy objects, this object's GBinderIpc will
|
||||
* become a remote, and the remote's GBinderIpc will become local
|
||||
* because they work in the opposite direction.
|
||||
*/
|
||||
gbinder_proxy_object_converter_init(&convert, self, object->ipc,
|
||||
remote->ipc);
|
||||
|
||||
/* Forward the transaction */
|
||||
fwd = gbinder_remote_request_convert_to_local(req, &convert.pub);
|
||||
tx->id = gbinder_ipc_transact(remote->ipc, remote->handle, code, flags,
|
||||
fwd, gbinder_proxy_tx_reply, gbinder_proxy_tx_destroy, tx);
|
||||
gbinder_local_request_unref(fwd);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
} else {
|
||||
GVERBOSE_("dropped: %d dead:%d", priv->dropped, remote->dead);
|
||||
*status = (-EBADMSG);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
gbinder_proxy_object_can_handle_transaction(
|
||||
GBinderLocalObject* self,
|
||||
const char* iface,
|
||||
guint code)
|
||||
{
|
||||
/* Process all transactions on the main thread */
|
||||
return GBINDER_LOCAL_TRANSACTION_SUPPORTED;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_acquire(
|
||||
GBinderLocalObject* object)
|
||||
{
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
if (!remote->dead && !priv->dropped && !priv->acquired) {
|
||||
/* Not acquired yet */
|
||||
priv->acquired = TRUE;
|
||||
gbinder_driver_acquire(remote->ipc->driver, remote->handle);
|
||||
}
|
||||
GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->acquire(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_drop(
|
||||
GBinderLocalObject* object)
|
||||
{
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
|
||||
priv->dropped = TRUE;
|
||||
GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->drop(object);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderProxyObject*
|
||||
gbinder_proxy_object_new(
|
||||
GBinderIpc* src,
|
||||
GBinderRemoteObject* remote)
|
||||
{
|
||||
if (G_LIKELY(remote)) {
|
||||
/*
|
||||
* We don't need to specify the interface list because all
|
||||
* transactions (including HIDL_GET_DESCRIPTOR_TRANSACTION
|
||||
* and HIDL_DESCRIPTOR_CHAIN_TRANSACTION) are getting forwared
|
||||
* to the remote object.
|
||||
*/
|
||||
GBinderLocalObject* object = gbinder_local_object_new_with_type
|
||||
(THIS_TYPE, src, NULL, NULL, NULL);
|
||||
|
||||
if (object) {
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
|
||||
GDEBUG("Proxy %p %s => %u %s created", self, gbinder_ipc_name(src),
|
||||
remote->handle, gbinder_ipc_name(remote->ipc));
|
||||
self->remote = gbinder_remote_object_ref(remote);
|
||||
return self;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
GBinderLocalObject* local = &self->parent;
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
/*
|
||||
* gbinder_local_object_finalize() will also try to do the same thing
|
||||
* i.e. invalidate self but proxy objects need to do it before releasing
|
||||
* the handle, to leave no room for race conditions. That's not very good
|
||||
* because it grabs ipc-wide mutex but shouldn'd have much of an impact
|
||||
* on the performance because finalizing a proxy is not supposed to be a
|
||||
* frequent operation.
|
||||
*/
|
||||
gbinder_ipc_invalidate_local_object(local->ipc, local);
|
||||
if (priv->acquired) {
|
||||
gbinder_driver_release(remote->ipc->driver, remote->handle);
|
||||
}
|
||||
GDEBUG("Proxy %p %s => %u %s gone", self,
|
||||
gbinder_ipc_name(self->parent.ipc), remote->handle,
|
||||
gbinder_ipc_name(remote->ipc));
|
||||
gbinder_remote_object_unref(remote);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_init(
|
||||
GBinderProxyObject* self)
|
||||
{
|
||||
GBinderProxyObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
THIS_TYPE, GBinderProxyObjectPriv);
|
||||
|
||||
self->priv = priv;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_class_init(
|
||||
GBinderProxyObjectClass* klass)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GBinderProxyObjectPriv));
|
||||
object_class->finalize = gbinder_proxy_object_finalize;
|
||||
klass->can_handle_transaction = gbinder_proxy_object_can_handle_transaction;
|
||||
klass->handle_transaction = gbinder_proxy_object_handle_transaction;
|
||||
klass->acquire = gbinder_proxy_object_acquire;
|
||||
klass->drop = gbinder_proxy_object_drop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
66
src/gbinder_proxy_object.h
Normal file
66
src/gbinder_proxy_object.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_PROXY_OBJECT_H
|
||||
#define GBINDER_PROXY_OBJECT_H
|
||||
|
||||
#include "gbinder_local_object_p.h"
|
||||
|
||||
typedef struct gbinder_proxy_object_priv GBinderProxyObjectPriv;
|
||||
|
||||
struct gbinder_proxy_object {
|
||||
GBinderLocalObject parent;
|
||||
GBinderProxyObjectPriv* priv;
|
||||
GBinderRemoteObject* remote;
|
||||
};
|
||||
|
||||
GType gbinder_proxy_object_get_type(void) GBINDER_INTERNAL;
|
||||
#define GBINDER_TYPE_PROXY_OBJECT gbinder_proxy_object_get_type()
|
||||
#define GBINDER_PROXY_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_PROXY_OBJECT, GBinderProxyObject))
|
||||
|
||||
/* Registers with src and forwards all transactions to the remote */
|
||||
GBinderProxyObject*
|
||||
gbinder_proxy_object_new(
|
||||
GBinderIpc* src,
|
||||
GBinderRemoteObject* remote)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_PROXY_OBJECT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2024 Jolla Ltd.
|
||||
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -90,7 +90,7 @@ gbinder_reader_at_end(
|
||||
{
|
||||
const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
|
||||
|
||||
return p->ptr >= p->end;
|
||||
return !p || p->ptr >= p->end;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -123,13 +123,74 @@ gboolean
|
||||
gbinder_reader_read_bool(
|
||||
GBinderReader* reader,
|
||||
gboolean* value)
|
||||
{
|
||||
/*
|
||||
* Android's libhwbinder writes bool as a single byte and pads it
|
||||
* with zeros, but libbinder writes bool as int32 in native byte
|
||||
* order. The latter becomes either [0x01, 0x00, 0x00, 0x00] or
|
||||
* [0x00, 0x00, 0x00, 0x01] depending on the byte order. Reading
|
||||
* uint32 and comparing it with zero works in either case.
|
||||
*/
|
||||
if (value) {
|
||||
guint32 padded;
|
||||
|
||||
if (gbinder_reader_read_uint32(reader, &padded)) {
|
||||
*value = (padded != 0);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
return gbinder_reader_read_uint32(reader, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int8(
|
||||
GBinderReader* reader,
|
||||
gint8* value) /* Since 1.1.15 */
|
||||
{
|
||||
return gbinder_reader_read_uint8(reader, (guint8*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint8(
|
||||
GBinderReader* reader,
|
||||
guint8* value) /* Since 1.1.15 */
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
/* Boolean values are supposed to be padded to 4-byte boundary */
|
||||
/* Primitive values are supposed to be padded to 4-byte boundary */
|
||||
if (gbinder_reader_can_read(p, 4)) {
|
||||
if (value) {
|
||||
*value = (p->ptr[0] != 0);
|
||||
*value = p->ptr[0];
|
||||
}
|
||||
p->ptr += 4;
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int16(
|
||||
GBinderReader* reader,
|
||||
gint16* value) /* Since 1.1.15 */
|
||||
{
|
||||
return gbinder_reader_read_uint16(reader, (guint16*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint16(
|
||||
GBinderReader* reader,
|
||||
guint16* value) /* Since 1.1.15 */
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
/* Primitive values are supposed to be padded to 4-byte boundary */
|
||||
if (gbinder_reader_can_read(p, 4)) {
|
||||
if (value) {
|
||||
*value = *(guint16*)p->ptr;
|
||||
}
|
||||
p->ptr += 4;
|
||||
return TRUE;
|
||||
@@ -296,7 +357,8 @@ gbinder_reader_read_nullable_object(
|
||||
if (gbinder_reader_can_read_object(p)) {
|
||||
const GBinderReaderData* data = p->data;
|
||||
const guint eaten = data->reg->io->decode_binder_object(p->ptr,
|
||||
gbinder_reader_bytes_remaining(reader), data->reg, out);
|
||||
gbinder_reader_bytes_remaining(reader), data->reg, out,
|
||||
gbinder_buffer_protocol(data->buffer));
|
||||
|
||||
if (eaten) {
|
||||
p->ptr += eaten;
|
||||
@@ -320,9 +382,9 @@ gbinder_reader_read_object(
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_reader_read_buffer_impl(
|
||||
gbinder_reader_read_buffer_object(
|
||||
GBinderReader* reader,
|
||||
GBinderBuffer** out)
|
||||
GBinderIoBufferObject* out)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
@@ -339,7 +401,6 @@ gbinder_reader_read_buffer_impl(
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (out) *out = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -347,34 +408,70 @@ GBinderBuffer*
|
||||
gbinder_reader_read_buffer(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderBuffer* buf = NULL;
|
||||
GBinderIoBufferObject obj;
|
||||
|
||||
gbinder_reader_read_buffer_impl(reader, &buf);
|
||||
return buf;
|
||||
if (gbinder_reader_read_buffer_object(reader, &obj)) {
|
||||
const GBinderReaderData* data = gbinder_reader_cast(reader)->data;
|
||||
GBinderBuffer* buf = data->buffer;
|
||||
|
||||
return gbinder_buffer_new_with_parent(buf, obj.data, obj.size);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_skip_buffer(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
return gbinder_reader_read_buffer_impl(reader, NULL);
|
||||
return gbinder_reader_read_buffer_object(reader, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is supposed to be used to read aidl parcelables, and is not
|
||||
* guaranteed to work on any other kind of parcelable.
|
||||
*/
|
||||
const void*
|
||||
gbinder_reader_read_parcelable(
|
||||
GBinderReader* reader,
|
||||
gsize* size) /* Since 1.1.19 */
|
||||
{
|
||||
guint32 non_null, payload_size = 0;
|
||||
|
||||
if (gbinder_reader_read_uint32(reader, &non_null) && non_null &&
|
||||
gbinder_reader_read_uint32(reader, &payload_size) &&
|
||||
payload_size >= sizeof(payload_size)) {
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
payload_size -= sizeof(payload_size);
|
||||
if (p->ptr + payload_size <= p->end) {
|
||||
const void* out = p->ptr;
|
||||
|
||||
/* Success */
|
||||
p->ptr += payload_size;
|
||||
if (size) {
|
||||
*size = payload_size;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
if (size) {
|
||||
*size = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Helper for gbinder_reader_read_hidl_struct() macro */
|
||||
const void*
|
||||
gbinder_reader_read_hidl_struct1(
|
||||
GBinderReader* reader,
|
||||
gsize size) /* since 1.0.9 */
|
||||
gsize size) /* Since 1.0.9 */
|
||||
{
|
||||
const void* result = NULL;
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
GBinderIoBufferObject obj;
|
||||
|
||||
/* Check the size */
|
||||
if (buf && buf->size == size) {
|
||||
result = buf->data;
|
||||
if (gbinder_reader_read_buffer_object(reader, &obj) && obj.size == size) {
|
||||
return obj.data;
|
||||
}
|
||||
gbinder_buffer_free(buf);
|
||||
return result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Doesn't copy the data */
|
||||
@@ -384,30 +481,28 @@ gbinder_reader_read_hidl_vec(
|
||||
gsize* count,
|
||||
gsize* elemsize)
|
||||
{
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
gsize out_count = 0, out_elemsize = 0;
|
||||
GBinderIoBufferObject obj;
|
||||
const void* out = NULL;
|
||||
gsize out_count = 0, out_elemsize = 0;
|
||||
|
||||
if (buf && buf->size == sizeof(GBinderHidlVec)) {
|
||||
const GBinderHidlVec* vec = buf->data;
|
||||
if (gbinder_reader_read_buffer_object(reader, &obj) &&
|
||||
obj.data && obj.size == sizeof(GBinderHidlVec)) {
|
||||
const GBinderHidlVec* vec = obj.data;
|
||||
const void* next = vec->data.ptr;
|
||||
|
||||
if (next) {
|
||||
GBinderBuffer* vbuf = gbinder_reader_read_buffer(reader);
|
||||
|
||||
if (vbuf && vbuf->data == next && ((!vec->count && !vbuf->size) ||
|
||||
(vec->count && vbuf->size && !(vbuf->size % vec->count)))) {
|
||||
out_elemsize = vec->count ? (vbuf->size / vec->count) : 0;
|
||||
if (gbinder_reader_read_buffer_object(reader, &obj) &&
|
||||
obj.data == next && ((!vec->count && !obj.size) ||
|
||||
(vec->count && obj.size && !(obj.size % vec->count)))) {
|
||||
out_elemsize = vec->count ? (obj.size / vec->count) : 0;
|
||||
out_count = vec->count;
|
||||
out = vbuf->data;
|
||||
out = obj.data;
|
||||
}
|
||||
gbinder_buffer_free(vbuf);
|
||||
} else if (!vec->count) {
|
||||
/* Any non-NULL pointer just to indicate success */
|
||||
/* Any non-NULL pointer just to indicate success? */
|
||||
out = vec;
|
||||
}
|
||||
}
|
||||
gbinder_buffer_free(buf);
|
||||
if (elemsize) {
|
||||
*elemsize = out_elemsize;
|
||||
}
|
||||
@@ -422,7 +517,7 @@ const void*
|
||||
gbinder_reader_read_hidl_vec1(
|
||||
GBinderReader* reader,
|
||||
gsize* count,
|
||||
guint expected_elem_size) /* since 1.0.9 */
|
||||
guint expected_elem_size) /* Since 1.0.9 */
|
||||
{
|
||||
gsize actual;
|
||||
const void* data = gbinder_reader_read_hidl_vec(reader, count, &actual);
|
||||
@@ -431,89 +526,94 @@ gbinder_reader_read_hidl_vec1(
|
||||
return (data && (actual == expected_elem_size || !actual)) ? data : NULL;
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_reader_read_hidl_string_c(
|
||||
GBinderReader* reader) /* Since 1.0.23 */
|
||||
{
|
||||
GBinderIoBufferObject obj;
|
||||
|
||||
if (gbinder_reader_read_buffer_object(reader, &obj) &&
|
||||
obj.data && obj.size == sizeof(GBinderHidlString)) {
|
||||
const GBinderHidlString* str = obj.data;
|
||||
|
||||
if (gbinder_reader_read_buffer_object(reader, &obj) &&
|
||||
obj.has_parent &&
|
||||
obj.parent_offset == GBINDER_HIDL_STRING_BUFFER_OFFSET &&
|
||||
obj.data == str->data.str &&
|
||||
obj.size == str->len + 1 &&
|
||||
str->data.str[str->len] == 0) {
|
||||
return str->data.str;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char*
|
||||
gbinder_reader_read_hidl_string(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
char* str = NULL;
|
||||
|
||||
if (buf && buf->size == sizeof(GBinderHidlString)) {
|
||||
const GBinderHidlString* s = buf->data;
|
||||
GBinderBuffer* sbuf = gbinder_reader_read_buffer(reader);
|
||||
|
||||
if (sbuf && sbuf->size == s->len + 1 &&
|
||||
sbuf->data == s->data.str &&
|
||||
s->data.str[s->len] == 0) {
|
||||
str = g_strdup(s->data.str);
|
||||
}
|
||||
gbinder_buffer_free(sbuf);
|
||||
}
|
||||
gbinder_buffer_free(buf);
|
||||
return str;
|
||||
/* This function should've been called gbinder_reader_dup_hidl_string */
|
||||
return g_strdup(gbinder_reader_read_hidl_string_c(reader));
|
||||
}
|
||||
|
||||
char**
|
||||
gbinder_reader_read_hidl_string_vec(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
GBinderIoBufferObject obj;
|
||||
|
||||
/* First buffer contains hidl_vector */
|
||||
if (buf && buf->size == sizeof(GBinderHidlVec)) {
|
||||
GBinderHidlVec* vec = buf->data;
|
||||
if (gbinder_reader_read_buffer_object(reader, &obj) &&
|
||||
obj.data && obj.size == sizeof(GBinderHidlVec)) {
|
||||
GBinderHidlVec* vec = obj.data;
|
||||
const guint n = vec->count;
|
||||
const void* next = vec->data.ptr;
|
||||
|
||||
gbinder_buffer_free(buf);
|
||||
if (!next && !n) {
|
||||
char** out = g_new(char*, 1);
|
||||
/* Should this be considered an error? */
|
||||
return g_new0(char*, 1);
|
||||
} else if (gbinder_reader_read_buffer_object(reader, &obj) &&
|
||||
/* The second buffer (if any) contains n hidl_string's */
|
||||
obj.parent_offset == GBINDER_HIDL_VEC_BUFFER_OFFSET &&
|
||||
obj.has_parent &&
|
||||
obj.data == next &&
|
||||
obj.size == (sizeof(GBinderHidlString) * n)) {
|
||||
const GBinderHidlString* strings = obj.data;
|
||||
GPtrArray* list = g_ptr_array_sized_new(n + 1);
|
||||
guint i;
|
||||
|
||||
out[0] = NULL;
|
||||
return out;
|
||||
} else {
|
||||
/* The second buffer (if any) contains n hidl_string's */
|
||||
buf = gbinder_reader_read_buffer(reader);
|
||||
if (buf && buf->data == next &&
|
||||
buf->size == (sizeof(GBinderHidlString) * n)) {
|
||||
const GBinderHidlString* strings = buf->data;
|
||||
GBinderBuffer* sbuf;
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
guint i;
|
||||
/* Now we expect n buffers containing the actual data */
|
||||
for (i = 0; i < n &&
|
||||
gbinder_reader_read_buffer_object(reader, &obj); i++) {
|
||||
const GBinderHidlString* s = strings + i;
|
||||
const gsize expected_offset = (i * sizeof(*s)) +
|
||||
GBINDER_HIDL_STRING_BUFFER_OFFSET;
|
||||
if (obj.has_parent &&
|
||||
obj.parent_offset == expected_offset &&
|
||||
obj.data == s->data.str &&
|
||||
obj.size == s->len + 1 &&
|
||||
s->data.str[s->len] == 0) {
|
||||
char* name = g_strdup(s->data.str);
|
||||
|
||||
/* Now we expect n buffers containing the actual data */
|
||||
for (i=0; i<n &&
|
||||
(sbuf = gbinder_reader_read_buffer(reader)); i++) {
|
||||
const GBinderHidlString* s = strings + i;
|
||||
if (sbuf->size == s->len + 1 &&
|
||||
sbuf->data == s->data.str &&
|
||||
s->data.str[s->len] == 0) {
|
||||
char* name = g_strdup(s->data.str);
|
||||
|
||||
g_ptr_array_add(list, name);
|
||||
GVERBOSE_("%u. %s", i + 1, name);
|
||||
gbinder_buffer_free(sbuf);
|
||||
} else {
|
||||
GWARN("Unexpected hidl_string buffer %p/%u vs %p/%u",
|
||||
sbuf->data, (guint)sbuf->size, s->data.str, s->len);
|
||||
gbinder_buffer_free(sbuf);
|
||||
break;
|
||||
}
|
||||
g_ptr_array_add(list, name);
|
||||
GVERBOSE_("%u. %s", i + 1, name);
|
||||
} else {
|
||||
GWARN("Unexpected hidl_string buffer %p/%u vs %p/%u",
|
||||
obj.data, (guint)obj.size, s->data.str, s->len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == n) {
|
||||
gbinder_buffer_free(buf);
|
||||
g_ptr_array_add(list, NULL);
|
||||
return (char**)g_ptr_array_free(list, FALSE);
|
||||
}
|
||||
|
||||
g_ptr_array_set_free_func(list, g_free);
|
||||
g_ptr_array_free(list, TRUE);
|
||||
}
|
||||
|
||||
if (i == n) {
|
||||
g_ptr_array_add(list, NULL);
|
||||
return (char**)g_ptr_array_free(list, FALSE);
|
||||
}
|
||||
|
||||
g_ptr_array_set_free_func(list, g_free);
|
||||
g_ptr_array_free(list, TRUE);
|
||||
}
|
||||
}
|
||||
GWARN("Invalid hidl_vec<string>");
|
||||
gbinder_buffer_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -546,7 +646,7 @@ gbinder_reader_read_nullable_string16(
|
||||
GBinderReader* reader,
|
||||
char** out)
|
||||
{
|
||||
gunichar2* str;
|
||||
const gunichar2* str;
|
||||
gsize len;
|
||||
|
||||
if (gbinder_reader_read_nullable_string16_utf16(reader, &str, &len)) {
|
||||
@@ -561,8 +661,8 @@ gbinder_reader_read_nullable_string16(
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_string16_utf16(
|
||||
GBinderReader* reader,
|
||||
gunichar2** out,
|
||||
gsize* out_len) /* since 1.0.17 */
|
||||
const gunichar2** out,
|
||||
gsize* out_len) /* Since 1.0.17 */
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
@@ -582,7 +682,7 @@ gbinder_reader_read_nullable_string16_utf16(
|
||||
return TRUE;
|
||||
} else if (len >= 0) {
|
||||
const guint32 padded_len = G_ALIGN4((len + 1)*2);
|
||||
gunichar2* utf16 = (gunichar2*)(p->ptr + 4);
|
||||
const gunichar2* utf16 = (gunichar2*)(p->ptr + 4);
|
||||
|
||||
if ((p->ptr + padded_len + 4) <= p->end) {
|
||||
p->ptr += padded_len + 4;
|
||||
@@ -599,6 +699,21 @@ gbinder_reader_read_nullable_string16_utf16(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const gunichar2*
|
||||
gbinder_reader_read_string16_utf16(
|
||||
GBinderReader* reader,
|
||||
gsize* len) /* Since 1.0.26 */
|
||||
{
|
||||
const gunichar2* str;
|
||||
|
||||
/*
|
||||
* Use gbinder_reader_read_nullable_string16_utf16 to distinguish
|
||||
* NULL string from a parsing failure.
|
||||
*/
|
||||
return gbinder_reader_read_nullable_string16_utf16(reader, &str, len) ?
|
||||
str : NULL;
|
||||
}
|
||||
|
||||
char*
|
||||
gbinder_reader_read_string16(
|
||||
GBinderReader* reader)
|
||||
@@ -638,7 +753,7 @@ gbinder_reader_skip_string16(
|
||||
const void*
|
||||
gbinder_reader_read_byte_array(
|
||||
GBinderReader* reader,
|
||||
gsize* len) /* since 1.0.12 */
|
||||
gsize* len) /* Since 1.0.12 */
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
const void* data = NULL;
|
||||
@@ -655,19 +770,45 @@ gbinder_reader_read_byte_array(
|
||||
*len = (gsize)*ptr;
|
||||
p->ptr += sizeof(*ptr);
|
||||
data = p->ptr;
|
||||
p->ptr += *len;
|
||||
/* Android aligns byte array reads and writes to 4 bytes */
|
||||
p->ptr += G_ALIGN4(*len);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
const void*
|
||||
gbinder_reader_get_data(
|
||||
const GBinderReader* reader,
|
||||
gsize* size) /* Since 1.1.14 */
|
||||
{
|
||||
const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
|
||||
|
||||
if (p) {
|
||||
const GBinderReaderData* data = p->data;
|
||||
|
||||
if (data && data->buffer) {
|
||||
if (size) {
|
||||
*size = data->buffer->size;
|
||||
}
|
||||
return data->buffer->data;
|
||||
}
|
||||
}
|
||||
|
||||
/* No data */
|
||||
if (size) {
|
||||
*size = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_read(
|
||||
const GBinderReader* reader)
|
||||
{
|
||||
const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
|
||||
|
||||
return p->ptr - p->start;
|
||||
return p ? (p->ptr - p->start) : 0;
|
||||
}
|
||||
|
||||
gsize
|
||||
@@ -676,7 +817,7 @@ gbinder_reader_bytes_remaining(
|
||||
{
|
||||
const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
|
||||
|
||||
return p->end - p->ptr;
|
||||
return p ? (p->end - p->ptr) : 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -684,8 +825,11 @@ gbinder_reader_copy(
|
||||
GBinderReader* dest,
|
||||
const GBinderReader* src)
|
||||
{
|
||||
/* It's actually quite simple :) */
|
||||
memcpy(dest, src, sizeof(*dest));
|
||||
if (src) {
|
||||
memcpy(dest, src, sizeof(*dest));
|
||||
} else {
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -48,7 +48,8 @@ gbinder_reader_init(
|
||||
GBinderReader* reader,
|
||||
GBinderReaderData* data,
|
||||
gsize offset,
|
||||
gsize len);
|
||||
gsize len)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_READER_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -33,19 +33,21 @@
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_eventloop_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
struct gbinder_remote_object_priv {
|
||||
GMainContext* context;
|
||||
gboolean acquired;
|
||||
};
|
||||
|
||||
typedef GObjectClass GBinderRemoteObjectClass;
|
||||
GType gbinder_remote_object_get_type(void) GBINDER_INTERNAL;
|
||||
G_DEFINE_TYPE(GBinderRemoteObject, gbinder_remote_object, G_TYPE_OBJECT)
|
||||
|
||||
GType gbinder_remote_object_get_type(void);
|
||||
#define GBINDER_TYPE_REMOTE_OBJECT (gbinder_remote_object_get_type())
|
||||
#define GBINDER_REMOTE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_REMOTE_OBJECT, GBinderRemoteObject))
|
||||
#define PARENT_CLASS gbinder_remote_object_parent_class
|
||||
#define THIS_TYPE (gbinder_remote_object_get_type())
|
||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj,THIS_TYPE,GBinderRemoteObject)
|
||||
|
||||
enum gbinder_remote_object_signal {
|
||||
SIGNAL_DEATH,
|
||||
@@ -62,21 +64,100 @@ static guint gbinder_remote_object_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_died_on_main_thread(
|
||||
GBinderRemoteObject* self)
|
||||
gbinder_remote_object_handle_death_on_main_thread(
|
||||
gpointer user_data)
|
||||
{
|
||||
GASSERT(!self->dead);
|
||||
self->dead = TRUE;
|
||||
g_signal_emit(self, gbinder_remote_object_signals[SIGNAL_DEATH], 0);
|
||||
GBinderRemoteObject* self = THIS(user_data);
|
||||
|
||||
if (!self->dead) {
|
||||
GBinderIpc* ipc = self->ipc;
|
||||
GBinderDriver* driver = ipc->driver;
|
||||
GBinderRemoteObjectPriv* priv = self->priv;
|
||||
|
||||
self->dead = TRUE;
|
||||
if (priv->acquired) {
|
||||
priv->acquired = FALSE;
|
||||
/* Release the dead node */
|
||||
gbinder_driver_release(driver, self->handle);
|
||||
}
|
||||
/* ServiceManager always has the same handle, and can be reanimated. */
|
||||
if (self->handle != GBINDER_SERVICEMANAGER_HANDLE) {
|
||||
gbinder_ipc_invalidate_remote_handle(ipc, self->handle);
|
||||
}
|
||||
gbinder_driver_dead_binder_done(driver, self);
|
||||
g_signal_emit(self, gbinder_remote_object_signals[SIGNAL_DEATH], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
/*==========================================================================*
|
||||
* Internal interface
|
||||
*==========================================================================*/
|
||||
|
||||
gboolean
|
||||
gbinder_remote_object_died_handle(
|
||||
gpointer self)
|
||||
gbinder_remote_object_reanimate(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
gbinder_remote_object_died_on_main_thread(GBINDER_REMOTE_OBJECT(self));
|
||||
return G_SOURCE_REMOVE;
|
||||
/*
|
||||
* Don't try to reanimate those who hasn't died yet. Reanimation is
|
||||
* kind of a special case and should only be used for servicemanager
|
||||
* objects.
|
||||
*/
|
||||
if (self->dead) {
|
||||
GBinderIpc* ipc = self->ipc;
|
||||
guint32 handle = self->handle;
|
||||
|
||||
/* Kick the horse */
|
||||
GASSERT(self->handle == GBINDER_SERVICEMANAGER_HANDLE);
|
||||
if (gbinder_ipc_ping_sync(ipc, handle, &gbinder_ipc_sync_main) == 0) {
|
||||
GBinderRemoteObjectPriv* priv = self->priv;
|
||||
GBinderDriver* driver = ipc->driver;
|
||||
|
||||
/* Wow, it's alive! */
|
||||
self->dead = FALSE;
|
||||
priv->acquired = TRUE;
|
||||
gbinder_ipc_looper_check(ipc); /* For death notifications */
|
||||
gbinder_driver_acquire(driver, handle);
|
||||
gbinder_driver_request_death_notification(driver, self);
|
||||
}
|
||||
}
|
||||
return !self->dead;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_object_handle_death_notification(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
/* This function is invoked from the looper thread, the caller has
|
||||
* checked the object pointer */
|
||||
GVERBOSE_("%p %u", self, self->handle);
|
||||
gbinder_idle_callback_invoke_later
|
||||
(gbinder_remote_object_handle_death_on_main_thread,
|
||||
gbinder_remote_object_ref(self), g_object_unref);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_object_commit_suicide(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
/* This function is only invoked by GBinderProxyObject in context of
|
||||
* the main thread, the object pointer is checked by the caller */
|
||||
if (!self->dead) {
|
||||
GBinderIpc* ipc = self->ipc;
|
||||
GBinderDriver* driver = ipc->driver;
|
||||
GBinderRemoteObjectPriv* priv = self->priv;
|
||||
|
||||
self->dead = TRUE;
|
||||
gbinder_driver_clear_death_notification(driver, self);
|
||||
if (priv->acquired) {
|
||||
priv->acquired = FALSE;
|
||||
/* Release the dead node */
|
||||
gbinder_driver_release(driver, self->handle);
|
||||
}
|
||||
GVERBOSE_("%p %u", self, self->handle);
|
||||
gbinder_ipc_invalidate_remote_handle(self->ipc, self->handle);
|
||||
/* Don't submit BC_DEAD_BINDER_DONE because this is a suicide */
|
||||
g_signal_emit(self, gbinder_remote_object_signals[SIGNAL_DEATH], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -86,15 +167,32 @@ gbinder_remote_object_died_handle(
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_object_new(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle)
|
||||
guint32 handle,
|
||||
REMOTE_OBJECT_CREATE create)
|
||||
{
|
||||
if (G_LIKELY(ipc) && gbinder_driver_acquire(ipc->driver, handle)) {
|
||||
GBinderRemoteObject* self = g_object_new
|
||||
(GBINDER_TYPE_REMOTE_OBJECT, NULL);
|
||||
if (G_LIKELY(ipc)) {
|
||||
GBinderRemoteObject* self = g_object_new(THIS_TYPE, NULL);
|
||||
GBinderRemoteObjectPriv* priv = self->priv;
|
||||
|
||||
self->ipc = gbinder_ipc_ref(ipc);
|
||||
self->handle = handle;
|
||||
gbinder_driver_request_death_notification(ipc->driver, self);
|
||||
switch (create) {
|
||||
case REMOTE_OBJECT_CREATE_DEAD:
|
||||
self->dead = TRUE;
|
||||
break;
|
||||
case REMOTE_OBJECT_CREATE_ACQUIRED:
|
||||
priv->acquired = TRUE;
|
||||
/* fallthrough */
|
||||
case REMOTE_OBJECT_CREATE_ALIVE:
|
||||
break;
|
||||
}
|
||||
if (!self->dead) {
|
||||
gbinder_ipc_looper_check(self->ipc); /* For death notifications */
|
||||
if (priv->acquired) {
|
||||
gbinder_driver_acquire(ipc->driver, handle);
|
||||
}
|
||||
gbinder_driver_request_death_notification(ipc->driver, self);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
@@ -105,7 +203,7 @@ gbinder_remote_object_ref(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(GBINDER_REMOTE_OBJECT(self));
|
||||
g_object_ref(THIS(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
@@ -117,10 +215,17 @@ gbinder_remote_object_unref(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_REMOTE_OBJECT(self));
|
||||
g_object_unref(THIS(self));
|
||||
}
|
||||
}
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_remote_object_ipc(
|
||||
GBinderRemoteObject* self) /* Since 1.0.30 */
|
||||
{
|
||||
return G_LIKELY(self) ? self->ipc : NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_object_is_dead(
|
||||
GBinderRemoteObject* self)
|
||||
@@ -152,18 +257,6 @@ gbinder_remote_object_remove_handler(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_object_handle_death_notification(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
/* This function is invoked from the looper thread, the caller has
|
||||
* checked the object pointer */
|
||||
GVERBOSE_("%p %u", self, self->handle);
|
||||
g_main_context_invoke_full(self->priv->context, G_PRIORITY_DEFAULT,
|
||||
gbinder_remote_object_died_handle, gbinder_remote_object_ref(self),
|
||||
g_object_unref);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
@@ -174,36 +267,41 @@ gbinder_remote_object_init(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
GBinderRemoteObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
GBINDER_TYPE_REMOTE_OBJECT, GBinderRemoteObjectPriv);
|
||||
THIS_TYPE, GBinderRemoteObjectPriv);
|
||||
|
||||
priv->context = g_main_context_default();
|
||||
self->priv = priv;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_dispose(
|
||||
GObject* remote)
|
||||
GObject* object)
|
||||
{
|
||||
GBinderRemoteObject* self = GBINDER_REMOTE_OBJECT(remote);
|
||||
GBinderRemoteObject* self = THIS(object);
|
||||
|
||||
gbinder_ipc_remote_object_disposed(self->ipc, self);
|
||||
G_OBJECT_CLASS(gbinder_remote_object_parent_class)->dispose(remote);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_finalize(
|
||||
GObject* remote)
|
||||
GObject* object)
|
||||
{
|
||||
GBinderRemoteObject* self = GBINDER_REMOTE_OBJECT(remote);
|
||||
GBinderRemoteObject* self = THIS(object);
|
||||
GBinderRemoteObjectPriv* priv = self->priv;
|
||||
GBinderIpc* ipc = self->ipc;
|
||||
GBinderDriver* driver = ipc->driver;
|
||||
|
||||
gbinder_driver_clear_death_notification(driver, self);
|
||||
gbinder_driver_release(driver, self->handle);
|
||||
gbinder_ipc_invalidate_remote_handle(ipc, self->handle);
|
||||
if (!self->dead) {
|
||||
gbinder_driver_clear_death_notification(driver, self);
|
||||
}
|
||||
if (priv->acquired) {
|
||||
gbinder_driver_release(driver, self->handle);
|
||||
}
|
||||
gbinder_ipc_unref(ipc);
|
||||
G_OBJECT_CLASS(gbinder_remote_object_parent_class)->finalize(remote);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -51,14 +51,33 @@ struct gbinder_remote_object {
|
||||
#define gbinder_remote_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
|
||||
#define gbinder_remote_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
|
||||
|
||||
typedef enum gbinder_remote_object_create {
|
||||
REMOTE_OBJECT_CREATE_DEAD,
|
||||
REMOTE_OBJECT_CREATE_ALIVE,
|
||||
REMOTE_OBJECT_CREATE_ACQUIRED
|
||||
} REMOTE_OBJECT_CREATE;
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_object_new(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle);
|
||||
guint32 handle,
|
||||
REMOTE_OBJECT_CREATE create)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_remote_object_reanimate(
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_remote_object_handle_death_notification(
|
||||
GBinderRemoteObject* obj);
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_remote_object_commit_suicide(
|
||||
GBinderRemoteObject* self)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_REMOTE_OBJECT_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -73,15 +73,12 @@ gbinder_remote_reply_set_data(
|
||||
GBinderRemoteReply* self,
|
||||
GBinderBuffer* buffer)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* data = &self->data;
|
||||
/* The caller checks the pointer for NULL */
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
gbinder_buffer_free(data->buffer);
|
||||
data->buffer = buffer;
|
||||
data->objects = gbinder_buffer_objects(buffer);
|
||||
} else {
|
||||
gbinder_buffer_free(buffer);
|
||||
}
|
||||
gbinder_buffer_free(data->buffer);
|
||||
data->buffer = buffer;
|
||||
data->objects = gbinder_buffer_objects(buffer);
|
||||
}
|
||||
|
||||
GBinderRemoteReply*
|
||||
@@ -117,11 +114,24 @@ gbinder_remote_reply_is_empty(
|
||||
GBinderLocalReply*
|
||||
gbinder_remote_reply_copy_to_local(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
return gbinder_remote_reply_convert_to_local(self, NULL);
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_remote_reply_convert_to_local(
|
||||
GBinderRemoteReply* self,
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* d = &self->data;
|
||||
GBinderObjectRegistry* reg = d->reg;
|
||||
|
||||
return gbinder_local_reply_new_from_data(d->buffer);
|
||||
if (reg) {
|
||||
return gbinder_local_reply_set_contents(gbinder_local_reply_new
|
||||
(reg->io, gbinder_buffer_protocol(d->buffer)),
|
||||
d->buffer, convert);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -39,16 +39,25 @@
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_remote_reply_new(
|
||||
GBinderObjectRegistry* reg);
|
||||
GBinderObjectRegistry* reg)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_remote_reply_convert_to_local(
|
||||
GBinderRemoteReply* reply,
|
||||
GBinderObjectConverter* convert)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_remote_reply_set_data(
|
||||
GBinderRemoteReply* reply,
|
||||
GBinderBuffer* buffer);
|
||||
GBinderBuffer* buffer)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_is_empty(
|
||||
GBinderRemoteReply* reply);
|
||||
GBinderRemoteReply* reply)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_REMOTE_REPLY_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -34,13 +34,18 @@
|
||||
#include "gbinder_reader_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_object_converter.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
struct gbinder_remote_request {
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct gbinder_remote_request_priv {
|
||||
GBinderRemoteRequest pub;
|
||||
gint refcount;
|
||||
pid_t pid;
|
||||
uid_t euid;
|
||||
@@ -49,7 +54,11 @@ struct gbinder_remote_request {
|
||||
char* iface2;
|
||||
gsize header_size;
|
||||
GBinderReaderData data;
|
||||
};
|
||||
} GBinderRemoteRequestPriv;
|
||||
|
||||
GBINDER_INLINE_FUNC GBinderRemoteRequestPriv*
|
||||
gbinder_remote_request_cast(GBinderRemoteRequest* pub)
|
||||
{ return G_LIKELY(pub) ? G_CAST(pub,GBinderRemoteRequestPriv,pub) : NULL; }
|
||||
|
||||
GBinderRemoteRequest*
|
||||
gbinder_remote_request_new(
|
||||
@@ -58,7 +67,7 @@ gbinder_remote_request_new(
|
||||
pid_t pid,
|
||||
uid_t euid)
|
||||
{
|
||||
GBinderRemoteRequest* self = g_slice_new0(GBinderRemoteRequest);
|
||||
GBinderRemoteRequestPriv* self = g_slice_new0(GBinderRemoteRequestPriv);
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
@@ -66,17 +75,45 @@ gbinder_remote_request_new(
|
||||
self->euid = euid;
|
||||
self->protocol = protocol;
|
||||
data->reg = gbinder_object_registry_ref(reg);
|
||||
return self;
|
||||
return &self->pub;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_remote_request_copy_to_local(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* d = &self->data;
|
||||
|
||||
return gbinder_local_request_new_from_data(d->buffer);
|
||||
return gbinder_local_request_new_from_data(d->buffer, NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_remote_request_convert_to_local(
|
||||
GBinderRemoteRequest* req,
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
if (!convert || convert->protocol == self->protocol) {
|
||||
/* The same protocol, the same format of RPC header */
|
||||
return gbinder_local_request_new_from_data(data->buffer, convert);
|
||||
} else {
|
||||
/* Need to translate to another format */
|
||||
GBinderLocalRequest* local = gbinder_local_request_new_iface
|
||||
(convert->io, convert->protocol, self->iface);
|
||||
|
||||
gbinder_local_request_append_contents(local, data->buffer,
|
||||
self->header_size, convert);
|
||||
return local;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -84,21 +121,27 @@ gbinder_remote_request_copy_to_local(
|
||||
static
|
||||
void
|
||||
gbinder_remote_request_free(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequestPriv* self)
|
||||
{
|
||||
GBinderReaderData* data = &self->data;
|
||||
GBinderRemoteRequest* req = &self->pub;
|
||||
|
||||
GASSERT(!req->tx);
|
||||
if (req->tx) {
|
||||
GWARN("Request is dropped without completing the transaction");
|
||||
gbinder_remote_request_complete(req, NULL, -ECANCELED);
|
||||
}
|
||||
gbinder_object_registry_unref(data->reg);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
g_free(self->iface2);
|
||||
g_slice_free(GBinderRemoteRequest, self);
|
||||
g_slice_free(GBinderRemoteRequestPriv, self);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
void
|
||||
gbinder_remote_request_init_reader2(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderRemoteRequestPriv* self,
|
||||
GBinderReader* p)
|
||||
{
|
||||
/* The caller has already checked the request for NULL */
|
||||
@@ -115,56 +158,60 @@ gbinder_remote_request_init_reader2(
|
||||
|
||||
void
|
||||
gbinder_remote_request_set_data(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderRemoteRequest* req,
|
||||
guint32 txcode,
|
||||
GBinderBuffer* buffer)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* data = &self->data;
|
||||
GBinderReader reader;
|
||||
/* The caller never passes NULL req */
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
GBinderReaderData* data = &self->data;
|
||||
GBinderReader reader;
|
||||
|
||||
g_free(self->iface2);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
data->buffer = buffer;
|
||||
data->objects = gbinder_buffer_objects(buffer);
|
||||
g_free(self->iface2);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
data->buffer = buffer;
|
||||
data->objects = gbinder_buffer_objects(buffer);
|
||||
|
||||
/* Parse RPC header */
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
self->iface = self->protocol->read_rpc_header(&reader, txcode,
|
||||
&self->iface2);
|
||||
if (self->iface) {
|
||||
self->header_size = gbinder_reader_bytes_read(&reader);
|
||||
} else {
|
||||
/* No RPC header */
|
||||
self->header_size = 0;
|
||||
}
|
||||
/* Parse RPC header */
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
self->iface = self->protocol->read_rpc_header(&reader, txcode,
|
||||
&self->iface2);
|
||||
if (self->iface) {
|
||||
self->header_size = gbinder_reader_bytes_read(&reader);
|
||||
} else {
|
||||
gbinder_buffer_free(buffer);
|
||||
/* No RPC header */
|
||||
self->header_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_remote_request_interface(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
return G_LIKELY(self) ? self->iface : NULL;
|
||||
}
|
||||
|
||||
GBinderRemoteRequest*
|
||||
gbinder_remote_request_ref(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
g_atomic_int_inc(&self->refcount);
|
||||
}
|
||||
return self;
|
||||
return req;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_request_unref(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->refcount)) {
|
||||
@@ -175,9 +222,11 @@ gbinder_remote_request_unref(
|
||||
|
||||
void
|
||||
gbinder_remote_request_init_reader(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderRemoteRequest* req,
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_remote_request_init_reader2(self, reader);
|
||||
} else {
|
||||
@@ -187,15 +236,19 @@ gbinder_remote_request_init_reader(
|
||||
|
||||
pid_t
|
||||
gbinder_remote_request_sender_pid(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
return G_LIKELY(self) ? self->pid : (uid_t)(-1);
|
||||
}
|
||||
|
||||
uid_t
|
||||
gbinder_remote_request_sender_euid(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
return G_LIKELY(self) ? self->euid : (uid_t)(-1);
|
||||
}
|
||||
|
||||
@@ -209,9 +262,11 @@ gbinder_remote_request_read_int32(
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_uint32(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderRemoteRequest* req,
|
||||
guint32* value)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
@@ -231,9 +286,11 @@ gbinder_remote_request_read_int64(
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_uint64(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderRemoteRequest* req,
|
||||
guint64* value)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
@@ -245,8 +302,10 @@ gbinder_remote_request_read_uint64(
|
||||
|
||||
const char*
|
||||
gbinder_remote_request_read_string8(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
@@ -258,8 +317,10 @@ gbinder_remote_request_read_string8(
|
||||
|
||||
char*
|
||||
gbinder_remote_request_read_string16(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
@@ -271,8 +332,10 @@ gbinder_remote_request_read_string16(
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_request_read_object(
|
||||
GBinderRemoteRequest* self)
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
|
||||
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -37,18 +37,30 @@
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
struct gbinder_remote_request {
|
||||
GBinderIpcLooperTx* tx;
|
||||
};
|
||||
|
||||
GBinderRemoteRequest*
|
||||
gbinder_remote_request_new(
|
||||
GBinderObjectRegistry* reg,
|
||||
const GBinderRpcProtocol* protocol,
|
||||
pid_t pid,
|
||||
uid_t euid);
|
||||
uid_t euid)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_remote_request_set_data(
|
||||
GBinderRemoteRequest* request,
|
||||
guint txcode,
|
||||
GBinderBuffer* buffer);
|
||||
GBinderBuffer* buffer)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_remote_request_convert_to_local(
|
||||
GBinderRemoteRequest* req,
|
||||
GBinderObjectConverter* convert)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_REMOTE_REQUEST_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -33,6 +33,18 @@
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_writer.h"
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_log.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
|
||||
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
|
||||
#define UNSET_WORK_SOURCE (-1)
|
||||
|
||||
#define BINDER_VND_HEADER GBINDER_FOURCC('V', 'N', 'D', 'R')
|
||||
#define BINDER_SYS_HEADER GBINDER_FOURCC('S', 'Y', 'S', 'T')
|
||||
|
||||
/*==========================================================================*
|
||||
* GBinderIpcProtocol callbacks (see Parcel::writeInterfaceToken in Android)
|
||||
@@ -40,19 +52,47 @@
|
||||
*
|
||||
* platform/system/libhwbinder/Parcel.cpp
|
||||
* platform/frameworks/native/libs/binder/Parcel.cpp
|
||||
*
|
||||
* which mutate from version to version. Specific device => protocol
|
||||
* mapping can be optionally configured in /etc/gbinder.conf file.
|
||||
* The default protocol configuration looks like this:
|
||||
*
|
||||
* [Protocol]
|
||||
* Default = aidl
|
||||
* /dev/binder = aidl
|
||||
* /dev/hwbinder = hidl
|
||||
*
|
||||
*==========================================================================*/
|
||||
|
||||
#define CONF_GROUP GBINDER_CONFIG_GROUP_PROTOCOL
|
||||
#define CONF_DEFAULT GBINDER_CONFIG_VALUE_DEFAULT
|
||||
|
||||
static GHashTable* gbinder_rpc_protocol_map = NULL;
|
||||
|
||||
/*
|
||||
* Default protocol for those binder devices which which haven't been
|
||||
* explicitely mapped.
|
||||
*/
|
||||
#define DEFAULT_PROTOCOL gbinder_rpc_protocol_aidl
|
||||
static const GBinderRpcProtocol DEFAULT_PROTOCOL;
|
||||
static const GBinderRpcProtocol* gbinder_rpc_protocol_default =
|
||||
&DEFAULT_PROTOCOL;
|
||||
|
||||
/*==========================================================================*
|
||||
* /dev/binder
|
||||
* The original AIDL protocol.
|
||||
*==========================================================================*/
|
||||
|
||||
/* No idea what that is... */
|
||||
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
|
||||
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_binder_write_rpc_header(
|
||||
gbinder_rpc_protocol_aidl_write_ping(
|
||||
GBinderWriter* writer)
|
||||
{
|
||||
/* No payload */
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_aidl_write_rpc_header(
|
||||
GBinderWriter* writer,
|
||||
const char* iface)
|
||||
{
|
||||
@@ -67,7 +107,7 @@ gbinder_rpc_protocol_binder_write_rpc_header(
|
||||
|
||||
static
|
||||
const char*
|
||||
gbinder_rpc_protocol_binder_read_rpc_header(
|
||||
gbinder_rpc_protocol_aidl_read_rpc_header(
|
||||
GBinderReader* reader,
|
||||
guint32 txcode,
|
||||
char** iface)
|
||||
@@ -83,13 +123,166 @@ gbinder_rpc_protocol_binder_read_rpc_header(
|
||||
return *iface;
|
||||
}
|
||||
|
||||
static const GBinderRpcProtocol gbinder_rpc_protocol_aidl = {
|
||||
.name = "aidl",
|
||||
.ping_tx = GBINDER_PING_TRANSACTION,
|
||||
.write_ping = gbinder_rpc_protocol_aidl_write_ping,
|
||||
.write_rpc_header = gbinder_rpc_protocol_aidl_write_rpc_header,
|
||||
.read_rpc_header = gbinder_rpc_protocol_aidl_read_rpc_header
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* /dev/hwbinder
|
||||
* AIDL protocol appeared in Android 10 (API level 29)
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_hwbinder_write_rpc_header(
|
||||
gbinder_rpc_protocol_aidl2_write_rpc_header(
|
||||
GBinderWriter* writer,
|
||||
const char* iface)
|
||||
{
|
||||
/*
|
||||
* writeInt32(IPCThreadState::self()->getStrictModePolicy() |
|
||||
* STRICT_MODE_PENALTY_GATHER);
|
||||
* writeInt32(IPCThreadState::kUnsetWorkSource);
|
||||
* writeString16(interface);
|
||||
*/
|
||||
gbinder_writer_append_int32(writer, BINDER_RPC_FLAGS);
|
||||
gbinder_writer_append_int32(writer, UNSET_WORK_SOURCE);
|
||||
gbinder_writer_append_string16(writer, iface);
|
||||
}
|
||||
|
||||
static
|
||||
const char*
|
||||
gbinder_rpc_protocol_aidl2_read_rpc_header(
|
||||
GBinderReader* reader,
|
||||
guint32 txcode,
|
||||
char** iface)
|
||||
{
|
||||
if (txcode > GBINDER_TRANSACTION(0,0,0)) {
|
||||
/* Internal transaction e.g. GBINDER_DUMP_TRANSACTION etc. */
|
||||
*iface = NULL;
|
||||
} else if (gbinder_reader_read_int32(reader, NULL) /* flags */ &&
|
||||
gbinder_reader_read_int32(reader, NULL) /* work source */) {
|
||||
*iface = gbinder_reader_read_string16(reader);
|
||||
} else {
|
||||
*iface = NULL;
|
||||
}
|
||||
return *iface;
|
||||
}
|
||||
|
||||
static const GBinderRpcProtocol gbinder_rpc_protocol_aidl2 = {
|
||||
.name = "aidl2",
|
||||
.ping_tx = GBINDER_PING_TRANSACTION,
|
||||
.write_ping = gbinder_rpc_protocol_aidl_write_ping, /* no payload */
|
||||
.write_rpc_header = gbinder_rpc_protocol_aidl2_write_rpc_header,
|
||||
.read_rpc_header = gbinder_rpc_protocol_aidl2_read_rpc_header
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* AIDL protocol appeared in Android 11 (API level 30)
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_aidl3_write_rpc_header(
|
||||
GBinderWriter* writer,
|
||||
const char* iface)
|
||||
{
|
||||
gbinder_writer_append_int32(writer, BINDER_RPC_FLAGS);
|
||||
gbinder_writer_append_int32(writer, UNSET_WORK_SOURCE);
|
||||
gbinder_writer_append_int32(writer, BINDER_SYS_HEADER);
|
||||
gbinder_writer_append_string16(writer, iface);
|
||||
}
|
||||
|
||||
static
|
||||
const char*
|
||||
gbinder_rpc_protocol_aidl3_read_rpc_header(
|
||||
GBinderReader* reader,
|
||||
guint32 txcode,
|
||||
char** iface)
|
||||
{
|
||||
if (txcode > GBINDER_TRANSACTION(0,0,0)) {
|
||||
*iface = NULL;
|
||||
} else if (gbinder_reader_read_int32(reader, NULL) /* flags */ &&
|
||||
gbinder_reader_read_int32(reader, NULL) /* work source */ &&
|
||||
gbinder_reader_read_int32(reader, NULL) /* sys header */) {
|
||||
*iface = gbinder_reader_read_string16(reader);
|
||||
} else {
|
||||
*iface = NULL;
|
||||
}
|
||||
|
||||
return *iface;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_aidl3_finish_flatten_binder(
|
||||
void* out,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
if (G_LIKELY(obj)) {
|
||||
*(guint32*)out = obj->stability;
|
||||
} else {
|
||||
*(guint32*)out = GBINDER_STABILITY_UNDECLARED;
|
||||
}
|
||||
}
|
||||
|
||||
static const GBinderRpcProtocol gbinder_rpc_protocol_aidl3 = {
|
||||
.name = "aidl3",
|
||||
.ping_tx = GBINDER_PING_TRANSACTION,
|
||||
.write_ping = gbinder_rpc_protocol_aidl_write_ping, /* no payload */
|
||||
.write_rpc_header = gbinder_rpc_protocol_aidl3_write_rpc_header,
|
||||
.read_rpc_header = gbinder_rpc_protocol_aidl3_read_rpc_header,
|
||||
.flat_binder_object_extra = 4,
|
||||
.finish_flatten_binder = gbinder_rpc_protocol_aidl3_finish_flatten_binder
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* AIDL protocol appeared in Android 12 (API level 31), but reverted in
|
||||
* Android 13 (API level 33).
|
||||
*==========================================================================*/
|
||||
|
||||
#define BINDER_WIRE_FORMAT_VERSION_AIDL4 1
|
||||
struct stability_category {
|
||||
guint8 binder_wire_format_version;
|
||||
guint8 reserved[2];
|
||||
guint8 stability_level;
|
||||
};
|
||||
G_STATIC_ASSERT(sizeof(struct stability_category) == sizeof(guint32));
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_aidl4_finish_flatten_binder(
|
||||
void* out,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
struct stability_category cat = {
|
||||
.binder_wire_format_version = BINDER_WIRE_FORMAT_VERSION_AIDL4,
|
||||
.reserved = { 0, 0, },
|
||||
.stability_level = obj ? obj->stability : GBINDER_STABILITY_UNDECLARED,
|
||||
};
|
||||
|
||||
memcpy(out, &cat, sizeof(cat));
|
||||
}
|
||||
|
||||
static const GBinderRpcProtocol gbinder_rpc_protocol_aidl4 = {
|
||||
.name = "aidl4",
|
||||
.ping_tx = GBINDER_PING_TRANSACTION,
|
||||
.write_ping = gbinder_rpc_protocol_aidl_write_ping, /* no payload */
|
||||
.write_rpc_header = gbinder_rpc_protocol_aidl3_write_rpc_header,
|
||||
.read_rpc_header = gbinder_rpc_protocol_aidl3_read_rpc_header,
|
||||
.flat_binder_object_extra = 4,
|
||||
.finish_flatten_binder = gbinder_rpc_protocol_aidl4_finish_flatten_binder
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* The original /dev/hwbinder protocol.
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_hidl_write_rpc_header(
|
||||
GBinderWriter* writer,
|
||||
const char* iface)
|
||||
{
|
||||
@@ -99,9 +292,18 @@ gbinder_rpc_protocol_hwbinder_write_rpc_header(
|
||||
gbinder_writer_append_string8(writer, iface);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_hidl_write_ping(
|
||||
GBinderWriter* writer)
|
||||
{
|
||||
gbinder_rpc_protocol_hidl_write_rpc_header(writer,
|
||||
"android.hidl.base@1.0::IBase");
|
||||
}
|
||||
|
||||
static
|
||||
const char*
|
||||
gbinder_rpc_protocol_hwbinder_read_rpc_header(
|
||||
gbinder_rpc_protocol_hidl_read_rpc_header(
|
||||
GBinderReader* reader,
|
||||
guint32 txcode,
|
||||
char** iface)
|
||||
@@ -110,26 +312,135 @@ gbinder_rpc_protocol_hwbinder_read_rpc_header(
|
||||
return gbinder_reader_read_string8(reader);
|
||||
}
|
||||
|
||||
static const GBinderRpcProtocol gbinder_rpc_protocol_hidl = {
|
||||
.name = "hidl",
|
||||
.ping_tx = HIDL_PING_TRANSACTION,
|
||||
.write_ping = gbinder_rpc_protocol_hidl_write_ping,
|
||||
.write_rpc_header = gbinder_rpc_protocol_hidl_write_rpc_header,
|
||||
.read_rpc_header = gbinder_rpc_protocol_hidl_read_rpc_header
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
/* All known protocols */
|
||||
static const GBinderRpcProtocol* gbinder_rpc_protocol_list[] = {
|
||||
&gbinder_rpc_protocol_aidl,
|
||||
&gbinder_rpc_protocol_aidl2,
|
||||
&gbinder_rpc_protocol_aidl3,
|
||||
&gbinder_rpc_protocol_aidl4,
|
||||
&gbinder_rpc_protocol_hidl
|
||||
};
|
||||
|
||||
static
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_find(
|
||||
const char* name)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(gbinder_rpc_protocol_list); i++) {
|
||||
if (!g_ascii_strcasecmp(gbinder_rpc_protocol_list[i]->name, name)) {
|
||||
return gbinder_rpc_protocol_list[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_map_add_default(
|
||||
GHashTable* map,
|
||||
const char* dev,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
if (!g_hash_table_contains(map, dev)) {
|
||||
g_hash_table_insert(map, g_strdup(dev), (gpointer) protocol);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gconstpointer
|
||||
gbinder_rpc_protocol_value_map(
|
||||
const char* name)
|
||||
{
|
||||
return gbinder_rpc_protocol_find(name);
|
||||
}
|
||||
|
||||
static
|
||||
GHashTable*
|
||||
gbinder_rpc_protocol_load_config()
|
||||
{
|
||||
GHashTable* map = gbinder_config_load(CONF_GROUP,
|
||||
gbinder_rpc_protocol_value_map);
|
||||
|
||||
/* Add default configuration if it's not overridden */
|
||||
gbinder_rpc_protocol_map_add_default(map,
|
||||
GBINDER_DEFAULT_BINDER, &gbinder_rpc_protocol_aidl);
|
||||
gbinder_rpc_protocol_map_add_default(map,
|
||||
GBINDER_DEFAULT_HWBINDER, &gbinder_rpc_protocol_hidl);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/* Runs at exit */
|
||||
void
|
||||
gbinder_rpc_protocol_exit()
|
||||
{
|
||||
if (gbinder_rpc_protocol_map) {
|
||||
g_hash_table_destroy(gbinder_rpc_protocol_map);
|
||||
gbinder_rpc_protocol_map = NULL;
|
||||
}
|
||||
/* Reset the default too, mostly for unit testing */
|
||||
gbinder_rpc_protocol_default = &DEFAULT_PROTOCOL;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
const GBinderRpcProtocol gbinder_rpc_protocol_binder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_binder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_binder_write_rpc_header
|
||||
};
|
||||
|
||||
const GBinderRpcProtocol gbinder_rpc_protocol_hwbinder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_hwbinder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_hwbinder_write_rpc_header
|
||||
};
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_for_device(
|
||||
const char* dev)
|
||||
{
|
||||
return (dev && !strcmp(dev, GBINDER_DEFAULT_HWBINDER)) ?
|
||||
&gbinder_rpc_protocol_hwbinder : &gbinder_rpc_protocol_binder;
|
||||
if (dev) {
|
||||
const GBinderRpcProtocol* protocol;
|
||||
|
||||
if (!gbinder_rpc_protocol_map) {
|
||||
const GBinderRpcProtocol* p;
|
||||
|
||||
/* One-time initialization */
|
||||
gbinder_rpc_protocol_map = gbinder_rpc_protocol_load_config();
|
||||
|
||||
/* "Default" is a special value stored in a special variable */
|
||||
p = g_hash_table_lookup(gbinder_rpc_protocol_map, CONF_DEFAULT);
|
||||
if (p) {
|
||||
g_hash_table_remove(gbinder_rpc_protocol_map, CONF_DEFAULT);
|
||||
gbinder_rpc_protocol_default = p;
|
||||
} else {
|
||||
gbinder_rpc_protocol_default = &DEFAULT_PROTOCOL;
|
||||
}
|
||||
}
|
||||
protocol = g_hash_table_lookup(gbinder_rpc_protocol_map, dev);
|
||||
if (protocol) {
|
||||
GDEBUG("Using %s protocol for %s", protocol->name, dev);
|
||||
return protocol;
|
||||
}
|
||||
GDEBUG("Using default protocol %s for %s",
|
||||
gbinder_rpc_protocol_default->name, dev);
|
||||
} else {
|
||||
GDEBUG("Using default protocol %s",
|
||||
gbinder_rpc_protocol_default->name);
|
||||
}
|
||||
return gbinder_rpc_protocol_default;
|
||||
}
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_by_name(
|
||||
const char* protocol_name)
|
||||
{
|
||||
return gbinder_rpc_protocol_find(protocol_name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,10 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -37,23 +36,47 @@
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
/*
|
||||
* For whatever reason services communicating via /dev/binder
|
||||
* and /dev/hwbinder use slightly different RPC headers.
|
||||
* There are several versions of binder RPC protocol with diffferent
|
||||
* transaction headers and transaction codes.
|
||||
*/
|
||||
|
||||
struct gbinder_rpc_protocol {
|
||||
const char* name;
|
||||
guint32 ping_tx;
|
||||
void (*write_ping)(GBinderWriter* writer);
|
||||
void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
|
||||
const char* (*read_rpc_header)(GBinderReader* reader, guint32 txcode,
|
||||
char** iface);
|
||||
void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
|
||||
|
||||
/*
|
||||
* For the sake of simplicity, let's assume that the trailer has a
|
||||
* fixed size and that size is the same on both 32 and 64 bit platforms.
|
||||
* Also note that finish_unflatten_binder() is only invoked for the
|
||||
* remote objects that are not NULL, otherwise flat_binder_object_extra
|
||||
* bytes are just skipped.
|
||||
*/
|
||||
gsize flat_binder_object_extra;
|
||||
void (*finish_flatten_binder)(void* out, GBinderLocalObject* obj);
|
||||
void (*finish_unflatten_binder)(const void* in, GBinderRemoteObject* obj);
|
||||
};
|
||||
|
||||
extern const GBinderRpcProtocol gbinder_rpc_protocol_binder;
|
||||
extern const GBinderRpcProtocol gbinder_rpc_protocol_hwbinder;
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_by_name(
|
||||
const char* protocol_name)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Returns one of the above based on the device name */
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_for_device(
|
||||
const char* dev);
|
||||
const char* dev)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Runs at exit, declared here strictly for unit tests */
|
||||
void
|
||||
gbinder_rpc_protocol_exit(
|
||||
void)
|
||||
GBINDER_DESTRUCTOR
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_RPC_PROTOCOL_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -32,18 +32,71 @@
|
||||
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_eventloop_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
|
||||
#include <gutil_idlepool.h>
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*==========================================================================*
|
||||
*
|
||||
* Different versions of Android come with different flavors of service
|
||||
* managers. They are usually based on these two more or less independent
|
||||
* variants:
|
||||
*
|
||||
* platform/frameworks/native/cmds/servicemanager/ServiceManager.cpp
|
||||
* platform/system/hwservicemanager/ServiceManager.cpp
|
||||
*
|
||||
* They are talking slightly different protocols which slightly mutate
|
||||
* from version to version. If that's not complex enough, different
|
||||
* kinds of service managers can be running simultaneously, serving
|
||||
* different binder devices. Specific device => servicemanager mapping
|
||||
* can be optionally configured in /etc/gbinder.conf file. The default
|
||||
* service manager configuration looks like this:
|
||||
*
|
||||
* [ServiceManager]
|
||||
* Default = aidl
|
||||
* /dev/binder = aidl
|
||||
* /dev/hwbinder = hidl
|
||||
*
|
||||
*==========================================================================*/
|
||||
|
||||
#define CONF_GROUP GBINDER_CONFIG_GROUP_SERVICEMANAGER
|
||||
#define CONF_DEFAULT GBINDER_CONFIG_VALUE_DEFAULT
|
||||
|
||||
typedef struct gbinder_servicemanager_type {
|
||||
const char* name;
|
||||
GType (*get_type)(void);
|
||||
} GBinderServiceManagerType;
|
||||
|
||||
static const GBinderServiceManagerType gbinder_servicemanager_types[] = {
|
||||
{ "aidl", gbinder_servicemanager_aidl_get_type },
|
||||
{ "aidl2", gbinder_servicemanager_aidl2_get_type },
|
||||
{ "aidl3", gbinder_servicemanager_aidl3_get_type },
|
||||
{ "aidl4", gbinder_servicemanager_aidl4_get_type },
|
||||
{ "hidl", gbinder_servicemanager_hidl_get_type }
|
||||
};
|
||||
|
||||
#define SERVICEMANAGER_TYPE_AIDL (gbinder_servicemanager_types + 0)
|
||||
#define SERVICEMANAGER_TYPE_HIDL (gbinder_servicemanager_types + 4)
|
||||
#define SERVICEMANAGER_TYPE_DEFAULT SERVICEMANAGER_TYPE_AIDL
|
||||
|
||||
static GHashTable* gbinder_servicemanager_map = NULL;
|
||||
static const GBinderServiceManagerType* gbinder_servicemanager_default =
|
||||
SERVICEMANAGER_TYPE_DEFAULT;
|
||||
|
||||
#define PRESENSE_WAIT_MS_MIN (100)
|
||||
#define PRESENSE_WAIT_MS_MAX (1000)
|
||||
#define PRESENSE_WAIT_MS_STEP (100)
|
||||
|
||||
typedef struct gbinder_servicemanager_watch {
|
||||
char* name;
|
||||
char* detail;
|
||||
@@ -53,6 +106,12 @@ typedef struct gbinder_servicemanager_watch {
|
||||
|
||||
struct gbinder_servicemanager_priv {
|
||||
GHashTable* watch_table;
|
||||
gulong death_id;
|
||||
gboolean present;
|
||||
GBinderEventLoopTimeout* presence_check;
|
||||
guint presence_check_delay_ms;
|
||||
GBinderEventLoopCallback* autorelease_cb;
|
||||
GSList* autorelease;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
|
||||
@@ -62,9 +121,6 @@ G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
|
||||
#define GBINDER_SERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER, \
|
||||
GBinderServiceManager)
|
||||
#define GBINDER_SERVICEMANAGER_CLASS(klass) \
|
||||
G_TYPE_CHECK_CLASS_CAST((klass), GBINDER_TYPE_SERVICEMANAGER, \
|
||||
GBinderServiceManagerClass)
|
||||
#define GBINDER_SERVICEMANAGER_GET_CLASS(obj) \
|
||||
G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_SERVICEMANAGER, \
|
||||
GBinderServiceManagerClass)
|
||||
@@ -72,10 +128,12 @@ G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
|
||||
G_TYPE_CHECK_CLASS_TYPE(klass, GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
enum gbinder_servicemanager_signal {
|
||||
SIGNAL_PRESENCE,
|
||||
SIGNAL_REGISTRATION,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
static const char SIGNAL_PRESENCE_NAME[] = "servicemanager-presence";
|
||||
static const char SIGNAL_REGISTRATION_NAME[] = "servicemanager-registration";
|
||||
#define DETAIL_LEN 32
|
||||
|
||||
@@ -141,7 +199,8 @@ gbinder_servicemanager_list_tx_exec(
|
||||
{
|
||||
GBinderServiceManagerListTxData* data = tx->user_data;
|
||||
|
||||
data->result = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->list(data->sm);
|
||||
data->result = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->
|
||||
list(data->sm, &gbinder_ipc_sync_worker);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -154,6 +213,7 @@ gbinder_servicemanager_list_tx_done(
|
||||
if (!data->func(data->sm, data->result, data->user_data)) {
|
||||
g_strfreev(data->result);
|
||||
}
|
||||
data->result = NULL;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -163,6 +223,7 @@ gbinder_servicemanager_list_tx_free(
|
||||
{
|
||||
GBinderServiceManagerListTxData* data = user_data;
|
||||
|
||||
g_strfreev(data->result);
|
||||
gbinder_servicemanager_unref(data->sm);
|
||||
g_slice_free(GBinderServiceManagerListTxData, data);
|
||||
}
|
||||
@@ -183,8 +244,9 @@ gbinder_servicemanager_get_service_tx_exec(
|
||||
{
|
||||
GBinderServiceManagerGetServiceTxData* data = tx->user_data;
|
||||
|
||||
data->obj = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->get_service
|
||||
(data->sm, data->name, &data->status);
|
||||
data->obj = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->
|
||||
get_service(data->sm, data->name, &data->status,
|
||||
&gbinder_ipc_sync_worker);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -226,8 +288,8 @@ gbinder_servicemanager_add_service_tx_exec(
|
||||
{
|
||||
GBinderServiceManagerAddServiceTxData* data = tx->user_data;
|
||||
|
||||
data->status = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->add_service
|
||||
(data->sm, data->name, data->obj);
|
||||
data->status = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->
|
||||
add_service(data->sm, data->name, data->obj, &gbinder_ipc_sync_worker);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -253,6 +315,202 @@ gbinder_servicemanager_add_service_tx_free(
|
||||
g_slice_free(GBinderServiceManagerAddServiceTxData, data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_reanimated(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
|
||||
if (priv->presence_check) {
|
||||
gbinder_timeout_remove(priv->presence_check);
|
||||
priv->presence_check = NULL;
|
||||
}
|
||||
GINFO("Service manager %s has appeared", self->dev);
|
||||
/* Re-arm the watches */
|
||||
if (g_hash_table_size(priv->watch_table) > 0) {
|
||||
gpointer value;
|
||||
GHashTableIter it;
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
|
||||
g_hash_table_iter_init(&it, priv->watch_table);
|
||||
while (g_hash_table_iter_next(&it, NULL, &value)) {
|
||||
GBinderServiceManagerWatch* watch = value;
|
||||
|
||||
GASSERT(!watch->watched);
|
||||
watch->watched = klass->watch(self, watch->name);
|
||||
if (watch->watched) {
|
||||
GDEBUG("Watching %s", watch->name);
|
||||
} else {
|
||||
GWARN("Failed to watch %s", watch->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_signal_emit(self, gbinder_servicemanager_signals[SIGNAL_PRESENCE], 0);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_servicemanager_presense_check_timer(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(user_data);
|
||||
GBinderRemoteObject* remote = self->client->remote;
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
gboolean result;
|
||||
|
||||
GASSERT(remote->dead);
|
||||
gbinder_servicemanager_ref(self);
|
||||
if (gbinder_remote_object_reanimate(remote)) {
|
||||
/* Done */
|
||||
priv->presence_check = NULL;
|
||||
gbinder_servicemanager_reanimated(self);
|
||||
result = G_SOURCE_REMOVE;
|
||||
} else if (priv->presence_check_delay_ms < PRESENSE_WAIT_MS_MAX) {
|
||||
priv->presence_check_delay_ms += PRESENSE_WAIT_MS_STEP;
|
||||
priv->presence_check =
|
||||
gbinder_timeout_add(priv->presence_check_delay_ms,
|
||||
gbinder_servicemanager_presense_check_timer, self);
|
||||
result = G_SOURCE_REMOVE;
|
||||
} else {
|
||||
result = G_SOURCE_CONTINUE;
|
||||
}
|
||||
gbinder_servicemanager_unref(self);
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_presence_check_start(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
|
||||
GASSERT(!priv->presence_check);
|
||||
priv->presence_check_delay_ms = PRESENSE_WAIT_MS_MIN;
|
||||
priv->presence_check = gbinder_timeout_add(PRESENSE_WAIT_MS_MIN,
|
||||
gbinder_servicemanager_presense_check_timer, self);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_died(
|
||||
GBinderRemoteObject* remote,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(user_data);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
|
||||
GWARN("Service manager %s has died", self->dev);
|
||||
gbinder_servicemanager_presence_check_start(self);
|
||||
|
||||
/* Will re-arm watches after servicemanager gets restarted */
|
||||
if (g_hash_table_size(priv->watch_table) > 0) {
|
||||
gpointer value;
|
||||
GHashTableIter it;
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
|
||||
g_hash_table_iter_init(&it, priv->watch_table);
|
||||
while (g_hash_table_iter_next(&it, NULL, &value)) {
|
||||
GBinderServiceManagerWatch* watch = value;
|
||||
|
||||
if (watch->watched) {
|
||||
GDEBUG("Unwatching %s", watch->name);
|
||||
watch->watched = FALSE;
|
||||
klass->unwatch(self, watch->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_signal_emit(self, gbinder_servicemanager_signals[SIGNAL_PRESENCE], 0);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_sleep_ms(
|
||||
gulong ms)
|
||||
{
|
||||
struct timespec wait;
|
||||
|
||||
wait.tv_sec = ms/1000; /* seconds */
|
||||
wait.tv_nsec = (ms % 1000) * 1000000; /* nanoseconds */
|
||||
while (nanosleep(&wait, &wait) == -1 && errno == EINTR &&
|
||||
(wait.tv_sec > 0 || wait.tv_nsec > 0));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_autorelease_cb(
|
||||
gpointer data)
|
||||
{
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(data);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
GSList* list = priv->autorelease;
|
||||
|
||||
priv->autorelease_cb = NULL;
|
||||
priv->autorelease = NULL;
|
||||
g_slist_free_full(list, g_object_unref);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_map_add_default(
|
||||
GHashTable* map,
|
||||
const char* dev,
|
||||
const GBinderServiceManagerType* type)
|
||||
{
|
||||
if (!g_hash_table_contains(map, dev)) {
|
||||
g_hash_table_insert(map, g_strdup(dev), (gpointer) type);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gconstpointer
|
||||
gbinder_servicemanager_value_map(
|
||||
const char* name)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(gbinder_servicemanager_types); i++) {
|
||||
const GBinderServiceManagerType* t = gbinder_servicemanager_types + i;
|
||||
|
||||
if (!g_strcmp0(name, t->name)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
GHashTable*
|
||||
gbinder_servicemanager_load_config()
|
||||
{
|
||||
GHashTable* map = gbinder_config_load(CONF_GROUP,
|
||||
gbinder_servicemanager_value_map);
|
||||
|
||||
/* Add default configuration if it's not overridden */
|
||||
gbinder_servicemanager_map_add_default(map,
|
||||
GBINDER_DEFAULT_BINDER, SERVICEMANAGER_TYPE_AIDL);
|
||||
gbinder_servicemanager_map_add_default(map,
|
||||
GBINDER_DEFAULT_HWBINDER, SERVICEMANAGER_TYPE_HIDL);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/* Runs at exit */
|
||||
void
|
||||
gbinder_servicemanager_exit(
|
||||
void)
|
||||
{
|
||||
if (gbinder_servicemanager_map) {
|
||||
g_hash_table_destroy(gbinder_servicemanager_map);
|
||||
gbinder_servicemanager_map = NULL;
|
||||
}
|
||||
/* Reset the default too, mostly for unit testing */
|
||||
gbinder_servicemanager_default = SERVICEMANAGER_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internal interface
|
||||
*==========================================================================*/
|
||||
@@ -260,7 +518,8 @@ gbinder_servicemanager_add_service_tx_free(
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev)
|
||||
const char* dev,
|
||||
const char* rpc_protocol)
|
||||
{
|
||||
GBinderServiceManager* self = NULL;
|
||||
GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
|
||||
@@ -269,23 +528,26 @@ gbinder_servicemanager_new_with_type(
|
||||
GBinderIpc* ipc;
|
||||
|
||||
if (!dev) dev = klass->default_device;
|
||||
ipc = gbinder_ipc_new(dev, klass->rpc_protocol);
|
||||
ipc = gbinder_ipc_new(dev, rpc_protocol);
|
||||
if (ipc) {
|
||||
GBinderRemoteObject* object = gbinder_ipc_get_remote_object
|
||||
(ipc, klass->handle);
|
||||
/* Create a (possibly) dead service manager object */
|
||||
GBinderRemoteObject* object = gbinder_ipc_get_service_manager(ipc);
|
||||
|
||||
if (object) {
|
||||
gboolean first_ref;
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&klass->mutex);
|
||||
if (klass->table) {
|
||||
self = g_hash_table_lookup(klass->table, dev);
|
||||
}
|
||||
if (self) {
|
||||
first_ref = FALSE;
|
||||
gbinder_servicemanager_ref(self);
|
||||
} else {
|
||||
char* key = g_strdup(dev); /* Owned by the hashtable */
|
||||
|
||||
GVERBOSE_("%s", dev);
|
||||
first_ref = TRUE;
|
||||
self = g_object_new(type, NULL);
|
||||
self->client = gbinder_client_new(object, klass->iface);
|
||||
self->dev = gbinder_remote_object_dev(object);
|
||||
@@ -297,6 +559,20 @@ gbinder_servicemanager_new_with_type(
|
||||
}
|
||||
g_mutex_unlock(&klass->mutex);
|
||||
/* Unlock */
|
||||
if (first_ref) {
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
|
||||
priv->death_id =
|
||||
gbinder_remote_object_add_death_handler(object,
|
||||
gbinder_servicemanager_died, self);
|
||||
/* Query the actual state if necessary */
|
||||
gbinder_remote_object_reanimate(object);
|
||||
if (object->dead) {
|
||||
gbinder_servicemanager_presence_check_start(self);
|
||||
}
|
||||
GDEBUG("%s has %sservice manager", dev,
|
||||
object->dead ? "no " : "");
|
||||
}
|
||||
gbinder_remote_object_unref(object);
|
||||
}
|
||||
gbinder_ipc_unref(ipc);
|
||||
@@ -344,10 +620,57 @@ GBinderServiceManager*
|
||||
gbinder_servicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
if (!g_strcmp0(dev, GBINDER_DEFAULT_HWBINDER)) {
|
||||
return gbinder_hwservicemanager_new(dev);
|
||||
return gbinder_servicemanager_new2(dev, NULL, NULL);
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new2(
|
||||
const char* dev,
|
||||
const char* sm_protocol,
|
||||
const char* rpc_protocol) /* Since 1.1.20 */
|
||||
{
|
||||
if (!dev) {
|
||||
return NULL;
|
||||
} else if (!sm_protocol) {
|
||||
const GBinderServiceManagerType* type;
|
||||
|
||||
/* One-time initialization */
|
||||
if (!gbinder_servicemanager_map) {
|
||||
gbinder_servicemanager_map = gbinder_servicemanager_load_config();
|
||||
|
||||
/* "Default" is a special value stored in a special variable */
|
||||
type = g_hash_table_lookup(gbinder_servicemanager_map,
|
||||
CONF_DEFAULT);
|
||||
if (type) {
|
||||
g_hash_table_remove(gbinder_servicemanager_map, CONF_DEFAULT);
|
||||
gbinder_servicemanager_default = type;
|
||||
} else {
|
||||
gbinder_servicemanager_default = SERVICEMANAGER_TYPE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no protocol is specified, pick one up based on the device name */
|
||||
type = g_hash_table_lookup(gbinder_servicemanager_map, dev);
|
||||
if (type) {
|
||||
GDEBUG("Using %s service manager for %s", type->name, dev);
|
||||
} else {
|
||||
type = gbinder_servicemanager_default;
|
||||
GDEBUG("Using default service manager %s for %s", type->name, dev);
|
||||
}
|
||||
return gbinder_servicemanager_new_with_type(type->get_type(), dev,
|
||||
rpc_protocol);
|
||||
} else {
|
||||
return gbinder_defaultservicemanager_new(dev);
|
||||
/* If protocol name is specified, it must be a valid one */
|
||||
const GBinderServiceManagerType* type =
|
||||
gbinder_servicemanager_value_map(sm_protocol);
|
||||
|
||||
if (type) {
|
||||
return gbinder_servicemanager_new_with_type(type->get_type(), dev,
|
||||
rpc_protocol);
|
||||
} else {
|
||||
GWARN("Unknown servicemanager protocol %s", sm_protocol);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,10 +680,25 @@ gbinder_servicemanager_new_local_object(
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
{
|
||||
const char* ifaces[2];
|
||||
|
||||
ifaces[0] = iface;
|
||||
ifaces[1] = NULL;
|
||||
return gbinder_servicemanager_new_local_object2
|
||||
(self, ifaces, txproc, user_data);
|
||||
}
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_servicemanager_new_local_object2(
|
||||
GBinderServiceManager* self,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return gbinder_ipc_new_local_object(gbinder_client_ipc(self->client),
|
||||
iface, txproc, user_data);
|
||||
return gbinder_local_object_new(gbinder_client_ipc(self->client),
|
||||
ifaces, txproc, user_data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -384,6 +722,65 @@ gbinder_servicemanager_unref(
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_servicemanager_device(
|
||||
GBinderServiceManager* self) /* Since 1.1.14 */
|
||||
{
|
||||
return G_LIKELY(self) ? self->dev : NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_servicemanager_is_present(
|
||||
GBinderServiceManager* self) /* Since 1.0.25 */
|
||||
{
|
||||
return G_LIKELY(self) && !self->client->remote->dead;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_servicemanager_wait(
|
||||
GBinderServiceManager* self,
|
||||
long max_wait_ms) /* Since 1.0.25 */
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* remote = self->client->remote;
|
||||
|
||||
if (!remote->dead) {
|
||||
return TRUE;
|
||||
} else if (gbinder_remote_object_reanimate(remote)) {
|
||||
gbinder_servicemanager_reanimated(self);
|
||||
return TRUE;
|
||||
} else if (max_wait_ms != 0) {
|
||||
/* Zero timeout means a singe check and it's already done */
|
||||
long delay_ms = PRESENSE_WAIT_MS_MIN;
|
||||
|
||||
while (max_wait_ms != 0) {
|
||||
if (max_wait_ms > 0) {
|
||||
if (max_wait_ms < delay_ms) {
|
||||
delay_ms = max_wait_ms;
|
||||
max_wait_ms = 0;
|
||||
} else {
|
||||
max_wait_ms -= delay_ms;
|
||||
}
|
||||
}
|
||||
gbinder_servicemanager_sleep_ms(delay_ms);
|
||||
if (gbinder_remote_object_reanimate(remote)) {
|
||||
gbinder_servicemanager_reanimated(self);
|
||||
return TRUE;
|
||||
}
|
||||
if (delay_ms < PRESENSE_WAIT_MS_MAX) {
|
||||
delay_ms += PRESENSE_WAIT_MS_STEP;
|
||||
if (delay_ms > PRESENSE_WAIT_MS_MAX) {
|
||||
delay_ms = PRESENSE_WAIT_MS_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Timeout */
|
||||
GWARN("Timeout waiting for service manager %s", self->dev);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_list(
|
||||
GBinderServiceManager* self,
|
||||
@@ -411,7 +808,8 @@ gbinder_servicemanager_list_sync(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return GBINDER_SERVICEMANAGER_GET_CLASS(self)->list(self);
|
||||
return GBINDER_SERVICEMANAGER_GET_CLASS(self)->
|
||||
list(self, &gbinder_ipc_sync_main);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -450,12 +848,17 @@ gbinder_servicemanager_get_service_sync(
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
|
||||
if (G_LIKELY(self) && name) {
|
||||
obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)->get_service
|
||||
(self, name, status);
|
||||
if (!self->pool) {
|
||||
self->pool = gutil_idle_pool_new();
|
||||
obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)->
|
||||
get_service(self, name, status, &gbinder_ipc_sync_main);
|
||||
if (obj) {
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
|
||||
priv->autorelease = g_slist_prepend(priv->autorelease, obj);
|
||||
if (!priv->autorelease_cb) {
|
||||
priv->autorelease_cb = gbinder_idle_callback_schedule_new
|
||||
(gbinder_servicemanager_autorelease_cb, self, NULL);
|
||||
}
|
||||
}
|
||||
gutil_idle_pool_add_object(self->pool, obj);
|
||||
} else if (status) {
|
||||
*status = (-EINVAL);
|
||||
}
|
||||
@@ -496,8 +899,8 @@ gbinder_servicemanager_add_service_sync(
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
if (G_LIKELY(self) && name && obj) {
|
||||
return GBINDER_SERVICEMANAGER_GET_CLASS(self)->add_service
|
||||
(self, name, obj);
|
||||
return GBINDER_SERVICEMANAGER_GET_CLASS(self)->
|
||||
add_service(self, name, obj, &gbinder_ipc_sync_main);
|
||||
} else {
|
||||
return (-EINVAL);
|
||||
}
|
||||
@@ -513,6 +916,16 @@ gbinder_servicemanager_cancel(
|
||||
}
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_presence_handler(
|
||||
GBinderServiceManager* self,
|
||||
GBinderServiceManagerFunc func,
|
||||
void* user_data) /* Since 1.0.25 */
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(func)) ? g_signal_connect(self,
|
||||
SIGNAL_PRESENCE_NAME, G_CALLBACK(func), user_data) : 0;
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_registration_handler(
|
||||
GBinderServiceManager* self,
|
||||
@@ -546,8 +959,8 @@ gbinder_servicemanager_add_registration_handler(
|
||||
watch = gbinder_servicemanager_watch_new(name);
|
||||
g_hash_table_insert(priv->watch_table, watch->name, watch);
|
||||
}
|
||||
if (!watch->watched) {
|
||||
watch->watched = klass->watch(self, name);
|
||||
if (!watch->watched && !self->client->remote->dead) {
|
||||
watch->watched = klass->watch(self, watch->name);
|
||||
if (watch->watched) {
|
||||
GDEBUG("Watching %s", watch->name);
|
||||
} else {
|
||||
@@ -570,31 +983,73 @@ gbinder_servicemanager_remove_handler(
|
||||
GBinderServiceManager* self,
|
||||
gulong id) /* Since 1.0.13 */
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
GHashTableIter it;
|
||||
gpointer value;
|
||||
gbinder_servicemanager_remove_handlers(self, &id, 1);
|
||||
}
|
||||
|
||||
g_signal_handler_disconnect(self, id);
|
||||
g_hash_table_iter_init(&it, priv->watch_table);
|
||||
while (g_hash_table_iter_next(&it, NULL, &value)) {
|
||||
GBinderServiceManagerWatch* watch = value;
|
||||
void
|
||||
gbinder_servicemanager_remove_handlers(
|
||||
GBinderServiceManager* self,
|
||||
gulong* ids,
|
||||
guint count) /* Since 1.0.25 */
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(ids) && G_LIKELY(count)) {
|
||||
guint i, disconnected = 0;
|
||||
|
||||
if (watch->watched && !g_signal_has_handler_pending(self,
|
||||
gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
|
||||
watch->quark, TRUE)) {
|
||||
/* This must be the one we have just removed */
|
||||
GDEBUG("Unwatching %s", watch->name);
|
||||
watch->watched = FALSE;
|
||||
klass->unwatch(self, watch->name);
|
||||
break;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (ids[i]) {
|
||||
g_signal_handler_disconnect(self, ids[i]);
|
||||
disconnected++;
|
||||
ids[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (disconnected) {
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
GHashTableIter it;
|
||||
gpointer value;
|
||||
|
||||
g_hash_table_iter_init(&it, priv->watch_table);
|
||||
while (disconnected && g_hash_table_iter_next(&it, NULL, &value)) {
|
||||
GBinderServiceManagerWatch* watch = value;
|
||||
|
||||
if (watch->watched && !g_signal_has_handler_pending(self,
|
||||
gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
|
||||
watch->quark, TRUE)) {
|
||||
/* This must be one of those we have just removed */
|
||||
GDEBUG("Unwatching %s", watch->name);
|
||||
watch->watched = FALSE;
|
||||
klass->unwatch(self, watch->name);
|
||||
disconnected--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* These two exist mostly for backward compatibility. Normally,
|
||||
* gbinder_servicemanager_new() should be used, to allow the type of
|
||||
* service manager to be configurable per device via /etc/gbinder.conf
|
||||
*/
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_defaultservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_servicemanager_aidl_get_type(), dev, NULL);
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_servicemanager_hidl_get_type(), dev, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
@@ -662,8 +1117,11 @@ gbinder_servicemanager_finalize(
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
|
||||
gbinder_timeout_remove(priv->presence_check);
|
||||
gbinder_remote_object_remove_handler(self->client->remote, priv->death_id);
|
||||
gbinder_idle_callback_destroy(priv->autorelease_cb);
|
||||
g_slist_free_full(priv->autorelease, g_object_unref);
|
||||
g_hash_table_destroy(priv->watch_table);
|
||||
gutil_idle_pool_destroy(self->pool);
|
||||
gbinder_client_unref(self->client);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
@@ -674,13 +1132,18 @@ gbinder_servicemanager_class_init(
|
||||
GBinderServiceManagerClass* klass)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
GType type = G_OBJECT_CLASS_TYPE(klass);
|
||||
|
||||
g_mutex_init(&klass->mutex);
|
||||
g_type_class_add_private(klass, sizeof(GBinderServiceManagerPriv));
|
||||
object_class->dispose = gbinder_servicemanager_dispose;
|
||||
object_class->finalize = gbinder_servicemanager_finalize;
|
||||
gbinder_servicemanager_signals[SIGNAL_PRESENCE] =
|
||||
g_signal_new(SIGNAL_PRESENCE_NAME, type,
|
||||
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
gbinder_servicemanager_signals[SIGNAL_REGISTRATION] =
|
||||
g_signal_new(SIGNAL_REGISTRATION_NAME, G_OBJECT_CLASS_TYPE(klass),
|
||||
g_signal_new(SIGNAL_REGISTRATION_NAME, type,
|
||||
G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, 0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||
}
|
||||
|
||||
331
src/gbinder_servicemanager_aidl.c
Normal file
331
src/gbinder_servicemanager_aidl.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_aidl.h"
|
||||
#include "gbinder_servicepoll.h"
|
||||
#include "gbinder_eventloop_p.h"
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
|
||||
typedef struct gbinder_servicemanager_aidl_watch {
|
||||
GBinderServicePoll* poll;
|
||||
char* name;
|
||||
gulong handler_id;
|
||||
GBinderEventLoopTimeout* notify;
|
||||
} GBinderServiceManagerAidlWatch;
|
||||
|
||||
struct gbinder_servicemanager_aidl_priv {
|
||||
GBinderServicePoll* poll;
|
||||
GHashTable* watch_table;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GBinderServiceManagerAidl,
|
||||
gbinder_servicemanager_aidl,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define PARENT_CLASS gbinder_servicemanager_aidl_parent_class
|
||||
#define GBINDER_SERVICEMANAGER_AIDL(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER_AIDL, \
|
||||
GBinderServiceManagerAidl)
|
||||
|
||||
#define SERVICEMANAGER_AIDL_IFACE "android.os.IServiceManager"
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl_watch_proc(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name_added,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderServiceManagerAidlWatch* watch = user_data;
|
||||
|
||||
if (!g_strcmp0(name_added, watch->name)) {
|
||||
GBinderServiceManager* manager =
|
||||
gbinder_servicepoll_manager(watch->poll);
|
||||
|
||||
if (watch->notify) {
|
||||
gbinder_timeout_remove(watch->notify);
|
||||
watch->notify = NULL;
|
||||
}
|
||||
gbinder_servicemanager_service_registered(manager, name_added);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_servicemanager_aidl_watch_notify(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServiceManagerAidlWatch* watch = user_data;
|
||||
GBinderServiceManager* manager = gbinder_servicepoll_manager(watch->poll);
|
||||
char* name = g_strdup(watch->name);
|
||||
|
||||
GASSERT(watch->notify);
|
||||
watch->notify = NULL;
|
||||
gbinder_servicemanager_service_registered(manager, name);
|
||||
g_free(name);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl_watch_free(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServiceManagerAidlWatch* watch = user_data;
|
||||
|
||||
gbinder_timeout_remove(watch->notify);
|
||||
gbinder_servicepoll_remove_handler(watch->poll, watch->handler_id);
|
||||
gbinder_servicepoll_unref(watch->poll);
|
||||
g_free(watch->name);
|
||||
g_slice_free(GBinderServiceManagerAidlWatch, watch);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderServiceManagerAidlWatch*
|
||||
gbinder_servicemanager_aidl_watch_new(
|
||||
GBinderServiceManagerAidl* self,
|
||||
const char* name)
|
||||
{
|
||||
GBinderServiceManagerAidlPriv* priv = self->priv;
|
||||
GBinderServiceManagerAidlWatch* watch =
|
||||
g_slice_new0(GBinderServiceManagerAidlWatch);
|
||||
|
||||
watch->name = g_strdup(name);
|
||||
watch->poll = gbinder_servicepoll_new(&self->manager, &priv->poll);
|
||||
watch->handler_id = gbinder_servicepoll_add_handler(priv->poll,
|
||||
gbinder_servicemanager_aidl_watch_proc, watch);
|
||||
return watch;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_aidl_list_services_req(
|
||||
GBinderClient* client,
|
||||
gint32 index)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
gbinder_local_request_append_int32(req, index);
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_aidl_add_service_req(
|
||||
GBinderClient* client,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
gbinder_local_request_append_int32(req, 0);
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
char**
|
||||
gbinder_servicemanager_aidl_list(
|
||||
GBinderServiceManager* manager,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
GBinderClient* client = manager->client;
|
||||
GBinderServiceManagerAidlClass* klass =
|
||||
GBINDER_SERVICEMANAGER_AIDL_GET_CLASS(manager);
|
||||
GBinderLocalRequest* req = klass->list_services_req(client, 0);
|
||||
GBinderRemoteReply* reply;
|
||||
|
||||
while ((reply = gbinder_client_transact_sync_reply2(client,
|
||||
LIST_SERVICES_TRANSACTION, req, NULL, api)) != NULL) {
|
||||
char* service = gbinder_remote_reply_read_string16(reply);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
if (service) {
|
||||
g_ptr_array_add(list, service);
|
||||
gbinder_local_request_unref(req);
|
||||
req = klass->list_services_req(client, list->len);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
g_ptr_array_add(list, NULL);
|
||||
return (char**)g_ptr_array_free(list, FALSE);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderRemoteObject*
|
||||
gbinder_servicemanager_aidl_get_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
int* status,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
GBinderRemoteObject* obj;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
reply = gbinder_client_transact_sync_reply2(self->client,
|
||||
CHECK_SERVICE_TRANSACTION, req, status, api);
|
||||
|
||||
obj = gbinder_remote_reply_read_object(reply);
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
gbinder_servicemanager_aidl_add_service(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
int status;
|
||||
GBinderClient* client = manager->client;
|
||||
GBinderLocalRequest* req = GBINDER_SERVICEMANAGER_AIDL_GET_CLASS
|
||||
(manager)->add_service_req(client, name, obj);
|
||||
GBinderRemoteReply* reply = gbinder_client_transact_sync_reply2(client,
|
||||
ADD_SERVICE_TRANSACTION, req, &status, api);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
gbinder_servicemanager_aidl_check_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
return GBINDER_SERVICEMANAGER_NAME_OK;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_servicemanager_aidl_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderServiceManagerAidl* self = GBINDER_SERVICEMANAGER_AIDL(manager);
|
||||
GBinderServiceManagerAidlPriv* priv = self->priv;
|
||||
GBinderServiceManagerAidlWatch* watch =
|
||||
gbinder_servicemanager_aidl_watch_new(self, name);
|
||||
|
||||
g_hash_table_replace(priv->watch_table, watch->name, watch);
|
||||
if (gbinder_servicepoll_is_known_name(watch->poll, name)) {
|
||||
watch->notify = gbinder_idle_add
|
||||
(gbinder_servicemanager_aidl_watch_notify, watch);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl_unwatch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderServiceManagerAidl* self = GBINDER_SERVICEMANAGER_AIDL(manager);
|
||||
GBinderServiceManagerAidlPriv* priv = self->priv;
|
||||
|
||||
g_hash_table_remove(priv->watch_table, name);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl_init(
|
||||
GBinderServiceManagerAidl* self)
|
||||
{
|
||||
GBinderServiceManagerAidlPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
GBINDER_TYPE_SERVICEMANAGER_AIDL, GBinderServiceManagerAidlPriv);
|
||||
|
||||
self->priv = priv;
|
||||
priv->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
NULL, gbinder_servicemanager_aidl_watch_free);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServiceManagerAidl* self = GBINDER_SERVICEMANAGER_AIDL(object);
|
||||
GBinderServiceManagerAidlPriv* priv = self->priv;
|
||||
|
||||
g_hash_table_destroy(priv->watch_table);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl_class_init(
|
||||
GBinderServiceManagerAidlClass* klass)
|
||||
{
|
||||
GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(klass);
|
||||
GObjectClass* object = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GBinderServiceManagerAidlPriv));
|
||||
klass->list_services_req = gbinder_servicemanager_aidl_list_services_req;
|
||||
klass->add_service_req = gbinder_servicemanager_aidl_add_service_req;
|
||||
|
||||
manager->iface = SERVICEMANAGER_AIDL_IFACE;
|
||||
manager->default_device = GBINDER_DEFAULT_BINDER;
|
||||
|
||||
manager->list = gbinder_servicemanager_aidl_list;
|
||||
manager->get_service = gbinder_servicemanager_aidl_get_service;
|
||||
manager->add_service = gbinder_servicemanager_aidl_add_service;
|
||||
manager->check_name = gbinder_servicemanager_aidl_check_name;
|
||||
/* normalize_name is not needed */
|
||||
manager->watch = gbinder_servicemanager_aidl_watch;
|
||||
manager->unwatch = gbinder_servicemanager_aidl_unwatch;
|
||||
|
||||
object->finalize = gbinder_servicemanager_aidl_finalize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
77
src/gbinder_servicemanager_aidl.h
Normal file
77
src/gbinder_servicemanager_aidl.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Jolla Ltd.
|
||||
* Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_SERVICEMANAGER_AIDL_H
|
||||
#define GBINDER_SERVICEMANAGER_AIDL_H
|
||||
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
|
||||
typedef struct gbinder_servicemanager_aidl_priv GBinderServiceManagerAidlPriv;
|
||||
typedef struct gbinder_servicemanager_aidl {
|
||||
GBinderServiceManager manager;
|
||||
GBinderServiceManagerAidlPriv* priv;
|
||||
} GBinderServiceManagerAidl;
|
||||
|
||||
typedef struct gbinder_servicemanager_aidl_class {
|
||||
GBinderServiceManagerClass parent;
|
||||
GBinderLocalRequest* (*list_services_req)
|
||||
(GBinderClient* client, gint32 index);
|
||||
GBinderLocalRequest* (*add_service_req)
|
||||
(GBinderClient* client, const char* name, GBinderLocalObject* obj);
|
||||
} GBinderServiceManagerAidlClass;
|
||||
|
||||
#define GBINDER_TYPE_SERVICEMANAGER_AIDL \
|
||||
gbinder_servicemanager_aidl_get_type()
|
||||
#define GBINDER_SERVICEMANAGER_AIDL_GET_CLASS(obj) \
|
||||
G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_SERVICEMANAGER_AIDL, \
|
||||
GBinderServiceManagerAidlClass)
|
||||
|
||||
enum gbinder_servicemanager_aidl_calls {
|
||||
GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
CHECK_SERVICE_TRANSACTION,
|
||||
ADD_SERVICE_TRANSACTION,
|
||||
LIST_SERVICES_TRANSACTION
|
||||
};
|
||||
|
||||
#define DUMP_FLAG_PRIORITY_DEFAULT (0x08)
|
||||
#define DUMP_FLAG_PRIORITY_ALL (0x0f)
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_AIDL_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
|
||||
100
src/gbinder_servicemanager_aidl2.c
Normal file
100
src/gbinder_servicemanager_aidl2.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Jolla Ltd.
|
||||
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_aidl.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
#include <gbinder_local_request.h>
|
||||
|
||||
/* Variant of AIDL servicemanager appeared in Android 9 (API level 28) */
|
||||
|
||||
typedef GBinderServiceManagerAidl GBinderServiceManagerAidl2;
|
||||
typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl2Class;
|
||||
|
||||
G_DEFINE_TYPE(GBinderServiceManagerAidl2,
|
||||
gbinder_servicemanager_aidl2,
|
||||
GBINDER_TYPE_SERVICEMANAGER_AIDL)
|
||||
|
||||
#define PARENT_CLASS gbinder_servicemanager_aidl2_parent_class
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_aidl2_list_services_req(
|
||||
GBinderClient* client,
|
||||
gint32 index)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
gbinder_local_request_append_int32(req, index);
|
||||
gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_ALL);
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_aidl2_add_service_req(
|
||||
GBinderClient* client,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
gbinder_local_request_append_int32(req, 0);
|
||||
gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl2_init(
|
||||
GBinderServiceManagerAidl* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl2_class_init(
|
||||
GBinderServiceManagerAidl2Class* cls)
|
||||
{
|
||||
cls->list_services_req = gbinder_servicemanager_aidl2_list_services_req;
|
||||
cls->add_service_req = gbinder_servicemanager_aidl2_add_service_req;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
162
src/gbinder_servicemanager_aidl3.c
Normal file
162
src/gbinder_servicemanager_aidl3.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
|
||||
* Copyright (C) 2021 Madhushan Nishantha <jlmadushan@gmail.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_aidl_p.h"
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
|
||||
/* Variant of AIDL servicemanager appeared in Android 11 (API level 30) */
|
||||
|
||||
typedef GBinderServiceManagerAidl GBinderServiceManagerAidl3;
|
||||
typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl3Class;
|
||||
|
||||
G_DEFINE_TYPE(GBinderServiceManagerAidl3,
|
||||
gbinder_servicemanager_aidl3,
|
||||
GBINDER_TYPE_SERVICEMANAGER_AIDL)
|
||||
|
||||
#define PARENT_CLASS gbinder_servicemanager_aidl3_parent_class
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_servicemanager_aidl3_get_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
int* status,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
GBinderClient* client = self->client;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
GBinderRemoteObject* obj;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
reply = gbinder_client_transact_sync_reply2(client,
|
||||
CHECK_SERVICE_TRANSACTION, req, status, api);
|
||||
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
gbinder_reader_read_int32(&reader, NULL /* status? */);
|
||||
obj = gbinder_reader_read_object(&reader);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return obj;
|
||||
}
|
||||
|
||||
char**
|
||||
gbinder_servicemanager_aidl3_list(
|
||||
GBinderServiceManager* manager,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
GBinderClient* client = manager->client;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
/*
|
||||
* Starting from Android 11, no `index` field is required but
|
||||
* only with `dump priority` field to request to list services.
|
||||
* As a result, a vector of strings which stands for service
|
||||
* list is given in the binder response.
|
||||
*/
|
||||
gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_ALL);
|
||||
reply = gbinder_client_transact_sync_reply2(client,
|
||||
LIST_SERVICES_TRANSACTION, req, NULL, api);
|
||||
|
||||
if (reply) {
|
||||
GBinderReader reader;
|
||||
gint32 count;
|
||||
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
gbinder_reader_read_int32(&reader, NULL /* status */);
|
||||
if (gbinder_reader_read_int32(&reader, &count)) {
|
||||
int i;
|
||||
|
||||
/* Iterate each service name */
|
||||
for (i = 0; i < count; i++) {
|
||||
g_ptr_array_add(list, gbinder_reader_read_string16(&reader));
|
||||
}
|
||||
}
|
||||
gbinder_remote_reply_unref(reply);
|
||||
}
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
g_ptr_array_add(list, NULL);
|
||||
return (char**)g_ptr_array_free(list, FALSE);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_aidl3_add_service_req(
|
||||
GBinderClient* client,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
gbinder_local_request_append_int32(req, 0);
|
||||
gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl3_init(
|
||||
GBinderServiceManagerAidl3* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl3_class_init(
|
||||
GBinderServiceManagerAidl3Class* klass)
|
||||
{
|
||||
GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(klass);
|
||||
|
||||
klass->add_service_req = gbinder_servicemanager_aidl3_add_service_req;
|
||||
manager->list = gbinder_servicemanager_aidl3_list;
|
||||
manager->get_service = gbinder_servicemanager_aidl3_get_service;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
115
src/gbinder_servicemanager_aidl4.c
Normal file
115
src/gbinder_servicemanager_aidl4.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Jolla Ltd.
|
||||
* Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
|
||||
* Copyright (C) 2021 Madhushan Nishantha <jlmadushan@gmail.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_aidl_p.h"
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
|
||||
/* Variant of AIDL servicemanager appeared in Android 12 (API level 31) */
|
||||
|
||||
typedef GBinderServiceManagerAidl GBinderServiceManagerAidl4;
|
||||
typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl4Class;
|
||||
|
||||
G_DEFINE_TYPE(GBinderServiceManagerAidl4,
|
||||
gbinder_servicemanager_aidl4,
|
||||
GBINDER_TYPE_SERVICEMANAGER_AIDL)
|
||||
|
||||
#define PARENT_CLASS gbinder_servicemanager_aidl4_parent_class
|
||||
|
||||
#define BINDER_WIRE_FORMAT_VERSION (1)
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_aidl4_add_service_req(
|
||||
GBinderClient* client,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
|
||||
/*
|
||||
* When reading nullable strong binder, from Android 12, the format of
|
||||
* the `stability` field passed on the wire was changed and evolved to
|
||||
* `struct Category`, which consists of the following members with 4 bytes
|
||||
* long.
|
||||
*
|
||||
* struct Category {
|
||||
* uint8_t version;
|
||||
* uint8_t reserved[2];
|
||||
* Level level; <- bitmask of Stability::Level
|
||||
* }
|
||||
*
|
||||
* Hmmm, is that ^ really true?
|
||||
*/
|
||||
gbinder_local_request_append_int32(req,
|
||||
GBINDER_FOURCC(GBINDER_STABILITY_SYSTEM, 0, 0,
|
||||
BINDER_WIRE_FORMAT_VERSION));
|
||||
gbinder_local_request_append_int32(req, 0);
|
||||
gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl4_init(
|
||||
GBinderServiceManagerAidl* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_aidl4_class_init(
|
||||
GBinderServiceManagerAidl4Class* cls)
|
||||
{
|
||||
GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(cls);
|
||||
cls->add_service_req = gbinder_servicemanager_aidl4_add_service_req;
|
||||
manager->list = gbinder_servicemanager_aidl3_list;
|
||||
manager->get_service = gbinder_servicemanager_aidl3_get_service;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
|
||||
61
src/gbinder_servicemanager_aidl_p.h
Normal file
61
src/gbinder_servicemanager_aidl_p.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
|
||||
#define GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
|
||||
|
||||
#include "gbinder_servicemanager_aidl.h"
|
||||
|
||||
char**
|
||||
gbinder_servicemanager_aidl3_list(
|
||||
GBinderServiceManager* manager,
|
||||
const GBinderIpcSyncApi* api)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_servicemanager_aidl3_get_service(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name,
|
||||
int* status,
|
||||
const GBinderIpcSyncApi* api)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -31,10 +31,9 @@
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
#include <gbinder_local_object.h>
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
@@ -42,30 +41,30 @@
|
||||
#include <gbinder_reader.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct gbinder_hwservicemanager_watch {
|
||||
typedef struct gbinder_servicemanager_hidl_watch {
|
||||
char* name;
|
||||
GBinderLocalObject* callback;
|
||||
} GBinderHwServiceManagerWatch;
|
||||
} GBinderServiceManagerHidlWatch;
|
||||
|
||||
typedef GBinderServiceManagerClass GBinderHwServiceManagerClass;
|
||||
typedef struct gbinder_hwservicemanager {
|
||||
typedef GBinderServiceManagerClass GBinderServiceManagerHidlClass;
|
||||
typedef struct gbinder_servicemanager_hidl {
|
||||
GBinderServiceManager manager;
|
||||
GHashTable* watch_table;
|
||||
} GBinderHwServiceManager;
|
||||
} GBinderServiceManagerHidl;
|
||||
|
||||
G_DEFINE_TYPE(GBinderHwServiceManager,
|
||||
gbinder_hwservicemanager,
|
||||
G_DEFINE_TYPE(GBinderServiceManagerHidl,
|
||||
gbinder_servicemanager_hidl,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define PARENT_CLASS gbinder_hwservicemanager_parent_class
|
||||
#define GBINDER_TYPE_HWSERVICEMANAGER (gbinder_hwservicemanager_get_type())
|
||||
#define GBINDER_HWSERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_HWSERVICEMANAGER, \
|
||||
GBinderHwServiceManager)
|
||||
#define PARENT_CLASS gbinder_servicemanager_hidl_parent_class
|
||||
#define GBINDER_TYPE_SERVICEMANAGER_HIDL \
|
||||
gbinder_servicemanager_hidl_get_type()
|
||||
#define GBINDER_SERVICEMANAGER_HIDL(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER_HIDL, \
|
||||
GBinderServiceManagerHidl)
|
||||
|
||||
enum gbinder_hwservicemanager_calls {
|
||||
enum gbinder_servicemanager_hidl_calls {
|
||||
GET_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
ADD_TRANSACTION,
|
||||
GET_TRANSPORT_TRANSACTION,
|
||||
@@ -76,20 +75,18 @@ enum gbinder_hwservicemanager_calls {
|
||||
REGISTER_PASSTHROUGH_CLIENT_TRANSACTION
|
||||
};
|
||||
|
||||
enum gbinder_hwservicemanager_notifications {
|
||||
enum gbinder_servicemanager_hidl_notifications {
|
||||
ON_REGISTRATION_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION
|
||||
};
|
||||
|
||||
/* As a special case, ServiceManager's handle is zero */
|
||||
#define HWSERVICEMANAGER_HANDLE (0)
|
||||
#define HWSERVICEMANAGER_IFACE "android.hidl.manager@1.0::IServiceManager"
|
||||
#define HWSERVICEMANAGER_NOTIFICATION_IFACE \
|
||||
#define SERVICEMANAGER_HIDL_IFACE "android.hidl.manager@1.0::IServiceManager"
|
||||
#define SERVICEMANAGER_HIDL_NOTIFICATION_IFACE \
|
||||
"android.hidl.manager@1.0::IServiceNotification"
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_handle_registration(
|
||||
GBinderHwServiceManager* self,
|
||||
gbinder_servicemanager_hidl_handle_registration(
|
||||
GBinderServiceManagerHidl* self,
|
||||
GBinderReader* reader)
|
||||
{
|
||||
char* fqname = gbinder_reader_read_hidl_string(reader);
|
||||
@@ -113,7 +110,7 @@ gbinder_hwservicemanager_handle_registration(
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_hwservicemanager_notification(
|
||||
gbinder_servicemanager_hidl_notification(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
@@ -121,22 +118,22 @@ gbinder_hwservicemanager_notification(
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(user_data);
|
||||
GBinderServiceManagerHidl* self = GBINDER_SERVICEMANAGER_HIDL(user_data);
|
||||
const char* iface = gbinder_remote_request_interface(req);
|
||||
|
||||
if (!g_strcmp0(iface, HWSERVICEMANAGER_NOTIFICATION_IFACE)) {
|
||||
if (!g_strcmp0(iface, SERVICEMANAGER_HIDL_NOTIFICATION_IFACE)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
switch (code) {
|
||||
case ON_REGISTRATION_TRANSACTION:
|
||||
GDEBUG(HWSERVICEMANAGER_NOTIFICATION_IFACE " %u onRegistration",
|
||||
GDEBUG(SERVICEMANAGER_HIDL_NOTIFICATION_IFACE " %u onRegistration",
|
||||
code);
|
||||
gbinder_hwservicemanager_handle_registration(self, &reader);
|
||||
gbinder_servicemanager_hidl_handle_registration(self, &reader);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
break;
|
||||
default:
|
||||
GDEBUG(HWSERVICEMANAGER_NOTIFICATION_IFACE " %u", code);
|
||||
GDEBUG(SERVICEMANAGER_HIDL_NOTIFICATION_IFACE " %u", code);
|
||||
*status = GBINDER_STATUS_FAILED;
|
||||
break;
|
||||
}
|
||||
@@ -147,22 +144,15 @@ gbinder_hwservicemanager_notification(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_hwservicemanager_get_type(), dev);
|
||||
}
|
||||
|
||||
static
|
||||
char**
|
||||
gbinder_hwservicemanager_list(
|
||||
GBinderServiceManager* self)
|
||||
gbinder_servicemanager_hidl_list(
|
||||
GBinderServiceManager* self,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
GBinderRemoteReply* reply = gbinder_client_transact_sync_reply
|
||||
(self->client, LIST_TRANSACTION, req, NULL);
|
||||
GBinderRemoteReply* reply = gbinder_client_transact_sync_reply2
|
||||
(self->client, LIST_TRANSACTION, req, NULL, api);
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
if (reply) {
|
||||
@@ -186,10 +176,11 @@ gbinder_hwservicemanager_list(
|
||||
|
||||
static
|
||||
GBinderRemoteObject*
|
||||
gbinder_hwservicemanager_get_service(
|
||||
gbinder_servicemanager_hidl_get_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* fqinstance,
|
||||
int* status)
|
||||
int* status,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
/* e.g. "android.hardware.radio@1.1::IRadio/slot1" */
|
||||
const char* sep = strchr(fqinstance, '/');
|
||||
@@ -204,8 +195,8 @@ gbinder_hwservicemanager_get_service(
|
||||
gbinder_local_request_append_hidl_string(req, fqname);
|
||||
gbinder_local_request_append_hidl_string(req, name);
|
||||
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
GET_TRANSACTION, req, status);
|
||||
reply = gbinder_client_transact_sync_reply2(self->client,
|
||||
GET_TRANSACTION, req, status, api);
|
||||
|
||||
if (reply) {
|
||||
GBinderReader reader;
|
||||
@@ -233,10 +224,11 @@ gbinder_hwservicemanager_get_service(
|
||||
|
||||
static
|
||||
int
|
||||
gbinder_hwservicemanager_add_service(
|
||||
gbinder_servicemanager_hidl_add_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
GBinderLocalObject* obj,
|
||||
const GBinderIpcSyncApi* api)
|
||||
{
|
||||
int status;
|
||||
GBinderRemoteReply* reply;
|
||||
@@ -246,8 +238,8 @@ gbinder_hwservicemanager_add_service(
|
||||
gbinder_local_request_append_hidl_string(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
ADD_TRANSACTION, req, &status);
|
||||
reply = gbinder_client_transact_sync_reply2(self->client,
|
||||
ADD_TRANSACTION, req, &status, api);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
@@ -256,10 +248,10 @@ gbinder_hwservicemanager_add_service(
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_watch_free(
|
||||
gbinder_servicemanager_hidl_watch_free(
|
||||
gpointer data)
|
||||
{
|
||||
GBinderHwServiceManagerWatch* watch = data;
|
||||
GBinderServiceManagerHidlWatch* watch = data;
|
||||
|
||||
g_free(watch->name);
|
||||
gbinder_local_object_drop(watch->callback);
|
||||
@@ -268,7 +260,7 @@ gbinder_hwservicemanager_watch_free(
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
gbinder_hwservicemanager_check_name(
|
||||
gbinder_servicemanager_hidl_check_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
@@ -289,32 +281,32 @@ gbinder_hwservicemanager_check_name(
|
||||
|
||||
static
|
||||
char*
|
||||
gbinder_hwservicemanager_normalize_name(
|
||||
gbinder_servicemanager_hidl_normalize_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
/* Slash must be there, see gbinder_hwservicemanager_check_name() above */
|
||||
/* Slash must be there, see gbinder_servicemanager_hidl_check_name() */
|
||||
return g_strndup(name, strchr(name, '/') - name);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_hwservicemanager_watch(
|
||||
gbinder_servicemanager_hidl_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(manager);
|
||||
GBinderServiceManagerHidl* self = GBINDER_SERVICEMANAGER_HIDL(manager);
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(manager->client);
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderHwServiceManagerWatch* watch =
|
||||
g_new0(GBinderHwServiceManagerWatch, 1);
|
||||
GBinderServiceManagerHidlWatch* watch =
|
||||
g_new0(GBinderServiceManagerHidlWatch, 1);
|
||||
gboolean success = FALSE;
|
||||
int status;
|
||||
|
||||
watch->name = g_strdup(name);
|
||||
watch->callback = gbinder_servicemanager_new_local_object(manager,
|
||||
HWSERVICEMANAGER_NOTIFICATION_IFACE,
|
||||
gbinder_hwservicemanager_notification, self);
|
||||
SERVICEMANAGER_HIDL_NOTIFICATION_IFACE,
|
||||
gbinder_servicemanager_hidl_notification, self);
|
||||
g_hash_table_replace(self->watch_table, watch->name, watch);
|
||||
|
||||
/* registerForNotifications(string fqName, string name,
|
||||
@@ -346,28 +338,29 @@ gbinder_hwservicemanager_watch(
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_unwatch(
|
||||
gbinder_servicemanager_hidl_unwatch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
g_hash_table_remove(GBINDER_HWSERVICEMANAGER(manager)->watch_table, name);
|
||||
g_hash_table_remove(GBINDER_SERVICEMANAGER_HIDL(manager)->
|
||||
watch_table, name);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_init(
|
||||
GBinderHwServiceManager* self)
|
||||
gbinder_servicemanager_hidl_init(
|
||||
GBinderServiceManagerHidl* self)
|
||||
{
|
||||
self->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
NULL, gbinder_hwservicemanager_watch_free);
|
||||
NULL, gbinder_servicemanager_hidl_watch_free);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_finalize(
|
||||
gbinder_servicemanager_hidl_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(object);
|
||||
GBinderServiceManagerHidl* self = GBINDER_SERVICEMANAGER_HIDL(object);
|
||||
|
||||
g_hash_table_destroy(self->watch_table);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
@@ -375,22 +368,20 @@ gbinder_hwservicemanager_finalize(
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_class_init(
|
||||
GBinderHwServiceManagerClass* klass)
|
||||
gbinder_servicemanager_hidl_class_init(
|
||||
GBinderServiceManagerHidlClass* klass)
|
||||
{
|
||||
klass->handle = HWSERVICEMANAGER_HANDLE;
|
||||
klass->iface = HWSERVICEMANAGER_IFACE;
|
||||
klass->iface = SERVICEMANAGER_HIDL_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_HWBINDER;
|
||||
klass->rpc_protocol = &gbinder_rpc_protocol_hwbinder;
|
||||
|
||||
klass->list = gbinder_hwservicemanager_list;
|
||||
klass->get_service = gbinder_hwservicemanager_get_service;
|
||||
klass->add_service = gbinder_hwservicemanager_add_service;
|
||||
klass->check_name = gbinder_hwservicemanager_check_name;
|
||||
klass->normalize_name = gbinder_hwservicemanager_normalize_name;
|
||||
klass->watch = gbinder_hwservicemanager_watch;
|
||||
klass->unwatch = gbinder_hwservicemanager_unwatch;
|
||||
G_OBJECT_CLASS(klass)->finalize = gbinder_hwservicemanager_finalize;
|
||||
klass->list = gbinder_servicemanager_hidl_list;
|
||||
klass->get_service = gbinder_servicemanager_hidl_get_service;
|
||||
klass->add_service = gbinder_servicemanager_hidl_add_service;
|
||||
klass->check_name = gbinder_servicemanager_hidl_check_name;
|
||||
klass->normalize_name = gbinder_servicemanager_hidl_normalize_name;
|
||||
klass->watch = gbinder_servicemanager_hidl_watch;
|
||||
klass->unwatch = gbinder_servicemanager_hidl_unwatch;
|
||||
G_OBJECT_CLASS(klass)->finalize = gbinder_servicemanager_hidl_finalize;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -46,7 +46,6 @@ typedef struct gbinder_servicemanager {
|
||||
GBinderServiceManagerPriv* priv;
|
||||
const char* dev;
|
||||
GBinderClient* client;
|
||||
GUtilIdlePool* pool;
|
||||
} GBinderServiceManager;
|
||||
|
||||
typedef enum gbinder_servicemanager_name_check {
|
||||
@@ -60,18 +59,15 @@ typedef struct gbinder_servicemanager_class {
|
||||
GMutex mutex;
|
||||
GHashTable* table;
|
||||
|
||||
guint32 handle;
|
||||
const char* iface;
|
||||
const char* default_device;
|
||||
const GBinderRpcProtocol* rpc_protocol;
|
||||
|
||||
/* Methods (synchronous) */
|
||||
char** (*list)(GBinderServiceManager* self);
|
||||
GBinderRemoteObject* (*get_service)
|
||||
(GBinderServiceManager* self, const char* name, int* status);
|
||||
int (*add_service)
|
||||
(GBinderServiceManager* self, const char* name,
|
||||
GBinderLocalObject* obj);
|
||||
char** (*list)(GBinderServiceManager* self, const GBinderIpcSyncApi* api);
|
||||
GBinderRemoteObject* (*get_service)(GBinderServiceManager* self,
|
||||
const char* name, int* status, const GBinderIpcSyncApi* api);
|
||||
int (*add_service)(GBinderServiceManager* self, const char* name,
|
||||
GBinderLocalObject* obj, const GBinderIpcSyncApi* api);
|
||||
|
||||
/* Checking/normalizing watch names */
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK (*check_name)
|
||||
@@ -83,18 +79,41 @@ typedef struct gbinder_servicemanager_class {
|
||||
void (*unwatch)(GBinderServiceManager* self, const char* name);
|
||||
} GBinderServiceManagerClass;
|
||||
|
||||
GType gbinder_servicemanager_get_type(void);
|
||||
GType gbinder_servicemanager_get_type(void) GBINDER_INTERNAL;
|
||||
#define GBINDER_TYPE_SERVICEMANAGER (gbinder_servicemanager_get_type())
|
||||
#define GBINDER_SERVICEMANAGER_CLASS(klass) \
|
||||
G_TYPE_CHECK_CLASS_CAST((klass), GBINDER_TYPE_SERVICEMANAGER, \
|
||||
GBinderServiceManagerClass)
|
||||
|
||||
#define gbinder_servicemanager_ipc(sm) gbinder_client_ipc(sm->client)
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev);
|
||||
const char* dev,
|
||||
const char* rpc_protocol)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_servicemanager_service_registered(
|
||||
GBinderServiceManager* self,
|
||||
const char* name);
|
||||
const char* name)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Declared for unit tests */
|
||||
void
|
||||
gbinder_servicemanager_exit(
|
||||
void)
|
||||
GBINDER_INTERNAL
|
||||
GBINDER_DESTRUCTOR;
|
||||
|
||||
/* Derived types */
|
||||
|
||||
GType gbinder_servicemanager_aidl_get_type(void) GBINDER_INTERNAL;
|
||||
GType gbinder_servicemanager_aidl2_get_type(void) GBINDER_INTERNAL;
|
||||
GType gbinder_servicemanager_aidl3_get_type(void) GBINDER_INTERNAL;
|
||||
GType gbinder_servicemanager_aidl4_get_type(void) GBINDER_INTERNAL;
|
||||
GType gbinder_servicemanager_hidl_get_type(void) GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
|
||||
|
||||
|
||||
205
src/gbinder_servicename.c
Normal file
205
src/gbinder_servicename.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
#include "gbinder_eventloop_p.h"
|
||||
#include "gbinder_servicename.h"
|
||||
#include "gbinder_servicemanager.h"
|
||||
#include "gbinder_local_object.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
/* Since 1.0.26 */
|
||||
|
||||
#define GBINDER_SERVICENAME_RETRY_INTERVAL_MS (500)
|
||||
|
||||
typedef struct gbinder_servicename_priv {
|
||||
GBinderServiceName pub;
|
||||
gint refcount;
|
||||
char* name;
|
||||
GBinderLocalObject* object;
|
||||
GBinderServiceManager* sm;
|
||||
GBinderEventLoopTimeout* retry_timer;
|
||||
gulong presence_id;
|
||||
gulong add_call_id;
|
||||
} GBinderServiceNamePriv;
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicename_add_service(
|
||||
GBinderServiceNamePriv* priv);
|
||||
|
||||
GBINDER_INLINE_FUNC GBinderServiceNamePriv*
|
||||
gbinder_servicename_cast(GBinderServiceName* pub)
|
||||
{ return G_CAST(pub, GBinderServiceNamePriv, pub); }
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_servicename_add_service_retry(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServiceNamePriv* priv = user_data;
|
||||
|
||||
priv->retry_timer = NULL;
|
||||
gbinder_servicename_add_service(priv);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicename_add_service_done(
|
||||
GBinderServiceManager* sm,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderServiceNamePriv* priv = user_data;
|
||||
|
||||
GASSERT(priv->add_call_id);
|
||||
priv->add_call_id = 0;
|
||||
if (status) {
|
||||
GWARN("Error %d adding name \"%s\"", status, priv->name);
|
||||
gbinder_timeout_remove(priv->retry_timer);
|
||||
priv->retry_timer =
|
||||
gbinder_timeout_add(GBINDER_SERVICENAME_RETRY_INTERVAL_MS,
|
||||
gbinder_servicename_add_service_retry, priv);
|
||||
} else {
|
||||
GDEBUG("Service \"%s\" has been registered", priv->name);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicename_add_service(
|
||||
GBinderServiceNamePriv* priv)
|
||||
{
|
||||
GDEBUG("Adding service \"%s\"", priv->name);
|
||||
gbinder_servicemanager_cancel(priv->sm, priv->add_call_id);
|
||||
priv->add_call_id = gbinder_servicemanager_add_service(priv->sm,
|
||||
priv->name, priv->object, gbinder_servicename_add_service_done, priv);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicename_presence_handler(
|
||||
GBinderServiceManager* sm,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderServiceNamePriv* priv = user_data;
|
||||
|
||||
if (gbinder_servicemanager_is_present(sm)) {
|
||||
gbinder_servicename_add_service(priv);
|
||||
} else {
|
||||
if (priv->add_call_id) {
|
||||
gbinder_servicemanager_cancel(priv->sm, priv->add_call_id);
|
||||
priv->add_call_id = 0;
|
||||
}
|
||||
if (priv->retry_timer) {
|
||||
gbinder_timeout_remove(priv->retry_timer);
|
||||
priv->retry_timer = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderServiceName*
|
||||
gbinder_servicename_new(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderLocalObject* object,
|
||||
const char* name)
|
||||
{
|
||||
if (G_LIKELY(sm) && G_LIKELY(object) && G_LIKELY(name)) {
|
||||
GBinderServiceNamePriv* priv = g_slice_new0(GBinderServiceNamePriv);
|
||||
GBinderServiceName* self = &priv->pub;
|
||||
|
||||
g_atomic_int_set(&priv->refcount, 1);
|
||||
priv->object = gbinder_local_object_ref(object);
|
||||
priv->sm = gbinder_servicemanager_ref(sm);
|
||||
self->name = priv->name = g_strdup(name);
|
||||
priv->presence_id = gbinder_servicemanager_add_presence_handler(sm,
|
||||
gbinder_servicename_presence_handler, priv);
|
||||
if (gbinder_servicemanager_is_present(sm)) {
|
||||
gbinder_servicename_add_service(priv);
|
||||
}
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GBinderServiceName*
|
||||
gbinder_servicename_ref(
|
||||
GBinderServiceName* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderServiceNamePriv* priv = gbinder_servicename_cast(self);
|
||||
|
||||
GASSERT(priv->refcount > 0);
|
||||
g_atomic_int_inc(&priv->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_servicename_unref(
|
||||
GBinderServiceName* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderServiceNamePriv* priv = gbinder_servicename_cast(self);
|
||||
|
||||
GASSERT(priv->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&priv->refcount)) {
|
||||
gbinder_servicemanager_cancel(priv->sm, priv->add_call_id);
|
||||
gbinder_servicemanager_remove_handler(priv->sm, priv->presence_id);
|
||||
gbinder_servicemanager_unref(priv->sm);
|
||||
gbinder_local_object_unref(priv->object);
|
||||
gbinder_timeout_remove(priv->retry_timer);
|
||||
g_free(priv->name);
|
||||
gutil_slice_free(priv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "gbinder_servicepoll.h"
|
||||
#include "gbinder_servicemanager.h"
|
||||
#include "gbinder_eventloop_p.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
|
||||
@@ -46,13 +47,15 @@ struct gbinder_servicepoll {
|
||||
GBinderServiceManager* manager;
|
||||
char** list;
|
||||
gulong list_id;
|
||||
guint timer_id;
|
||||
GBinderEventLoopTimeout* timer;
|
||||
};
|
||||
|
||||
#define PARENT_CLASS gbinder_servicepoll_parent_class
|
||||
#define THIS_TYPE gbinder_servicepoll_get_type()
|
||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GBinderServicePoll)
|
||||
|
||||
GType THIS_TYPE GBINDER_INTERNAL;
|
||||
G_DEFINE_TYPE(GBinderServicePoll, gbinder_servicepoll, G_TYPE_OBJECT)
|
||||
#define GBINDER_TYPE_SERVICEPOLL (gbinder_servicepoll_get_type())
|
||||
#define GBINDER_SERVICEPOLL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_SERVICEPOLL, GBinderServicePoll))
|
||||
|
||||
enum gbinder_servicepoll_signal {
|
||||
SIGNAL_NAME_ADDED,
|
||||
@@ -75,7 +78,7 @@ gbinder_servicepoll_list(
|
||||
char** services,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderServicePoll* self = GBINDER_SERVICEPOLL(user_data);
|
||||
GBinderServicePoll* self = THIS(user_data);
|
||||
|
||||
gbinder_servicepoll_ref(self);
|
||||
self->list_id = 0;
|
||||
@@ -121,7 +124,7 @@ gboolean
|
||||
gbinder_servicepoll_timer(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServicePoll* self = GBINDER_SERVICEPOLL(user_data);
|
||||
GBinderServicePoll* self = THIS(user_data);
|
||||
|
||||
if (!self->list_id) {
|
||||
self->list_id = gbinder_servicemanager_list(self->manager,
|
||||
@@ -135,7 +138,7 @@ GBinderServicePoll*
|
||||
gbinder_servicepoll_create(
|
||||
GBinderServiceManager* manager)
|
||||
{
|
||||
GBinderServicePoll* self = g_object_new(GBINDER_TYPE_SERVICEPOLL, NULL);
|
||||
GBinderServicePoll* self = g_object_new(THIS_TYPE, NULL);
|
||||
|
||||
self->manager = gbinder_servicemanager_ref(manager);
|
||||
self->list_id = gbinder_servicemanager_list(manager,
|
||||
@@ -170,7 +173,7 @@ gbinder_servicepoll_ref(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(GBINDER_SERVICEPOLL(self));
|
||||
g_object_ref(THIS(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
@@ -182,7 +185,7 @@ gbinder_servicepoll_unref(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_SERVICEPOLL(self));
|
||||
g_object_unref(THIS(self));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +233,7 @@ void
|
||||
gbinder_servicepoll_init(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
self->timer_id = g_timeout_add(gbinder_servicepoll_interval_ms,
|
||||
self->timer = gbinder_timeout_add(gbinder_servicepoll_interval_ms,
|
||||
gbinder_servicepoll_timer, self);
|
||||
}
|
||||
|
||||
@@ -239,12 +242,13 @@ void
|
||||
gbinder_servicepoll_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServicePoll* self = GBINDER_SERVICEPOLL(object);
|
||||
GBinderServicePoll* self = THIS(object);
|
||||
|
||||
g_source_remove(self->timer_id);
|
||||
gbinder_timeout_remove(self->timer);
|
||||
gbinder_servicemanager_cancel(self->manager, self->list_id);
|
||||
gbinder_servicemanager_unref(self->manager);
|
||||
g_strfreev(self->list);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
extern guint gbinder_servicepoll_interval_ms;
|
||||
extern guint gbinder_servicepoll_interval_ms GBINDER_INTERNAL;
|
||||
|
||||
typedef
|
||||
void
|
||||
@@ -47,35 +47,42 @@ void
|
||||
GBinderServicePoll*
|
||||
gbinder_servicepoll_new(
|
||||
GBinderServiceManager* manager,
|
||||
GBinderServicePoll** weakptr);
|
||||
GBinderServicePoll** weakptr)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderServicePoll*
|
||||
gbinder_servicepoll_ref(
|
||||
GBinderServicePoll* poll);
|
||||
GBinderServicePoll* poll)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_servicepoll_unref(
|
||||
GBinderServicePoll* poll);
|
||||
GBinderServicePoll* poll)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicepoll_manager(
|
||||
GBinderServicePoll* poll);
|
||||
GBinderServicePoll* poll)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gboolean
|
||||
gbinder_servicepoll_is_known_name(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name);
|
||||
const char* name)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
gulong
|
||||
gbinder_servicepoll_add_handler(
|
||||
GBinderServicePoll* poll,
|
||||
GBinderServicePollFunc func,
|
||||
void* user_data);
|
||||
void* user_data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_servicepoll_remove_handler(
|
||||
GBinderServicePoll* poll,
|
||||
gulong id);
|
||||
gulong id)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_SERVICEPOLL_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
@@ -58,7 +59,10 @@ gbinder_system_ioctl(
|
||||
int request,
|
||||
void* data)
|
||||
{
|
||||
return ioctl(fd, request, data);
|
||||
int ret;
|
||||
|
||||
while ((ret = ioctl(fd, request, data)) < 0 && errno == EINTR);
|
||||
return ret >= 0 ? 0 : -errno;
|
||||
}
|
||||
|
||||
void*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -38,29 +38,34 @@
|
||||
int
|
||||
gbinder_system_open(
|
||||
const char* path,
|
||||
int flags);
|
||||
int flags)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_system_close(
|
||||
int fd);
|
||||
int fd)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_system_ioctl(
|
||||
int fd,
|
||||
int request,
|
||||
void* data);
|
||||
void* data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void*
|
||||
gbinder_system_mmap(
|
||||
size_t length,
|
||||
int prot,
|
||||
int flags,
|
||||
int fd);
|
||||
int fd)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
int
|
||||
gbinder_system_munmap(
|
||||
void* addr,
|
||||
size_t length);
|
||||
size_t length)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_SYSTEM_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -36,17 +36,23 @@
|
||||
#include <gbinder_types.h>
|
||||
|
||||
typedef struct gbinder_buffer_contents GBinderBufferContents;
|
||||
typedef struct gbinder_buffer_contents_list GBinderBufferContentsList;
|
||||
typedef struct gbinder_cleanup GBinderCleanup;
|
||||
typedef struct gbinder_driver GBinderDriver;
|
||||
typedef struct gbinder_handler GBinderHandler;
|
||||
typedef struct gbinder_io GBinderIo;
|
||||
typedef struct gbinder_ipc GBinderIpc;
|
||||
typedef struct gbinder_object_converter GBinderObjectConverter;
|
||||
typedef struct gbinder_object_registry GBinderObjectRegistry;
|
||||
typedef struct gbinder_output_data GBinderOutputData;
|
||||
typedef struct gbinder_proxy_object GBinderProxyObject;
|
||||
typedef struct gbinder_rpc_protocol GBinderRpcProtocol;
|
||||
typedef struct gbinder_servicepoll GBinderServicePoll;
|
||||
typedef struct gbinder_ipc_looper_tx GBinderIpcLooperTx;
|
||||
typedef struct gbinder_ipc_sync_api GBinderIpcSyncApi;
|
||||
|
||||
#define GBINDER_INLINE_FUNC static inline
|
||||
#define GBINDER_INTERNAL G_GNUC_INTERNAL
|
||||
#define GBINDER_DESTRUCTOR __attribute__((destructor))
|
||||
|
||||
#define GBINDER_TRANSACTION(c2,c3,c4) GBINDER_FOURCC('_',c2,c3,c4)
|
||||
#define GBINDER_PING_TRANSACTION GBINDER_TRANSACTION('P','N','G')
|
||||
@@ -68,6 +74,9 @@ typedef struct gbinder_servicepoll GBinderServicePoll;
|
||||
#define HIDL_DEBUG_TRANSACTION HIDL_FOURCC('D','B','G')
|
||||
#define HIDL_HASH_CHAIN_TRANSACTION HIDL_FOURCC('H','S','H')
|
||||
|
||||
/* As a special case, ServiceManager's handle is zero */
|
||||
#define GBINDER_SERVICEMANAGER_HANDLE (0)
|
||||
|
||||
#endif /* GBINDER_TYPES_PRIVATE_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2024 Jolla Ltd.
|
||||
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
* You may use this file under the terms of the BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -32,12 +32,16 @@
|
||||
|
||||
#include "gbinder_writer_p.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_fmq_p.h"
|
||||
#include "gbinder_local_object.h"
|
||||
#include "gbinder_object_converter.h"
|
||||
#include "gbinder_io.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_macros.h>
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
@@ -48,6 +52,20 @@ typedef struct gbinder_writer_priv {
|
||||
GBinderWriterData* data;
|
||||
} GBinderWriterPriv;
|
||||
|
||||
const GBinderWriterType gbinder_writer_type_byte = { "byte", 1, NULL };
|
||||
const GBinderWriterType gbinder_writer_type_int32 = { "int32", 4, NULL };
|
||||
static const GBinderWriterField gbinder_writer_type_hidl_string_f[] = {
|
||||
{
|
||||
"hidl_string.data.str", 0, NULL,
|
||||
gbinder_writer_field_hidl_string_write_buf, NULL
|
||||
},
|
||||
GBINDER_WRITER_FIELD_END()
|
||||
};
|
||||
const GBinderWriterType gbinder_writer_type_hidl_string = {
|
||||
"hidl_string", sizeof(GBinderHidlString),
|
||||
gbinder_writer_type_hidl_string_f
|
||||
};
|
||||
|
||||
G_STATIC_ASSERT(sizeof(GBinderWriter) >= sizeof(GBinderWriterPriv));
|
||||
|
||||
GBINDER_INLINE_FUNC GBinderWriterPriv* gbinder_writer_cast(GBinderWriter* pub)
|
||||
@@ -55,52 +73,90 @@ GBINDER_INLINE_FUNC GBinderWriterPriv* gbinder_writer_cast(GBinderWriter* pub)
|
||||
GBINDER_INLINE_FUNC GBinderWriterData* gbinder_writer_data(GBinderWriter* pub)
|
||||
{ return G_LIKELY(pub) ? gbinder_writer_cast(pub)->data : NULL; }
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_buffer_cleanup(
|
||||
gpointer data)
|
||||
{
|
||||
gbinder_buffer_contents_unref((GBinderBufferContents*)data);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_set_contents(
|
||||
GBinderWriterData* data,
|
||||
GBinderBuffer* buffer)
|
||||
GBinderBuffer* buffer,
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
gsize bufsize;
|
||||
const guint8* bufdata = gbinder_buffer_data(buffer, &bufsize);
|
||||
const GBinderIo* io = gbinder_buffer_io(buffer);
|
||||
GBinderBufferContents* contents = gbinder_buffer_contents(buffer);
|
||||
|
||||
GASSERT(data->io == io);
|
||||
g_byte_array_set_size(data->bytes, 0);
|
||||
gutil_int_array_set_count(data->offsets, 0);
|
||||
data->buffers_size = 0;
|
||||
gbinder_cleanup_reset(data->cleanup);
|
||||
gbinder_writer_data_append_contents(data, buffer, 0, convert);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_contents(
|
||||
GBinderWriterData* data,
|
||||
GBinderBuffer* buffer,
|
||||
gsize off,
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
GBinderBufferContents* contents = gbinder_buffer_contents(buffer);
|
||||
|
||||
g_byte_array_append(data->bytes, bufdata, bufsize);
|
||||
if (contents) {
|
||||
gsize bufsize;
|
||||
GByteArray* dest = data->bytes;
|
||||
const guint8* bufdata = gbinder_buffer_data(buffer, &bufsize);
|
||||
void** objects = gbinder_buffer_objects(buffer);
|
||||
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup,
|
||||
gbinder_writer_data_buffer_cleanup,
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, (GDestroyNotify)
|
||||
gbinder_buffer_contents_unref,
|
||||
gbinder_buffer_contents_ref(contents));
|
||||
if (objects && *objects) {
|
||||
const GBinderIo* io = gbinder_buffer_io(buffer);
|
||||
const GBinderRpcProtocol* proto = gbinder_buffer_protocol(buffer);
|
||||
|
||||
/* GBinderIo must be the same because it's defined by the kernel */
|
||||
GASSERT(io == data->io);
|
||||
if (!data->offsets) {
|
||||
data->offsets = gutil_int_array_new();
|
||||
}
|
||||
while (*objects) {
|
||||
const guint8* obj = *objects++;
|
||||
gsize offset = obj - bufdata;
|
||||
gsize objsize = io->object_data_size(obj);
|
||||
gsize objsize, offset = obj - bufdata;
|
||||
GBinderLocalObject* local;
|
||||
guint32 handle;
|
||||
|
||||
GASSERT(offset >= off && offset < bufsize);
|
||||
if (offset > off) {
|
||||
/* Copy serialized data preceeding this object */
|
||||
g_byte_array_append(dest, bufdata + off, offset - off);
|
||||
off = offset;
|
||||
}
|
||||
/* Offset in the destination buffer */
|
||||
gutil_int_array_append(data->offsets, dest->len);
|
||||
|
||||
/* Convert remote object into local if necessary */
|
||||
if (convert && io->decode_binder_handle(obj, &handle, proto) &&
|
||||
(local = gbinder_object_converter_handle_to_local
|
||||
(convert, handle))) {
|
||||
const guint pos = dest->len;
|
||||
|
||||
g_byte_array_set_size(dest, pos +
|
||||
GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
objsize = io->encode_local_object(dest->data + pos,
|
||||
local, proto);
|
||||
g_byte_array_set_size(dest, pos + objsize);
|
||||
|
||||
/* Keep the reference */
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup,
|
||||
(GDestroyNotify) gbinder_local_object_unref, local);
|
||||
} else {
|
||||
objsize = io->object_size(obj, proto);
|
||||
g_byte_array_append(dest, obj, objsize);
|
||||
}
|
||||
|
||||
GASSERT(offset > 0 && offset < bufsize);
|
||||
gutil_int_array_append(data->offsets, (int)offset);
|
||||
/* Size of each buffer has to be 8-byte aligned */
|
||||
data->buffers_size += G_ALIGN8(objsize);
|
||||
data->buffers_size += G_ALIGN8(io->object_data_size(obj));
|
||||
off += objsize;
|
||||
}
|
||||
}
|
||||
if (off < bufsize) {
|
||||
/* Copy remaining data */
|
||||
g_byte_array_append(dest, bufdata + off, bufsize - off);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,30 +172,6 @@ gbinder_writer_data_record_offset(
|
||||
gutil_int_array_append(data->offsets, offset);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_write_buffer_object(
|
||||
GBinderWriterData* data,
|
||||
const void* ptr,
|
||||
gsize size,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
GByteArray* buf = data->bytes;
|
||||
const guint offset = buf->len;
|
||||
guint n;
|
||||
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(buf, offset + GBINDER_MAX_BUFFER_OBJECT_SIZE);
|
||||
/* Write the object */
|
||||
n = data->io->encode_buffer_object(buf->data + offset, ptr, size, parent);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(buf, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
/* The driver seems to require each buffer to be 8-byte aligned */
|
||||
data->buffers_size += G_ALIGN8(size);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_init(
|
||||
GBinderWriter* self,
|
||||
@@ -149,6 +181,54 @@ gbinder_writer_init(
|
||||
gbinder_writer_cast(self)->data = data;
|
||||
}
|
||||
|
||||
const void*
|
||||
gbinder_writer_get_data(
|
||||
GBinderWriter* self,
|
||||
gsize* size) /* Since 1.1.14 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
GByteArray* buf = data->bytes;
|
||||
|
||||
if (size) {
|
||||
*size = buf->len;
|
||||
}
|
||||
return buf->data;
|
||||
} else {
|
||||
if (size) {
|
||||
*size = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_writer_bytes_written(
|
||||
GBinderWriter* self) /* since 1.0.21 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
return G_LIKELY(data) ? data->bytes->len : 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_append_padded(
|
||||
GByteArray* buf,
|
||||
const void* data,
|
||||
guint size)
|
||||
{
|
||||
/* Primitive values are padded to 4-byte boundary */
|
||||
const guint padded_size = 4;
|
||||
guint8* ptr;
|
||||
|
||||
g_byte_array_set_size(buf, buf->len + padded_size);
|
||||
ptr = buf->data + (buf->len - padded_size);
|
||||
memcpy(ptr, data, size);
|
||||
memset(ptr + size, 0, padded_size - size);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_bool(
|
||||
GBinderWriter* self,
|
||||
@@ -166,12 +246,33 @@ gbinder_writer_data_append_bool(
|
||||
GBinderWriterData* data,
|
||||
gboolean value)
|
||||
{
|
||||
guint8 padded[4];
|
||||
const guint8 b = (value != FALSE);
|
||||
|
||||
/* Boolean values are padded to 4-byte boundary */
|
||||
padded[0] = (value != FALSE);
|
||||
padded[1] = padded[2] = padded[3] = 0;
|
||||
g_byte_array_append(data->bytes, padded, sizeof(padded));
|
||||
gbinder_writer_data_append_padded(data->bytes, &b, sizeof(b));
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_int8(
|
||||
GBinderWriter* self,
|
||||
guint8 value) /* Since 1.1.15 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_padded(data->bytes, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_int16(
|
||||
GBinderWriter* self,
|
||||
guint16 value) /* Since 1.1.15 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_padded(data->bytes, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -199,6 +300,26 @@ gbinder_writer_data_append_int32(
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_overwrite_int32(
|
||||
GBinderWriter* self,
|
||||
gsize offset,
|
||||
gint32 value) /* since 1.0.21 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
GByteArray* buf = data->bytes;
|
||||
|
||||
if (buf->len >= offset + sizeof(gint32)) {
|
||||
*((gint32*)(buf->data + offset)) = value;
|
||||
} else {
|
||||
GWARN("Can't overwrite at %lu as buffer is only %u bytes long",
|
||||
(gulong)offset, buf->len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_int64(
|
||||
GBinderWriter* self,
|
||||
@@ -402,37 +523,37 @@ gbinder_writer_data_append_string16_len(
|
||||
gsize padded_len = G_ALIGN4((len+1)*2);
|
||||
guint32* len_ptr;
|
||||
gunichar2* utf16_ptr;
|
||||
gunichar2* utf16 = NULL;
|
||||
|
||||
/* Create utf-16 string to make sure of its size */
|
||||
if (len > 0) {
|
||||
glong utf16_len = 0;
|
||||
|
||||
utf16 = g_utf8_to_utf16(utf8, num_bytes, NULL, &utf16_len, NULL);
|
||||
if (utf16) {
|
||||
len = utf16_len;
|
||||
padded_len = G_ALIGN4((len+1)*2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Preallocate space */
|
||||
g_byte_array_set_size(buf, old_size + padded_len + 4);
|
||||
len_ptr = (guint32*)(buf->data + old_size);
|
||||
utf16_ptr = (gunichar2*)(len_ptr + 1);
|
||||
|
||||
/* TODO: this could be optimized for ASCII strings, i.e. if
|
||||
* len equals num_bytes */
|
||||
if (len > 0) {
|
||||
glong utf16_len = 0;
|
||||
gunichar2* utf16 = g_utf8_to_utf16(utf8, num_bytes, NULL,
|
||||
&utf16_len, NULL);
|
||||
|
||||
if (utf16) {
|
||||
len = utf16_len;
|
||||
padded_len = G_ALIGN4((len+1)*2);
|
||||
memcpy(utf16_ptr, utf16, (len+1)*2);
|
||||
g_free(utf16);
|
||||
}
|
||||
/* Copy string */
|
||||
if (utf16) {
|
||||
memcpy(utf16_ptr, utf16, len*2);
|
||||
g_free(utf16);
|
||||
}
|
||||
|
||||
/* Actual length */
|
||||
*len_ptr = len;
|
||||
|
||||
/* Zero padding */
|
||||
if (padded_len - (len + 1)*2) {
|
||||
memset(utf16_ptr + (len + 1), 0, padded_len - (len + 1)*2);
|
||||
if (padded_len > len*2) {
|
||||
memset(utf16_ptr + len, 0, padded_len - len*2);
|
||||
}
|
||||
|
||||
/* Correct the packet size if necessaary */
|
||||
g_byte_array_set_size(buf, old_size + padded_len + 4);
|
||||
} else if (utf8) {
|
||||
/* Empty string */
|
||||
gbinder_writer_data_append_string16_empty(data);
|
||||
@@ -514,17 +635,6 @@ gbinder_writer_append_bytes(
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
gbinder_writer_data_prepare(
|
||||
GBinderWriterData* data)
|
||||
{
|
||||
if (!data->offsets) {
|
||||
data->offsets = gutil_int_array_new();
|
||||
}
|
||||
return data->offsets->count;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_close_fd(
|
||||
@@ -537,7 +647,6 @@ gbinder_writer_data_close_fd(
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_append_fd(
|
||||
GBinderWriterData* data,
|
||||
@@ -579,6 +688,50 @@ gbinder_writer_append_fd(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_fda_object(
|
||||
GBinderWriterData* data,
|
||||
const GBinderFds *fds,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
GByteArray* buf = data->bytes;
|
||||
const guint offset = buf->len;
|
||||
guint written;
|
||||
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(buf, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
|
||||
written = data->io->encode_fda_object(buf->data + offset, fds, parent);
|
||||
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(buf, offset + written);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_fds(
|
||||
GBinderWriterData* data,
|
||||
const GBinderFds *fds,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
if (fds) {
|
||||
/* Size, fds data buffer and fd_array_object */
|
||||
const gsize fds_total = sizeof(GBinderFds) +
|
||||
sizeof(int) * (fds->num_fds + fds->num_ints);
|
||||
GBinderParent fds_parent;
|
||||
|
||||
gbinder_writer_data_append_int64(data, fds_total);
|
||||
fds_parent.index = gbinder_writer_data_append_buffer_object(data,
|
||||
fds, fds_total, parent);
|
||||
fds_parent.offset = sizeof(GBinderFds);
|
||||
gbinder_writer_data_append_fda_object(data, fds, &fds_parent);
|
||||
} else {
|
||||
/* If the pointer is null only write zero size */
|
||||
gbinder_writer_data_append_int64(data, 0);
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
gbinder_writer_append_buffer_object_with_parent(
|
||||
GBinderWriter* self,
|
||||
@@ -608,6 +761,135 @@ gbinder_writer_append_buffer_object(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_append_fields(
|
||||
GBinderWriter* writer,
|
||||
const void* obj,
|
||||
const GBinderWriterField* fields,
|
||||
const GBinderParent* parent) /* Since 1.1.27 */
|
||||
{
|
||||
if (fields) {
|
||||
const GBinderWriterField* field = fields;
|
||||
const guint8* base_ptr = obj;
|
||||
GBinderParent parent2;
|
||||
|
||||
parent2.index = parent->index;
|
||||
for (field = fields; field->type || field->write_buf; field++) {
|
||||
const void* field_ptr = base_ptr + field->offset;
|
||||
|
||||
parent2.offset = parent->offset + field->offset;
|
||||
if (field->write_buf) {
|
||||
field->write_buf(writer, field_ptr, field, &parent2);
|
||||
} else {
|
||||
gbinder_writer_append_buffer_object_with_parent(writer,
|
||||
*(void**)field_ptr, field->type->size, &parent2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that gbinder_writer_append_struct doesn't copy the data, it writes
|
||||
* buffer objects pointing to whatever was passed in. The caller must make
|
||||
* sure that those pointers outlive the transaction. That's most commonly
|
||||
* done with by using gbinder_writer_malloc() and friends for allocating
|
||||
* memory for the transaction.
|
||||
*/
|
||||
void
|
||||
gbinder_writer_append_struct(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
const GBinderWriterType* type,
|
||||
const GBinderParent* parent) /* Since 1.1.27 */
|
||||
{
|
||||
if (type) {
|
||||
GBinderParent child;
|
||||
|
||||
child.offset = 0;
|
||||
child.index = gbinder_writer_append_buffer_object_with_parent(writer,
|
||||
ptr, type->size, parent);
|
||||
gbinder_writer_append_fields(writer, ptr, type->fields, &child);
|
||||
} else {
|
||||
/* No type - no fields */
|
||||
gbinder_writer_append_buffer_object_with_parent(writer, ptr, 0, parent);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends top-level vec<type>. Allocates GBinderHidlVec for that, but
|
||||
* unlike gbinder_writer_append_hidl_vec(), doesn't copy the contents
|
||||
* of the vector.
|
||||
*/
|
||||
void
|
||||
gbinder_writer_append_struct_vec(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
guint count,
|
||||
const GBinderWriterType* type) /* Since 1.1.29 */
|
||||
{
|
||||
GBinderHidlVec* vec = gbinder_writer_new0(writer, GBinderHidlVec);
|
||||
GBinderWriterField vec_f[2];
|
||||
GBinderWriterType vec_t;
|
||||
|
||||
memset(vec_f, 0, sizeof(vec_f));
|
||||
vec_f->name = "hidl_vec.data.ptr";
|
||||
vec_f->type = type;
|
||||
vec_f->write_buf = gbinder_writer_field_hidl_vec_write_buf;
|
||||
|
||||
memset(&vec_t, 0, sizeof(vec_t));
|
||||
vec_t.name = "hidl_vec";
|
||||
vec_t.size = sizeof(GBinderHidlVec);
|
||||
vec_t.fields = vec_f;
|
||||
|
||||
vec->owns_buffer = TRUE;
|
||||
vec->data.ptr = ptr;
|
||||
vec->count = count;
|
||||
|
||||
gbinder_writer_append_struct(writer, vec, &vec_t, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_field_hidl_vec_write_buf(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
const GBinderWriterField* field,
|
||||
const GBinderParent* parent) /* Since 1.1.27 */
|
||||
{
|
||||
const GBinderHidlVec* vec = ptr;
|
||||
const guint8* buf = vec->data.ptr;
|
||||
const GBinderWriterType* elem_type = field->type;
|
||||
|
||||
if (elem_type) {
|
||||
GBinderParent child;
|
||||
guint i;
|
||||
|
||||
child.index = gbinder_writer_append_buffer_object_with_parent
|
||||
(writer, buf, vec->count * elem_type->size, parent);
|
||||
for (i = 0; i < vec->count; i++) {
|
||||
child.offset = elem_type->size * i;
|
||||
gbinder_writer_append_fields(writer, buf + child.offset,
|
||||
elem_type->fields, &child);
|
||||
}
|
||||
} else {
|
||||
/* Probably a programming error but write an empty buffer anyway */
|
||||
gbinder_writer_append_buffer_object_with_parent(writer, buf, 0, parent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_field_hidl_string_write_buf(
|
||||
GBinderWriter* writer,
|
||||
const void* ptr,
|
||||
const GBinderWriterField* field,
|
||||
const GBinderParent* parent) /* Since 1.1.27 */
|
||||
{
|
||||
const GBinderHidlString* str = ptr;
|
||||
|
||||
gbinder_writer_append_buffer_object_with_parent(writer, str->data.str,
|
||||
str->data.str ? (str->len + 1) : 0, parent);
|
||||
}
|
||||
|
||||
guint
|
||||
gbinder_writer_data_append_buffer_object(
|
||||
GBinderWriterData* data,
|
||||
@@ -615,12 +897,69 @@ gbinder_writer_data_append_buffer_object(
|
||||
gsize size,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
guint index = gbinder_writer_data_prepare(data);
|
||||
const guint index = data->offsets ? data->offsets->count : 0;
|
||||
GByteArray* buf = data->bytes;
|
||||
const guint offset = buf->len;
|
||||
guint n;
|
||||
|
||||
gbinder_writer_data_write_buffer_object(data, ptr, size, parent);
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(buf, offset + GBINDER_MAX_BUFFER_OBJECT_SIZE);
|
||||
/* Write the object */
|
||||
n = data->io->encode_buffer_object(buf->data + offset, ptr, size, parent);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(buf, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
/* The driver seems to require each buffer to be 8-byte aligned */
|
||||
data->buffers_size += G_ALIGN8(size);
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is supposed to be used to write aidl parcelables, and is not
|
||||
* guaranteed to work on any other kind of parcelable.
|
||||
*/
|
||||
void
|
||||
gbinder_writer_append_parcelable(
|
||||
GBinderWriter* self,
|
||||
const void* buf,
|
||||
gsize len) /* Since 1.1.19 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_parcelable(data, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is compatible with aidl parcelables, and is not guaranteed to work
|
||||
* with any other kind of parcelable.
|
||||
*/
|
||||
void
|
||||
gbinder_writer_data_append_parcelable(
|
||||
GBinderWriterData* data,
|
||||
const void* ptr,
|
||||
gsize size)
|
||||
{
|
||||
if (ptr) {
|
||||
/* Non-null */
|
||||
gbinder_writer_data_append_int32(data, 1);
|
||||
|
||||
/*
|
||||
* Write the parcelable size, taking in account the size of this
|
||||
* integer as well.
|
||||
*/
|
||||
gbinder_writer_data_append_int32(data, size + sizeof(gint32));
|
||||
|
||||
/* Append the parcelable data */
|
||||
g_byte_array_append(data->bytes, ptr, size);
|
||||
} else {
|
||||
/* Null */
|
||||
gbinder_writer_data_append_int32(data, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string(
|
||||
GBinderWriter* self,
|
||||
@@ -633,6 +972,21 @@ gbinder_writer_append_hidl_string(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string_copy(
|
||||
GBinderWriter* self,
|
||||
const char* str) /* Since 1.1.13 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
static const char empty[] = "";
|
||||
|
||||
gbinder_writer_data_append_hidl_string(data, str ? (str[0] ?
|
||||
gbinder_writer_strdup(self, str) : empty) : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_vec(
|
||||
GBinderWriterData* data,
|
||||
@@ -643,11 +997,7 @@ gbinder_writer_data_append_hidl_vec(
|
||||
GBinderParent vec_parent;
|
||||
GBinderHidlVec* vec = g_new0(GBinderHidlVec, 1);
|
||||
const gsize total = count * elemsize;
|
||||
void* buf = g_memdup(base, total);
|
||||
|
||||
/* Prepare parent descriptor for the string data */
|
||||
vec_parent.index = gbinder_writer_data_prepare(data);
|
||||
vec_parent.offset = GBINDER_HIDL_VEC_BUFFER_OFFSET;
|
||||
void* buf = gutil_memdup(base, total);
|
||||
|
||||
/* Fill in the vector descriptor */
|
||||
if (buf) {
|
||||
@@ -658,13 +1008,11 @@ gbinder_writer_data_append_hidl_vec(
|
||||
vec->owns_buffer = TRUE;
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, vec);
|
||||
|
||||
/* Write the buffer object pointing to the vector descriptor */
|
||||
gbinder_writer_data_write_buffer_object(data, vec, sizeof(*vec), NULL);
|
||||
|
||||
/* Not sure what's the right way to deal with NULL vectors... */
|
||||
if (buf) {
|
||||
gbinder_writer_data_write_buffer_object(data, buf, total, &vec_parent);
|
||||
}
|
||||
/* Every vector, even the one without data, requires two buffer objects */
|
||||
vec_parent.offset = GBINDER_HIDL_VEC_BUFFER_OFFSET;
|
||||
vec_parent.index = gbinder_writer_data_append_buffer_object(data,
|
||||
vec, sizeof(*vec), NULL);
|
||||
gbinder_writer_data_append_buffer_object(data, buf, total, &vec_parent);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -690,10 +1038,6 @@ gbinder_writer_data_append_hidl_string(
|
||||
GBinderHidlString* hidl_string = g_new0(GBinderHidlString, 1);
|
||||
const gsize len = str ? strlen(str) : 0;
|
||||
|
||||
/* Prepare parent descriptor for the string data */
|
||||
str_parent.index = gbinder_writer_data_prepare(data);
|
||||
str_parent.offset = GBINDER_HIDL_STRING_BUFFER_OFFSET;
|
||||
|
||||
/* Fill in the string descriptor and store it */
|
||||
hidl_string->data.str = str;
|
||||
hidl_string->len = len;
|
||||
@@ -701,16 +1045,18 @@ gbinder_writer_data_append_hidl_string(
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, hidl_string);
|
||||
|
||||
/* Write the buffer object pointing to the string descriptor */
|
||||
gbinder_writer_data_write_buffer_object(data, hidl_string,
|
||||
sizeof(*hidl_string), NULL);
|
||||
str_parent.offset = GBINDER_HIDL_STRING_BUFFER_OFFSET;
|
||||
str_parent.index = gbinder_writer_data_append_buffer_object(data,
|
||||
hidl_string, sizeof(*hidl_string), NULL);
|
||||
|
||||
/* Not sure what's the right way to deal with NULL strings... */
|
||||
if (str) {
|
||||
/* Write the buffer pointing to the string data including the
|
||||
* NULL terminator, referencing string descriptor as a parent. */
|
||||
gbinder_writer_data_write_buffer_object(data, str, len+1, &str_parent);
|
||||
gbinder_writer_data_append_buffer_object(data, str, len+1, &str_parent);
|
||||
GVERBOSE_("\"%s\" %u %u %u", str, (guint)len, (guint)str_parent.index,
|
||||
(guint)data->buffers_size);
|
||||
} else {
|
||||
gbinder_writer_data_append_buffer_object(data, NULL, 0, &str_parent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,10 +1089,6 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
count = gutil_strv_length((char**)strv);
|
||||
}
|
||||
|
||||
/* Prepare parent descriptor for the vector data */
|
||||
vec_parent.index = gbinder_writer_data_prepare(data);
|
||||
vec_parent.offset = GBINDER_HIDL_VEC_BUFFER_OFFSET;
|
||||
|
||||
/* Fill in the vector descriptor */
|
||||
if (count > 0) {
|
||||
strings = g_new0(GBinderHidlString, count);
|
||||
@@ -769,7 +1111,10 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
}
|
||||
|
||||
/* Write the vector object */
|
||||
gbinder_writer_data_write_buffer_object(data, vec, sizeof(*vec), NULL);
|
||||
vec_parent.offset = GBINDER_HIDL_VEC_BUFFER_OFFSET;
|
||||
vec_parent.index = gbinder_writer_data_append_buffer_object(data,
|
||||
vec, sizeof(*vec), NULL);
|
||||
|
||||
if (strings) {
|
||||
GBinderParent str_parent;
|
||||
|
||||
@@ -778,7 +1123,7 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
str_parent.offset = GBINDER_HIDL_STRING_BUFFER_OFFSET;
|
||||
|
||||
/* Write the vector data (it's parent for the string data) */
|
||||
gbinder_writer_data_write_buffer_object(data, strings,
|
||||
gbinder_writer_data_append_buffer_object(data, strings,
|
||||
sizeof(*strings) * count, &vec_parent);
|
||||
|
||||
/* Write the string data */
|
||||
@@ -786,14 +1131,21 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
GBinderHidlString* hidl_str = strings + i;
|
||||
|
||||
if (hidl_str->data.str) {
|
||||
gbinder_writer_data_write_buffer_object(data,
|
||||
gbinder_writer_data_append_buffer_object(data,
|
||||
hidl_str->data.str, hidl_str->len + 1, &str_parent);
|
||||
GVERBOSE_("%d. \"%s\" %u %u %u", i + 1, hidl_str->data.str,
|
||||
(guint)hidl_str->len, (guint)str_parent.index,
|
||||
(guint)data->buffers_size);
|
||||
} else {
|
||||
GVERBOSE_("%d. NULL %u %u %u", i + 1, (guint)hidl_str->len,
|
||||
(guint)str_parent.index, (guint)data->buffers_size);
|
||||
gbinder_writer_data_append_buffer_object(data, NULL, 0,
|
||||
&str_parent);
|
||||
}
|
||||
str_parent.offset += sizeof(GBinderHidlString);
|
||||
}
|
||||
} else {
|
||||
gbinder_writer_data_append_buffer_object(data, NULL, 0, &vec_parent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -821,11 +1173,14 @@ gbinder_writer_data_append_local_object(
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(buf, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
/* Write the object */
|
||||
n = data->io->encode_local_object(buf->data + offset, obj);
|
||||
n = data->io->encode_local_object(buf->data + offset, obj, data->protocol);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(buf, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
|
||||
if (obj) {
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -851,25 +1206,96 @@ gbinder_writer_append_byte_array(
|
||||
GASSERT(len >= 0);
|
||||
if (G_LIKELY(data)) {
|
||||
GByteArray* buf = data->bytes;
|
||||
void* ptr;
|
||||
gsize padded_len;
|
||||
guint8* ptr;
|
||||
|
||||
if (!byte_array) {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
g_byte_array_set_size(buf, buf->len + sizeof(len) + len);
|
||||
ptr = buf->data + (buf->len - sizeof(len) - len);
|
||||
/*
|
||||
* Android aligns byte array reads and writes to 4 bytes and
|
||||
* pads with 0xFF.
|
||||
*/
|
||||
padded_len = G_ALIGN4(len);
|
||||
g_byte_array_set_size(buf, buf->len + sizeof(len) + padded_len);
|
||||
ptr = buf->data + (buf->len - sizeof(len) - padded_len);
|
||||
|
||||
if (len > 0) {
|
||||
*((gint32*)ptr) = len;
|
||||
ptr += sizeof(len);
|
||||
memcpy(ptr, byte_array, len);
|
||||
/* FF padding */
|
||||
if (padded_len > len) {
|
||||
memset(ptr + len, 0xff, padded_len - len);
|
||||
}
|
||||
} else {
|
||||
*((gint32*)ptr) = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if GBINDER_FMQ_SUPPORTED
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_append_fmq_descriptor(
|
||||
GBinderWriterData* data,
|
||||
const GBinderFmq* queue)
|
||||
{
|
||||
GBinderParent parent;
|
||||
GBinderMQDescriptor* desc = gbinder_fmq_get_descriptor(queue);
|
||||
GBinderMQDescriptor* mqdesc = gutil_memdup(desc,
|
||||
sizeof(GBinderMQDescriptor));
|
||||
|
||||
const gsize vec_total =
|
||||
desc->grantors.count * sizeof(GBinderFmqGrantorDescriptor);
|
||||
void* vec_buf = gutil_memdup(desc->grantors.data.ptr, vec_total);
|
||||
|
||||
const gsize fds_total = sizeof(GBinderFds) +
|
||||
sizeof(int) * (desc->data.fds->num_fds + desc->data.fds->num_ints);
|
||||
GBinderFds* fds = gutil_memdup(desc->data.fds, fds_total);
|
||||
|
||||
mqdesc->data.fds = fds;
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, fds);
|
||||
|
||||
/* Fill in the grantor vector descriptor */
|
||||
if (vec_buf) {
|
||||
mqdesc->grantors.count = desc->grantors.count;
|
||||
mqdesc->grantors.data.ptr = vec_buf;
|
||||
mqdesc->grantors.owns_buffer = TRUE;
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, vec_buf);
|
||||
}
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, mqdesc);
|
||||
|
||||
/* Write the FMQ descriptor object */
|
||||
parent.index = gbinder_writer_data_append_buffer_object(data,
|
||||
mqdesc, sizeof(*mqdesc), NULL);
|
||||
|
||||
/* Write the vector data buffer */
|
||||
parent.offset = GBINDER_MQ_DESCRIPTOR_GRANTORS_OFFSET;
|
||||
gbinder_writer_data_append_buffer_object(data, vec_buf, vec_total,
|
||||
&parent);
|
||||
|
||||
/* Write the fds */
|
||||
parent.offset = GBINDER_MQ_DESCRIPTOR_FDS_OFFSET;
|
||||
gbinder_writer_data_append_fds(data, mqdesc->data.fds, &parent);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_fmq_descriptor(
|
||||
GBinderWriter* self,
|
||||
const GBinderFmq* queue) /* since 1.1.14 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data) && G_LIKELY(queue)) {
|
||||
gbinder_writer_data_append_fmq_descriptor(data, queue);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GBINDER_FMQ_SUPPORTED */
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_remote_object(
|
||||
GBinderWriterData* data,
|
||||
@@ -885,8 +1311,11 @@ gbinder_writer_data_append_remote_object(
|
||||
n = data->io->encode_remote_object(buf->data + offset, obj);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(buf, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
|
||||
if (obj) {
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
@@ -924,6 +1353,14 @@ gbinder_writer_malloc0(
|
||||
return gbinder_writer_alloc(self, size, g_malloc0, g_free);
|
||||
}
|
||||
|
||||
char*
|
||||
gbinder_writer_strdup(
|
||||
GBinderWriter* writer,
|
||||
const char* str) /* since 1.1.13 */
|
||||
{
|
||||
return str ? gbinder_writer_memdup(writer, str, strlen(str) + 1) : NULL;
|
||||
}
|
||||
|
||||
void*
|
||||
gbinder_writer_memdup(
|
||||
GBinderWriter* self,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -14,8 +14,8 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
typedef struct gbinder_writer_data {
|
||||
const GBinderIo* io;
|
||||
const GBinderRpcProtocol* protocol;
|
||||
GByteArray* bytes;
|
||||
GUtilIntArray* offsets;
|
||||
gsize buffers_size;
|
||||
@@ -48,94 +49,133 @@ typedef struct gbinder_writer_data {
|
||||
void
|
||||
gbinder_writer_init(
|
||||
GBinderWriter* writer,
|
||||
GBinderWriterData* data);
|
||||
GBinderWriterData* data)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_set_contents(
|
||||
GBinderWriterData* data,
|
||||
GBinderBuffer* buffer);
|
||||
GBinderBuffer* buffer,
|
||||
GBinderObjectConverter* convert)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_contents(
|
||||
GBinderWriterData* data,
|
||||
GBinderBuffer* buffer,
|
||||
gsize data_offset,
|
||||
GBinderObjectConverter* convert)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_bool(
|
||||
GBinderWriterData* data,
|
||||
gboolean value);
|
||||
gboolean value)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_int32(
|
||||
GBinderWriterData* data,
|
||||
guint32 value);
|
||||
guint32 value)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_int64(
|
||||
GBinderWriterData* data,
|
||||
guint64 value);
|
||||
guint64 value)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_float(
|
||||
GBinderWriterData* data,
|
||||
gfloat value);
|
||||
gfloat value)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_double(
|
||||
GBinderWriterData* data,
|
||||
gdouble value);
|
||||
gdouble value)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string8(
|
||||
GBinderWriterData* data,
|
||||
const char* str);
|
||||
const char* str)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string8_len(
|
||||
GBinderWriterData* data,
|
||||
const char* str,
|
||||
gsize len);
|
||||
gsize len)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string16(
|
||||
GBinderWriterData* data,
|
||||
const char* utf8);
|
||||
const char* utf8)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string16_len(
|
||||
GBinderWriterData* data,
|
||||
const char* utf8,
|
||||
gssize num_bytes);
|
||||
gssize num_bytes)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
guint
|
||||
gbinder_writer_data_append_buffer_object(
|
||||
GBinderWriterData* data,
|
||||
const void* ptr,
|
||||
gsize size,
|
||||
const GBinderParent* parent);
|
||||
const GBinderParent* parent)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_parcelable(
|
||||
GBinderWriterData* data,
|
||||
const void* ptr,
|
||||
gsize size)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_vec(
|
||||
GBinderWriterData* data,
|
||||
const void* base,
|
||||
guint count,
|
||||
guint elemsize);
|
||||
guint elemsize)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_string(
|
||||
GBinderWriterData* data,
|
||||
const char* str);
|
||||
const char* str)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_string_vec(
|
||||
GBinderWriterData* data,
|
||||
const char* strv[],
|
||||
gssize count);
|
||||
gssize count)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_local_object(
|
||||
GBinderWriterData* data,
|
||||
GBinderLocalObject* obj);
|
||||
GBinderLocalObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_remote_object(
|
||||
GBinderWriterData* data,
|
||||
GBinderRemoteObject* obj);
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_fd(
|
||||
GBinderWriterData* data,
|
||||
int fd)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_WRITER_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
all:
|
||||
%:
|
||||
@$(MAKE) -C binder-bridge $*
|
||||
@$(MAKE) -C binder-client $*
|
||||
@$(MAKE) -C binder-dump $*
|
||||
@$(MAKE) -C binder-list $*
|
||||
@$(MAKE) -C binder-ping $*
|
||||
@$(MAKE) -C binder-service $*
|
||||
@$(MAKE) -C binder-call $*
|
||||
@$(MAKE) -C rild-card-status $*
|
||||
|
||||
5
test/ashmem-test/Makefile
Normal file
5
test/ashmem-test/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = ashmem-test
|
||||
|
||||
include ../common/Makefile
|
||||
260
test/ashmem-test/ashmem-test.c
Normal file
260
test/ashmem-test/ashmem-test.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <gbinder.h>
|
||||
|
||||
#include <gutil_misc.h>
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define RET_OK (0)
|
||||
#define RET_NOTFOUND (1)
|
||||
#define RET_INVARG (2)
|
||||
#define RET_ERR (3)
|
||||
|
||||
#define DEFAULT_BINDER GBINDER_DEFAULT_HWBINDER
|
||||
#define ALLOCATOR_IFACE "android.hidl.allocator@1.0::IAllocator"
|
||||
#define DEFAULT_FQNAME ALLOCATOR_IFACE "/ashmem"
|
||||
#define TX_ALLOCATE GBINDER_FIRST_CALL_TRANSACTION
|
||||
|
||||
typedef struct app_options {
|
||||
const char* fqname;
|
||||
char* dev;
|
||||
gsize size;
|
||||
} AppOptions;
|
||||
|
||||
static
|
||||
void
|
||||
app_dumpmem(
|
||||
const GBinderHidlMemory* mem)
|
||||
{
|
||||
const GBinderFds* fds = mem->data.fds;
|
||||
|
||||
GDEBUG("Name: %s", mem->name.data.str);
|
||||
GDEBUG("Size: %" G_GUINT64_FORMAT " bytes", mem->size);
|
||||
|
||||
GASSERT(fds->version == GBINDER_HIDL_FDS_VERSION);
|
||||
GDEBUG("Contains %u fd(s)", fds->num_fds);
|
||||
if (fds->num_fds) {
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < fds->num_fds; i++) {
|
||||
int fd = gbinder_fds_get_fd(fds, i);
|
||||
guint8* ptr = mmap(NULL, mem->size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
if (ptr) {
|
||||
gsize off = 0;
|
||||
|
||||
GDEBUG("fd %d => %p", fd, ptr);
|
||||
while (off < mem->size) {
|
||||
char line[GUTIL_HEXDUMP_BUFSIZE];
|
||||
guint n = gutil_hexdump(line, ptr + off, mem->size - off);
|
||||
|
||||
GDEBUG("%04X: %s", (uint) off, line);
|
||||
off += n;
|
||||
}
|
||||
munmap(ptr, mem->size);
|
||||
} else {
|
||||
GDEBUG("fd %d", fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
app_allocate(
|
||||
const AppOptions* opt,
|
||||
GBinderClient* client)
|
||||
{
|
||||
GBinderLocalRequest* request = gbinder_client_new_request(client);
|
||||
GBinderRemoteReply* reply;
|
||||
int status, ret;
|
||||
|
||||
gbinder_local_request_append_int64(request, opt->size);
|
||||
reply = gbinder_client_transact_sync_reply(client, TX_ALLOCATE,
|
||||
request, &status);
|
||||
|
||||
if (reply) {
|
||||
GBinderReader reader;
|
||||
gint32 tx_status;
|
||||
gboolean success;
|
||||
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
if (gbinder_reader_read_int32(&reader, &tx_status) &&
|
||||
gbinder_reader_read_bool(&reader, &success) &&
|
||||
tx_status == GBINDER_STATUS_OK &&
|
||||
success) {
|
||||
const GBinderHidlMemory* mem = gbinder_reader_read_hidl_struct
|
||||
(&reader, GBinderHidlMemory);
|
||||
|
||||
if (mem) {
|
||||
GINFO("OK");
|
||||
app_dumpmem(mem);
|
||||
} else {
|
||||
GINFO("OOPS");
|
||||
}
|
||||
} else {
|
||||
GINFO("FAILED");
|
||||
}
|
||||
ret = RET_OK;
|
||||
} else {
|
||||
GERR("Call failed (%d)", status);
|
||||
ret = RET_ERR;
|
||||
}
|
||||
|
||||
gbinder_local_request_unref(request);
|
||||
gbinder_remote_reply_unref(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
app_run(
|
||||
const AppOptions* opt)
|
||||
{
|
||||
int ret = RET_NOTFOUND;
|
||||
GBinderServiceManager* sm = gbinder_servicemanager_new(opt->dev);
|
||||
|
||||
if (sm) {
|
||||
int status = 0;
|
||||
GBinderRemoteObject* remote = gbinder_servicemanager_get_service_sync
|
||||
(sm, opt->fqname, &status);
|
||||
|
||||
if (remote) {
|
||||
GBinderClient* client = gbinder_client_new(remote, ALLOCATOR_IFACE);
|
||||
|
||||
ret = app_allocate(opt, client);
|
||||
gbinder_client_unref(client);
|
||||
} else {
|
||||
GERR("%s not found", opt->fqname);
|
||||
}
|
||||
gbinder_servicemanager_unref(sm);
|
||||
} else {
|
||||
GERR("No servicemanager at %s", opt->dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_verbose(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_quiet(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_NONE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_init(
|
||||
AppOptions* opt,
|
||||
int argc,
|
||||
char* argv[])
|
||||
{
|
||||
gboolean ok = FALSE;
|
||||
GOptionEntry entries[] = {
|
||||
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_verbose, "Enable verbose output", NULL },
|
||||
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_quiet, "Be quiet", NULL },
|
||||
{ "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
|
||||
"Binder device [" DEFAULT_BINDER "]", "DEVICE" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
GError* error = NULL;
|
||||
GOptionContext* options = g_option_context_new("[FQNAME]");
|
||||
|
||||
gutil_log_timestamp = FALSE;
|
||||
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||
|
||||
g_option_context_add_main_entries(options, entries, NULL);
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
if (!opt->dev || !opt->dev[0]) {
|
||||
opt->dev = g_strdup(DEFAULT_BINDER);
|
||||
}
|
||||
if (argc < 3) {
|
||||
opt->fqname = ((argc == 2) ? argv[1] : DEFAULT_FQNAME);
|
||||
opt->size = 64;
|
||||
ok = TRUE;
|
||||
} else {
|
||||
char* help = g_option_context_get_help(options, TRUE, NULL);
|
||||
|
||||
fprintf(stderr, "%s", help);
|
||||
g_free(help);
|
||||
}
|
||||
} else {
|
||||
GERR("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
g_option_context_free(options);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
AppOptions opt;
|
||||
int ret = RET_INVARG;
|
||||
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
if (app_init(&opt, argc, argv)) {
|
||||
ret = app_run(&opt);
|
||||
}
|
||||
g_free(opt.dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
5
test/binder-bridge/Makefile
Normal file
5
test/binder-bridge/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = binder-bridge
|
||||
|
||||
include ../common/Makefile
|
||||
196
test/binder-bridge/binder-bridge.c
Normal file
196
test/binder-bridge/binder-bridge.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <gbinder.h>
|
||||
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <glib-unix.h>
|
||||
|
||||
#define RET_OK (0)
|
||||
#define RET_NODEV (1)
|
||||
#define RET_INVARG (2)
|
||||
|
||||
typedef struct app_options {
|
||||
const char* src;
|
||||
const char* dest;
|
||||
char* src_name;
|
||||
const char* dest_name;
|
||||
const char** ifaces;
|
||||
} AppOptions;
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_signal(
|
||||
gpointer loop)
|
||||
{
|
||||
GINFO("Caught signal, shutting down...");
|
||||
g_main_loop_quit(loop);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
app_run(
|
||||
const AppOptions* opt)
|
||||
{
|
||||
int ret = RET_NODEV;
|
||||
GBinderServiceManager* src = gbinder_servicemanager_new(opt->src);
|
||||
|
||||
if (src) {
|
||||
GBinderServiceManager* dest = gbinder_servicemanager_new(opt->dest);
|
||||
|
||||
if (dest) {
|
||||
GMainLoop* loop = g_main_loop_new(NULL, TRUE);
|
||||
guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, loop);
|
||||
guint sigint = g_unix_signal_add(SIGINT, app_signal, loop);
|
||||
GBinderBridge* bridge = gbinder_bridge_new2
|
||||
(opt->src_name, opt->dest_name, opt->ifaces, src, dest);
|
||||
|
||||
g_main_loop_run(loop);
|
||||
|
||||
if (sigtrm) g_source_remove(sigtrm);
|
||||
if (sigint) g_source_remove(sigint);
|
||||
g_main_loop_unref(loop);
|
||||
gbinder_bridge_free(bridge);
|
||||
gbinder_servicemanager_unref(dest);
|
||||
ret = RET_OK;
|
||||
} else {
|
||||
GERR("No servicemanager at %s", opt->dest);
|
||||
}
|
||||
gbinder_servicemanager_unref(src);
|
||||
} else {
|
||||
GERR("No servicemanager at %s", opt->src);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_verbose(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_quiet(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_NONE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_init(
|
||||
AppOptions* opt,
|
||||
int argc,
|
||||
char* argv[])
|
||||
{
|
||||
gboolean ok = FALSE;
|
||||
GOptionEntry entries[] = {
|
||||
{ "source", 's', 0, G_OPTION_ARG_STRING, &opt->src_name,
|
||||
"Register a different name on source", "NAME" },
|
||||
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_verbose, "Enable verbose output", NULL },
|
||||
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_quiet, "Be quiet", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
GError* error = NULL;
|
||||
GOptionContext* options = g_option_context_new("SRC DST NAME IFACES...");
|
||||
|
||||
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||
|
||||
g_option_context_add_main_entries(options, entries, NULL);
|
||||
g_option_context_set_summary(options,
|
||||
"Forwards calls from device SRC to device DST.");
|
||||
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
if (argc >= 5) {
|
||||
int i;
|
||||
const int first_iface = 4;
|
||||
|
||||
opt->src = argv[1];
|
||||
opt->dest = argv[2];
|
||||
opt->dest_name = argv[3];
|
||||
opt->ifaces = g_new(const char*, argc - first_iface + 1);
|
||||
for (i = first_iface; i < argc; i++) {
|
||||
opt->ifaces[i - first_iface] = argv[i];
|
||||
}
|
||||
opt->ifaces[i - first_iface] = NULL;
|
||||
ok = TRUE;
|
||||
} else {
|
||||
char* help = g_option_context_get_help(options, TRUE, NULL);
|
||||
|
||||
fprintf(stderr, "%s", help);
|
||||
g_free(help);
|
||||
}
|
||||
} else {
|
||||
GERR("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
g_option_context_free(options);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
AppOptions opt;
|
||||
int ret = RET_INVARG;
|
||||
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
if (app_init(&opt, argc, argv)) {
|
||||
ret = app_run(&opt);
|
||||
}
|
||||
g_free(opt.src_name);
|
||||
g_free(opt.ifaces);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user