Compare commits
121 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
3
AUTHORS
3
AUTHORS
@@ -6,3 +6,6 @@ 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>
|
||||
|
||||
4
LICENSE
4
LICENSE
@@ -1,5 +1,5 @@
|
||||
Copyright (C) 2018-2021 Jolla Ltd.
|
||||
Copyright (C) 2018-2021 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:
|
||||
|
||||
|
||||
5
Makefile
5
Makefile
@@ -16,7 +16,7 @@
|
||||
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 1
|
||||
VERSION_RELEASE = 12
|
||||
VERSION_RELEASE = 31
|
||||
|
||||
# Version for pkg-config
|
||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
@@ -82,6 +82,7 @@ SRC = \
|
||||
gbinder_config.c \
|
||||
gbinder_driver.c \
|
||||
gbinder_eventloop.c \
|
||||
gbinder_fmq.c \
|
||||
gbinder_io_32.c \
|
||||
gbinder_io_64.c \
|
||||
gbinder_ipc.c \
|
||||
@@ -103,6 +104,8 @@ SRC += \
|
||||
gbinder_servicemanager.c \
|
||||
gbinder_servicemanager_aidl.c \
|
||||
gbinder_servicemanager_aidl2.c \
|
||||
gbinder_servicemanager_aidl3.c \
|
||||
gbinder_servicemanager_aidl4.c \
|
||||
gbinder_servicemanager_hidl.c
|
||||
|
||||
SRC += \
|
||||
|
||||
12
README
12
README
@@ -5,7 +5,7 @@ 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 transation APIs
|
||||
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
|
||||
@@ -22,8 +22,8 @@ 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 and hidl.
|
||||
This list is expected to expand further in the future. The default
|
||||
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]
|
||||
@@ -36,9 +36,11 @@ configuration is as follows:
|
||||
/dev/binder = aidl
|
||||
/dev/hwbinder = hidl
|
||||
|
||||
Alternatively, one can specify the desired Android API level:
|
||||
Alternatively and preferably, one can specify the desired Android API
|
||||
level:
|
||||
|
||||
[General]
|
||||
ApiLevel = 29
|
||||
|
||||
and let libgbinder pick the appropriate preset.
|
||||
and let libgbinder pick the appropriate preset. Full list of presets can
|
||||
be found in src/gbinder_config.c
|
||||
|
||||
129
debian/changelog
vendored
129
debian/changelog
vendored
@@ -1,3 +1,132 @@
|
||||
libgbinder (1.1.31) unstable; urgency=low
|
||||
|
||||
* Fixed serialization issues on big-endian
|
||||
* Refactored binder simulation for unit tests
|
||||
|
||||
-- Slava Monich <slava@monich.com> Wed, 04 Jan 2023 19:10:37 +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) 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
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
5
|
||||
7
|
||||
|
||||
4
debian/control
vendored
4
debian/control
vendored
@@ -2,7 +2,7 @@ Source: libgbinder
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Maintainer: Slava Monich <slava.monich@jolla.com>
|
||||
Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.52), flex, bison
|
||||
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
|
||||
@@ -14,7 +14,7 @@ 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)
|
||||
Description: Development files for libgbinder
|
||||
|
||||
Package: libgbinder-tools
|
||||
|
||||
4
debian/copyright
vendored
4
debian/copyright
vendored
@@ -1,5 +1,5 @@
|
||||
Copyright (C) 2018-2021 Jolla Ltd.
|
||||
Copyright (C) 2018-2021 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:
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#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"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 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:
|
||||
*
|
||||
@@ -78,6 +78,11 @@ 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);
|
||||
|
||||
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-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-2019 Jolla Ltd.
|
||||
* Copyright (C) 2018-2019 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,6 +142,11 @@ 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,
|
||||
@@ -201,6 +226,11 @@ gbinder_reader_read_byte_array(
|
||||
GBinderReader* reader,
|
||||
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(
|
||||
const GBinderReader* reader);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 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:
|
||||
*
|
||||
@@ -76,7 +76,15 @@ 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(
|
||||
@@ -112,6 +120,10 @@ 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 */
|
||||
@@ -189,7 +201,7 @@ gbinder_servicemanager_remove_handlers(
|
||||
gulong* ids,
|
||||
guint count); /* Since 1.0.25 */
|
||||
|
||||
#define gbinder_servicemanager_remove_all_handlers(r,ids) \
|
||||
#define gbinder_servicemanager_remove_all_handlers(sm,ids) \
|
||||
gbinder_servicemanager_remove_handlers(sm, ids, G_N_ELEMENTS(ids))
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -62,6 +62,7 @@ G_BEGIN_DECLS
|
||||
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;
|
||||
|
||||
@@ -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,15 +232,11 @@ gbinder_writer_append_fd(
|
||||
GBinderWriter* writer,
|
||||
int fd); /* Since 1.0.18 */
|
||||
|
||||
gsize
|
||||
gbinder_writer_bytes_written(
|
||||
GBinderWriter* writer); /* since 1.0.21 */
|
||||
|
||||
void
|
||||
gbinder_writer_overwrite_int32(
|
||||
gbinder_writer_append_fds(
|
||||
GBinderWriter* writer,
|
||||
gsize offset,
|
||||
gint32 value); /* since 1.0.21 */
|
||||
const GBinderFds* fds,
|
||||
const GBinderParent* parent); /* Since 1.1.14 */
|
||||
|
||||
guint
|
||||
gbinder_writer_append_buffer_object_with_parent(
|
||||
@@ -142,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,
|
||||
@@ -174,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)))
|
||||
@@ -192,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,6 +1,6 @@
|
||||
Name: libgbinder
|
||||
|
||||
Version: 1.1.12
|
||||
Version: 1.1.31
|
||||
Release: 0
|
||||
Summary: Binder client library
|
||||
License: BSD
|
||||
@@ -11,8 +11,14 @@ Source: %{name}-%{version}.tar.bz2
|
||||
|
||||
BuildRequires: pkgconfig(glib-2.0)
|
||||
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 $?)
|
||||
|
||||
Requires: libglibutil >= %{libglibutil_version}
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
@@ -23,7 +29,6 @@ C interfaces for Android binder
|
||||
%package devel
|
||||
Summary: Development library for %{name}
|
||||
Requires: %{name} = %{version}
|
||||
Requires: pkgconfig
|
||||
|
||||
%description devel
|
||||
This package contains the development library for %{name}.
|
||||
@@ -39,7 +44,6 @@ make -C test/binder-ping KEEP_SYMBOLS=1 release
|
||||
make -C test/binder-call KEEP_SYMBOLS=1 release
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev
|
||||
make -C test/binder-bridge DESTDIR=%{buildroot} install
|
||||
make -C test/binder-list DESTDIR=%{buildroot} install
|
||||
@@ -56,9 +60,13 @@ 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -251,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-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -73,6 +73,11 @@ gbinder_buffer_io(
|
||||
GBinderBuffer* buf)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_buffer_protocol(
|
||||
GBinderBuffer* buf)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void**
|
||||
gbinder_buffer_objects(
|
||||
GBinderBuffer* buffer)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -282,7 +282,8 @@ gbinder_client_new2(
|
||||
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), NULL);
|
||||
(gbinder_driver_io(driver), gbinder_driver_protocol(driver),
|
||||
NULL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -351,15 +352,32 @@ gbinder_client_interface2(
|
||||
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);
|
||||
GBinderDriver* driver = self->remote->ipc->driver;
|
||||
|
||||
return gbinder_local_request_new(io, priv->ranges->rpc_header);
|
||||
return gbinder_local_request_new(gbinder_driver_io(driver),
|
||||
gbinder_driver_protocol(driver), priv->ranges->rpc_header);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -371,13 +389,14 @@ gbinder_client_new_request2(
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderClientPriv* priv = gbinder_client_cast(self);
|
||||
const GBinderClientIfaceRange* r = gbinder_client_find_range
|
||||
const GBinderClientIfaceRange* range = gbinder_client_find_range
|
||||
(priv, code);
|
||||
|
||||
if (r) {
|
||||
const GBinderIo* io = gbinder_driver_io(self->remote->ipc->driver);
|
||||
if (range) {
|
||||
GBinderDriver* driver = self->remote->ipc->driver;
|
||||
|
||||
return gbinder_local_request_new(io, r->rpc_header);
|
||||
return gbinder_local_request_new(gbinder_driver_io(driver),
|
||||
gbinder_driver_protocol(driver), range->rpc_header);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -113,9 +113,45 @@ static const GBinderConfigPresetGroup gbinder_config_29[] = {
|
||||
{ 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_servicemanager[] = {
|
||||
{ "/dev/binder", "aidl4" },
|
||||
{ "/dev/vndbinder", "aidl4" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const GBinderConfigPresetGroup gbinder_config_31[] = {
|
||||
{ GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
|
||||
{ GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_31_servicemanager },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Presets sorted by API level in descending order */
|
||||
|
||||
static const GBinderConfigPreset gbinder_config_presets[] = {
|
||||
{ 31, gbinder_config_31 },
|
||||
{ 30, gbinder_config_30 },
|
||||
{ 29, gbinder_config_29 },
|
||||
{ 28, gbinder_config_28 }
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -82,6 +82,7 @@ struct gbinder_driver {
|
||||
void* vm;
|
||||
gsize vmsize;
|
||||
char* dev;
|
||||
const char* name;
|
||||
const GBinderIo* io;
|
||||
const GBinderRpcProtocol* protocol;
|
||||
};
|
||||
@@ -169,6 +170,14 @@ gbinder_driver_verbose_transaction_data(
|
||||
GVERBOSE("> %s %d (%u bytes, %u objects)", name,
|
||||
tx->status, (guint)tx->size, n);
|
||||
}
|
||||
} else if (tx->code) {
|
||||
if (tx->target) {
|
||||
GVERBOSE("> %s %p 0x%08x (%u bytes, %u objects)", name,
|
||||
tx->target, tx->code, (guint)tx->size, n);
|
||||
} else {
|
||||
GVERBOSE("> %s 0x%08x (%u bytes, %u objects)", name,
|
||||
tx->code, (guint)tx->size, n);
|
||||
}
|
||||
} else {
|
||||
if (tx->target) {
|
||||
GVERBOSE("> %s %p (%u bytes, %u objects)", name,
|
||||
@@ -187,6 +196,14 @@ gbinder_driver_verbose_transaction_data(
|
||||
GVERBOSE("> %s %d (%u bytes)", name, tx->status, (guint)
|
||||
tx->size);
|
||||
}
|
||||
} else if (tx->code) {
|
||||
if (tx->target) {
|
||||
GVERBOSE("> %s %p 0x%08x (%u bytes)", name,
|
||||
tx->target, tx->code, (guint)tx->size);
|
||||
} else {
|
||||
GVERBOSE("> %s 0x%08x (%u bytes)", name,
|
||||
tx->code, (guint)tx->size);
|
||||
}
|
||||
} else {
|
||||
if (tx->target) {
|
||||
GVERBOSE("> %s %p (%u bytes)", name, tx->target, (guint)
|
||||
@@ -549,7 +566,8 @@ gbinder_driver_handle_transaction(
|
||||
tx.flags, &txstatus);
|
||||
break;
|
||||
default:
|
||||
GWARN("Unhandled transaction %s 0x%08x", iface, tx.code);
|
||||
GWARN("Unhandled transaction %s 0x%08x from %s", iface, tx.code,
|
||||
self->name);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -879,6 +897,9 @@ gbinder_driver_new(
|
||||
self->vm = vm;
|
||||
self->vmsize = vmsize;
|
||||
self->dev = g_strdup(dev);
|
||||
self->name = self->dev + /* Shorter version for logging */
|
||||
(g_str_has_prefix(self->dev, "/dev/") ? 5 : 0);
|
||||
|
||||
if (gbinder_system_ioctl(fd, BINDER_SET_MAX_THREADS,
|
||||
&max_threads) < 0) {
|
||||
GERR("%s failed to set max threads (%u): %s", dev,
|
||||
@@ -1303,8 +1324,9 @@ GBinderLocalRequest*
|
||||
gbinder_driver_local_request_new_ping(
|
||||
GBinderDriver* self)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(self->io, NULL);
|
||||
GBinderWriter writer;
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(self->io,
|
||||
self->protocol, NULL);
|
||||
|
||||
gbinder_local_request_init_writer(req, &writer);
|
||||
self->protocol->write_ping(&writer);
|
||||
|
||||
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-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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"
|
||||
@@ -94,7 +95,8 @@ GBINDER_IO_FN(write_read)(
|
||||
static
|
||||
gsize
|
||||
GBINDER_IO_FN(object_size)(
|
||||
const void* obj)
|
||||
const void* obj,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
if (obj) {
|
||||
const struct binder_object_header* hdr = obj;
|
||||
@@ -104,7 +106,8 @@ GBINDER_IO_FN(object_size)(
|
||||
case BINDER_TYPE_WEAK_BINDER:
|
||||
case BINDER_TYPE_HANDLE:
|
||||
case BINDER_TYPE_WEAK_HANDLE:
|
||||
return sizeof(struct flat_binder_object);
|
||||
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:
|
||||
@@ -166,7 +169,8 @@ static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_local_object)(
|
||||
void* out,
|
||||
GBinderLocalObject* obj)
|
||||
GBinderLocalObject* obj,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
struct flat_binder_object* dest = out;
|
||||
|
||||
@@ -176,9 +180,14 @@ GBINDER_IO_FN(encode_local_object)(
|
||||
dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->binder = (uintptr_t)obj;
|
||||
} else {
|
||||
dest->hdr.type = BINDER_TYPE_WEAK_BINDER;
|
||||
dest->hdr.type = BINDER_TYPE_HANDLE;
|
||||
}
|
||||
return sizeof(*dest);
|
||||
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
|
||||
@@ -215,6 +224,23 @@ GBINDER_IO_FN(encode_fd_object)(
|
||||
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);
|
||||
}
|
||||
|
||||
/* Encodes binder_buffer_object */
|
||||
static
|
||||
guint
|
||||
@@ -263,7 +289,7 @@ GBINDER_IO_FN(encode_ptr_cookie)(
|
||||
/* We never send these cookies and don't expect them back */
|
||||
dest->ptr = (uintptr_t)obj;
|
||||
dest->cookie = 0;
|
||||
return sizeof(dest);
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Fills binder_transaction_data for BC_TRANSACTION/REPLY */
|
||||
@@ -483,7 +509,8 @@ static
|
||||
guint
|
||||
GBINDER_IO_FN(decode_binder_handle)(
|
||||
const void* data,
|
||||
guint32* handle)
|
||||
guint32* handle,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
const struct flat_binder_object* obj = data;
|
||||
|
||||
@@ -492,7 +519,7 @@ GBINDER_IO_FN(decode_binder_handle)(
|
||||
if (handle) {
|
||||
*handle = obj->handle;
|
||||
}
|
||||
return sizeof(*obj);
|
||||
return sizeof(*obj) + protocol->flat_binder_object_extra;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -503,7 +530,8 @@ 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;
|
||||
|
||||
@@ -513,15 +541,18 @@ GBINDER_IO_FN(decode_binder_object)(
|
||||
if (out) {
|
||||
*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);
|
||||
return sizeof(*obj) + protocol->flat_binder_object_extra;
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
@@ -637,6 +668,7 @@ const GBinderIo GBINDER_IO_PREFIX = {
|
||||
.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_handle_cookie = GBINDER_IO_FN(encode_handle_cookie),
|
||||
.encode_ptr_cookie = GBINDER_IO_FN(encode_ptr_cookie),
|
||||
@@ -663,6 +695,10 @@ 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) <=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -126,7 +126,7 @@ struct gbinder_io {
|
||||
} br;
|
||||
|
||||
/* Size of the object and its extra data */
|
||||
gsize (*object_size)(const void* obj);
|
||||
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
|
||||
@@ -142,10 +142,13 @@ struct gbinder_io {
|
||||
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)
|
||||
@@ -187,9 +190,11 @@ struct gbinder_io {
|
||||
void (*decode_transaction_data)(const void* data, GBinderIoTxData* tx);
|
||||
void* (*decode_ptr_cookie)(const void* data);
|
||||
guint (*decode_cookie)(const void* data, guint64* cookie);
|
||||
guint (*decode_binder_handle)(const void* obj, guint32* handle);
|
||||
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,
|
||||
GBinderIoBufferObject* out);
|
||||
guint (*decode_fd_object)(const void* data, gsize size, int* fd);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -58,11 +58,13 @@
|
||||
#include <time.h>
|
||||
|
||||
typedef struct gbinder_ipc_looper GBinderIpcLooper;
|
||||
typedef GObjectClass GBinderIpcClass;
|
||||
|
||||
struct gbinder_ipc_priv {
|
||||
GBinderIpc* self;
|
||||
GThreadPool* tx_pool;
|
||||
GHashTable* tx_table;
|
||||
char* dev;
|
||||
char* key;
|
||||
const char* name;
|
||||
GBinderObjectRegistry object_registry;
|
||||
@@ -78,11 +80,12 @@ struct gbinder_ipc_priv {
|
||||
GBinderIpcLooper* blocked_loopers;
|
||||
};
|
||||
|
||||
typedef GObjectClass GBinderIpcClass;
|
||||
#define PARENT_CLASS gbinder_ipc_parent_class
|
||||
#define THIS_TYPE gbinder_ipc_get_type()
|
||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GBinderIpc)
|
||||
|
||||
GType THIS_TYPE GBINDER_INTERNAL;
|
||||
G_DEFINE_TYPE(GBinderIpc, gbinder_ipc, G_TYPE_OBJECT)
|
||||
#define GBINDER_TYPE_IPC (gbinder_ipc_get_type())
|
||||
#define GBINDER_IPC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_IPC, GBinderIpc))
|
||||
|
||||
/*
|
||||
* Binder requests are blocking, worker threads are needed in order to
|
||||
@@ -207,9 +210,6 @@ typedef struct gbinder_ipc_tx_custom {
|
||||
GDestroyNotify fn_custom_destroy;
|
||||
} GBinderIpcTxCustom;
|
||||
|
||||
GBINDER_INLINE_FUNC const char* gbinder_ipc_name(GBinderIpc* self)
|
||||
{ return self->priv->name; }
|
||||
|
||||
static
|
||||
GBinderIpcLooper*
|
||||
gbinder_ipc_looper_new(
|
||||
@@ -266,6 +266,15 @@ gbinder_ipc_wait(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
char*
|
||||
gbinder_ipc_make_key(
|
||||
const char* dev,
|
||||
const char* protocol)
|
||||
{
|
||||
return g_strdup_printf("%s:%s", protocol, dev);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* GBinderIpcLooperTx
|
||||
*==========================================================================*/
|
||||
@@ -1115,6 +1124,23 @@ gbinder_ipc_tx_handler_transact(
|
||||
* GBinderObjectRegistry
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_ipc_invalidate_local_object_locked(
|
||||
GBinderIpc* self,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GBinderIpcPriv* priv = self->priv;
|
||||
|
||||
if (priv->local_objects && g_hash_table_remove(priv->local_objects, obj)) {
|
||||
GVERBOSE_("%p %s", obj, gbinder_ipc_name(self));
|
||||
if (g_hash_table_size(priv->local_objects) == 0) {
|
||||
g_hash_table_unref(priv->local_objects);
|
||||
priv->local_objects = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_ipc_invalidate_remote_handle_locked(
|
||||
@@ -1140,6 +1166,20 @@ gbinder_ipc_invalidate_remote_handle_locked(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_ipc_invalidate_local_object(
|
||||
GBinderIpc* self,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GBinderIpcPriv* priv = self->priv;
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&priv->local_objects_mutex);
|
||||
gbinder_ipc_invalidate_local_object_locked(self, obj);
|
||||
g_mutex_unlock(&priv->local_objects_mutex);
|
||||
/* Unlock */
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_ipc_invalidate_remote_handle(
|
||||
GBinderIpc* self,
|
||||
@@ -1183,14 +1223,8 @@ gbinder_ipc_local_object_disposed(
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&priv->local_objects_mutex);
|
||||
if (obj->object.ref_count == 1 && priv->local_objects) {
|
||||
if (g_hash_table_remove(priv->local_objects, obj)) {
|
||||
GVERBOSE_("%p %s", obj, gbinder_ipc_name(self));
|
||||
if (g_hash_table_size(priv->local_objects) == 0) {
|
||||
g_hash_table_unref(priv->local_objects);
|
||||
priv->local_objects = NULL;
|
||||
}
|
||||
}
|
||||
if (g_atomic_int_get(&obj->object.ref_count) == 1) {
|
||||
gbinder_ipc_invalidate_local_object_locked(self, obj);
|
||||
}
|
||||
g_mutex_unlock(&priv->local_objects_mutex);
|
||||
/* Unlock */
|
||||
@@ -1203,9 +1237,32 @@ gbinder_ipc_remote_object_disposed(
|
||||
{
|
||||
GBinderIpcPriv* priv = self->priv;
|
||||
|
||||
/*
|
||||
* Check of ref_count for 1 makes it possible (albeit quite unlikely)
|
||||
* that GBinderRemoteObject still remains in remote_objects table
|
||||
* when it's being finalized.
|
||||
*
|
||||
* For this to happen, other thread must re-reference GBinderRemoteObject
|
||||
* right before we grab the lock here (making ref_count greater than 1)
|
||||
* and then release that reference before g_object_unref() re-checks the
|
||||
* refcount.
|
||||
*
|
||||
* That's why another gbinder_ipc_invalidate_remote_handle() call from
|
||||
* gbinder_remote_object_finalize() is necessary to make sure that stale
|
||||
* object pointer isn't stored in the hashtable.
|
||||
*
|
||||
* We still have to invalidate the handle here because it's the last
|
||||
* point when GObject can be legitimately re-referenced and brought
|
||||
* back to life. Which means that GBinderIpc mutex has to acquired
|
||||
* twice during GBinderRemoteObject destruction.
|
||||
*
|
||||
* The same applies to GBinderLocalObject too, except that it calls
|
||||
* gbinder_ipc_invalidate_local_object() from its finalize() handler.
|
||||
*/
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&priv->remote_objects_mutex);
|
||||
if (obj->object.ref_count == 1) {
|
||||
if (g_atomic_int_get(&obj->object.ref_count) == 1) {
|
||||
gbinder_ipc_invalidate_remote_handle_locked(self, obj->handle);
|
||||
}
|
||||
g_mutex_unlock(&priv->remote_objects_mutex);
|
||||
@@ -1250,10 +1307,10 @@ gbinder_ipc_priv_get_local_object(
|
||||
if (obj) {
|
||||
gbinder_local_object_ref(obj);
|
||||
} else {
|
||||
GWARN("Unknown local object %p", pointer);
|
||||
GWARN("Unknown local object %p %s", pointer, priv->name);
|
||||
}
|
||||
} else {
|
||||
GWARN("Unknown local object %p", pointer);
|
||||
GWARN("Unknown local object %p %s", pointer, priv->name);
|
||||
}
|
||||
g_mutex_unlock(&priv->local_objects_mutex);
|
||||
/* Unlock */
|
||||
@@ -1297,6 +1354,8 @@ gbinder_ipc_priv_get_remote_object(
|
||||
}
|
||||
GVERBOSE_("%p handle %u %s", obj, handle, gbinder_ipc_name(self));
|
||||
g_hash_table_replace(priv->remote_objects, key, obj);
|
||||
} else {
|
||||
GWARN("Unknown handle %u %s", handle, priv->name);
|
||||
}
|
||||
g_mutex_unlock(&priv->remote_objects_mutex);
|
||||
/* Unlock */
|
||||
@@ -1794,20 +1853,25 @@ const GBinderIpcSyncApi gbinder_ipc_sync_main = {
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_new(
|
||||
const char* dev)
|
||||
const char* dev,
|
||||
const char* protocol_name)
|
||||
{
|
||||
GBinderIpc* self = NULL;
|
||||
const GBinderRpcProtocol* protocol;
|
||||
char* key;
|
||||
const GBinderRpcProtocol* protocol = (protocol_name ?
|
||||
gbinder_rpc_protocol_by_name(protocol_name) : NULL);
|
||||
|
||||
if (!dev || !dev[0]) dev = GBINDER_DEFAULT_BINDER;
|
||||
protocol = gbinder_rpc_protocol_for_device(dev); /* Never returns NULL */
|
||||
if (!protocol) protocol = gbinder_rpc_protocol_for_device(dev);
|
||||
key = gbinder_ipc_make_key(dev, protocol->name);
|
||||
|
||||
/* Lock */
|
||||
pthread_mutex_lock(&gbinder_ipc_mutex);
|
||||
if (gbinder_ipc_table) {
|
||||
self = g_hash_table_lookup(gbinder_ipc_table, dev);
|
||||
self = g_hash_table_lookup(gbinder_ipc_table, key);
|
||||
}
|
||||
if (self) {
|
||||
g_free(key);
|
||||
gbinder_ipc_ref(self);
|
||||
} else {
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, protocol);
|
||||
@@ -1815,10 +1879,11 @@ gbinder_ipc_new(
|
||||
if (driver) {
|
||||
GBinderIpcPriv* priv;
|
||||
|
||||
self = g_object_new(GBINDER_TYPE_IPC, NULL);
|
||||
self = g_object_new(THIS_TYPE, NULL);
|
||||
priv = self->priv;
|
||||
self->driver = driver;
|
||||
self->dev = priv->key = g_strdup(dev);
|
||||
self->dev = priv->dev = g_strdup(dev);
|
||||
priv->key = key;
|
||||
self->priv->object_registry.io = gbinder_driver_io(driver);
|
||||
/* gbinder_ipc_dispose will remove iself from the table */
|
||||
if (!gbinder_ipc_table) {
|
||||
@@ -1826,8 +1891,10 @@ gbinder_ipc_new(
|
||||
}
|
||||
g_hash_table_replace(gbinder_ipc_table, priv->key, self);
|
||||
/* With "/dev/" prefix, it may be too long to be a thread name */
|
||||
priv->name = priv->key +
|
||||
(g_str_has_prefix(priv->key, "/dev/") ? 5 : 0);
|
||||
priv->name = self->dev +
|
||||
(g_str_has_prefix(priv->dev, "/dev/") ? 5 : 0);
|
||||
} else {
|
||||
g_free(key);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&gbinder_ipc_mutex);
|
||||
@@ -1840,7 +1907,7 @@ gbinder_ipc_ref(
|
||||
GBinderIpc* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(GBINDER_IPC(self));
|
||||
g_object_ref(THIS(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
@@ -1852,10 +1919,17 @@ gbinder_ipc_unref(
|
||||
GBinderIpc* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_IPC(self));
|
||||
g_object_unref(THIS(self));
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_ipc_name(
|
||||
GBinderIpc* self)
|
||||
{
|
||||
return G_LIKELY(self) ? self->priv->name : NULL;
|
||||
}
|
||||
|
||||
GBinderObjectRegistry*
|
||||
gbinder_ipc_object_registry(
|
||||
GBinderIpc* self)
|
||||
@@ -1983,7 +2057,7 @@ gbinder_ipc_init(
|
||||
.get_local = gbinder_ipc_object_registry_get_local,
|
||||
.get_remote = gbinder_ipc_object_registry_get_remote
|
||||
};
|
||||
GBinderIpcPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self, GBINDER_TYPE_IPC,
|
||||
GBinderIpcPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self, THIS_TYPE,
|
||||
GBinderIpcPriv);
|
||||
|
||||
g_mutex_init(&priv->looper_mutex);
|
||||
@@ -2034,7 +2108,7 @@ void
|
||||
gbinder_ipc_dispose(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderIpc* self = GBINDER_IPC(object);
|
||||
GBinderIpc* self = THIS(object);
|
||||
|
||||
GVERBOSE_("%s", self->dev);
|
||||
/* Lock */
|
||||
@@ -2058,7 +2132,7 @@ gbinder_ipc_dispose(
|
||||
/* Unlock */
|
||||
|
||||
gbinder_ipc_stop_loopers(self);
|
||||
G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -2066,7 +2140,7 @@ void
|
||||
gbinder_ipc_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderIpc* self = GBINDER_IPC(object);
|
||||
GBinderIpc* self = THIS(object);
|
||||
GBinderIpcPriv* priv = self->priv;
|
||||
|
||||
GASSERT(!priv->local_objects);
|
||||
@@ -2080,8 +2154,9 @@ gbinder_ipc_finalize(
|
||||
GASSERT(!g_hash_table_size(priv->tx_table));
|
||||
g_hash_table_unref(priv->tx_table);
|
||||
gbinder_driver_unref(self->driver);
|
||||
g_free(priv->dev);
|
||||
g_free(priv->key);
|
||||
G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -2117,9 +2192,8 @@ gbinder_ipc_exit()
|
||||
/* Unlock */
|
||||
|
||||
for (i = ipcs; i; i = i->next) {
|
||||
GBinderIpc* ipc = GBINDER_IPC(i->data);
|
||||
GBinderIpc* ipc = THIS(i->data);
|
||||
GBinderIpcPriv* priv = ipc->priv;
|
||||
GThreadPool* pool = priv->tx_pool;
|
||||
GSList* local_objs = NULL;
|
||||
GSList* tx_keys = NULL;
|
||||
GSList* k;
|
||||
@@ -2130,8 +2204,12 @@ gbinder_ipc_exit()
|
||||
gbinder_ipc_stop_loopers(ipc);
|
||||
|
||||
/* Make sure pooled transaction complete too */
|
||||
priv->tx_pool = NULL;
|
||||
g_thread_pool_free(pool, FALSE, TRUE);
|
||||
if (priv->tx_pool) {
|
||||
GThreadPool* pool = priv->tx_pool;
|
||||
|
||||
priv->tx_pool = NULL;
|
||||
g_thread_pool_free(pool, FALSE, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since this function is supposed to be invoked on the main thread,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -100,7 +100,8 @@ extern const GBinderIpcSyncApi gbinder_ipc_sync_worker GBINDER_INTERNAL;
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_new(
|
||||
const char* dev)
|
||||
const char* dev,
|
||||
const char* protocol)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderIpc*
|
||||
@@ -113,6 +114,11 @@ gbinder_ipc_unref(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
const char*
|
||||
gbinder_ipc_name(
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_ipc_looper_check(
|
||||
GBinderIpc* ipc)
|
||||
@@ -149,7 +155,7 @@ gbinder_ipc_register_local_object(
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_ipc_get_service_manager(
|
||||
GBinderIpc* self)
|
||||
GBinderIpc* ipc)
|
||||
GBINDER_INTERNAL
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
@@ -196,21 +202,27 @@ gbinder_ipc_cancel(
|
||||
/* Internal for GBinderLocalObject */
|
||||
void
|
||||
gbinder_ipc_local_object_disposed(
|
||||
GBinderIpc* self,
|
||||
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,
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
/* Needed by unit tests */
|
||||
gboolean
|
||||
gbinder_ipc_set_max_threads(
|
||||
GBinderIpc* self,
|
||||
GBinderIpc* ipc,
|
||||
gint max_threads)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -89,6 +89,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(
|
||||
@@ -139,8 +148,7 @@ gbinder_local_object_ping_transaction(
|
||||
GBinderRemoteRequest* req,
|
||||
int* status)
|
||||
{
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
|
||||
GVERBOSE(" PING_TRANSACTION");
|
||||
gbinder_local_reply_append_int32(reply, GBINDER_STATUS_OK);
|
||||
@@ -155,9 +163,8 @@ gbinder_local_object_interface_transaction(
|
||||
GBinderRemoteRequest* req,
|
||||
int* status)
|
||||
{
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
|
||||
GVERBOSE(" INTERFACE_TRANSACTION");
|
||||
gbinder_local_reply_append_string16(reply, priv->ifaces[0]);
|
||||
@@ -173,8 +180,7 @@ 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);
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
|
||||
GVERBOSE(" HIDL_PING_TRANSACTION \"%s\"",
|
||||
gbinder_remote_request_interface(req));
|
||||
@@ -191,9 +197,8 @@ gbinder_local_object_hidl_get_descriptor_transaction(
|
||||
int* status)
|
||||
{
|
||||
/*android.hidl.base@1.0::IBase interfaceDescriptor() */
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderLocalReply* reply = gbinder_local_object_create_reply(self);
|
||||
GBinderWriter writer;
|
||||
|
||||
GVERBOSE(" HIDL_GET_DESCRIPTOR_TRANSACTION \"%s\"",
|
||||
@@ -213,8 +218,7 @@ 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;
|
||||
|
||||
GVERBOSE(" HIDL_DESCRIPTOR_CHAIN_TRANSACTION \"%s\"",
|
||||
@@ -480,7 +484,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;
|
||||
}
|
||||
@@ -644,6 +648,7 @@ gbinder_local_object_finalize(
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
GASSERT(!self->strong_refs);
|
||||
gbinder_ipc_invalidate_local_object(self->ipc, self);
|
||||
gbinder_ipc_unref(self->ipc);
|
||||
g_strfreev(priv->ifaces);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -92,6 +92,8 @@ GType gbinder_local_object_get_type(void) GBINDER_INTERNAL;
|
||||
|
||||
#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))
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_new_with_type(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -72,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;
|
||||
@@ -87,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;
|
||||
@@ -307,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-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -39,7 +39,8 @@
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new(
|
||||
const GBinderIo* io)
|
||||
const GBinderIo* io,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
GBinderOutputData*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -74,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;
|
||||
@@ -89,6 +91,7 @@ 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);
|
||||
@@ -111,9 +114,10 @@ gbinder_local_request_new_iface(
|
||||
const GBinderRpcProtocol* protocol,
|
||||
const char* iface)
|
||||
{
|
||||
GBinderLocalRequest* self = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalRequest* self = gbinder_local_request_new(io, protocol, NULL);
|
||||
|
||||
if (self && G_LIKELY(protocol) && G_LIKELY(iface)) {
|
||||
/* gbinder_local_request_new() fails if protocol is NULL */
|
||||
if (self && G_LIKELY(iface)) {
|
||||
GBinderWriter writer;
|
||||
|
||||
gbinder_local_request_init_writer(self, &writer);
|
||||
@@ -128,7 +132,7 @@ gbinder_local_request_new_from_data(
|
||||
GBinderObjectConverter* convert)
|
||||
{
|
||||
GBinderLocalRequest* self = gbinder_local_request_new
|
||||
(gbinder_buffer_io(buffer), NULL);
|
||||
(gbinder_buffer_io(buffer), gbinder_buffer_protocol(buffer), NULL);
|
||||
|
||||
if (self) {
|
||||
gbinder_writer_data_append_contents(&self->data, buffer, 0, convert);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -40,6 +40,7 @@
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new(
|
||||
const GBinderIo* io,
|
||||
const GBinderRpcProtocol* protocol,
|
||||
GBytes* init)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -60,11 +60,9 @@ struct gbinder_proxy_tx {
|
||||
};
|
||||
|
||||
struct gbinder_proxy_object_priv {
|
||||
gulong remote_death_id;
|
||||
gboolean acquired;
|
||||
gboolean dropped;
|
||||
GBinderProxyTx* tx;
|
||||
GMutex mutex; /* Protects the hashtable below */
|
||||
GHashTable* subproxies;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GBinderProxyObject, gbinder_proxy_object, \
|
||||
@@ -76,79 +74,12 @@ G_DEFINE_TYPE(GBinderProxyObject, gbinder_proxy_object, \
|
||||
#define THIS_TYPE GBINDER_TYPE_PROXY_OBJECT
|
||||
#define PARENT_CLASS gbinder_proxy_object_parent_class
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_subproxy_gone(
|
||||
gpointer proxy,
|
||||
GObject* subproxy)
|
||||
{
|
||||
GBinderProxyObject* self = THIS(proxy);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&priv->mutex);
|
||||
g_hash_table_remove(priv->subproxies, subproxy);
|
||||
if (g_hash_table_size(priv->subproxies) == 0) {
|
||||
g_hash_table_unref(priv->subproxies);
|
||||
priv->subproxies = NULL;
|
||||
}
|
||||
g_mutex_unlock(&priv->mutex);
|
||||
/* Unlock */
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_drop_subproxies(
|
||||
GBinderProxyObject* self)
|
||||
{
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
GSList* list = NULL;
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&priv->mutex);
|
||||
if (priv->subproxies) {
|
||||
GHashTableIter it;
|
||||
gpointer value;
|
||||
|
||||
g_hash_table_iter_init(&it, priv->subproxies);
|
||||
while (g_hash_table_iter_next(&it, NULL, &value)) {
|
||||
list = g_slist_append(list, gbinder_local_object_ref(value));
|
||||
g_object_weak_unref(G_OBJECT(value),
|
||||
gbinder_proxy_object_subproxy_gone, self);
|
||||
}
|
||||
g_hash_table_destroy(priv->subproxies);
|
||||
priv->subproxies = NULL;
|
||||
}
|
||||
g_mutex_unlock(&priv->mutex);
|
||||
/* Unlock */
|
||||
|
||||
/* Drop (and possibly destroy) the objects outside of the lock */
|
||||
g_slist_free_full(list, (GDestroyNotify) gbinder_local_object_drop);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_remote_death_proc(
|
||||
GBinderRemoteObject* obj,
|
||||
void* proxy)
|
||||
{
|
||||
GBinderProxyObject* self = THIS(proxy);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
|
||||
GDEBUG("Remote object %u died on %s", obj->handle, obj->ipc->dev);
|
||||
gbinder_remote_object_remove_handler(obj, priv->remote_death_id);
|
||||
priv->remote_death_id = 0;
|
||||
/* Drop the implicit reference */
|
||||
gbinder_local_object_unref(&self->parent);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Converter
|
||||
*==========================================================================*/
|
||||
|
||||
typedef struct gbinder_proxy_object_converter {
|
||||
GBinderObjectConverter pub;
|
||||
GBinderProxyObject* proxy;
|
||||
GBinderIpc* remote;
|
||||
GBinderIpc* local;
|
||||
} GBinderProxyObjectConverter;
|
||||
@@ -182,8 +113,6 @@ gbinder_proxy_object_converter_handle_to_local(
|
||||
guint32 handle)
|
||||
{
|
||||
GBinderProxyObjectConverter* c = gbinder_proxy_object_converter_cast(pub);
|
||||
GBinderProxyObject* proxy = c->proxy;
|
||||
GBinderProxyObjectPriv* priv = proxy->priv;
|
||||
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 */);
|
||||
@@ -192,32 +121,7 @@ gbinder_proxy_object_converter_handle_to_local(
|
||||
|
||||
if (!local && !remote->dead) {
|
||||
/* GBinderProxyObject will reference GBinderRemoteObject */
|
||||
GBinderProxyObject* subp = gbinder_proxy_object_new(c->local, remote);
|
||||
|
||||
/*
|
||||
* Auto-created proxies may get spontaneously destroyed and
|
||||
* not necessarily on the UI thread.
|
||||
*/
|
||||
subp->priv->remote_death_id = gbinder_remote_object_add_death_handler
|
||||
(remote, gbinder_proxy_remote_death_proc, subp);
|
||||
|
||||
/*
|
||||
* Remote keeps an implicit reference to this auto-created
|
||||
* proxy. The reference gets released when the remote object
|
||||
* dies, i.e. by gbinder_proxy_remote_death_proc().
|
||||
*/
|
||||
gbinder_local_object_ref(local = GBINDER_LOCAL_OBJECT(subp));
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&priv->mutex);
|
||||
if (!priv->subproxies) {
|
||||
priv->subproxies = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
}
|
||||
g_hash_table_insert(priv->subproxies, subp, subp);
|
||||
g_object_weak_ref(G_OBJECT(subp),
|
||||
gbinder_proxy_object_subproxy_gone, proxy);
|
||||
g_mutex_unlock(&priv->mutex);
|
||||
/* Unlock */
|
||||
local = &gbinder_proxy_object_new(c->local, remote)->parent;
|
||||
}
|
||||
|
||||
/* Release the reference returned by gbinder_object_registry_get_remote */
|
||||
@@ -241,7 +145,6 @@ gbinder_proxy_object_converter_init(
|
||||
GBinderIpc* dest = proxy->parent.ipc;
|
||||
|
||||
memset(convert, 0, sizeof(*convert));
|
||||
convert->proxy = proxy;
|
||||
convert->remote = remote;
|
||||
convert->local = local;
|
||||
pub->f = &gbinder_converter_fn;
|
||||
@@ -346,7 +249,7 @@ gbinder_proxy_object_handle_transaction(
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
if (!priv->dropped && !gbinder_remote_object_is_dead(remote)) {
|
||||
if (!priv->dropped && !remote->dead) {
|
||||
GBinderLocalRequest* fwd;
|
||||
GBinderProxyTx* tx = g_slice_new0(GBinderProxyTx);
|
||||
GBinderProxyObjectConverter convert;
|
||||
@@ -374,6 +277,7 @@ gbinder_proxy_object_handle_transaction(
|
||||
gbinder_local_request_unref(fwd);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
} else {
|
||||
GVERBOSE_("dropped: %d dead:%d", priv->dropped, remote->dead);
|
||||
*status = (-EBADMSG);
|
||||
}
|
||||
return NULL;
|
||||
@@ -397,33 +301,16 @@ gbinder_proxy_object_acquire(
|
||||
{
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
if (priv->remote_death_id && !object->strong_refs) {
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
/* First strong ref, acquire the attached remote object */
|
||||
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_release(
|
||||
GBinderLocalObject* object)
|
||||
{
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
|
||||
if (priv->remote_death_id && object->strong_refs == 1) {
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
/* Last strong ref, release the attached remote object */
|
||||
gbinder_driver_release(remote->ipc->driver, remote->handle);
|
||||
}
|
||||
GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->release(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_proxy_object_drop(
|
||||
@@ -433,7 +320,6 @@ gbinder_proxy_object_drop(
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
|
||||
priv->dropped = TRUE;
|
||||
gbinder_proxy_object_drop_subproxies(self);
|
||||
GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->drop(object);
|
||||
}
|
||||
|
||||
@@ -459,6 +345,8 @@ gbinder_proxy_object_new(
|
||||
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;
|
||||
}
|
||||
@@ -477,11 +365,25 @@ gbinder_proxy_object_finalize(
|
||||
{
|
||||
GBinderProxyObject* self = THIS(object);
|
||||
GBinderProxyObjectPriv* priv = self->priv;
|
||||
GBinderLocalObject* local = &self->parent;
|
||||
GBinderRemoteObject* remote = self->remote;
|
||||
|
||||
gbinder_proxy_object_drop_subproxies(self);
|
||||
gbinder_remote_object_remove_handler(self->remote, priv->remote_death_id);
|
||||
gbinder_remote_object_unref(self->remote);
|
||||
g_mutex_clear(&priv->mutex);
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
@@ -494,7 +396,6 @@ gbinder_proxy_object_init(
|
||||
THIS_TYPE, GBinderProxyObjectPriv);
|
||||
|
||||
self->priv = priv;
|
||||
g_mutex_init(&priv->mutex);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -509,7 +410,6 @@ gbinder_proxy_object_class_init(
|
||||
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->release = gbinder_proxy_object_release;
|
||||
klass->drop = gbinder_proxy_object_drop;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Jolla Ltd.
|
||||
* Copyright (C) 2018-2019 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
|
||||
@@ -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;
|
||||
@@ -364,6 +426,40 @@ gbinder_reader_skip_buffer(
|
||||
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(
|
||||
@@ -680,13 +776,38 @@ gbinder_reader_read_byte_array(
|
||||
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
|
||||
@@ -695,7 +816,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
|
||||
@@ -703,8 +824,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-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -149,6 +149,7 @@ gbinder_remote_object_commit_suicide(
|
||||
GBinderRemoteObjectPriv* priv = self->priv;
|
||||
|
||||
self->dead = TRUE;
|
||||
gbinder_driver_clear_death_notification(driver, self);
|
||||
if (priv->acquired) {
|
||||
priv->acquired = FALSE;
|
||||
/* Release the dead node */
|
||||
@@ -294,6 +295,7 @@ gbinder_remote_object_finalize(
|
||||
GBinderIpc* ipc = self->ipc;
|
||||
GBinderDriver* driver = ipc->driver;
|
||||
|
||||
gbinder_ipc_invalidate_remote_handle(ipc, self->handle);
|
||||
if (!self->dead) {
|
||||
gbinder_driver_clear_death_notification(driver, self);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -131,8 +131,9 @@ gbinder_remote_reply_convert_to_local(
|
||||
GBinderObjectRegistry* reg = d->reg;
|
||||
|
||||
if (reg) {
|
||||
return gbinder_local_reply_set_contents
|
||||
(gbinder_local_reply_new(reg->io), d->buffer, convert);
|
||||
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-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 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:
|
||||
*
|
||||
@@ -40,6 +40,9 @@
|
||||
#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)
|
||||
* Note that there are two slightly different kinds of Parcels:
|
||||
@@ -173,6 +176,61 @@ static const GBinderRpcProtocol gbinder_rpc_protocol_aidl2 = {
|
||||
.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)
|
||||
{
|
||||
*(guint32*)out = GBINDER_STABILITY_SYSTEM;
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* The original /dev/hwbinder protocol.
|
||||
*==========================================================================*/
|
||||
@@ -225,6 +283,7 @@ static const GBinderRpcProtocol gbinder_rpc_protocol_hidl = {
|
||||
static const GBinderRpcProtocol* gbinder_rpc_protocol_list[] = {
|
||||
&gbinder_rpc_protocol_aidl,
|
||||
&gbinder_rpc_protocol_aidl2,
|
||||
&gbinder_rpc_protocol_aidl3,
|
||||
&gbinder_rpc_protocol_hidl
|
||||
};
|
||||
|
||||
@@ -331,6 +390,13 @@ gbinder_rpc_protocol_for_device(
|
||||
return gbinder_rpc_protocol_default;
|
||||
}
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_by_name(
|
||||
const char* protocol_name)
|
||||
{
|
||||
return gbinder_rpc_protocol_find(protocol_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 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:
|
||||
*
|
||||
@@ -47,8 +47,24 @@ struct gbinder_rpc_protocol {
|
||||
void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
|
||||
const char* (*read_rpc_header)(GBinderReader* reader, guint32 txcode,
|
||||
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);
|
||||
};
|
||||
|
||||
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(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -82,11 +82,13 @@ typedef struct gbinder_servicemanager_type {
|
||||
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 + 2)
|
||||
#define SERVICEMANAGER_TYPE_HIDL (gbinder_servicemanager_types + 4)
|
||||
#define SERVICEMANAGER_TYPE_DEFAULT SERVICEMANAGER_TYPE_AIDL
|
||||
|
||||
static GHashTable* gbinder_servicemanager_map = NULL;
|
||||
@@ -518,7 +520,8 @@ gbinder_servicemanager_exit(
|
||||
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);
|
||||
@@ -527,7 +530,7 @@ gbinder_servicemanager_new_with_type(
|
||||
GBinderIpc* ipc;
|
||||
|
||||
if (!dev) dev = klass->default_device;
|
||||
ipc = gbinder_ipc_new(dev);
|
||||
ipc = gbinder_ipc_new(dev, rpc_protocol);
|
||||
if (ipc) {
|
||||
/* Create a (possibly) dead service manager object */
|
||||
GBinderRemoteObject* object = gbinder_ipc_get_service_manager(ipc);
|
||||
@@ -619,25 +622,36 @@ GBinderServiceManager*
|
||||
gbinder_servicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
if (dev) {
|
||||
const GBinderServiceManagerType* type = NULL;
|
||||
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) {
|
||||
const GBinderServiceManagerType* t;
|
||||
|
||||
/* One-time initialization */
|
||||
gbinder_servicemanager_map = gbinder_servicemanager_load_config();
|
||||
|
||||
/* "Default" is a special value stored in a special variable */
|
||||
t = g_hash_table_lookup(gbinder_servicemanager_map, CONF_DEFAULT);
|
||||
if (t) {
|
||||
type = g_hash_table_lookup(gbinder_servicemanager_map,
|
||||
CONF_DEFAULT);
|
||||
if (type) {
|
||||
g_hash_table_remove(gbinder_servicemanager_map, CONF_DEFAULT);
|
||||
gbinder_servicemanager_default = t;
|
||||
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);
|
||||
@@ -645,9 +659,21 @@ gbinder_servicemanager_new(
|
||||
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);
|
||||
return gbinder_servicemanager_new_with_type(type->get_type(), dev,
|
||||
rpc_protocol);
|
||||
} else {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderLocalObject*
|
||||
@@ -698,6 +724,13 @@ 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 */
|
||||
@@ -1008,7 +1041,7 @@ gbinder_defaultservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_servicemanager_aidl_get_type(), dev);
|
||||
(gbinder_servicemanager_aidl_get_type(), dev, NULL);
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
@@ -1016,7 +1049,7 @@ gbinder_hwservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_servicemanager_hidl_get_type(), dev);
|
||||
(gbinder_servicemanager_hidl_get_type(), dev, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
|
||||
@@ -61,16 +61,6 @@ G_DEFINE_TYPE(GBinderServiceManagerAidl,
|
||||
#define GBINDER_SERVICEMANAGER_AIDL(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER_AIDL, \
|
||||
GBinderServiceManagerAidl)
|
||||
#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 SERVICEMANAGER_AIDL_IFACE "android.os.IServiceManager"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Jolla Ltd.
|
||||
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||
* 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:
|
||||
*
|
||||
@@ -51,10 +51,20 @@ typedef struct gbinder_servicemanager_aidl_class {
|
||||
|
||||
#define GBINDER_TYPE_SERVICEMANAGER_AIDL \
|
||||
gbinder_servicemanager_aidl_get_type()
|
||||
#define GBINDER_SERVICEMANAGER_AIDL_CLASS(klass) \
|
||||
G_TYPE_CHECK_CLASS_CAST((klass), GBINDER_TYPE_SERVICEMANAGER_AIDL, \
|
||||
#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 */
|
||||
|
||||
/*
|
||||
@@ -64,3 +74,4 @@ typedef struct gbinder_servicemanager_aidl_class {
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@ G_DEFINE_TYPE(GBinderServiceManagerAidl2,
|
||||
GBINDER_TYPE_SERVICEMANAGER_AIDL)
|
||||
|
||||
#define PARENT_CLASS gbinder_servicemanager_aidl2_parent_class
|
||||
#define DUMP_FLAG_PRIORITY_DEFAULT (0x08)
|
||||
#define DUMP_FLAG_PRIORITY_ALL (0x0f)
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
|
||||
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:
|
||||
*/
|
||||
@@ -90,7 +90,8 @@ GType gbinder_servicemanager_get_type(void) GBINDER_INTERNAL;
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev)
|
||||
const char* dev,
|
||||
const char* rpc_protocol)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
@@ -110,6 +111,8 @@ gbinder_servicemanager_exit(
|
||||
|
||||
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 */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 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:
|
||||
*
|
||||
@@ -50,10 +50,12 @@ struct gbinder_servicepoll {
|
||||
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,
|
||||
@@ -76,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;
|
||||
@@ -122,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,
|
||||
@@ -136,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,
|
||||
@@ -171,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;
|
||||
@@ -183,7 +185,7 @@ gbinder_servicepoll_unref(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_SERVICEPOLL(self));
|
||||
g_object_unref(THIS(self));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,12 +242,13 @@ void
|
||||
gbinder_servicepoll_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServicePoll* self = GBINDER_SERVICEPOLL(object);
|
||||
GBinderServicePoll* self = THIS(object);
|
||||
|
||||
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-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -77,6 +77,13 @@ typedef struct gbinder_ipc_sync_api GBinderIpcSyncApi;
|
||||
/* As a special case, ServiceManager's handle is zero */
|
||||
#define GBINDER_SERVICEMANAGER_HANDLE (0)
|
||||
|
||||
typedef enum gbinder_stability_level {
|
||||
GBINDER_STABILITY_UNDECLARED = 0,
|
||||
GBINDER_STABILITY_VENDOR = 0x03,
|
||||
GBINDER_STABILITY_SYSTEM = 0x0c,
|
||||
GBINDER_STABILITY_VINTF = 0x3f
|
||||
} GBINDER_STABILITY_LEVEL;
|
||||
|
||||
#endif /* GBINDER_TYPES_PRIVATE_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#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"
|
||||
@@ -51,6 +52,20 @@ typedef struct gbinder_writer_priv {
|
||||
GBinderWriterData* data;
|
||||
} GBinderWriterPriv;
|
||||
|
||||
const GBinderWriterType gbinder_writer_type_byte = { "int32", 4, NULL };
|
||||
const GBinderWriterType gbinder_writer_type_int32 = { "byte", 1, 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)
|
||||
@@ -91,6 +106,7 @@ gbinder_writer_data_append_contents(
|
||||
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);
|
||||
@@ -113,21 +129,22 @@ gbinder_writer_data_append_contents(
|
||||
gutil_int_array_append(data->offsets, dest->len);
|
||||
|
||||
/* Convert remote object into local if necessary */
|
||||
if (convert && io->decode_binder_handle(obj, &handle) &&
|
||||
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);
|
||||
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);
|
||||
objsize = io->object_size(obj, proto);
|
||||
g_byte_array_append(dest, obj, objsize);
|
||||
}
|
||||
|
||||
@@ -155,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,
|
||||
@@ -188,12 +181,52 @@ 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 data->bytes->len;
|
||||
|
||||
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
|
||||
@@ -213,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
|
||||
@@ -581,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(
|
||||
@@ -604,7 +647,6 @@ gbinder_writer_data_close_fd(
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_append_fd(
|
||||
GBinderWriterData* data,
|
||||
@@ -646,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,
|
||||
@@ -675,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,
|
||||
@@ -682,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,
|
||||
@@ -700,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,
|
||||
@@ -712,10 +999,6 @@ gbinder_writer_data_append_hidl_vec(
|
||||
const gsize total = count * elemsize;
|
||||
void* buf = gutil_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;
|
||||
|
||||
/* Fill in the vector descriptor */
|
||||
if (buf) {
|
||||
vec->data.ptr = buf;
|
||||
@@ -726,8 +1009,10 @@ gbinder_writer_data_append_hidl_vec(
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, vec);
|
||||
|
||||
/* Every vector, even the one without data, requires two buffer objects */
|
||||
gbinder_writer_data_write_buffer_object(data, vec, sizeof(*vec), NULL);
|
||||
gbinder_writer_data_write_buffer_object(data, buf, total, &vec_parent);
|
||||
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
|
||||
@@ -753,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;
|
||||
@@ -764,17 +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);
|
||||
|
||||
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_write_buffer_object(data, NULL, 0, &str_parent);
|
||||
gbinder_writer_data_append_buffer_object(data, NULL, 0, &str_parent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,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);
|
||||
@@ -833,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;
|
||||
|
||||
@@ -842,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 */
|
||||
@@ -850,7 +1131,7 @@ 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,
|
||||
@@ -858,13 +1139,13 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
} else {
|
||||
GVERBOSE_("%d. NULL %u %u %u", i + 1, (guint)hidl_str->len,
|
||||
(guint)str_parent.index, (guint)data->buffers_size);
|
||||
gbinder_writer_data_write_buffer_object(data, NULL, 0,
|
||||
gbinder_writer_data_append_buffer_object(data, NULL, 0,
|
||||
&str_parent);
|
||||
}
|
||||
str_parent.offset += sizeof(GBinderHidlString);
|
||||
}
|
||||
} else {
|
||||
gbinder_writer_data_write_buffer_object(data, NULL, 0, &vec_parent);
|
||||
gbinder_writer_data_append_buffer_object(data, NULL, 0, &vec_parent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,7 +1173,7 @@ 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 */
|
||||
@@ -941,6 +1222,67 @@ gbinder_writer_append_byte_array(
|
||||
}
|
||||
}
|
||||
|
||||
#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,
|
||||
@@ -995,6 +1337,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-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
typedef struct gbinder_writer_data {
|
||||
const GBinderIo* io;
|
||||
const GBinderRpcProtocol* protocol;
|
||||
GByteArray* bytes;
|
||||
GUtilIntArray* offsets;
|
||||
gsize buffers_size;
|
||||
@@ -130,6 +131,13 @@ gbinder_writer_data_append_buffer_object(
|
||||
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,
|
||||
@@ -163,6 +171,12 @@ gbinder_writer_data_append_remote_object(
|
||||
GBinderRemoteObject* obj)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_fd(
|
||||
GBinderWriterData* data,
|
||||
int fd)
|
||||
GBINDER_INTERNAL;
|
||||
|
||||
#endif /* GBINDER_WRITER_PRIVATE_H */
|
||||
|
||||
/*
|
||||
|
||||
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:
|
||||
*/
|
||||
@@ -1,154 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Executable
|
||||
#
|
||||
|
||||
EXE = binder-bridge
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
|
||||
#
|
||||
# Install
|
||||
#
|
||||
|
||||
INSTALL = install
|
||||
|
||||
INSTALL_BIN_DIR = $(DESTDIR)/usr/bin
|
||||
|
||||
install: release $(INSTALL_BIN_DIR)
|
||||
$(INSTALL) -m 755 $(RELEASE_EXE) $(INSTALL_BIN_DIR)
|
||||
|
||||
$(INSTALL_BIN_DIR):
|
||||
$(INSTALL) -d $@
|
||||
include ../common/Makefile
|
||||
|
||||
@@ -49,10 +49,9 @@ CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include -I$(GEN_DIR) -I$(SRC_DIR)
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
CFLAGS += -fPIC $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
LDFLAGS += -pie $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021 Franz-Josef Haider <franz.haider@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
@@ -80,9 +80,11 @@ go_through_transaction_ast(
|
||||
|
||||
switch(v->type) {
|
||||
case INT8_TYPE:
|
||||
if (cur_pass == BUILD_TRANSACTION) GDEBUG("int8");
|
||||
if (cur_pass == BUILD_TRANSACTION) {
|
||||
GDEBUG("int8 %u", (guint)(*((guint8*)v->value)));
|
||||
}
|
||||
if (parent_idx == -1) {
|
||||
gbinder_writer_append_int32(&app->writer, *((int*)v->value));
|
||||
gbinder_writer_append_int8(&app->writer, *((guint8*)v->value));
|
||||
} else if (cur_pass == FILL_BUFFERS) {
|
||||
*((unsigned char*)(((char*)buf)+offset)) =
|
||||
*((unsigned char*)v->value);
|
||||
@@ -91,7 +93,9 @@ go_through_transaction_ast(
|
||||
break;
|
||||
|
||||
case INT32_TYPE:
|
||||
if (cur_pass == BUILD_TRANSACTION) GDEBUG("int32");
|
||||
if (cur_pass == BUILD_TRANSACTION) {
|
||||
GDEBUG("int32 %d", *((int*)v->value));
|
||||
}
|
||||
if (parent_idx == -1) {
|
||||
gbinder_writer_append_int32(&app->writer, *((int*)v->value));
|
||||
} else if (cur_pass == FILL_BUFFERS) {
|
||||
@@ -101,7 +105,9 @@ go_through_transaction_ast(
|
||||
break;
|
||||
|
||||
case INT64_TYPE:
|
||||
if (cur_pass == BUILD_TRANSACTION) GDEBUG("int64");
|
||||
if (cur_pass == BUILD_TRANSACTION) {
|
||||
GDEBUG("int64 %" G_GINT64_MODIFIER "d", *((gint64*)v->value));
|
||||
}
|
||||
if (parent_idx == -1) {
|
||||
gbinder_writer_append_int64(&app->writer, *((gint64*)v->value));
|
||||
} else if (cur_pass == FILL_BUFFERS) {
|
||||
@@ -111,7 +117,9 @@ go_through_transaction_ast(
|
||||
break;
|
||||
|
||||
case FLOAT_TYPE:
|
||||
if (cur_pass == BUILD_TRANSACTION) GDEBUG("float");
|
||||
if (cur_pass == BUILD_TRANSACTION) {
|
||||
GDEBUG("float %g", (double)*((float*)v->value));
|
||||
}
|
||||
if (parent_idx == -1) {
|
||||
gbinder_writer_append_float(&app->writer, *((float*)v->value));
|
||||
} else if (cur_pass == FILL_BUFFERS) {
|
||||
@@ -120,7 +128,9 @@ go_through_transaction_ast(
|
||||
offset += sizeof(float);
|
||||
break;
|
||||
case DOUBLE_TYPE:
|
||||
if (cur_pass == BUILD_TRANSACTION) GDEBUG("double");
|
||||
if (cur_pass == BUILD_TRANSACTION) {
|
||||
GDEBUG("double %g", *((double*)v->value));
|
||||
}
|
||||
if (parent_idx == -1) {
|
||||
gbinder_writer_append_double(&app->writer,*((double*)v->value));
|
||||
} else if (cur_pass == FILL_BUFFERS) {
|
||||
@@ -130,7 +140,9 @@ go_through_transaction_ast(
|
||||
break;
|
||||
|
||||
case STRING8_TYPE:
|
||||
if (cur_pass == BUILD_TRANSACTION) GDEBUG("string8");
|
||||
if (cur_pass == BUILD_TRANSACTION) {
|
||||
GDEBUG("string8 %s", (char*)v->value);
|
||||
}
|
||||
gbinder_writer_append_string8(&app->writer, v->value);
|
||||
/* offset not incremented since it only makes sense for hidl */
|
||||
break;
|
||||
@@ -579,7 +591,7 @@ app_run(
|
||||
App* app)
|
||||
{
|
||||
const AppOptions* opt = app->opt;
|
||||
char* iface = opt->iface ? g_strdup(opt->iface) : NULL;
|
||||
char* iface;
|
||||
int status = 0;
|
||||
int rargc = 1;
|
||||
char* service = opt->argv[rargc++];
|
||||
@@ -598,7 +610,6 @@ app_run(
|
||||
service, &status);
|
||||
if (!obj) {
|
||||
GERR("No such service: %s", service);
|
||||
g_free(iface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -764,14 +775,34 @@ app_init(
|
||||
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
char* help;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Remove the "--" argument. If any of our arguments is a negative
|
||||
* number, the user will have to add the "--" flag to stop the parser.
|
||||
* But "--" is still passed to us and we have to ignore it.
|
||||
*/
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--")) {
|
||||
if (i < (argc - 1)) {
|
||||
memmove(argv + i, argv + (i + 1),
|
||||
sizeof(char*) * (argc - i - 1));
|
||||
}
|
||||
i--;
|
||||
argc--;
|
||||
|
||||
/*
|
||||
* There's no need to have more than one "--", but let's
|
||||
* remove any number of those.
|
||||
*/
|
||||
}
|
||||
}
|
||||
if (argc > 2) {
|
||||
opt->argc = argc;
|
||||
opt->argv = argv;
|
||||
ok = TRUE;
|
||||
} else {
|
||||
help = g_option_context_get_help(options, TRUE, NULL);
|
||||
char* help = g_option_context_get_help(options, TRUE, NULL);
|
||||
fprintf(stderr, "%s", help);
|
||||
g_free(help);
|
||||
}
|
||||
@@ -800,7 +831,6 @@ int main(int argc, char* argv[])
|
||||
GERR("servicemanager seems to be missing");
|
||||
}
|
||||
}
|
||||
g_free(opt.iface);
|
||||
g_free(opt.dev);
|
||||
return app.ret;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
typedef struct app_options {
|
||||
char* dev;
|
||||
char* iface;
|
||||
gboolean oneway;
|
||||
gboolean aidl;
|
||||
gint transaction;
|
||||
|
||||
@@ -55,11 +55,11 @@ char* handle_str8(char* text) {
|
||||
"}" { return('}'); }
|
||||
"[" { return('['); }
|
||||
"]" { return(']'); }
|
||||
{D}*{INT8_SUFFIX} { cmdlinelval.int8_value = atoi(yytext); return(INT8_VALUE); }
|
||||
{D}*{INT64_SUFFIX} { cmdlinelval.int64_value = atol(yytext); return(INT64_VALUE); }
|
||||
{D}* { cmdlinelval.int32_value = atoi(yytext); return(INT32_VALUE); }
|
||||
{D}+"."{D}*{INT64_SUFFIX} { cmdlinelval.double_value = atof(yytext); return(DOUBLE_VALUE); }
|
||||
{D}+"."{D}* { cmdlinelval.float_value = atof(yytext); return(FLOAT_VALUE); }
|
||||
-?{D}+{INT8_SUFFIX} { cmdlinelval.int8_value = atoi(yytext); return(INT8_VALUE); }
|
||||
-?{D}+{INT64_SUFFIX} { cmdlinelval.int64_value = atol(yytext); return(INT64_VALUE); }
|
||||
-?{D}+ { cmdlinelval.int32_value = atoi(yytext); return(INT32_VALUE); }
|
||||
-?{D}+"."{D}*{INT64_SUFFIX} { cmdlinelval.double_value = atof(yytext); return(DOUBLE_VALUE); }
|
||||
-?{D}+"."{D}* { cmdlinelval.float_value = atof(yytext); return(FLOAT_VALUE); }
|
||||
"reply" { return(REPLY); }
|
||||
\".*\"{HSTRING_SUFFIX} { cmdlinelval.hstring_value = handle_str(yytext); return(HSTRING_VALUE); }
|
||||
\".*\"{UTF16_SUFFIX} { cmdlinelval.string16_value = handle_str(yytext); return(STRING16_VALUE); }
|
||||
|
||||
@@ -1,140 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Executable
|
||||
#
|
||||
|
||||
EXE = binder-client
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
include ../common/Makefile
|
||||
|
||||
@@ -1,140 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Executable
|
||||
#
|
||||
|
||||
EXE = binder-dump
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
include ../common/Makefile
|
||||
|
||||
@@ -171,6 +171,8 @@ app_init(
|
||||
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 [" DEV_DEFAULT "]", "DEVICE" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -187,7 +189,7 @@ app_init(
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
char* help;
|
||||
|
||||
opt->dev = g_strdup(DEV_DEFAULT);
|
||||
if (!opt->dev || !opt->dev[0]) opt->dev = g_strdup(DEV_DEFAULT);
|
||||
switch (argc) {
|
||||
case 2:
|
||||
opt->service = argv[1];
|
||||
|
||||
@@ -1,154 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Executable
|
||||
#
|
||||
|
||||
EXE = binder-list
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
|
||||
#
|
||||
# Install
|
||||
#
|
||||
|
||||
INSTALL = install
|
||||
|
||||
INSTALL_BIN_DIR = $(DESTDIR)/usr/bin
|
||||
|
||||
install: release $(INSTALL_BIN_DIR)
|
||||
$(INSTALL) -m 755 $(RELEASE_EXE) $(INSTALL_BIN_DIR)
|
||||
|
||||
$(INSTALL_BIN_DIR):
|
||||
$(INSTALL) -d $@
|
||||
include ../common/Makefile
|
||||
|
||||
@@ -1,154 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Executable
|
||||
#
|
||||
|
||||
EXE = binder-ping
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
|
||||
#
|
||||
# Install
|
||||
#
|
||||
|
||||
INSTALL = install
|
||||
|
||||
INSTALL_BIN_DIR = $(DESTDIR)/usr/bin
|
||||
|
||||
install: release $(INSTALL_BIN_DIR)
|
||||
$(INSTALL) -m 755 $(RELEASE_EXE) $(INSTALL_BIN_DIR)
|
||||
|
||||
$(INSTALL_BIN_DIR):
|
||||
$(INSTALL) -d $@
|
||||
include ../common/Makefile
|
||||
|
||||
@@ -1,140 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Executable
|
||||
#
|
||||
|
||||
EXE = binder-service
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
include ../common/Makefile
|
||||
|
||||
152
test/common/Makefile
Normal file
152
test/common/Makefile
Normal file
@@ -0,0 +1,152 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release install clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Executable must be defined
|
||||
#
|
||||
|
||||
ifndef EXE
|
||||
${error EXE not defined}
|
||||
endif
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC ?= $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
CFLAGS += -fPIC $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS += -pie $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
KEEP_SYMBOLS ?= 0
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
|
||||
#
|
||||
# Install
|
||||
#
|
||||
|
||||
INSTALL = install
|
||||
|
||||
INSTALL_BIN_DIR = $(DESTDIR)/usr/bin
|
||||
|
||||
install: release $(INSTALL_BIN_DIR)
|
||||
$(INSTALL) -m 755 $(RELEASE_EXE) $(INSTALL_BIN_DIR)
|
||||
|
||||
$(INSTALL_BIN_DIR):
|
||||
$(INSTALL) -d $@
|
||||
@@ -1,140 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: all debug release clean cleaner
|
||||
.PHONY: libgbinder-release libgbinder-debug
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Executable
|
||||
#
|
||||
|
||||
EXE = rild-card-status
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = $(EXE).c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
BUILD_DIR = build
|
||||
LIB_DIR = ../..
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall
|
||||
INCLUDES = -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: libgbinder-debug $(DEBUG_EXE)
|
||||
|
||||
release: libgbinder-release $(RELEASE_EXE)
|
||||
|
||||
clean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
cleaner: clean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||
ifeq ($(KEEP_SYMBOLS),0)
|
||||
strip $@
|
||||
endif
|
||||
|
||||
libgbinder-debug:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||
|
||||
libgbinder-release:
|
||||
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||
include ../common/Makefile
|
||||
|
||||
@@ -9,6 +9,7 @@ all:
|
||||
@$(MAKE) -C unit_config $*
|
||||
@$(MAKE) -C unit_driver $*
|
||||
@$(MAKE) -C unit_eventloop $*
|
||||
@$(MAKE) -C unit_fmq $*
|
||||
@$(MAKE) -C unit_ipc $*
|
||||
@$(MAKE) -C unit_local_object $*
|
||||
@$(MAKE) -C unit_local_reply $*
|
||||
@@ -23,6 +24,8 @@ all:
|
||||
@$(MAKE) -C unit_servicemanager $*
|
||||
@$(MAKE) -C unit_servicemanager_aidl $*
|
||||
@$(MAKE) -C unit_servicemanager_aidl2 $*
|
||||
@$(MAKE) -C unit_servicemanager_aidl3 $*
|
||||
@$(MAKE) -C unit_servicemanager_aidl4 $*
|
||||
@$(MAKE) -C unit_servicemanager_hidl $*
|
||||
@$(MAKE) -C unit_servicename $*
|
||||
@$(MAKE) -C unit_servicepoll $*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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,56 +35,82 @@
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
typedef struct test_binder TestBinder;
|
||||
#define B_TYPE_LARGE 0x85
|
||||
#define BINDER_TYPE_BINDER GBINDER_FOURCC('s', 'b', '*', B_TYPE_LARGE)
|
||||
#define BINDER_TYPE_HANDLE GBINDER_FOURCC('s', 'h', '*', B_TYPE_LARGE)
|
||||
#define BINDER_TYPE_PTR GBINDER_FOURCC('p', 't', '*', B_TYPE_LARGE)
|
||||
|
||||
#define BUFFER_OBJECT_SIZE_32 (24)
|
||||
#define BUFFER_OBJECT_SIZE_64 (40)
|
||||
#define BINDER_OBJECT_SIZE_32 (16)
|
||||
#define BINDER_OBJECT_SIZE_64 (24)
|
||||
|
||||
typedef enum test_br_thread {
|
||||
THIS_THREAD = -3,
|
||||
LOOPER_THREAD = -2,
|
||||
TX_THREAD = -1,
|
||||
ANY_THREAD = 0
|
||||
} TEST_BR_THREAD;
|
||||
|
||||
void
|
||||
test_binder_br_noop(
|
||||
int fd);
|
||||
int fd,
|
||||
TEST_BR_THREAD dest);
|
||||
|
||||
void
|
||||
test_binder_br_increfs(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
void* ptr);
|
||||
|
||||
void
|
||||
test_binder_br_acquire(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
void* ptr);
|
||||
|
||||
void
|
||||
test_binder_br_release(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
void* ptr);
|
||||
|
||||
void
|
||||
test_binder_br_decrefs(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
void* ptr);
|
||||
|
||||
void
|
||||
test_binder_br_transaction_complete(
|
||||
int fd);
|
||||
|
||||
void
|
||||
test_binder_br_transaction_complete_later(
|
||||
int fd);
|
||||
int fd,
|
||||
TEST_BR_THREAD dest);
|
||||
|
||||
void
|
||||
test_binder_br_dead_binder(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
guint handle);
|
||||
|
||||
void
|
||||
test_binder_br_dead_binder_obj(
|
||||
int fd,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
test_binder_br_dead_reply(
|
||||
int fd);
|
||||
int fd,
|
||||
TEST_BR_THREAD dest);
|
||||
|
||||
void
|
||||
test_binder_br_failed_reply(
|
||||
int fd);
|
||||
int fd,
|
||||
TEST_BR_THREAD dest);
|
||||
|
||||
void
|
||||
test_binder_br_transaction(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
void* target,
|
||||
guint32 code,
|
||||
const GByteArray* bytes);
|
||||
@@ -92,6 +118,7 @@ test_binder_br_transaction(
|
||||
void
|
||||
test_binder_br_reply(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* bytes);
|
||||
@@ -99,35 +126,12 @@ test_binder_br_reply(
|
||||
void
|
||||
test_binder_br_reply_status(
|
||||
int fd,
|
||||
TEST_BR_THREAD dest,
|
||||
gint32 status);
|
||||
|
||||
void
|
||||
test_binder_br_reply_later(
|
||||
int fd,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* bytes);
|
||||
|
||||
void
|
||||
test_binder_br_reply_status_later(
|
||||
int fd,
|
||||
gint32 status);
|
||||
|
||||
typedef enum test_looper {
|
||||
TEST_LOOPER_DISABLE,
|
||||
TEST_LOOPER_ENABLE,
|
||||
TEST_LOOPER_ENABLE_ONE
|
||||
} TEST_LOOPER;
|
||||
|
||||
void
|
||||
test_binder_set_looper_enabled(
|
||||
int fd,
|
||||
TEST_LOOPER value);
|
||||
|
||||
void
|
||||
test_binder_set_passthrough(
|
||||
int fd,
|
||||
gboolean passthrough);
|
||||
test_binder_ignore_dead_object(
|
||||
int fd);
|
||||
|
||||
int
|
||||
test_binder_handle(
|
||||
|
||||
@@ -80,6 +80,10 @@ test_run_in_context(
|
||||
/* Helper macros */
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
# define TEST_INT8_BYTES_4(v) \
|
||||
(guint8)(v), 0, 0, 0
|
||||
# define TEST_INT16_BYTES_4(v) \
|
||||
(guint8)(v), (guint8)((v) >> 8), 0, 0
|
||||
# define TEST_INT16_BYTES(v) \
|
||||
(guint8)(v), (guint8)((v) >> 8)
|
||||
# define TEST_INT32_BYTES(v) \
|
||||
@@ -91,6 +95,10 @@ test_run_in_context(
|
||||
(guint8)(((guint64)(v)) >> 32), (guint8)(((guint64)(v)) >> 40), \
|
||||
(guint8)(((guint64)(v)) >> 48), (guint8)(((guint64)(v)) >> 56)
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
# define TEST_INT8_BYTES_4(v) \
|
||||
0, 0, 0, (guint8)(v)
|
||||
# define TEST_INT16_BYTES_4(v) \
|
||||
0, 0, (guint8)((v) >> 8), (guint8)(v)
|
||||
# define TEST_INT16_BYTES(v) \
|
||||
(guint8)((v) >> 8), (guint8)(v)
|
||||
# define TEST_INT32_BYTES(v) \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -277,9 +277,10 @@ test_servicemanager_hidl_add(
|
||||
const char* sep = strrchr(instance, '/');
|
||||
|
||||
GDEBUG("Adding '%s'", instance);
|
||||
/* Transfer remote_obj reference to the hashtable */
|
||||
g_hash_table_replace(self->objects, g_strdup(instance), remote_obj);
|
||||
if (sep) {
|
||||
/* Alread know the interface */
|
||||
/* Already know the interface */
|
||||
char* iface = g_strndup(instance, sep - instance);
|
||||
|
||||
test_servicemanager_hidl_notify_all(self, iface, sep + 1, FALSE);
|
||||
@@ -350,7 +351,7 @@ test_servicemanager_hidl_register_for_notifications(
|
||||
iface = gbinder_reader_read_hidl_string_c(&reader);
|
||||
instance = gbinder_reader_read_hidl_string_c(&reader);
|
||||
watcher = gbinder_reader_read_object(&reader);
|
||||
|
||||
|
||||
if (watcher) {
|
||||
GBinderClient* wc = gbinder_client_new(watcher, NOTIFICATION_IFACE);
|
||||
GHashTableIter it;
|
||||
@@ -481,6 +482,38 @@ test_servicemanager_hidl_lookup(
|
||||
return object;
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_servicemanager_hidl_remove(
|
||||
TestServiceManagerHidl* self,
|
||||
const char* fqname)
|
||||
{
|
||||
gboolean removed = FALSE;
|
||||
|
||||
if (self) {
|
||||
GBinderRemoteObject* obj;
|
||||
|
||||
/* Lock */
|
||||
g_mutex_lock(&self->mutex);
|
||||
obj = g_hash_table_lookup(self->objects, fqname);
|
||||
if (obj) {
|
||||
GHashTableIter it;
|
||||
gpointer key, value;
|
||||
|
||||
g_hash_table_iter_init(&it, self->objects);
|
||||
while (g_hash_table_iter_next(&it, &key, &value)) {
|
||||
if (value == obj) {
|
||||
GDEBUG("Removed name '%s' => %p", (char*) key, value);
|
||||
g_hash_table_iter_remove(&it);
|
||||
removed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_mutex_unlock(&self->mutex);
|
||||
/* Unlock */
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -58,6 +58,11 @@ test_servicemanager_hidl_lookup(
|
||||
TestServiceManagerHidl* self,
|
||||
const char* name);
|
||||
|
||||
gboolean
|
||||
test_servicemanager_hidl_remove(
|
||||
TestServiceManagerHidl* self,
|
||||
const char* fqname);
|
||||
|
||||
#endif /* TEST_SERVICEMANAGER_HIDL_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -11,6 +11,7 @@ unit_client \
|
||||
unit_config \
|
||||
unit_driver \
|
||||
unit_eventloop \
|
||||
unit_fmq \
|
||||
unit_ipc \
|
||||
unit_local_object \
|
||||
unit_local_reply \
|
||||
@@ -25,6 +26,8 @@ unit_remote_request \
|
||||
unit_servicemanager \
|
||||
unit_servicemanager_aidl \
|
||||
unit_servicemanager_aidl2 \
|
||||
unit_servicemanager_aidl3 \
|
||||
unit_servicemanager_aidl4 \
|
||||
unit_servicemanager_hidl \
|
||||
unit_servicename \
|
||||
unit_servicepoll \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -52,9 +52,7 @@
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define SRC_DEV "/dev/srcbinder"
|
||||
#define SRC_PRIV_DEV SRC_DEV "-private"
|
||||
#define DEST_DEV "/dev/dstbinder"
|
||||
#define DEST_PRIV_DEV DEST_DEV "-private"
|
||||
#define TEST_IFACE "gbinder@1.0::ITest"
|
||||
|
||||
#define TX_CODE GBINDER_FIRST_CALL_TRANSACTION
|
||||
@@ -74,75 +72,6 @@ typedef struct test_config {
|
||||
char* file;
|
||||
} TestConfig;
|
||||
|
||||
/*==========================================================================*
|
||||
* Test object (registered with two GBinderIpc's)
|
||||
*==========================================================================*/
|
||||
|
||||
typedef GBinderLocalObjectClass TestLocalObjectClass;
|
||||
typedef struct test_local_object {
|
||||
GBinderLocalObject parent;
|
||||
GBinderIpc* ipc2;
|
||||
} TestLocalObject;
|
||||
G_DEFINE_TYPE(TestLocalObject, test_local_object, GBINDER_TYPE_LOCAL_OBJECT)
|
||||
#define TEST_TYPE_LOCAL_OBJECT test_local_object_get_type()
|
||||
#define TEST_LOCAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
TEST_TYPE_LOCAL_OBJECT, TestLocalObject))
|
||||
|
||||
TestLocalObject*
|
||||
test_local_object_new(
|
||||
GBinderIpc* ipc,
|
||||
GBinderIpc* ipc2,
|
||||
const char* const* ifaces,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
{
|
||||
TestLocalObject* self = TEST_LOCAL_OBJECT
|
||||
(gbinder_local_object_new_with_type(TEST_TYPE_LOCAL_OBJECT,
|
||||
ipc, ifaces, txproc, user_data));
|
||||
|
||||
self->ipc2 = gbinder_ipc_ref(ipc2);
|
||||
gbinder_ipc_register_local_object(ipc2, &self->parent);
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_local_object_dispose(
|
||||
GObject* object)
|
||||
{
|
||||
TestLocalObject* self = TEST_LOCAL_OBJECT(object);
|
||||
|
||||
gbinder_ipc_local_object_disposed(self->ipc2, &self->parent);
|
||||
G_OBJECT_CLASS(test_local_object_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_local_object_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
gbinder_ipc_unref(TEST_LOCAL_OBJECT(object)->ipc2);
|
||||
G_OBJECT_CLASS(test_local_object_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_local_object_init(
|
||||
TestLocalObject* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_local_object_class_init(
|
||||
TestLocalObjectClass* klass)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = test_local_object_dispose;
|
||||
object_class->finalize = test_local_object_finalize;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
@@ -183,11 +112,10 @@ TestServiceManagerHidl*
|
||||
test_servicemanager_impl_new(
|
||||
const char* dev)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
TestServiceManagerHidl* sm = test_servicemanager_hidl_new(ipc);
|
||||
|
||||
test_binder_set_looper_enabled(fd, TRUE);
|
||||
test_binder_register_object(fd, GBINDER_LOCAL_OBJECT(sm),
|
||||
GBINDER_SERVICEMANAGER_HANDLE);
|
||||
gbinder_ipc_unref(ipc);
|
||||
@@ -338,18 +266,15 @@ test_basic_run(
|
||||
GBinderServiceManager* src;
|
||||
GBinderServiceManager* dest;
|
||||
GBinderIpc* src_ipc;
|
||||
GBinderIpc* src_priv_ipc;
|
||||
GBinderIpc* dest_ipc;
|
||||
GBinderIpc* dest_priv_ipc;
|
||||
GBinderBridge* bridge;
|
||||
TestLocalObject* obj;
|
||||
GBinderRemoteObject* br_src_obj;
|
||||
GBinderLocalObject* obj;
|
||||
GBinderRemoteObject* src_obj;
|
||||
GBinderLocalRequest* req;
|
||||
GBinderClient* src_client;
|
||||
const char* name = "test";
|
||||
const char* fqname = TEST_IFACE "/test";
|
||||
int src_fd, dest_fd, h, n = 0;
|
||||
int src_fd, dest_fd, n = 0;
|
||||
gulong id;
|
||||
|
||||
test_config_init(&config, NULL);
|
||||
@@ -357,22 +282,15 @@ test_basic_run(
|
||||
test.loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
/* obj (DEST) <=> bridge <=> (SRC) mirror */
|
||||
src_ipc = gbinder_ipc_new(SRC_DEV);
|
||||
src_priv_ipc = gbinder_ipc_new(SRC_PRIV_DEV);
|
||||
dest_ipc = gbinder_ipc_new(DEST_DEV);
|
||||
dest_priv_ipc = gbinder_ipc_new(DEST_PRIV_DEV);
|
||||
test.src_impl = test_servicemanager_impl_new(SRC_PRIV_DEV);
|
||||
dest_impl = test_servicemanager_impl_new(DEST_PRIV_DEV);
|
||||
src_ipc = gbinder_ipc_new(SRC_DEV, NULL);
|
||||
dest_ipc = gbinder_ipc_new(DEST_DEV, NULL);
|
||||
test.src_impl = test_servicemanager_impl_new(SRC_DEV);
|
||||
dest_impl = test_servicemanager_impl_new(DEST_DEV);
|
||||
src_fd = gbinder_driver_fd(src_ipc->driver);
|
||||
dest_fd = gbinder_driver_fd(dest_ipc->driver);
|
||||
obj = test_local_object_new(dest_ipc, dest_priv_ipc, TEST_IFACES,
|
||||
test_basic_cb, &n);
|
||||
obj = gbinder_local_object_new(dest_ipc, TEST_IFACES, test_basic_cb, &n);
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_set_passthrough(src_fd, TRUE);
|
||||
test_binder_set_passthrough(dest_fd, TRUE);
|
||||
test_binder_set_looper_enabled(src_fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_set_looper_enabled(dest_fd, TEST_LOOPER_ENABLE);
|
||||
src = gbinder_servicemanager_new(SRC_DEV);
|
||||
dest = gbinder_servicemanager_new(DEST_DEV);
|
||||
|
||||
@@ -387,7 +305,7 @@ test_basic_run(
|
||||
|
||||
/* Register the object and wait for completion */
|
||||
GDEBUG("Registering object '%s' => %p", name, obj);
|
||||
g_assert(gbinder_servicemanager_add_service(dest, name, &obj->parent,
|
||||
g_assert(gbinder_servicemanager_add_service(dest, name, obj,
|
||||
test_basic_add_cb, &test));
|
||||
|
||||
/* This loop quits after the name is added and notification is received */
|
||||
@@ -398,25 +316,12 @@ test_basic_run(
|
||||
gbinder_servicemanager_remove_handler(src, id);
|
||||
|
||||
/* Get a remote reference to the object created by the bridge */
|
||||
br_src_obj = gbinder_servicemanager_get_service_sync(src, fqname, NULL);
|
||||
g_assert(gbinder_remote_object_ref(br_src_obj)); /* autoreleased */
|
||||
g_assert(!br_src_obj->dead);
|
||||
|
||||
/*
|
||||
* This is a trick specific to test_binder simulation. We need to
|
||||
* associate src_obj with the other side of the socket, so that the
|
||||
* call goes like this:
|
||||
*
|
||||
* src_obj (src_priv) => (src) bridge (dest) => (dest_priv) => obj
|
||||
*
|
||||
* Note that the original src_obj gets autoreleased and doesn't need
|
||||
* to be explicitly unreferenced.
|
||||
*/
|
||||
src_obj = gbinder_remote_object_new(src_priv_ipc,
|
||||
br_src_obj->handle, REMOTE_OBJECT_CREATE_ALIVE);
|
||||
src_obj = gbinder_servicemanager_get_service_sync(src, fqname, NULL);
|
||||
g_assert(!src_obj->dead);
|
||||
|
||||
/* Make a call */
|
||||
GDEBUG("Submitting a call");
|
||||
/* src_client will hold a reference to src_obj */
|
||||
src_client = gbinder_client_new(src_obj, TEST_IFACE);
|
||||
req = gbinder_client_new_request(src_client);
|
||||
gbinder_local_request_append_int32(req, TX_PARAM);
|
||||
@@ -427,40 +332,38 @@ test_basic_run(
|
||||
/* Wait for completion */
|
||||
test_run(&test_opt, test.loop);
|
||||
|
||||
/* Kill the destination object and wait for auto-created object to die */
|
||||
g_assert(!br_src_obj->dead);
|
||||
id = gbinder_remote_object_add_death_handler(br_src_obj, test_basic_death,
|
||||
/* Kill the objects and wait for one of them to die */
|
||||
g_assert(!src_obj->dead);
|
||||
id = gbinder_remote_object_add_death_handler(src_obj, test_basic_death,
|
||||
test.loop);
|
||||
h = test_binder_handle(dest_fd, &obj->parent);
|
||||
g_assert_cmpint(h, > ,0); /* Zero is servicemanager */
|
||||
|
||||
GDEBUG("Killing destination object, handle %d", h);
|
||||
gbinder_local_object_drop(&obj->parent);
|
||||
test_binder_br_dead_binder(dest_fd, h);
|
||||
g_assert(test_servicemanager_hidl_remove(dest_impl, fqname));
|
||||
GDEBUG("Killing destination objects");
|
||||
/*
|
||||
* Need these BR_DEAD_BINDER because both servicemanagers and the
|
||||
* bridge live inside the same process and reference the same objects.
|
||||
* BR_DEAD_BINDER forces the bridge (proxy) to drop its reference.
|
||||
*/
|
||||
test_binder_br_dead_binder_obj(dest_fd, obj);
|
||||
test_binder_br_dead_binder(src_fd, ANY_THREAD, src_obj->handle);
|
||||
|
||||
/* Wait for the auto-created object to die */
|
||||
test_run(&test_opt, test.loop);
|
||||
g_assert(br_src_obj->dead);
|
||||
gbinder_remote_object_remove_handler(br_src_obj, id);
|
||||
g_assert(src_obj->dead);
|
||||
gbinder_remote_object_remove_handler(src_obj, id);
|
||||
|
||||
GDEBUG("Done");
|
||||
|
||||
gbinder_local_object_drop(obj);
|
||||
gbinder_bridge_free(bridge);
|
||||
gbinder_remote_object_unref(src_obj);
|
||||
gbinder_remote_object_unref(br_src_obj);
|
||||
test_servicemanager_hidl_free(test.src_impl);
|
||||
test_servicemanager_hidl_free(dest_impl);
|
||||
gbinder_servicemanager_unref(src);
|
||||
gbinder_servicemanager_unref(dest);
|
||||
gbinder_client_unref(src_client);
|
||||
test_binder_unregister_objects(src_fd);
|
||||
test_binder_unregister_objects(dest_fd);
|
||||
gbinder_ipc_unref(src_ipc);
|
||||
gbinder_ipc_unref(src_priv_ipc);
|
||||
gbinder_ipc_unref(dest_ipc);
|
||||
gbinder_ipc_unref(dest_priv_ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, test.loop);
|
||||
test_config_deinit(&config);
|
||||
g_main_loop_unref(test.loop);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_remote_reply.h"
|
||||
#include "gbinder_writer.h"
|
||||
|
||||
#include <gutil_log.h>
|
||||
|
||||
@@ -54,7 +55,7 @@ test_client_new(
|
||||
guint h,
|
||||
const char* iface)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, h, TRUE);
|
||||
GBinderClient* client = gbinder_client_new(obj, iface);
|
||||
@@ -79,6 +80,7 @@ test_null(
|
||||
g_assert(!gbinder_client_ref(NULL));
|
||||
g_assert(!gbinder_client_interface(NULL));
|
||||
g_assert(!gbinder_client_interface2(NULL, 0));
|
||||
g_assert(!gbinder_client_rpc_header(NULL, 0));
|
||||
gbinder_client_unref(NULL);
|
||||
g_assert(!gbinder_client_new_request(NULL));
|
||||
g_assert(!gbinder_client_new_request2(NULL, 0));
|
||||
@@ -97,7 +99,7 @@ void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, 0, TRUE);
|
||||
const char* iface = "foo";
|
||||
@@ -112,6 +114,7 @@ test_basic(
|
||||
gbinder_client_unref(client);
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -123,7 +126,7 @@ void
|
||||
test_interfaces(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, 0, TRUE);
|
||||
static const GBinderClientIfaceInfo ifaces[] = {
|
||||
@@ -131,6 +134,11 @@ test_interfaces(
|
||||
};
|
||||
GBinderClient* client = gbinder_client_new2(obj, ifaces,
|
||||
G_N_ELEMENTS(ifaces));
|
||||
GBinderWriter writer;
|
||||
GBinderLocalRequest* req;
|
||||
GBytes* rpc_header;
|
||||
gsize len;
|
||||
const void* hdr;
|
||||
|
||||
g_assert(client);
|
||||
g_assert_cmpstr(gbinder_client_interface(client), == ,"11");
|
||||
@@ -138,12 +146,25 @@ test_interfaces(
|
||||
g_assert_cmpstr(gbinder_client_interface2(client, 22), == ,"22");
|
||||
g_assert_cmpstr(gbinder_client_interface2(client, 33), == ,"33");
|
||||
g_assert(!gbinder_client_interface2(client, 34));
|
||||
g_assert(!gbinder_client_rpc_header(client, 34));
|
||||
g_assert(!gbinder_client_new_request2(client, 34));
|
||||
/* Those fail to allocate default request for out-of-range codes: */
|
||||
g_assert(!gbinder_client_transact_sync_reply(client, 34, NULL, NULL));
|
||||
g_assert_cmpint(gbinder_client_transact_sync_oneway(client, 34, NULL),
|
||||
== ,-EINVAL);
|
||||
g_assert(!gbinder_client_transact(client, 34, 0, NULL, NULL, NULL, NULL));
|
||||
|
||||
/* Check the RPC header */
|
||||
rpc_header = gbinder_client_rpc_header(client, 33);
|
||||
req = gbinder_client_new_request2(client, 33);
|
||||
g_assert(rpc_header);
|
||||
g_assert(req);
|
||||
gbinder_local_request_init_writer(req, &writer);
|
||||
hdr = gbinder_writer_get_data(&writer, &len);
|
||||
g_assert(hdr);
|
||||
g_assert_cmpuint(len, == ,g_bytes_get_size(rpc_header));
|
||||
g_assert(!memcmp(hdr, g_bytes_get_data(rpc_header, NULL), len));
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_client_unref(client);
|
||||
|
||||
/* Client with no interface info */
|
||||
@@ -155,6 +176,7 @@ test_interfaces(
|
||||
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -169,11 +191,12 @@ test_no_header(
|
||||
GBinderClient* client = test_client_new(0, NULL);
|
||||
int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
|
||||
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_ignore_dead_object(fd);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
g_assert(gbinder_client_transact_sync_oneway(client, 0, NULL) ==
|
||||
GBINDER_STATUS_OK);
|
||||
|
||||
gbinder_client_unref(client);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -200,10 +223,9 @@ test_dead(
|
||||
GBinderRemoteObject* obj = client->remote;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
const int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
|
||||
gbinder_remote_object_add_death_handler(obj, test_dead_done, loop);
|
||||
|
||||
test_binder_br_dead_binder(fd, handle);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
gbinder_remote_object_add_death_handler(obj, test_dead_done, loop);
|
||||
test_binder_br_dead_binder(fd, ANY_THREAD, handle);
|
||||
test_run(&test_opt, loop);
|
||||
g_assert(gbinder_remote_object_is_dead(obj));
|
||||
|
||||
@@ -212,7 +234,6 @@ test_dead(
|
||||
g_assert(!gbinder_client_transact(client, 0, 0, NULL, NULL, NULL, NULL));
|
||||
|
||||
gbinder_client_unref(client);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -231,17 +252,18 @@ test_sync_oneway(
|
||||
int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
|
||||
|
||||
g_assert(req);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
g_assert(gbinder_client_transact_sync_oneway(client, 0, req) ==
|
||||
GBINDER_STATUS_OK);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
/* Same but using the internal (empty) request */
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
g_assert(gbinder_client_transact_sync_oneway(client, 0, NULL) ==
|
||||
GBINDER_STATUS_OK);
|
||||
|
||||
gbinder_client_unref(client);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -257,7 +279,8 @@ test_sync_reply_tx(
|
||||
GBinderDriver* driver = gbinder_client_ipc(client)->driver;
|
||||
int fd = gbinder_driver_fd(driver);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
const GBinderRpcProtocol* protocol = gbinder_driver_protocol(driver);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io, protocol);
|
||||
GBinderRemoteReply* tx_reply;
|
||||
GBinderOutputData* data;
|
||||
const guint32 handle = 0;
|
||||
@@ -270,10 +293,11 @@ test_sync_reply_tx(
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply(fd, handle, code, data->bytes);
|
||||
test_binder_ignore_dead_object(fd);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, handle, code, data->bytes);
|
||||
|
||||
tx_reply = gbinder_client_transact_sync_reply(client, 0, req, &status);
|
||||
g_assert(tx_reply);
|
||||
@@ -302,6 +326,7 @@ test_sync_reply(
|
||||
test_sync_reply_tx(client, NULL);
|
||||
|
||||
gbinder_client_unref(client);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -360,7 +385,8 @@ test_reply_tx(
|
||||
GBinderDriver* driver = gbinder_client_ipc(client)->driver;
|
||||
int fd = gbinder_driver_fd(driver);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
const GBinderRpcProtocol* protocol = gbinder_driver_protocol(driver);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io, protocol);
|
||||
GBinderOutputData* data;
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
@@ -371,10 +397,11 @@ test_reply_tx(
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply(fd, handle, code, data->bytes);
|
||||
test_binder_ignore_dead_object(fd);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_reply(fd, TX_THREAD, handle, code, data->bytes);
|
||||
|
||||
id = gbinder_client_transact(client, 0, 0, req, done, destroy, loop);
|
||||
g_assert(id);
|
||||
@@ -402,6 +429,7 @@ test_reply(
|
||||
test_reply_tx(client, NULL, done, destroy);
|
||||
|
||||
gbinder_client_unref(client);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Jolla Ltd.
|
||||
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||
* 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:
|
||||
*
|
||||
@@ -230,6 +230,8 @@ test_dirs(
|
||||
char* file = g_build_filename(dir, "test.conf", NULL);
|
||||
char* file1 = g_build_filename(subdir, "a.conf", NULL);
|
||||
char* file2 = g_build_filename(subdir, "b.conf", NULL);
|
||||
char* file3 = g_build_filename(subdir, "c.conf", NULL);
|
||||
char* file4 = g_build_filename(subdir, "d.conf", NULL);
|
||||
char* random_file = g_build_filename(subdir, "foo", NULL);
|
||||
static const char garbage[] = "foo";
|
||||
static const char config[] =
|
||||
@@ -246,12 +248,24 @@ test_dirs(
|
||||
"/dev/binder = aidl2\n"
|
||||
"[ServiceManager]\n"
|
||||
"/dev/binder = aidl2\n";
|
||||
static const char config3[] =
|
||||
"[Protocol]\n"
|
||||
"/dev/binder3 = aidl3\n"
|
||||
"[ServiceManager]\n"
|
||||
"/dev/binder3 = aidl3\n";
|
||||
static const char config4[] =
|
||||
"[Protocol]\n"
|
||||
"/dev/binder4 = aidl3\n"
|
||||
"[ServiceManager]\n"
|
||||
"/dev/binder4 = aidl4\n";
|
||||
|
||||
g_assert_cmpint(mkdir(subdir, 0700), == ,0);
|
||||
g_assert_cmpint(mkdir(notafile, 0700), == ,0);
|
||||
g_assert(g_file_set_contents(file, config, -1, NULL));
|
||||
g_assert(g_file_set_contents(file1, config1, -1, NULL));
|
||||
g_assert(g_file_set_contents(file2, config2, -1, NULL));
|
||||
g_assert(g_file_set_contents(file3, config3, -1, NULL));
|
||||
g_assert(g_file_set_contents(file4, config4, -1, NULL));
|
||||
g_assert(g_file_set_contents(random_file, garbage, -1, NULL));
|
||||
|
||||
/* Reset the state */
|
||||
@@ -263,9 +277,13 @@ test_dirs(
|
||||
k = gbinder_config_get();
|
||||
g_assert(k);
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/hbinder",b), == ,"hidl");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/hwbinder",b), == ,"hidl");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
|
||||
|
||||
/* Remove the default file and try again */
|
||||
gbinder_config_exit();
|
||||
@@ -274,8 +292,12 @@ test_dirs(
|
||||
g_assert(k);
|
||||
g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/hwbinder",b), == ,"hidl");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
|
||||
|
||||
/* Damage one of the files and try again */
|
||||
gbinder_config_exit();
|
||||
@@ -285,7 +307,11 @@ test_dirs(
|
||||
g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
|
||||
g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
|
||||
|
||||
/* Disallow access to one of the files and try again */
|
||||
gbinder_config_exit();
|
||||
@@ -295,12 +321,28 @@ test_dirs(
|
||||
g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
|
||||
g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
|
||||
|
||||
/* Delete the remaining files and try again */
|
||||
/* Leave only one file (file4) in the subdirectory */
|
||||
gbinder_config_exit();
|
||||
g_assert_cmpint(remove(file1), == ,0);
|
||||
g_assert_cmpint(remove(file2), == ,0);
|
||||
g_assert_cmpint(remove(file3), == ,0);
|
||||
k = gbinder_config_get();
|
||||
g_assert(k);
|
||||
g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
|
||||
g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
|
||||
g_assert(!test_value(k,"Protocol","/dev/binder3",b));
|
||||
g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b),==,"aidl3");
|
||||
g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
|
||||
|
||||
/* Delete the remaining file and try again */
|
||||
gbinder_config_exit();
|
||||
g_assert_cmpint(remove(file4), == ,0);
|
||||
g_assert(!gbinder_config_get());
|
||||
|
||||
/* Undo all the damage */
|
||||
@@ -312,6 +354,8 @@ test_dirs(
|
||||
g_free(file);
|
||||
g_free(file1);
|
||||
g_free(file2);
|
||||
g_free(file3);
|
||||
g_free(file4);
|
||||
g_free(random_file);
|
||||
|
||||
remove(notafile);
|
||||
@@ -464,6 +508,34 @@ static const TestPresetsData test_presets_data [] = {
|
||||
"[ServiceManager]\n"
|
||||
"/dev/binder = aidl2\n"
|
||||
"/dev/vndbinder = aidl2\n"
|
||||
},{
|
||||
"30",
|
||||
|
||||
"[General]\n"
|
||||
"ApiLevel = 30",
|
||||
|
||||
"[General]\n"
|
||||
"ApiLevel = 30\n"
|
||||
"[Protocol]\n"
|
||||
"/dev/binder = aidl3\n"
|
||||
"/dev/vndbinder = aidl3\n"
|
||||
"[ServiceManager]\n"
|
||||
"/dev/binder = aidl3\n"
|
||||
"/dev/vndbinder = aidl3\n"
|
||||
},{
|
||||
"31",
|
||||
|
||||
"[General]\n"
|
||||
"ApiLevel = 31",
|
||||
|
||||
"[General]\n"
|
||||
"ApiLevel = 31\n"
|
||||
"[Protocol]\n"
|
||||
"/dev/binder = aidl3\n"
|
||||
"/dev/vndbinder = aidl3\n"
|
||||
"[ServiceManager]\n"
|
||||
"/dev/binder = aidl4\n"
|
||||
"/dev/vndbinder = aidl4\n"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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 "test_binder.h"
|
||||
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_handler.h"
|
||||
#include "gbinder_local_request_p.h"
|
||||
@@ -81,6 +82,7 @@ test_basic(
|
||||
|
||||
g_assert(!gbinder_handler_transact(NULL, NULL, NULL, 0, 0, NULL));
|
||||
g_assert(!gbinder_handler_can_loop(NULL));
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -97,11 +99,12 @@ test_noop(
|
||||
|
||||
g_assert(driver);
|
||||
g_assert(fd >= 0);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
g_assert(gbinder_driver_poll(driver, NULL) == POLLIN);
|
||||
g_assert(gbinder_driver_read(driver, NULL, NULL) == 0);
|
||||
|
||||
gbinder_driver_unref(driver);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -130,6 +133,7 @@ test_local_request(
|
||||
g_assert(!memcmp(data->bytes->data, rpc_header, sizeof(rpc_header)));
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_driver_unref(driver);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -140,12 +144,31 @@ test_local_request(
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const char* default_config_dir;
|
||||
const char* default_config_file;
|
||||
char* config_dir = g_dir_make_tmp("gbinder-test-driver-XXXXXX", NULL);
|
||||
char* config_file = g_build_filename(config_dir, "test.conf", NULL);
|
||||
int result;
|
||||
|
||||
/* Point gbinder_config_file to a non-existent file */
|
||||
default_config_dir = gbinder_config_dir;
|
||||
default_config_file = gbinder_config_file;
|
||||
gbinder_config_dir = config_dir;
|
||||
gbinder_config_file = config_file;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "basic", test_basic);
|
||||
g_test_add_func(TEST_PREFIX "noop", test_noop);
|
||||
g_test_add_func(TEST_PREFIX "local_request", test_local_request);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
result = g_test_run();
|
||||
|
||||
gbinder_config_dir = default_config_dir;
|
||||
gbinder_config_file = default_config_file;
|
||||
remove(config_dir);
|
||||
g_free(config_dir);
|
||||
g_free(config_file);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
5
unit/unit_fmq/Makefile
Normal file
5
unit/unit_fmq/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_fmq
|
||||
|
||||
include ../common/Makefile
|
||||
597
unit/unit_fmq/unit_fmq.c
Normal file
597
unit/unit_fmq/unit_fmq.c
Normal file
@@ -0,0 +1,597 @@
|
||||
/*
|
||||
* Copyright (C) 2018-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 "test_common.h"
|
||||
|
||||
#include "gbinder_fmq_p.h"
|
||||
|
||||
#if GBINDER_FMQ_SUPPORTED
|
||||
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
typedef struct test_fmq_data {
|
||||
const char* name;
|
||||
gsize item_size;
|
||||
gsize max_num_items;
|
||||
gint type;
|
||||
gint flags;
|
||||
gint fd;
|
||||
gsize buffer_size;
|
||||
} TestFmqData;
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static const TestFmqData test_fmq_tests_null[] = {
|
||||
{ "wrong_size", 0, 8,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE, 0, -1, 0 },
|
||||
{ "wrong_count", sizeof(guint32), 0,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE, 0, -1, 0 },
|
||||
{ "wrong_buffer_size", sizeof(guint32), 8,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE, 0, 1, 0 },
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestFmqData* test = test_data;
|
||||
GBinderFmq* fmq = gbinder_fmq_new(test->item_size, test->max_num_items,
|
||||
test->type, test->flags, test->fd, test->buffer_size);
|
||||
|
||||
g_assert(!fmq);
|
||||
g_assert(!gbinder_fmq_ref(fmq));
|
||||
gbinder_fmq_unref(fmq);
|
||||
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == 0);
|
||||
g_assert(gbinder_fmq_available_to_write(fmq) == 0);
|
||||
g_assert(gbinder_fmq_available_to_read_contiguous(fmq) == 0);
|
||||
g_assert(gbinder_fmq_available_to_write_contiguous(fmq) == 0);
|
||||
|
||||
g_assert(!gbinder_fmq_begin_read(fmq, 1));
|
||||
g_assert(!gbinder_fmq_begin_read((GBinderFmq*)0x1, 0));
|
||||
g_assert(!gbinder_fmq_begin_write(fmq, 1));
|
||||
g_assert(!gbinder_fmq_begin_write((GBinderFmq*)0x1, 0));
|
||||
|
||||
g_assert(!gbinder_fmq_read(fmq, (void*)0x1, 1));
|
||||
g_assert(!gbinder_fmq_read((GBinderFmq*)0x1, NULL, 1));
|
||||
g_assert(!gbinder_fmq_read((GBinderFmq*)0x1, (void*)0x1, 0));
|
||||
|
||||
g_assert(!gbinder_fmq_write(fmq, (const void*)0x1, 1));
|
||||
g_assert(!gbinder_fmq_write((GBinderFmq*)0x1, NULL, 1));
|
||||
g_assert(!gbinder_fmq_write((GBinderFmq*)0x1, (const void*)0x1, 0));
|
||||
|
||||
g_assert(gbinder_fmq_wait_timeout(fmq, 0, (guint32*)0x1, 0) == -EINVAL);
|
||||
g_assert(gbinder_fmq_wait_timeout((GBinderFmq*)0x1, 0, NULL, 0) == -EINVAL);
|
||||
g_assert(gbinder_fmq_wait(fmq, 0, (guint32*)0x1) == -EINVAL);
|
||||
g_assert(gbinder_fmq_wait((GBinderFmq*)0x1, 0, NULL) == -EINVAL);
|
||||
g_assert(gbinder_fmq_wake(fmq, 0) == -EINVAL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* read/write guint8
|
||||
*==========================================================================*/
|
||||
|
||||
static const TestFmqData test_fmq_tests_read_write_guint8[] = {
|
||||
{ "event_flag", sizeof(guint8), 8, GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG, -1, 0 },
|
||||
{ "no_event_flag", sizeof(guint8), 8, GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
0, -1, 0 },
|
||||
{ "no_reset", sizeof(guint8), 8, GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG |
|
||||
GBINDER_FMQ_FLAG_NO_RESET_POINTERS, -1, 0 },
|
||||
{ "unsync", sizeof(guint8), 8, GBINDER_FMQ_TYPE_UNSYNC_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG, -1, 0 },
|
||||
{ "unsync_no_reset", sizeof(guint8), 8, GBINDER_FMQ_TYPE_UNSYNC_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG |
|
||||
GBINDER_FMQ_FLAG_NO_RESET_POINTERS, -1, 0 },
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
test_read_write_guint8(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestFmqData* test = test_data;
|
||||
guint i;
|
||||
guint8 in_data[test->max_num_items];
|
||||
guint8 out_data[test->max_num_items];
|
||||
GBinderFmq* fmq = gbinder_fmq_new(test->item_size, test->max_num_items,
|
||||
test->type, test->flags, test->fd, test->buffer_size);
|
||||
|
||||
g_assert(fmq);
|
||||
|
||||
/* Intiailize input data with random numbers */
|
||||
for (i = 0; i < test->max_num_items; ++i) {
|
||||
in_data[i] = g_random_int() % G_MAXUINT8;
|
||||
}
|
||||
memset(out_data, 0, test->max_num_items);
|
||||
|
||||
/* Write data one value at a time */
|
||||
for (i = 0; i < test->max_num_items; ++i) {
|
||||
g_assert(gbinder_fmq_write(fmq, &in_data[i], 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == i + 1);
|
||||
}
|
||||
|
||||
/* Try to write one item to full buffer
|
||||
* only sync write fails if buffer is full */
|
||||
if (test->type == GBINDER_FMQ_TYPE_SYNC_READ_WRITE) {
|
||||
g_assert(!gbinder_fmq_write(fmq, &in_data[0], 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == test->max_num_items);
|
||||
}
|
||||
|
||||
/* Read data one value at a time */
|
||||
for (i = 0; i < test->max_num_items; ++i) {
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, 1));
|
||||
g_assert(out_data[0] == in_data[i]);
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) ==
|
||||
test->max_num_items - i - 1);
|
||||
}
|
||||
/* Try to read when there is no data */
|
||||
g_assert(!gbinder_fmq_read(fmq, &out_data, 1));
|
||||
|
||||
memset(out_data, 0, test->max_num_items);
|
||||
|
||||
/* Fill whole buffer with data */
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, test->max_num_items));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == test->max_num_items);
|
||||
/* Read whole buffer */
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, test->max_num_items));
|
||||
g_assert(!memcmp(in_data, out_data, test->max_num_items * test->item_size));
|
||||
|
||||
memset(out_data, 0, test->max_num_items);
|
||||
|
||||
/* Try to write too many items */
|
||||
g_assert(!gbinder_fmq_write(fmq, in_data, test->max_num_items + 1));
|
||||
|
||||
/* Overwrite unsync queue */
|
||||
if (test->type == GBINDER_FMQ_TYPE_UNSYNC_WRITE) {
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, test->max_num_items));
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, 1));
|
||||
/* Writing too much data to unsync queue causes read pointer to reset
|
||||
* on next read */
|
||||
g_assert(!gbinder_fmq_read(fmq, &out_data, 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == 0);
|
||||
}
|
||||
|
||||
gbinder_fmq_unref(fmq);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* read/write gint64
|
||||
*==========================================================================*/
|
||||
|
||||
static const TestFmqData test_fmq_tests_read_write_gint64[] = {
|
||||
{ "event_flag", sizeof(gint64), 8, GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG, -1, 0 },
|
||||
{ "no_event_flag", sizeof(gint64), 8, GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
0, -1, 0 },
|
||||
{ "no_reset", sizeof(gint64), 8, GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG |
|
||||
GBINDER_FMQ_FLAG_NO_RESET_POINTERS, -1, 0 },
|
||||
{ "unsync", sizeof(gint64), 8, GBINDER_FMQ_TYPE_UNSYNC_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG, -1, 0 },
|
||||
{ "unsync_no_reset", sizeof(guint64), 8, GBINDER_FMQ_TYPE_UNSYNC_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG |
|
||||
GBINDER_FMQ_FLAG_NO_RESET_POINTERS, -1, 0 },
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
test_read_write_gint64(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestFmqData* test = test_data;
|
||||
guint i;
|
||||
gint64 in_data[test->max_num_items];
|
||||
gint64 out_data[test->max_num_items];
|
||||
GBinderFmq* fmq = gbinder_fmq_new(test->item_size, test->max_num_items,
|
||||
test->type, test->flags, test->fd, test->buffer_size);
|
||||
|
||||
g_assert(fmq);
|
||||
|
||||
/* Intiailize input data with random numbers */
|
||||
for (i = 0; i < test->max_num_items; ++i) {
|
||||
in_data[i] = g_random_int();
|
||||
}
|
||||
memset(out_data, 0, test->max_num_items);
|
||||
|
||||
/* Write data one value at a time */
|
||||
for (i = 0; i < test->max_num_items; ++i) {
|
||||
g_assert(gbinder_fmq_write(fmq, &in_data[i], 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == i + 1);
|
||||
}
|
||||
|
||||
/* Try to write one item to full buffer
|
||||
* only sync write fails if buffer is full */
|
||||
if (test->type == GBINDER_FMQ_TYPE_SYNC_READ_WRITE) {
|
||||
g_assert(!gbinder_fmq_write(fmq, &in_data[0], 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == test->max_num_items);
|
||||
}
|
||||
|
||||
/* Read data one value at a time */
|
||||
for (i = 0; i < test->max_num_items; ++i) {
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, 1));
|
||||
g_assert(out_data[0] == in_data[i]);
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) ==
|
||||
test->max_num_items - i - 1);
|
||||
}
|
||||
/* Try to read when there is no data */
|
||||
g_assert(!gbinder_fmq_read(fmq, &out_data, 1));
|
||||
|
||||
memset(out_data, 0, test->max_num_items);
|
||||
|
||||
/* Fill whole buffer with data */
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, test->max_num_items));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == test->max_num_items);
|
||||
/* Read whole buffer */
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, test->max_num_items));
|
||||
g_assert(!memcmp(in_data, out_data, test->max_num_items * test->item_size));
|
||||
|
||||
memset(out_data, 0, test->max_num_items);
|
||||
|
||||
/* Try to write too many items */
|
||||
g_assert(!gbinder_fmq_write(fmq, in_data, test->max_num_items + 1));
|
||||
|
||||
/* Overwrite unsync queue */
|
||||
if (test->type == GBINDER_FMQ_TYPE_UNSYNC_WRITE) {
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, test->max_num_items));
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, 1));
|
||||
/* Writing too much data to unsync queue causes read pointer to reset
|
||||
* on next read */
|
||||
g_assert(!gbinder_fmq_read(fmq, &out_data, 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == 0);
|
||||
}
|
||||
|
||||
gbinder_fmq_unref(fmq);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* read/write counters
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_read_write_counters(
|
||||
void)
|
||||
{
|
||||
gint max_num_items = 8;
|
||||
gint write_count = 6;
|
||||
gint64 in_data[max_num_items];
|
||||
gint64 out_data[max_num_items];
|
||||
guint i;
|
||||
GBinderFmq* fmq = gbinder_fmq_new(sizeof(gint64), max_num_items,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG, -1, 0);
|
||||
|
||||
g_assert(fmq);
|
||||
|
||||
/* Intiailize input data with random numbers */
|
||||
for (i = 0; i < max_num_items; ++i) {
|
||||
in_data[i] = g_random_int();
|
||||
}
|
||||
memset(out_data, 0, max_num_items);
|
||||
|
||||
/* Write data one value at a time */
|
||||
for (i = 0; i < write_count; ++i) {
|
||||
g_assert(gbinder_fmq_write(fmq, &in_data[i], 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == i + 1);
|
||||
g_assert(gbinder_fmq_available_to_write(fmq) ==
|
||||
max_num_items - i - 1);
|
||||
}
|
||||
|
||||
/* Read data one value at a time */
|
||||
for (i = 0; i < 2; ++i) {
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, 1));
|
||||
g_assert(out_data[0] == in_data[i]);
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) ==
|
||||
write_count - i - 1);
|
||||
g_assert(gbinder_fmq_available_to_write(fmq) ==
|
||||
max_num_items - write_count + i + 1);
|
||||
g_assert(gbinder_fmq_available_to_write_contiguous(fmq) ==
|
||||
max_num_items - write_count);
|
||||
}
|
||||
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, 2));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == 2);
|
||||
g_assert(gbinder_fmq_available_to_write(fmq) == 6);
|
||||
g_assert(gbinder_fmq_available_to_write_contiguous(fmq) == 2);
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, 4));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == 6);
|
||||
g_assert(gbinder_fmq_available_to_read_contiguous(fmq) == 4);
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, 6));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == 0);
|
||||
g_assert(gbinder_fmq_available_to_read_contiguous(fmq) == 0);
|
||||
g_assert(gbinder_fmq_write(fmq, in_data, 6));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == 6);
|
||||
g_assert(gbinder_fmq_available_to_read_contiguous(fmq) == 6);
|
||||
g_assert(gbinder_fmq_available_to_write(fmq) == 2);
|
||||
g_assert(gbinder_fmq_available_to_write_contiguous(fmq) == 2);
|
||||
|
||||
gbinder_fmq_unref(fmq);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* read/write external fd
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_read_write_external_fd(
|
||||
void)
|
||||
{
|
||||
gint max_num_items = 8;
|
||||
gint64 in_data[max_num_items];
|
||||
gint64 out_data[max_num_items];
|
||||
gsize item_size = sizeof(gint64);
|
||||
guint i;
|
||||
GBinderFmq* fmq;
|
||||
|
||||
/* Allocate shared memory */
|
||||
|
||||
int shmem_fd = syscall(__NR_memfd_create, "MessageQueue", MFD_CLOEXEC);
|
||||
|
||||
g_assert(shmem_fd >= 0);
|
||||
g_assert(ftruncate(shmem_fd, max_num_items * item_size) >= 0);
|
||||
|
||||
fmq = gbinder_fmq_new(item_size, max_num_items,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE, GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG,
|
||||
shmem_fd, max_num_items * item_size);
|
||||
|
||||
g_assert(fmq);
|
||||
|
||||
/* Intiailize input data with random numbers */
|
||||
for (i = 0; i < max_num_items; ++i) {
|
||||
in_data[i] = g_random_int();
|
||||
}
|
||||
memset(out_data, 0, max_num_items);
|
||||
|
||||
/* Write data one value at a time */
|
||||
for (i = 0; i < max_num_items; ++i) {
|
||||
g_assert(gbinder_fmq_write(fmq, &in_data[i], 1));
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == i + 1);
|
||||
}
|
||||
|
||||
/* Read data one value at a time */
|
||||
for (i = 0; i < max_num_items; ++i) {
|
||||
g_assert(gbinder_fmq_read(fmq, &out_data, 1));
|
||||
g_assert(out_data[0] == in_data[i]);
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == max_num_items - i - 1);
|
||||
}
|
||||
|
||||
gbinder_fmq_unref(fmq);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* ref/unref
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_ref(
|
||||
void)
|
||||
{
|
||||
GBinderFmq* fmq = gbinder_fmq_new(sizeof(gint64), 2,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG, -1, 0);
|
||||
|
||||
g_assert(fmq);
|
||||
g_assert(gbinder_fmq_ref(fmq) == fmq);
|
||||
gbinder_fmq_unref(fmq);
|
||||
gbinder_fmq_unref(fmq);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* wait/wake
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_wait_wake(
|
||||
void)
|
||||
{
|
||||
gint ms = 100;
|
||||
guint32 state = 0;
|
||||
int result = 0;
|
||||
|
||||
/* Queue with event flag */
|
||||
GBinderFmq* fmq = gbinder_fmq_new(sizeof(gint64), 2,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG, -1, 0);
|
||||
|
||||
g_assert(fmq);
|
||||
|
||||
/* Wait until timeout */
|
||||
g_assert_cmpint(gbinder_fmq_wait_timeout(fmq, 0x2, &state, ms), ==,
|
||||
-ETIMEDOUT);
|
||||
|
||||
/* Invalid bit mask */
|
||||
g_assert_cmpint(gbinder_fmq_wait_timeout(fmq, 0x0, &state, ms),==,-EINVAL);
|
||||
|
||||
/* Bit already set */
|
||||
result = gbinder_fmq_wake(fmq, 0x4);
|
||||
g_assert(result == 0 || result == -ENOSYS);
|
||||
/* Only run wake/wait tests if FUTEX_WAKE_BITSET is supported */
|
||||
if (result == 0) {
|
||||
g_assert_cmpint(gbinder_fmq_wait(fmq, 0x4, &state),==,0);
|
||||
g_assert_cmpuint(state,==,0x4);
|
||||
|
||||
/* Bit already set, wait with more generic bit mask */
|
||||
state = 0;
|
||||
g_assert_cmpint(gbinder_fmq_wake(fmq, 0x4),==,0);
|
||||
g_assert_cmpint(gbinder_fmq_wait(fmq, 0xf, &state),==,0);
|
||||
g_assert_cmpuint(state,==,0x4);
|
||||
|
||||
/* Bit already set, wait with different bit mask */
|
||||
state = 0;
|
||||
g_assert_cmpint(gbinder_fmq_wake(fmq, 0x4),==,0);
|
||||
g_assert_cmpint(gbinder_fmq_wait_timeout(fmq, 0x2, &state, ms), ==,
|
||||
-ETIMEDOUT);
|
||||
g_assert_cmpint(gbinder_fmq_try_wait(fmq, 0x2, &state), == ,
|
||||
-ETIMEDOUT);
|
||||
}
|
||||
|
||||
gbinder_fmq_unref(fmq);
|
||||
|
||||
/* Queue without event flag */
|
||||
fmq = gbinder_fmq_new(sizeof(gint64), 2, GBINDER_FMQ_TYPE_SYNC_READ_WRITE,
|
||||
0, -1, 0);
|
||||
g_assert(fmq);
|
||||
g_assert_cmpint(gbinder_fmq_wait_timeout(fmq, 0x2, &state, ms),==,-ENOSYS);
|
||||
g_assert_cmpint(gbinder_fmq_wake(fmq, 0x4),==,-ENOSYS);
|
||||
|
||||
gbinder_fmq_unref(fmq);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* zero copy
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_zero_copy(
|
||||
void)
|
||||
{
|
||||
gint max_num_items = 8;
|
||||
gint write_count = 2;
|
||||
gint64 in_data[max_num_items];
|
||||
gint64 out_data[max_num_items];
|
||||
gsize item_size = sizeof(gint64);
|
||||
guint i;
|
||||
GBinderFmq* fmq = gbinder_fmq_new(item_size, max_num_items,
|
||||
GBINDER_FMQ_TYPE_SYNC_READ_WRITE, GBINDER_FMQ_FLAG_CONFIGURE_EVENT_FLAG,
|
||||
-1, 0);
|
||||
const void *read_ptr;
|
||||
void *write_ptr;
|
||||
|
||||
g_assert(fmq);
|
||||
|
||||
/* Intiailize input data with random numbers */
|
||||
for (i = 0; i < max_num_items; ++i) {
|
||||
in_data[i] = g_random_int();
|
||||
}
|
||||
memset(out_data, 0, max_num_items);
|
||||
|
||||
/* external write */
|
||||
g_assert_nonnull((write_ptr = gbinder_fmq_begin_write(fmq, write_count)));
|
||||
memcpy(write_ptr, in_data, write_count * item_size);
|
||||
gbinder_fmq_end_write(fmq, write_count);
|
||||
|
||||
g_assert(gbinder_fmq_available_to_read(fmq) == write_count);
|
||||
g_assert(gbinder_fmq_available_to_write(fmq) ==
|
||||
(max_num_items - write_count));
|
||||
|
||||
/* external read */
|
||||
g_assert_nonnull((read_ptr = gbinder_fmq_begin_read(fmq, write_count)));
|
||||
memcpy(out_data, read_ptr, write_count * item_size);
|
||||
gbinder_fmq_end_read(fmq, write_count);
|
||||
|
||||
g_assert(!memcmp(in_data, out_data, write_count * item_size));
|
||||
|
||||
gbinder_fmq_unref(fmq);
|
||||
}
|
||||
|
||||
#endif /* GBINDER_FMQ_SUPPORTED */
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/fmq/"
|
||||
#define TEST_(t) TEST_PREFIX t
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#if GBINDER_FMQ_SUPPORTED
|
||||
guint i;
|
||||
int test_fd;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
test_init(&test_opt, argc, argv);
|
||||
gbinder_log.level = gutil_log_default.level;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(test_fmq_tests_null); i++) {
|
||||
const TestFmqData* test = test_fmq_tests_null + i;
|
||||
char* path = g_strconcat(TEST_PREFIX, test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_null);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
/* Some test environments don't know how handle this syscall */
|
||||
test_fd = syscall(__NR_memfd_create, "test", MFD_CLOEXEC);
|
||||
if (test_fd < 0 && errno == ENOSYS) {
|
||||
GINFO("Skipping tests that rely on memfd_create");
|
||||
} else {
|
||||
close(test_fd);
|
||||
for (i = 0; i < G_N_ELEMENTS(test_fmq_tests_read_write_guint8); i++) {
|
||||
const TestFmqData* test = test_fmq_tests_read_write_guint8 + i;
|
||||
char* path = g_strconcat(TEST_("guint8/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_read_write_guint8);
|
||||
g_free(path);
|
||||
}
|
||||
for (i = 0; i < G_N_ELEMENTS(test_fmq_tests_read_write_gint64); i++) {
|
||||
const TestFmqData* test = test_fmq_tests_read_write_gint64 + i;
|
||||
char* path = g_strconcat(TEST_("gint64/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_read_write_gint64);
|
||||
g_free(path);
|
||||
}
|
||||
g_test_add_func(TEST_("read_write_counters"), test_read_write_counters);
|
||||
g_test_add_func(TEST_("read_write_external_fd"),
|
||||
test_read_write_external_fd);
|
||||
g_test_add_func(TEST_("ref"), test_ref);
|
||||
g_test_add_func(TEST_("wait_wake"), test_wait_wake);
|
||||
g_test_add_func(TEST_("zero_copy"), test_zero_copy);
|
||||
}
|
||||
#else /* GBINDER_FMQ_SUPPORTED */
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
#endif
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -70,6 +70,24 @@ test_quit_when_destroyed(
|
||||
test_quit_later((GMainLoop*)loop);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
test_local_request_new(
|
||||
GBinderIpc* ipc)
|
||||
{
|
||||
return gbinder_local_request_new(gbinder_driver_io(ipc->driver),
|
||||
gbinder_driver_protocol(ipc->driver), NULL);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
test_local_reply_new(
|
||||
GBinderIpc* ipc)
|
||||
{
|
||||
return gbinder_local_reply_new(gbinder_driver_io(ipc->driver),
|
||||
gbinder_driver_protocol(ipc->driver));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
@@ -79,26 +97,25 @@ void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* null = NULL;
|
||||
int status = INT_MAX;
|
||||
|
||||
g_assert(!gbinder_ipc_ref(null));
|
||||
gbinder_ipc_unref(null);
|
||||
g_assert(!gbinder_ipc_sync_main.sync_reply(null, 0, 0, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_sync_main.sync_reply(null, 0, 0, NULL, &status));
|
||||
g_assert(!gbinder_ipc_ref(NULL));
|
||||
gbinder_ipc_unref(NULL);
|
||||
g_assert(!gbinder_ipc_sync_main.sync_reply(NULL, 0, 0, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_sync_main.sync_reply(NULL, 0, 0, NULL, &status));
|
||||
g_assert_cmpint(status, == ,-EINVAL);
|
||||
g_assert(!gbinder_ipc_sync_worker.sync_reply(null, 0, 0, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_sync_worker.sync_reply(null, 0, 0, NULL, &status));
|
||||
g_assert(!gbinder_ipc_sync_worker.sync_reply(NULL, 0, 0, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_sync_worker.sync_reply(NULL, 0, 0, NULL, &status));
|
||||
g_assert_cmpint(status, == ,-EINVAL);
|
||||
g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(null, 0, 0, NULL), == ,
|
||||
g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(NULL, 0, 0, NULL), == ,
|
||||
-EINVAL);
|
||||
g_assert_cmpint(gbinder_ipc_sync_worker.sync_oneway(null, 0, 0, NULL), == ,
|
||||
g_assert_cmpint(gbinder_ipc_sync_worker.sync_oneway(NULL, 0, 0, NULL), == ,
|
||||
-EINVAL);
|
||||
g_assert(!gbinder_ipc_transact(null, 0, 0, 0, NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_transact_custom(null, NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_object_registry(null));
|
||||
gbinder_ipc_looper_check(null);
|
||||
gbinder_ipc_cancel(null, 0);
|
||||
g_assert(!gbinder_ipc_transact(NULL, 0, 0, 0, NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_transact_custom(NULL, NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_object_registry(NULL));
|
||||
gbinder_ipc_looper_check(NULL);
|
||||
gbinder_ipc_cancel(NULL, 0);
|
||||
|
||||
g_assert(!gbinder_object_registry_ref(NULL));
|
||||
gbinder_object_registry_unref(NULL);
|
||||
@@ -120,13 +137,23 @@ test_basic_find_none(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_basic_find(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
return obj == user_data;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderLocalObject* obj;
|
||||
|
||||
g_assert(ipc);
|
||||
g_assert(ipc2);
|
||||
@@ -136,18 +163,45 @@ test_basic(
|
||||
|
||||
g_assert(!gbinder_ipc_find_local_object(NULL, test_basic_find_none, NULL));
|
||||
g_assert(!gbinder_ipc_find_local_object(ipc, test_basic_find_none, NULL));
|
||||
obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
g_assert(obj);
|
||||
g_assert(!gbinder_ipc_find_local_object(ipc, test_basic_find_none, NULL));
|
||||
g_assert(gbinder_ipc_find_local_object(ipc, test_basic_find, obj) == obj);
|
||||
gbinder_local_object_unref(obj); /* Above call added a reference */
|
||||
gbinder_local_object_unref(obj);
|
||||
|
||||
/* Second gbinder_ipc_new returns the same (default) object */
|
||||
g_assert(gbinder_ipc_new(NULL) == ipc);
|
||||
g_assert(gbinder_ipc_new("") == ipc);
|
||||
g_assert(gbinder_ipc_new(NULL, NULL) == ipc);
|
||||
g_assert(gbinder_ipc_new("", NULL) == ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* Invalid path */
|
||||
g_assert(!gbinder_ipc_new("invalid path"));
|
||||
g_assert(!gbinder_ipc_new("invalid path", NULL));
|
||||
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* protocol
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_protocol(
|
||||
void)
|
||||
{
|
||||
/* GBinderIpc objects are identified by device + protocol combination */
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, "aidl");
|
||||
GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, "hidl");
|
||||
|
||||
g_assert(ipc);
|
||||
g_assert(ipc2);
|
||||
g_assert(ipc != ipc2);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_unref(ipc2);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
@@ -173,14 +227,13 @@ void
|
||||
test_async_oneway(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
id = gbinder_ipc_transact(ipc, 0, 1, GBINDER_TX_FLAG_ONEWAY,
|
||||
req, test_async_oneway_done, NULL, loop);
|
||||
g_assert(id);
|
||||
@@ -200,16 +253,14 @@ void
|
||||
test_sync_oneway(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(ipc, 0, 1, req), == ,0);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
@@ -222,13 +273,12 @@ void
|
||||
test_sync_reply_ok_status(
|
||||
int* status)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GBinderLocalReply* reply = test_local_reply_new(ipc);
|
||||
GBinderRemoteReply* tx_reply;
|
||||
GBinderOutputData* data;
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
const char* result_in = "foo";
|
||||
@@ -238,10 +288,10 @@ test_sync_reply_ok_status(
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply(fd, handle, code, data->bytes);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, handle, code, data->bytes);
|
||||
|
||||
tx_reply = gbinder_ipc_sync_main.sync_reply(ipc, handle, code, req, status);
|
||||
g_assert(tx_reply);
|
||||
@@ -254,7 +304,6 @@ test_sync_reply_ok_status(
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
@@ -279,36 +328,36 @@ void
|
||||
test_sync_reply_error(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
const gint expected_status = (-EINVAL);
|
||||
const gint unexpected_status = GBINDER_STATUS_FAILED;
|
||||
int status = INT_MAX;
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply_status(fd, expected_status);
|
||||
test_binder_ignore_dead_object(fd);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_reply_status(fd, TX_THREAD, expected_status);
|
||||
|
||||
g_assert(!gbinder_ipc_sync_main.sync_reply(ipc,handle,code,req,&status));
|
||||
g_assert_cmpint(status, == ,expected_status);
|
||||
|
||||
/* GBINDER_STATUS_FAILED gets replaced with -EFAULT */
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply_status(fd, unexpected_status);
|
||||
test_binder_ignore_dead_object(fd);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_reply_status(fd, TX_THREAD, unexpected_status);
|
||||
|
||||
g_assert(!gbinder_ipc_sync_main.sync_reply(ipc,handle,code,req,&status));
|
||||
g_assert_cmpint(status, == ,-EFAULT);
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
@@ -348,14 +397,13 @@ void
|
||||
test_transact_ok(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GBinderLocalReply* reply = test_local_reply_new(ipc);
|
||||
GBinderOutputData* data;
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
@@ -363,10 +411,10 @@ test_transact_ok(
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply(fd, handle, code, data->bytes);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_reply(fd, TX_THREAD, handle, code, data->bytes);
|
||||
|
||||
id = gbinder_ipc_transact(ipc, handle, code, 0, req,
|
||||
test_transact_ok_done, test_transact_ok_destroy, loop);
|
||||
@@ -379,7 +427,6 @@ test_transact_ok(
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -407,15 +454,14 @@ void
|
||||
test_transact_dead(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_dead_reply(fd);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_dead_reply(fd, TX_THREAD);
|
||||
|
||||
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_dead_done,
|
||||
NULL, loop);
|
||||
@@ -427,7 +473,6 @@ test_transact_dead(
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -455,15 +500,14 @@ void
|
||||
test_transact_failed(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_failed_reply(fd);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_failed_reply(fd, TX_THREAD);
|
||||
|
||||
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_failed_done,
|
||||
NULL, loop);
|
||||
@@ -475,7 +519,6 @@ test_transact_failed(
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -505,15 +548,14 @@ void
|
||||
test_transact_status(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply_status(fd, EXPECTED_STATUS);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_reply_status(fd, TX_THREAD, EXPECTED_STATUS);
|
||||
|
||||
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_status_done,
|
||||
NULL, loop);
|
||||
@@ -525,7 +567,6 @@ test_transact_status(
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -548,7 +589,7 @@ void
|
||||
test_transact_custom(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, NULL,
|
||||
test_transact_custom_done, NULL, loop);
|
||||
@@ -580,7 +621,7 @@ void
|
||||
test_transact_custom2(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, NULL, NULL,
|
||||
test_transact_custom_destroy, loop);
|
||||
@@ -613,7 +654,7 @@ void
|
||||
test_transact_custom3(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
/* Reusing test_transact_cancel_done and test_transact_cancel_destroy */
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_custom3_exec,
|
||||
@@ -623,7 +664,6 @@ test_transact_custom3(
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Reference to GBinderIpc is released by test_transact_custom3_exec */
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -663,7 +703,7 @@ void
|
||||
test_transact_cancel(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel_exec,
|
||||
test_transact_cancel_done, test_transact_cancel_destroy, loop);
|
||||
@@ -673,7 +713,6 @@ test_transact_cancel(
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -709,7 +748,7 @@ void
|
||||
test_transact_cancel2(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
/* Reusing test_transact_cancel_done and test_transact_cancel_destroy */
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel2_exec,
|
||||
@@ -719,7 +758,6 @@ test_transact_cancel2(
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -759,8 +797,7 @@ void
|
||||
test_transact_2way_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
@@ -771,9 +808,9 @@ test_transact_2way_run(
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, ifaces, test_transact_2way_incoming_proc, &incoming_call);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalRequest* incoming_req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GBinderLocalRequest* incoming_req = test_local_request_new(ipc);
|
||||
GBinderLocalReply* reply = test_local_reply_new(ipc);
|
||||
GBinderWriter writer;
|
||||
|
||||
/* Prepare reply */
|
||||
@@ -784,12 +821,13 @@ test_transact_2way_run(
|
||||
prot->write_rpc_header(&writer, "test");
|
||||
gbinder_writer_append_string8(&writer, "message");
|
||||
|
||||
test_binder_br_transaction(fd, obj, 2,
|
||||
test_binder_ignore_dead_object(fd);
|
||||
test_binder_br_transaction(fd, TX_THREAD, obj, 2,
|
||||
gbinder_local_request_data(req)->bytes);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_reply(fd, handle, code,
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
test_binder_br_noop(fd, TX_THREAD);
|
||||
test_binder_br_reply(fd, TX_THREAD, handle, code,
|
||||
gbinder_local_reply_data(reply)->bytes);
|
||||
|
||||
/* NB. Reusing test_transact_ok_done and test_transact_ok_destroy */
|
||||
@@ -808,7 +846,6 @@ test_transact_2way_run(
|
||||
g_idle_add(test_unref_ipc, ipc);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -844,14 +881,10 @@ void
|
||||
test_transact_unhandled_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderDriver* driver = ipc->driver;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalRequest* req = gbinder_driver_local_request_new_ping(driver);
|
||||
int fd = gbinder_driver_fd(driver);
|
||||
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
|
||||
g_assert(gbinder_ipc_transact(ipc, 1 /* Non-existent object */,
|
||||
gbinder_driver_protocol(driver)->ping_tx, 0, req,
|
||||
@@ -860,7 +893,6 @@ test_transact_unhandled_run(
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -905,8 +937,7 @@ void
|
||||
test_transact_incoming_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
@@ -914,8 +945,8 @@ test_transact_incoming_run(
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, ifaces, test_transact_incoming_proc, loop);
|
||||
GBinderLocalRequest* ping = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalRequest* ping = test_local_request_new(ipc);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GBinderWriter writer;
|
||||
|
||||
gbinder_local_request_init_writer(ping, &writer);
|
||||
@@ -925,13 +956,12 @@ test_transact_incoming_run(
|
||||
prot->write_rpc_header(&writer, "test");
|
||||
gbinder_writer_append_string8(&writer, "message");
|
||||
|
||||
test_binder_br_transaction(fd, obj, prot->ping_tx,
|
||||
test_binder_br_transaction(fd, LOOPER_THREAD, obj, prot->ping_tx,
|
||||
gbinder_local_request_data(ping)->bytes);
|
||||
test_binder_br_transaction_complete(fd); /* For reply */
|
||||
test_binder_br_transaction(fd, obj, 1,
|
||||
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
|
||||
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1,
|
||||
gbinder_local_request_data(req)->bytes);
|
||||
test_binder_br_transaction_complete(fd); /* For reply */
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Now we need to wait until GBinderIpc is destroyed */
|
||||
@@ -943,7 +973,6 @@ test_transact_incoming_run(
|
||||
g_idle_add(test_unref_ipc, ipc);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -986,8 +1015,7 @@ void
|
||||
test_transact_status_reply_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
@@ -995,7 +1023,7 @@ test_transact_status_reply_run(
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, ifaces, test_transact_status_reply_proc, loop);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
@@ -1004,9 +1032,8 @@ test_transact_status_reply_run(
|
||||
gbinder_writer_append_string8(&writer, "message");
|
||||
data = gbinder_local_request_data(req);
|
||||
|
||||
test_binder_br_transaction(fd, obj, 1, data->bytes);
|
||||
test_binder_br_transaction_complete(fd); /* For reply */
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE_ONE);
|
||||
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1, data->bytes);
|
||||
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Now we need to wait until GBinderIpc is destroyed */
|
||||
@@ -1017,7 +1044,6 @@ test_transact_status_reply_run(
|
||||
g_idle_add(test_unref_ipc, ipc);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -1103,8 +1129,7 @@ void
|
||||
test_transact_async_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
@@ -1112,7 +1137,7 @@ test_transact_async_run(
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, ifaces, test_transact_async_proc, loop);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
@@ -1121,9 +1146,8 @@ test_transact_async_run(
|
||||
gbinder_writer_append_string8(&writer, "message");
|
||||
data = gbinder_local_request_data(req);
|
||||
|
||||
test_binder_br_transaction(fd, obj, 1, data->bytes);
|
||||
test_binder_br_transaction_complete(fd); /* For reply */
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE_ONE);
|
||||
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1, data->bytes);
|
||||
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Now we need to wait until GBinderIpc is destroyed */
|
||||
@@ -1134,7 +1158,6 @@ test_transact_async_run(
|
||||
g_idle_add(test_unref_ipc, ipc);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -1186,8 +1209,7 @@ void
|
||||
test_transact_async_sync_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
@@ -1195,7 +1217,7 @@ test_transact_async_sync_run(
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, ifaces, test_transact_async_sync_proc, loop);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
@@ -1204,9 +1226,8 @@ test_transact_async_sync_run(
|
||||
gbinder_writer_append_string8(&writer, "message");
|
||||
data = gbinder_local_request_data(req);
|
||||
|
||||
test_binder_br_transaction(fd, obj, 1, data->bytes);
|
||||
test_binder_br_transaction_complete(fd); /* For reply */
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE_ONE);
|
||||
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1, data->bytes);
|
||||
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Now we need to wait until GBinderIpc is destroyed */
|
||||
@@ -1217,7 +1238,6 @@ test_transact_async_sync_run(
|
||||
g_idle_add(test_unref_ipc, ipc);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -1250,7 +1270,7 @@ void
|
||||
test_drop_remote_refs_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, NULL, NULL, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
@@ -1258,8 +1278,7 @@ test_drop_remote_refs_run(
|
||||
gulong id = gbinder_local_object_add_strong_refs_changed_handler(obj,
|
||||
test_drop_remote_refs_cb, loop);
|
||||
|
||||
test_binder_br_acquire(fd, obj);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_br_acquire(fd, ANY_THREAD, obj);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->strong_refs == 1);
|
||||
@@ -1301,14 +1320,13 @@ void
|
||||
test_cancel_on_exit(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new(ipc);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
/* This transaction will be cancelled by gbinder_ipc_exit */
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
gbinder_ipc_transact(ipc, 0, 1, GBINDER_TX_FLAG_ONEWAY,
|
||||
req, test_cancel_on_exit_not_reached, NULL, NULL);
|
||||
|
||||
@@ -1334,6 +1352,7 @@ int main(int argc, char* argv[])
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_("null"), test_null);
|
||||
g_test_add_func(TEST_("basic"), test_basic);
|
||||
g_test_add_func(TEST_("protocol"), test_protocol);
|
||||
g_test_add_func(TEST_("async_oneway"), test_async_oneway);
|
||||
g_test_add_func(TEST_("sync_oneway"), test_sync_oneway);
|
||||
g_test_add_func(TEST_("sync_reply_ok"), test_sync_reply_ok);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "test_binder.h"
|
||||
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
@@ -152,7 +153,7 @@ test_basic(
|
||||
{
|
||||
const char* const ifaces_foo[] = { "foo", NULL };
|
||||
const char* const ifaces_bar[] = { "bar", NULL };
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderLocalObject* foo;
|
||||
GBinderLocalObject* bar;
|
||||
@@ -187,6 +188,7 @@ test_basic(
|
||||
g_assert(gbinder_local_object_ref(bar) == bar);
|
||||
gbinder_local_object_drop(bar);
|
||||
gbinder_local_object_unref(bar);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -201,7 +203,7 @@ test_ping(
|
||||
int status = INT_MAX;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
@@ -232,6 +234,7 @@ test_ping(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -247,7 +250,7 @@ test_interface(
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
const char* const ifaces[] = { "x", NULL };
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces, NULL, NULL);
|
||||
@@ -281,6 +284,7 @@ test_interface(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -296,7 +300,7 @@ test_hidl_ping(
|
||||
int status = INT_MAX;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
@@ -331,6 +335,7 @@ test_hidl_ping(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -346,7 +351,7 @@ test_get_descriptor(
|
||||
int status = INT_MAX;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
@@ -384,6 +389,7 @@ test_get_descriptor(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -402,7 +408,7 @@ test_descriptor_chain(
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const char* const ifaces[] = { "android.hidl.base@1.0::IBase", NULL };
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces, NULL, NULL);
|
||||
@@ -435,6 +441,7 @@ test_descriptor_chain(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -476,7 +483,7 @@ test_custom_iface(
|
||||
int count = 0, status = INT_MAX;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces,
|
||||
@@ -545,6 +552,7 @@ test_custom_iface(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -583,7 +591,7 @@ test_reply_status(
|
||||
int count = 0, status = 0;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces,
|
||||
@@ -602,6 +610,7 @@ test_reply_status(
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_remote_request_unref(req);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -624,7 +633,7 @@ void
|
||||
test_increfs_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, NULL, NULL, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
@@ -633,16 +642,15 @@ test_increfs_run(
|
||||
test_increfs_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_increfs(fd, ipc);
|
||||
test_binder_br_increfs(fd, obj);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_br_increfs(fd, ANY_THREAD, ipc);
|
||||
test_binder_br_increfs(fd, ANY_THREAD, obj);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->weak_refs == 1);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -675,7 +683,7 @@ void
|
||||
test_decrefs_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, NULL, NULL, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
@@ -684,17 +692,16 @@ test_decrefs_run(
|
||||
test_decrefs_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_decrefs(fd, ipc);
|
||||
test_binder_br_increfs(fd, obj);
|
||||
test_binder_br_decrefs(fd, obj);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_br_decrefs(fd, ANY_THREAD, ipc);
|
||||
test_binder_br_increfs(fd, ANY_THREAD, obj);
|
||||
test_binder_br_decrefs(fd, ANY_THREAD, obj);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->weak_refs == 0);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -726,7 +733,7 @@ void
|
||||
test_acquire_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new
|
||||
(ipc, NULL, NULL, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
@@ -735,16 +742,15 @@ test_acquire_run(
|
||||
test_acquire_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_acquire(fd, ipc);
|
||||
test_binder_br_acquire(fd, obj);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_br_acquire(fd, ANY_THREAD, ipc);
|
||||
test_binder_br_acquire(fd, ANY_THREAD, obj);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->strong_refs == 1);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -777,7 +783,7 @@ void
|
||||
test_release_run(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
int fd = gbinder_driver_fd(ipc->driver);
|
||||
@@ -785,17 +791,16 @@ test_release_run(
|
||||
test_release_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_release(fd, ipc);
|
||||
test_binder_br_acquire(fd, obj);
|
||||
test_binder_br_release(fd, obj);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_br_release(fd, ANY_THREAD, ipc);
|
||||
test_binder_br_acquire(fd, ANY_THREAD, obj);
|
||||
test_binder_br_release(fd, ANY_THREAD, obj);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->strong_refs == 0);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -815,6 +820,18 @@ test_release(
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const char* default_config_dir;
|
||||
const char* default_config_file;
|
||||
char* config_dir = g_dir_make_tmp("gbinder-test-local-object-XXXXXX", NULL);
|
||||
char* config_file = g_build_filename(config_dir, "test.conf", NULL);
|
||||
int result;
|
||||
|
||||
/* Point gbinder_config_file to a non-existent file */
|
||||
default_config_dir = gbinder_config_dir;
|
||||
default_config_file = gbinder_config_file;
|
||||
gbinder_config_dir = config_dir;
|
||||
gbinder_config_file = config_file;
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
g_type_init();
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
@@ -833,7 +850,14 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_PREFIX "acquire", test_acquire);
|
||||
g_test_add_func(TEST_PREFIX "release", test_release);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
result = g_test_run();
|
||||
|
||||
gbinder_config_dir = default_config_dir;
|
||||
gbinder_config_file = default_config_file;
|
||||
remove(config_dir);
|
||||
g_free(config_dir);
|
||||
g_free(config_file);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "gbinder_local_object.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_writer.h"
|
||||
@@ -46,11 +47,6 @@
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define BUFFER_OBJECT_SIZE_32 (24)
|
||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
|
||||
#define BINDER_OBJECT_SIZE_32 (16)
|
||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
|
||||
|
||||
static
|
||||
void
|
||||
test_int_inc(
|
||||
@@ -70,6 +66,14 @@ test_buffer_from_bytes(
|
||||
return gbinder_buffer_new(driver, bytes->data, bytes->len, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
test_local_reply_new()
|
||||
{
|
||||
return gbinder_local_reply_new(&gbinder_io_32,
|
||||
gbinder_rpc_protocol_for_device(NULL));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
@@ -82,7 +86,10 @@ test_null(
|
||||
GBinderWriter writer;
|
||||
int count = 0;
|
||||
|
||||
g_assert(!gbinder_local_reply_new(NULL));
|
||||
g_assert(!gbinder_local_reply_new(NULL, NULL));
|
||||
g_assert(!gbinder_local_reply_new(&gbinder_io_32, NULL));
|
||||
g_assert(!gbinder_local_reply_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(NULL)));
|
||||
g_assert(!gbinder_local_reply_ref(NULL));
|
||||
gbinder_local_reply_unref(NULL);
|
||||
gbinder_local_reply_init_writer(NULL, NULL);
|
||||
@@ -106,6 +113,7 @@ test_null(
|
||||
g_assert(!gbinder_local_reply_append_hidl_string_vec(NULL, NULL, 0));
|
||||
g_assert(!gbinder_local_reply_append_local_object(NULL, NULL));
|
||||
g_assert(!gbinder_local_reply_append_remote_object(NULL, NULL));
|
||||
g_assert(!gbinder_local_reply_append_fd(NULL, 0));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -117,7 +125,7 @@ void
|
||||
test_cleanup(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
int count = 0;
|
||||
|
||||
gbinder_local_reply_cleanup(reply, NULL, &count);
|
||||
@@ -140,7 +148,7 @@ test_bool(
|
||||
{
|
||||
static const guint8 output_true[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
static const guint8 output_false[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_bool(reply, FALSE);
|
||||
@@ -151,7 +159,7 @@ test_bool(
|
||||
g_assert(!memcmp(data->bytes->data, output_false, data->bytes->len));
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
reply = test_local_reply_new();
|
||||
gbinder_local_reply_append_bool(reply, TRUE);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -160,7 +168,7 @@ test_bool(
|
||||
g_assert(!memcmp(data->bytes->data, output_true, data->bytes->len));
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
reply = test_local_reply_new();
|
||||
gbinder_local_reply_append_bool(reply, 42);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -170,6 +178,31 @@ test_bool(
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* fd
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_fd(
|
||||
void)
|
||||
{
|
||||
const gint32 fd = 1;
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
g_assert(gbinder_local_reply_append_fd(reply, fd));
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* int32
|
||||
*==========================================================================*/
|
||||
@@ -180,7 +213,7 @@ test_int32(
|
||||
void)
|
||||
{
|
||||
const guint32 value = 1234567;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
@@ -195,7 +228,7 @@ test_int32(
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* Same with writer */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
reply = test_local_reply_new();
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, value);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
@@ -216,7 +249,7 @@ test_int64(
|
||||
void)
|
||||
{
|
||||
const guint64 value = 123456789;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_int64(reply, value);
|
||||
@@ -238,7 +271,7 @@ test_float(
|
||||
void)
|
||||
{
|
||||
const gfloat value = 123456789;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_float(reply, value);
|
||||
@@ -260,7 +293,7 @@ test_double(
|
||||
void)
|
||||
{
|
||||
const gdouble value = 123456789;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_double(reply, value);
|
||||
@@ -284,7 +317,7 @@ test_string8(
|
||||
/* The size of the string gets aligned at 4-byte boundary */
|
||||
static const char input[] = "test";
|
||||
static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_string8(reply, input);
|
||||
@@ -296,7 +329,7 @@ test_string8(
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* NULL string doesn't get encoded at all (should it be?) */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
reply = test_local_reply_new();
|
||||
gbinder_local_reply_append_string8(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -320,7 +353,7 @@ test_string16(
|
||||
TEST_INT16_BYTES('x'), 0x00, 0x00
|
||||
};
|
||||
const gint32 null_output = -1;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_string16(reply, input);
|
||||
@@ -332,7 +365,7 @@ test_string16(
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* NULL string gets encoded as -1 */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
reply = test_local_reply_new();
|
||||
gbinder_local_reply_append_string16(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -351,7 +384,7 @@ void
|
||||
test_hidl_string(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -374,7 +407,7 @@ void
|
||||
test_hidl_string_vec(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -400,7 +433,7 @@ test_local_object(
|
||||
GBinderLocalReply* reply;
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(NULL);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(NULL, NULL);
|
||||
const char* const ifaces[] = { "android.hidl.base@1.0::IBase", NULL };
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces, NULL, NULL);
|
||||
|
||||
@@ -410,22 +443,22 @@ test_local_object(
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_64);
|
||||
g_assert_cmpuint(offsets->count, == ,1);
|
||||
g_assert_cmpuint(offsets->data[0], == ,0);
|
||||
g_assert_cmpuint(gbinder_output_data_buffers_size(data), == ,0);
|
||||
g_assert_cmpuint(data->bytes->len, == ,BINDER_OBJECT_SIZE_64);
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* Append NULL object (with 32-bit I/O module) */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
reply = test_local_reply_new();
|
||||
gbinder_local_reply_append_local_object(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_32);
|
||||
g_assert_cmpuint(offsets->count, == ,1);
|
||||
g_assert_cmpuint(offsets->data[0], == ,0);
|
||||
g_assert_cmpuint(gbinder_output_data_buffers_size(data), == ,0);
|
||||
g_assert_cmpuint(data->bytes->len, == ,BINDER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
@@ -439,7 +472,7 @@ void
|
||||
test_remote_object(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderLocalReply* reply = test_local_reply_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -468,7 +501,8 @@ test_remote_reply(
|
||||
static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalReply* req = gbinder_local_reply_new(io);
|
||||
GBinderLocalReply* req = gbinder_local_reply_new(io,
|
||||
gbinder_rpc_protocol_for_device(NULL));
|
||||
GBinderLocalReply* req2;
|
||||
GBinderOutputData* data2;
|
||||
const GByteArray* bytes;
|
||||
@@ -480,7 +514,7 @@ test_remote_reply(
|
||||
|
||||
/* Copy flat structures (no binder objects) */
|
||||
buffer = test_buffer_from_bytes(driver, bytes);
|
||||
req2 = gbinder_local_reply_new(io);
|
||||
req2 = gbinder_local_reply_new(io, gbinder_rpc_protocol_for_device(NULL));
|
||||
g_assert(gbinder_local_reply_set_contents(req2, buffer, NULL) == req2);
|
||||
gbinder_buffer_free(buffer);
|
||||
|
||||
@@ -511,6 +545,7 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "cleanup", test_cleanup);
|
||||
g_test_add_func(TEST_PREFIX "bool", test_bool);
|
||||
g_test_add_func(TEST_PREFIX "fd", test_fd);
|
||||
g_test_add_func(TEST_PREFIX "int32", test_int32);
|
||||
g_test_add_func(TEST_PREFIX "int64", test_int64);
|
||||
g_test_add_func(TEST_PREFIX "float", test_float);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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_request_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_writer.h"
|
||||
@@ -44,11 +45,6 @@
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define BUFFER_OBJECT_SIZE_32 (24)
|
||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
|
||||
#define BINDER_OBJECT_SIZE_32 (16)
|
||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
|
||||
|
||||
static
|
||||
void
|
||||
test_int_inc(
|
||||
@@ -80,6 +76,14 @@ test_buffer_from_bytes_and_objects(
|
||||
return gbinder_buffer_new(driver, bytes->data, bytes->len, objects);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
test_local_request_new()
|
||||
{
|
||||
return gbinder_local_request_new(&gbinder_io_32,
|
||||
gbinder_rpc_protocol_for_device(NULL), NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
@@ -92,7 +96,10 @@ test_null(
|
||||
GBinderWriter writer;
|
||||
int count = 0;
|
||||
|
||||
g_assert(!gbinder_local_request_new(NULL, NULL));
|
||||
g_assert(!gbinder_local_request_new(NULL, NULL, NULL));
|
||||
g_assert(!gbinder_local_request_new(&gbinder_io_32, NULL, NULL));
|
||||
g_assert(!gbinder_local_request_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(NULL), NULL));
|
||||
g_assert(!gbinder_local_request_ref(NULL));
|
||||
g_assert(!gbinder_local_request_new_from_data(NULL, NULL));
|
||||
gbinder_local_request_unref(NULL);
|
||||
@@ -125,7 +132,7 @@ void
|
||||
test_cleanup(
|
||||
void)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
int count = 0;
|
||||
|
||||
gbinder_local_request_cleanup(req, NULL, &count);
|
||||
@@ -149,7 +156,7 @@ test_init_data(
|
||||
const guint8 init_data[] = { 0x01, 0x02, 0x03, 0x04 };
|
||||
GBytes* init_bytes = g_bytes_new_static(init_data, sizeof(init_data));
|
||||
GBinderLocalRequest* req = gbinder_local_request_new
|
||||
(&gbinder_io_32, init_bytes);
|
||||
(&gbinder_io_32, gbinder_rpc_protocol_for_device(NULL), init_bytes);
|
||||
GBinderOutputData* data;
|
||||
|
||||
data = gbinder_local_request_data(req);
|
||||
@@ -161,7 +168,7 @@ test_init_data(
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
req = test_local_request_new();
|
||||
data = gbinder_local_request_data(req);
|
||||
g_assert(data->bytes);
|
||||
g_assert(!data->bytes->len);
|
||||
@@ -181,7 +188,7 @@ test_bool(
|
||||
{
|
||||
static const guint8 output_true[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
static const guint8 output_false[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_request_append_bool(req, FALSE);
|
||||
@@ -192,7 +199,7 @@ test_bool(
|
||||
g_assert(!memcmp(data->bytes->data, output_false, data->bytes->len));
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
req = test_local_request_new();
|
||||
gbinder_local_request_append_bool(req, TRUE);
|
||||
data = gbinder_local_request_data(req);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -201,7 +208,7 @@ test_bool(
|
||||
g_assert(!memcmp(data->bytes->data, output_true, data->bytes->len));
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
req = test_local_request_new();
|
||||
gbinder_local_request_append_bool(req, 42);
|
||||
data = gbinder_local_request_data(req);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -221,7 +228,7 @@ test_int32(
|
||||
void)
|
||||
{
|
||||
const guint32 value = 1234567;
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_request_append_int32(req, value);
|
||||
@@ -243,7 +250,7 @@ test_int64(
|
||||
void)
|
||||
{
|
||||
const guint64 value = 123456789;
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_request_append_int64(req, value);
|
||||
@@ -265,7 +272,7 @@ test_float(
|
||||
void)
|
||||
{
|
||||
const gfloat value = 123456789;
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_request_append_float(req, value);
|
||||
@@ -287,7 +294,7 @@ test_double(
|
||||
void)
|
||||
{
|
||||
const gdouble value = 123456789;
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_request_append_double(req, value);
|
||||
@@ -311,7 +318,7 @@ test_string8(
|
||||
/* The size of the string gets aligned at 4-byte boundary */
|
||||
static const char input[] = "test";
|
||||
static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_request_append_string8(req, input);
|
||||
@@ -323,7 +330,7 @@ test_string8(
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
/* NULL string doesn't get encoded at all (should it be?) */
|
||||
req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
req = test_local_request_new();
|
||||
gbinder_local_request_append_string8(req, NULL);
|
||||
data = gbinder_local_request_data(req);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -347,7 +354,7 @@ test_string16(
|
||||
TEST_INT16_BYTES('x'), 0x00, 0x00
|
||||
};
|
||||
const gint32 null_output = -1;
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_request_append_string16(req, input);
|
||||
@@ -359,7 +366,7 @@ test_string16(
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
/* NULL string gets encoded as -1 */
|
||||
req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
req = test_local_request_new();
|
||||
gbinder_local_request_append_string16(req, NULL);
|
||||
data = gbinder_local_request_data(req);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
@@ -378,7 +385,7 @@ void
|
||||
test_hidl_string(
|
||||
void)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -401,7 +408,7 @@ void
|
||||
test_hidl_string_vec(
|
||||
void)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -424,7 +431,7 @@ void
|
||||
test_local_object(
|
||||
void)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -448,7 +455,7 @@ void
|
||||
test_remote_object(
|
||||
void)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderLocalRequest* req = test_local_request_new();
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -477,7 +484,8 @@ test_remote_request(
|
||||
static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
const GBinderRpcProtocol* protocol = gbinder_driver_protocol(driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, protocol, NULL);
|
||||
GBinderLocalRequest* req2;
|
||||
GBinderOutputData* data2;
|
||||
const GByteArray* bytes;
|
||||
@@ -549,7 +557,8 @@ test_remote_request_obj(
|
||||
{
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
const GBinderRpcProtocol* protocol = gbinder_driver_protocol(driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, protocol, NULL);
|
||||
GBinderLocalRequest* req2;
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||
* Copyright (C) 2018-2020 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:
|
||||
*
|
||||
@@ -49,6 +49,7 @@ static const char TMP_DIR_TEMPLATE[] = "gbinder-test-protocol-XXXXXX";
|
||||
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
|
||||
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
|
||||
#define UNSET_WORK_SOURCE (-1)
|
||||
#define BINDER_SYS_HEADER GBINDER_FOURCC('S', 'Y', 'S', 'T')
|
||||
|
||||
typedef struct test_data {
|
||||
const char* name;
|
||||
@@ -80,6 +81,15 @@ static const guint8 test_header_aidl2 [] = {
|
||||
TEST_INT16_BYTES('o'), 0x00, 0x00
|
||||
};
|
||||
|
||||
static const guint8 test_header_aidl3 [] = {
|
||||
TEST_INT32_BYTES(BINDER_RPC_FLAGS),
|
||||
TEST_INT32_BYTES(UNSET_WORK_SOURCE),
|
||||
TEST_INT32_BYTES(BINDER_SYS_HEADER),
|
||||
TEST_INT32_BYTES(3),
|
||||
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'),
|
||||
TEST_INT16_BYTES('o'), 0x00, 0x00
|
||||
};
|
||||
|
||||
static const guint8 test_header_hidl [] = {
|
||||
'f', 'o', 'o', 0x00
|
||||
};
|
||||
@@ -97,6 +107,14 @@ static const TestHeaderData test_header_tests[] = {
|
||||
test_header_aidl2, 5 }, /* Short packet */
|
||||
{ "aidl2/short/3", "adl2", GBINDER_DEFAULT_BINDER, NULL,
|
||||
test_header_aidl2, 9 }, /* Short packet */
|
||||
{ "aidl3/ok", "aidl3", GBINDER_DEFAULT_BINDER, "foo",
|
||||
TEST_ARRAY_AND_SIZE(test_header_aidl3) },
|
||||
{ "aidl3/short/1", "aidl3", GBINDER_DEFAULT_BINDER, NULL,
|
||||
test_header_aidl3, 1 }, /* Short packet */
|
||||
{ "aidl3/short/2", "aidl3", GBINDER_DEFAULT_BINDER, NULL,
|
||||
test_header_aidl3, 5 }, /* Short packet */
|
||||
{ "aidl3/short/3", "adl3", GBINDER_DEFAULT_BINDER, NULL,
|
||||
test_header_aidl3, 9 }, /* Short packet */
|
||||
{ "hidl/ok", "hidl", GBINDER_DEFAULT_HWBINDER, "foo",
|
||||
TEST_ARRAY_AND_SIZE(test_header_hidl) },
|
||||
{ "hidl/short", "hidl", GBINDER_DEFAULT_HWBINDER, NULL,
|
||||
@@ -166,6 +184,9 @@ test_device(
|
||||
void)
|
||||
{
|
||||
const GBinderRpcProtocol* p;
|
||||
TestConfig config;
|
||||
|
||||
test_config_init(&config, "");
|
||||
|
||||
p = gbinder_rpc_protocol_for_device(NULL);
|
||||
g_assert(p);
|
||||
@@ -178,6 +199,8 @@ test_device(
|
||||
p = gbinder_rpc_protocol_for_device(GBINDER_DEFAULT_HWBINDER);
|
||||
g_assert(p);
|
||||
g_assert_cmpstr(p->name, == ,"hidl");
|
||||
|
||||
test_config_cleanup(&config);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -348,6 +371,7 @@ test_no_header2(
|
||||
static const TestData test_no_header_data[] = {
|
||||
{ "aidl", "aidl", GBINDER_DEFAULT_BINDER },
|
||||
{ "aidl2", "aidl2", GBINDER_DEFAULT_BINDER },
|
||||
{ "aidl3", "aidl3", GBINDER_DEFAULT_BINDER },
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -369,7 +393,8 @@ test_write_header(
|
||||
test_config_init2(&config, test->dev, test->prot);
|
||||
|
||||
prot = gbinder_rpc_protocol_for_device(test->dev);
|
||||
req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
req = gbinder_local_request_new(&gbinder_io_32,
|
||||
gbinder_rpc_protocol_for_device(NULL), NULL);
|
||||
gbinder_local_request_init_writer(req, &writer);
|
||||
prot->write_rpc_header(&writer, test->iface);
|
||||
data = gbinder_local_request_data(req);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2023 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -50,9 +51,7 @@
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define DEV "/dev/xbinder"
|
||||
#define DEV_PRIV DEV "-private"
|
||||
#define DEV2 "/dev/ybinder"
|
||||
#define DEV2_PRIV DEV2 "-private"
|
||||
|
||||
enum test_tx_codes {
|
||||
TX_CODE = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
@@ -190,38 +189,28 @@ test_basic_run(
|
||||
GBinderLocalObject* obj;
|
||||
GBinderProxyObject* proxy;
|
||||
GBinderRemoteObject* remote_obj;
|
||||
GBinderRemoteObject* remote_proxy;
|
||||
GBinderClient* proxy_client;
|
||||
GBinderClient* client;
|
||||
GBinderIpc* ipc_obj;
|
||||
GBinderIpc* ipc_proxy;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
int fd_obj, fd_proxy, n = 0;
|
||||
|
||||
test_config_init(&config, NULL);
|
||||
ipc_proxy = gbinder_ipc_new(DEV);
|
||||
ipc_obj = gbinder_ipc_new(DEV_PRIV);
|
||||
ipc_proxy = gbinder_ipc_new(DEV, NULL);
|
||||
ipc_obj = gbinder_ipc_new(DEV2, NULL);
|
||||
fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
|
||||
fd_obj = gbinder_driver_fd(ipc_obj->driver);
|
||||
obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_basic_cb, &n);
|
||||
remote_obj = gbinder_remote_object_new(ipc_proxy,
|
||||
remote_obj = gbinder_remote_object_new(ipc_obj,
|
||||
test_binder_register_object(fd_obj, obj, AUTO_HANDLE),
|
||||
REMOTE_OBJECT_CREATE_ALIVE);
|
||||
|
||||
/* remote_proxy(DEV_PRIV) => proxy (DEV) => obj (DEV) => DEV_PRIV */
|
||||
g_assert(!gbinder_proxy_object_new(NULL, remote_obj));
|
||||
g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
|
||||
remote_proxy = gbinder_remote_object_new(ipc_obj,
|
||||
test_binder_register_object(fd_proxy, &proxy->parent, AUTO_HANDLE),
|
||||
REMOTE_OBJECT_CREATE_ALIVE);
|
||||
proxy_client = gbinder_client_new(remote_proxy, TEST_IFACE);
|
||||
|
||||
test_binder_set_passthrough(fd_obj, TRUE);
|
||||
test_binder_set_passthrough(fd_proxy, TRUE);
|
||||
test_binder_set_looper_enabled(fd_obj, TEST_LOOPER_ENABLE);
|
||||
test_binder_set_looper_enabled(fd_proxy, TEST_LOOPER_ENABLE);
|
||||
client = gbinder_client_new(proxy->remote, TEST_IFACE);
|
||||
|
||||
/* Perform a transaction via proxy */
|
||||
g_assert(gbinder_client_transact(proxy_client, TX_CODE, 0, NULL,
|
||||
g_assert(gbinder_client_transact(client, TX_CODE, 0, NULL,
|
||||
test_basic_reply, NULL, loop));
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
@@ -232,11 +221,9 @@ test_basic_run(
|
||||
gbinder_local_object_drop(obj);
|
||||
gbinder_local_object_drop(&proxy->parent);
|
||||
gbinder_remote_object_unref(remote_obj);
|
||||
gbinder_remote_object_unref(remote_proxy);
|
||||
gbinder_client_unref(proxy_client);
|
||||
gbinder_client_unref(client);
|
||||
gbinder_ipc_unref(ipc_obj);
|
||||
gbinder_ipc_unref(ipc_proxy);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
test_config_deinit(&config);
|
||||
g_main_loop_unref(loop);
|
||||
@@ -303,6 +290,19 @@ test_param_cb(
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_param_canceled(
|
||||
GBinderClient* client,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* unused)
|
||||
{
|
||||
g_assert(!reply);
|
||||
g_assert_cmpint(status, == ,-ECANCELED);
|
||||
GDEBUG("Transaction cancelled");
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_param_reply(
|
||||
@@ -311,35 +311,19 @@ test_param_reply(
|
||||
int status,
|
||||
void* loop)
|
||||
{
|
||||
/*
|
||||
* Due to limitations of our binder simulation, the result can be
|
||||
* delivered to a wrong thread. As a result, we only known that one
|
||||
* of the callbacks get NULL result and one gets NULL loop, but we
|
||||
* don't really know which one gets what, i.e. we have to be ready
|
||||
* for any combination of these parameters.
|
||||
*
|
||||
* It's too difficult to fix (without writing almost a full-blown
|
||||
* binder implementation), let's just live with it for now :/
|
||||
*/
|
||||
if (reply) {
|
||||
GBinderReader reader;
|
||||
gint32 result = 0;
|
||||
GBinderReader reader;
|
||||
gint32 result = 0;
|
||||
|
||||
GDEBUG("Reply received");
|
||||
g_assert(reply);
|
||||
g_assert_cmpint(status, == ,0);
|
||||
GDEBUG("Reply received");
|
||||
|
||||
/* Make sure that result got delivered intact */
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
g_assert(gbinder_reader_read_int32(&reader, &result));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert_cmpint(result, == ,TX_RESULT);
|
||||
} else {
|
||||
/* The cancelled one */
|
||||
GDEBUG("Transaction cancelled");
|
||||
}
|
||||
|
||||
if (loop) {
|
||||
g_main_loop_quit((GMainLoop*)loop);
|
||||
}
|
||||
/* Make sure that result got delivered intact */
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
g_assert(gbinder_reader_read_int32(&reader, &result));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert_cmpint(result, == ,TX_RESULT);
|
||||
g_main_loop_quit((GMainLoop*)loop);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -351,54 +335,40 @@ test_param_run(
|
||||
GBinderLocalObject* obj;
|
||||
GBinderProxyObject* proxy;
|
||||
GBinderRemoteObject* remote_obj;
|
||||
GBinderRemoteObject* remote_proxy;
|
||||
GBinderClient* proxy_client;
|
||||
GBinderClient* client;
|
||||
GBinderLocalRequest* req;
|
||||
GBinderIpc* ipc_obj;
|
||||
GBinderIpc* ipc_remote_obj;
|
||||
GBinderIpc* ipc_proxy;
|
||||
GBinderIpc* ipc_remote_proxy;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
int fd_obj, fd_proxy, n = 0;
|
||||
|
||||
test_config_init(&config, NULL);
|
||||
ipc_obj = gbinder_ipc_new(DEV);
|
||||
ipc_remote_obj = gbinder_ipc_new(DEV_PRIV);
|
||||
ipc_proxy = gbinder_ipc_new(DEV2);
|
||||
ipc_remote_proxy = gbinder_ipc_new(DEV2_PRIV);
|
||||
ipc_proxy = gbinder_ipc_new(DEV2, NULL);
|
||||
ipc_obj = gbinder_ipc_new(DEV, NULL);
|
||||
fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
|
||||
fd_obj = gbinder_driver_fd(ipc_obj->driver);
|
||||
obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_param_cb, &n);
|
||||
remote_obj = gbinder_remote_object_new(ipc_remote_obj,
|
||||
remote_obj = gbinder_remote_object_new(ipc_obj,
|
||||
test_binder_register_object(fd_obj, obj, AUTO_HANDLE),
|
||||
REMOTE_OBJECT_CREATE_ALIVE);
|
||||
|
||||
/* remote_proxy(DEV2_PRIV) => proxy (DEV2) => obj (DEV) => DEV_PRIV */
|
||||
g_assert(!gbinder_proxy_object_new(NULL, remote_obj));
|
||||
g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
|
||||
remote_proxy = gbinder_remote_object_new(ipc_remote_proxy,
|
||||
test_binder_register_object(fd_proxy, &proxy->parent, AUTO_HANDLE),
|
||||
REMOTE_OBJECT_CREATE_ALIVE);
|
||||
proxy_client = gbinder_client_new(remote_proxy, TEST_IFACE);
|
||||
|
||||
test_binder_set_passthrough(fd_obj, TRUE);
|
||||
test_binder_set_passthrough(fd_proxy, TRUE);
|
||||
test_binder_set_looper_enabled(fd_obj, TEST_LOOPER_ENABLE);
|
||||
test_binder_set_looper_enabled(fd_proxy, TEST_LOOPER_ENABLE);
|
||||
client = gbinder_client_new(proxy->remote, TEST_IFACE);
|
||||
|
||||
/*
|
||||
* Perform two transactions via proxy. First one never gets completed
|
||||
* and eventually is cancelled, and the second one is replied to.
|
||||
*/
|
||||
req = gbinder_client_new_request(proxy_client);
|
||||
req = gbinder_client_new_request(client);
|
||||
gbinder_local_request_append_int32(req, TX_PARAM_DONT_REPLY);
|
||||
gbinder_client_transact(proxy_client, TX_CODE, 0, req, test_param_reply,
|
||||
gbinder_client_transact(client, TX_CODE, 0, req, test_param_canceled,
|
||||
NULL, NULL);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
req = gbinder_client_new_request(proxy_client);
|
||||
req = gbinder_client_new_request(client);
|
||||
gbinder_local_request_append_int32(req, TX_PARAM_REPLY);
|
||||
g_assert(gbinder_client_transact(proxy_client, TX_CODE, 0, req,
|
||||
g_assert(gbinder_client_transact(client, TX_CODE, 0, req,
|
||||
test_param_reply, NULL, loop));
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
@@ -412,13 +382,9 @@ test_param_run(
|
||||
gbinder_local_object_drop(obj);
|
||||
gbinder_local_object_drop(&proxy->parent);
|
||||
gbinder_remote_object_unref(remote_obj);
|
||||
gbinder_remote_object_unref(remote_proxy);
|
||||
gbinder_client_unref(proxy_client);
|
||||
gbinder_client_unref(client);
|
||||
gbinder_ipc_unref(ipc_obj);
|
||||
gbinder_ipc_unref(ipc_remote_obj);
|
||||
gbinder_ipc_unref(ipc_proxy);
|
||||
gbinder_ipc_unref(ipc_remote_proxy);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
test_config_deinit(&config);
|
||||
g_main_loop_unref(loop);
|
||||
@@ -438,7 +404,7 @@ test_param(
|
||||
|
||||
typedef struct test_obj_data {
|
||||
GMainLoop* loop;
|
||||
GBinderLocalObject* tmp_proxy;
|
||||
GBinderLocalObject* obj2;
|
||||
gboolean obj_call_handled;
|
||||
gboolean obj_call_finished;
|
||||
gboolean obj2_call_handled;
|
||||
@@ -539,9 +505,9 @@ test_obj_cb(
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
|
||||
/* Make sure temporary proxy won't get destroyed too early */
|
||||
test->tmp_proxy = test_binder_object(gbinder_driver_fd(obj->ipc->driver),
|
||||
test->obj2 = test_binder_object(gbinder_driver_fd(obj->ipc->driver),
|
||||
obj2->handle);
|
||||
g_assert(test->tmp_proxy);
|
||||
g_assert(test->obj2);
|
||||
|
||||
/* Call remote object */
|
||||
client2 = gbinder_client_new(obj2, TEST_IFACE2);
|
||||
@@ -597,8 +563,7 @@ test_obj_run(
|
||||
GBinderLocalObject* obj2;
|
||||
GBinderProxyObject* proxy;
|
||||
GBinderRemoteObject* remote_obj;
|
||||
GBinderRemoteObject* remote_proxy;
|
||||
GBinderClient* proxy_client;
|
||||
GBinderClient* client;
|
||||
GBinderIpc* ipc_obj;
|
||||
GBinderIpc* ipc_proxy;
|
||||
GBinderLocalRequest* req;
|
||||
@@ -608,35 +573,29 @@ test_obj_run(
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
ipc_proxy = gbinder_ipc_new(DEV);
|
||||
ipc_obj = gbinder_ipc_new(DEV_PRIV);
|
||||
ipc_proxy = gbinder_ipc_new(DEV2, NULL);
|
||||
ipc_obj = gbinder_ipc_new(DEV, NULL);
|
||||
fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
|
||||
fd_obj = gbinder_driver_fd(ipc_obj->driver);
|
||||
|
||||
obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_obj_cb, &test);
|
||||
obj2 = gbinder_local_object_new(ipc_obj, TEST_IFACES2, test_obj2_cb, &test);
|
||||
remote_obj = gbinder_remote_object_new(ipc_proxy,
|
||||
GDEBUG("obj %p", obj);
|
||||
remote_obj = gbinder_remote_object_new(ipc_obj,
|
||||
test_binder_register_object(fd_obj, obj, AUTO_HANDLE),
|
||||
REMOTE_OBJECT_CREATE_ALIVE);
|
||||
|
||||
/* remote_proxy(DEV_PRIV) => proxy (DEV) => obj (DEV) => DEV_PRIV */
|
||||
g_assert(!gbinder_proxy_object_new(NULL, remote_obj));
|
||||
g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
|
||||
remote_proxy = gbinder_remote_object_new(ipc_obj,
|
||||
test_binder_register_object(fd_proxy, &proxy->parent, AUTO_HANDLE),
|
||||
REMOTE_OBJECT_CREATE_ALIVE);
|
||||
proxy_client = gbinder_client_new(remote_proxy, TEST_IFACE);
|
||||
|
||||
test_binder_set_passthrough(fd_obj, TRUE);
|
||||
test_binder_set_passthrough(fd_proxy, TRUE);
|
||||
test_binder_set_looper_enabled(fd_obj, TEST_LOOPER_ENABLE);
|
||||
test_binder_set_looper_enabled(fd_proxy, TEST_LOOPER_ENABLE);
|
||||
GDEBUG("proxy %p", proxy);
|
||||
client = gbinder_client_new(proxy->remote, TEST_IFACE);
|
||||
|
||||
/* Pass object reference via proxy */
|
||||
req = gbinder_client_new_request(proxy_client);
|
||||
obj2 = gbinder_local_object_new(ipc_obj, TEST_IFACES2, test_obj2_cb, &test);
|
||||
GDEBUG("obj2 %p", obj2);
|
||||
req = gbinder_client_new_request(client);
|
||||
gbinder_local_request_append_int32(req, TX_PARAM1);
|
||||
gbinder_local_request_append_local_object(req, obj2);
|
||||
gbinder_local_request_append_int32(req, TX_PARAM2);
|
||||
gbinder_client_transact(proxy_client, TX_CODE, 0, req, test_obj_reply,
|
||||
gbinder_client_transact(client, TX_CODE, 0, req, test_obj_reply,
|
||||
NULL, &test);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
@@ -646,20 +605,19 @@ test_obj_run(
|
||||
g_assert(test.obj_call_finished);
|
||||
g_assert(test.obj2_call_handled);
|
||||
g_assert(test.obj2_call_finished);
|
||||
g_assert(test.tmp_proxy);
|
||||
gbinder_local_object_unref(test.tmp_proxy);
|
||||
g_assert(test.obj2);
|
||||
gbinder_local_object_unref(test.obj2);
|
||||
|
||||
test_binder_unregister_objects(fd_obj);
|
||||
test_binder_unregister_objects(fd_proxy);
|
||||
|
||||
gbinder_local_object_drop(obj);
|
||||
gbinder_local_object_drop(obj2);
|
||||
gbinder_local_object_drop(&proxy->parent);
|
||||
gbinder_remote_object_unref(remote_obj);
|
||||
gbinder_remote_object_unref(remote_proxy);
|
||||
gbinder_client_unref(proxy_client);
|
||||
gbinder_client_unref(client);
|
||||
gbinder_ipc_unref(ipc_obj);
|
||||
gbinder_ipc_unref(ipc_proxy);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, test.loop);
|
||||
test_config_deinit(&config);
|
||||
g_main_loop_unref(test.loop);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018-2022 Jolla Ltd.
|
||||
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2023 Slava Monich <slava@monich.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -31,6 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#include "test_binder.h"
|
||||
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
@@ -39,6 +41,8 @@
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_io.h"
|
||||
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
@@ -57,14 +61,46 @@ typedef struct binder_buffer_object_64 {
|
||||
} BinderObject64;
|
||||
|
||||
#define BINDER_TYPE_(c1,c2,c3) GBINDER_FOURCC(c1,c2,c3,0x85)
|
||||
#define BINDER_TYPE_HANDLE BINDER_TYPE_('s','h','*')
|
||||
#define BINDER_TYPE_PTR BINDER_TYPE_('p','t','*')
|
||||
#define BINDER_TYPE_FD BINDER_TYPE_('f', 'd', '*')
|
||||
#define BINDER_BUFFER_FLAG_HAS_PARENT 0x01
|
||||
#define BINDER_FLAG_ACCEPTS_FDS 0x100
|
||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
|
||||
G_STATIC_ASSERT(sizeof(BinderObject64) == BUFFER_OBJECT_SIZE_64);
|
||||
|
||||
static
|
||||
void
|
||||
test_init_reader(
|
||||
GBinderDriver* driver,
|
||||
GBinderReaderData* data,
|
||||
GBinderReader* reader,
|
||||
const void* bytes,
|
||||
gsize size)
|
||||
{
|
||||
data->buffer = gbinder_buffer_new(driver, gutil_memdup(bytes, size),
|
||||
size, NULL);
|
||||
gbinder_reader_init(reader, data, 0, size);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
GBinderReader reader;
|
||||
|
||||
/* NULL const pointers are tolerated */
|
||||
g_assert(gbinder_reader_at_end(NULL));
|
||||
g_assert(!gbinder_reader_bytes_read(NULL));
|
||||
g_assert(!gbinder_reader_bytes_remaining(NULL));
|
||||
g_assert(!gbinder_reader_get_data(NULL, NULL));
|
||||
|
||||
gbinder_reader_copy(&reader, NULL);
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* empty
|
||||
*==========================================================================*/
|
||||
@@ -76,14 +112,19 @@ test_empty(
|
||||
{
|
||||
GBinderReader reader;
|
||||
gsize count = 1, elemsize = 1;
|
||||
gsize len;
|
||||
gsize size = 1;
|
||||
|
||||
gbinder_reader_init(&reader, NULL, 0, 0);
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert(!gbinder_reader_get_data(&reader, NULL));
|
||||
g_assert(!gbinder_reader_get_data(&reader, &size));
|
||||
g_assert(!size);
|
||||
g_assert(!gbinder_reader_bytes_read(&reader));
|
||||
g_assert(!gbinder_reader_bytes_remaining(&reader));
|
||||
g_assert(!gbinder_reader_read_byte(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_bool(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_int8(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_int16(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_int32(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_uint32(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_int64(&reader, NULL));
|
||||
@@ -93,6 +134,7 @@ test_empty(
|
||||
g_assert(!gbinder_reader_read_object(&reader));
|
||||
g_assert(!gbinder_reader_read_nullable_object(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_buffer(&reader));
|
||||
g_assert(!gbinder_reader_read_parcelable(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_hidl_struct1(&reader, 1));
|
||||
g_assert(!gbinder_reader_read_hidl_vec(&reader, NULL, NULL));
|
||||
g_assert(!gbinder_reader_read_hidl_vec(&reader, &count, &elemsize));
|
||||
@@ -107,7 +149,7 @@ test_empty(
|
||||
g_assert(!gbinder_reader_read_string8(&reader));
|
||||
g_assert(!gbinder_reader_read_string16(&reader));
|
||||
g_assert(!gbinder_reader_skip_string16(&reader));
|
||||
g_assert(!gbinder_reader_read_byte_array(&reader, &len));
|
||||
g_assert(!gbinder_reader_read_byte_array(&reader, &size));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -133,7 +175,7 @@ test_byte(
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in));
|
||||
g_assert(gbinder_reader_read_byte(&reader, &out));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert(in == out);
|
||||
g_assert_cmpuint(in, == ,out);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in));
|
||||
g_assert(gbinder_reader_read_byte(&reader, NULL));
|
||||
@@ -152,8 +194,8 @@ void
|
||||
test_bool(
|
||||
void)
|
||||
{
|
||||
const guint8 in_true[4] = { 0x01, 0xff, 0xff, 0xff };
|
||||
const guint8 in_false[4] = { 0x00, 0xff, 0xff, 0xff };
|
||||
const guint8 in_true[] = { TEST_INT8_BYTES_4(TRUE) };
|
||||
const guint8 in_false[] = { TEST_INT8_BYTES_4(FALSE) };
|
||||
gboolean out = FALSE;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
@@ -172,7 +214,7 @@ test_bool(
|
||||
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
|
||||
g_assert(gbinder_reader_read_bool(&reader, &out));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert(out == TRUE);
|
||||
g_assert_cmpuint(out, == ,TRUE);
|
||||
|
||||
/* false */
|
||||
gbinder_buffer_free(data.buffer);
|
||||
@@ -192,6 +234,108 @@ test_bool(
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* int8
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_int8(
|
||||
void)
|
||||
{
|
||||
const guint8 in = 0x2a;
|
||||
const guint8 in4[] = { 0x2a, 0x00, 0x00, 0x00 };
|
||||
guint8 out1 = 0;
|
||||
gint8 out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
g_assert(driver);
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
/* Not enough data */
|
||||
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
|
||||
sizeof(in), NULL);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in));
|
||||
g_assert(!gbinder_reader_read_uint8(&reader, &out1));
|
||||
g_assert(!gbinder_reader_at_end(&reader));
|
||||
gbinder_buffer_free(data.buffer);
|
||||
|
||||
/* Enough data */
|
||||
data.buffer = gbinder_buffer_new(driver, g_memdup(in4, sizeof(in4)),
|
||||
sizeof(in4), NULL);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
|
||||
g_assert(gbinder_reader_read_uint8(&reader, &out1));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert_cmpuint(in, == ,out1);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
|
||||
g_assert(gbinder_reader_read_int8(&reader, &out2));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert_cmpint(in, == ,out2);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
|
||||
g_assert(gbinder_reader_read_int8(&reader, NULL));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
|
||||
gbinder_buffer_free(data.buffer);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* int16
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_int16(
|
||||
void)
|
||||
{
|
||||
const guint16 in = 42;
|
||||
const guint8 in4[] = { TEST_INT16_BYTES(42), 0x00, 0x00 };
|
||||
guint16 out1 = 0;
|
||||
gint16 out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
g_assert(driver);
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
/* Not enough data */
|
||||
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
|
||||
sizeof(in), NULL);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in));
|
||||
g_assert(!gbinder_reader_read_uint16(&reader, &out1));
|
||||
g_assert(!gbinder_reader_at_end(&reader));
|
||||
gbinder_buffer_free(data.buffer);
|
||||
|
||||
/* Enough data */
|
||||
data.buffer = gbinder_buffer_new(driver, g_memdup(in4, sizeof(in4)),
|
||||
sizeof(in4), NULL);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
|
||||
g_assert(gbinder_reader_read_uint16(&reader, &out1));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert_cmpuint(in, == ,out1);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
|
||||
g_assert(gbinder_reader_read_int16(&reader, &out2));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert_cmpint(in, == ,out2);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
|
||||
g_assert(gbinder_reader_read_int16(&reader, NULL));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
|
||||
gbinder_buffer_free(data.buffer);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* int32
|
||||
*==========================================================================*/
|
||||
@@ -624,7 +768,7 @@ test_hidl_struct(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestHidlStruct* test = test_data;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(test->in, test->in_size), test->in_size, NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -644,6 +788,7 @@ test_hidl_struct(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -828,7 +973,7 @@ test_hidl_vec(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestHidlVec* test = test_data;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(test->in, test->in_size), test->in_size, NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -879,6 +1024,7 @@ test_hidl_vec(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -934,7 +1080,7 @@ test_hidl_string_err(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestHidlStringErr* test = test_data;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(test->in, test->in_size), test->in_size, NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -960,6 +1106,7 @@ test_hidl_string_err(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -968,7 +1115,7 @@ test_hidl_string_err_skip(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestHidlStringErr* test = test_data;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(test->in, test->in_size), test->in_size, NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -994,6 +1141,7 @@ test_hidl_string_err_skip(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1013,7 +1161,7 @@ test_fd_ok(
|
||||
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -1037,6 +1185,7 @@ test_fd_ok(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1053,7 +1202,7 @@ test_fd_shortbuf(
|
||||
TEST_INT32_BYTES(BINDER_TYPE_FD),
|
||||
TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -1068,6 +1217,7 @@ test_fd_shortbuf(
|
||||
g_assert(gbinder_reader_read_fd(&reader) < 0);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1087,7 +1237,7 @@ test_fd_badtype(
|
||||
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -1111,6 +1261,7 @@ test_fd_badtype(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1130,7 +1281,7 @@ test_dupfd_ok(
|
||||
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -1158,6 +1309,7 @@ test_dupfd_ok(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1177,7 +1329,7 @@ test_dupfd_badtype(
|
||||
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -1201,6 +1353,7 @@ test_dupfd_badtype(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1220,7 +1373,7 @@ test_dupfd_badfd(
|
||||
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderReaderData data;
|
||||
@@ -1244,6 +1397,7 @@ test_dupfd_badfd(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1259,7 +1413,7 @@ test_hidl_string(
|
||||
guint bufcount,
|
||||
const char* result)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver, g_memdup(input, size),
|
||||
size, NULL);
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
@@ -1284,6 +1438,7 @@ test_hidl_string(
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -1530,7 +1685,7 @@ test_buffer(
|
||||
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
|
||||
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
@@ -1562,6 +1717,99 @@ test_buffer(
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* parcelable
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_parcelable(
|
||||
void)
|
||||
{
|
||||
const guint8 input_null_header[] = {
|
||||
TEST_INT32_BYTES(0)
|
||||
};
|
||||
const guint8 input_broken_header[] = {
|
||||
TEST_INT32_BYTES(1),
|
||||
TEST_INT32_BYTES(1)
|
||||
};
|
||||
const guint8 input_non_null_header[] = {
|
||||
TEST_INT32_BYTES(1),
|
||||
/* Size must be size of itself + payload */
|
||||
TEST_INT32_BYTES(sizeof(gint32) * 3)
|
||||
};
|
||||
const guint8 input_non_null_payload[] = {
|
||||
TEST_INT32_BYTES(10),
|
||||
TEST_INT32_BYTES(20)
|
||||
};
|
||||
gpointer in;
|
||||
gsize in_size, out_size;
|
||||
const void* out = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
g_assert(driver);
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
/* Missing payload */
|
||||
test_init_reader(driver, &data, &reader,
|
||||
TEST_ARRAY_AND_SIZE(input_non_null_header));
|
||||
out = gbinder_reader_read_parcelable(&reader, &out_size);
|
||||
g_assert(!out);
|
||||
g_assert_cmpuint(out_size, == ,0);
|
||||
gbinder_buffer_free(data.buffer);
|
||||
|
||||
/* Broken headers */
|
||||
test_init_reader(driver, &data, &reader, input_broken_header, 4);
|
||||
out = gbinder_reader_read_parcelable(&reader, &out_size);
|
||||
g_assert(!out);
|
||||
g_assert_cmpuint(out_size, == ,0);
|
||||
gbinder_buffer_free(data.buffer);
|
||||
|
||||
test_init_reader(driver, &data, &reader,
|
||||
TEST_ARRAY_AND_SIZE(input_broken_header));
|
||||
out = gbinder_reader_read_parcelable(&reader, &out_size);
|
||||
g_assert(!out);
|
||||
g_assert_cmpuint(out_size, == ,0);
|
||||
gbinder_buffer_free(data.buffer);
|
||||
|
||||
/* Null */
|
||||
test_init_reader(driver, &data, &reader,
|
||||
TEST_ARRAY_AND_SIZE(input_null_header));
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(input_null_header));
|
||||
out = gbinder_reader_read_parcelable(&reader, &out_size);
|
||||
g_assert(!out);
|
||||
g_assert_cmpuint(out_size, == ,0);
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
gbinder_buffer_free(data.buffer);
|
||||
|
||||
/* Non-null */
|
||||
in_size = sizeof(input_non_null_header) + sizeof(input_non_null_payload);
|
||||
in = g_malloc(in_size);
|
||||
memcpy(in, &input_non_null_header, sizeof(input_non_null_header));
|
||||
memcpy(in + sizeof(input_non_null_header), &input_non_null_payload,
|
||||
sizeof(input_non_null_payload));
|
||||
data.buffer = gbinder_buffer_new(driver, in, in_size, NULL);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, in_size);
|
||||
out = gbinder_reader_read_parcelable(&reader, &out_size);
|
||||
g_assert(memcmp(&input_non_null_payload, out,
|
||||
sizeof(input_non_null_payload)) == 0);
|
||||
g_assert_cmpuint(out_size, == ,sizeof(input_non_null_payload));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
|
||||
/* And verify NULL tolerance for the size parameter */
|
||||
gbinder_reader_init(&reader, &data, 0, in_size);
|
||||
out = gbinder_reader_read_parcelable(&reader, NULL);
|
||||
g_assert(memcmp(&input_non_null_payload, out,
|
||||
sizeof(input_non_null_payload)) == 0);
|
||||
|
||||
gbinder_buffer_free(data.buffer);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1576,9 +1824,10 @@ test_object(
|
||||
/* Using 64-bit I/O */
|
||||
static const guint8 input[] = {
|
||||
TEST_INT32_BYTES(BINDER_TYPE_HANDLE), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(1 /* handle*/), TEST_INT64_BYTES(0)
|
||||
TEST_INT32_BYTES(1 /* handle*/), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
@@ -1596,12 +1845,13 @@ test_object(
|
||||
|
||||
g_assert(gbinder_reader_read_nullable_object(&reader, &obj));
|
||||
g_assert(obj);
|
||||
g_assert(obj->handle == 1);
|
||||
g_assert_cmpuint(obj->handle, == ,1);
|
||||
|
||||
g_free(data.objects);
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1636,7 +1886,7 @@ test_object_invalid(
|
||||
TEST_INT32_BYTES(42 /* invalid type */), TEST_INT32_BYTES(0),
|
||||
TEST_INT64_BYTES(1 /* handle*/), TEST_INT64_BYTES(0)
|
||||
};
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(input, sizeof(input)), sizeof(input), NULL);
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
@@ -1658,6 +1908,7 @@ test_object_invalid(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1670,7 +1921,7 @@ test_vec(
|
||||
void)
|
||||
{
|
||||
/* Using 64-bit I/O */
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderReaderData data;
|
||||
GBinderReader reader;
|
||||
BinderObject64 obj;
|
||||
@@ -1710,6 +1961,7 @@ test_vec(
|
||||
g_free(data.objects);
|
||||
gbinder_buffer_free(data.buffer);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -1723,7 +1975,7 @@ test_hidl_string_vec(
|
||||
gsize size,
|
||||
const char* const* result)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver, g_memdup(input, size),
|
||||
size, NULL);
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
@@ -1746,8 +1998,7 @@ test_hidl_string_vec(
|
||||
data.objects[i] = NULL;
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, buf->size);
|
||||
out = gbinder_reader_read_hidl_string_vec(&reader)
|
||||
;
|
||||
out = gbinder_reader_read_hidl_string_vec(&reader);
|
||||
if (out) {
|
||||
const guint n = g_strv_length(out);
|
||||
|
||||
@@ -1765,6 +2016,7 @@ test_hidl_string_vec(
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -1864,7 +2116,6 @@ test_hidl_string_vec2(
|
||||
TEST_INT64_BYTES(2),
|
||||
TEST_INT64_BYTES(sizeof(GBinderHidlString) +
|
||||
GBINDER_HIDL_STRING_BUFFER_OFFSET)
|
||||
|
||||
};
|
||||
static const char* const result[] = { str1, str2, NULL };
|
||||
|
||||
@@ -1990,7 +2241,6 @@ test_hidl_string_vec5(
|
||||
TEST_INT64_BYTES(sizeof(str2)),
|
||||
TEST_INT64_BYTES(2),
|
||||
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
|
||||
|
||||
};
|
||||
|
||||
test_hidl_string_vec(TEST_ARRAY_AND_SIZE(input), NULL);
|
||||
@@ -2098,9 +2348,9 @@ test_copy(
|
||||
gint32 in_len2 = sizeof(in_data2) - 1;
|
||||
const void* out_data = NULL;
|
||||
gsize out_len = 0;
|
||||
void* tmp;
|
||||
guint8* ptr;
|
||||
gsize tmp_len = 2 * sizeof(guint32) + in_len1 + in_len2;
|
||||
void* buf;
|
||||
gsize buf_len = 2 * sizeof(guint32) + in_len1 + in_len2;
|
||||
|
||||
GBinderDriver* driver;
|
||||
GBinderReader reader;
|
||||
@@ -2109,7 +2359,7 @@ test_copy(
|
||||
|
||||
/* test for data */
|
||||
g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
|
||||
ptr = tmp = g_malloc0(tmp_len);
|
||||
ptr = buf = g_malloc0(buf_len);
|
||||
memcpy(ptr, &in_len1, sizeof(in_len1));
|
||||
ptr += sizeof(in_len1);
|
||||
memcpy(ptr, in_data1, in_len1);
|
||||
@@ -2119,28 +2369,40 @@ test_copy(
|
||||
memcpy(ptr, in_data2, in_len2);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.buffer = gbinder_buffer_new(driver, tmp, tmp_len, NULL);
|
||||
gbinder_reader_init(&reader, &data, 0, tmp_len);
|
||||
data.buffer = gbinder_buffer_new(driver, buf, buf_len, NULL);
|
||||
gbinder_reader_init(&reader, &data, 0, buf_len);
|
||||
|
||||
/* Read the first array */
|
||||
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
|
||||
g_assert((gsize)in_len1 == out_len);
|
||||
g_assert_cmpuint(in_len1, == ,out_len);
|
||||
g_assert(memcmp(in_data1, out_data, in_len1) == 0);
|
||||
|
||||
/* Fetch raw data */
|
||||
g_assert((out_data = gbinder_reader_get_data(&reader, &out_len)));
|
||||
g_assert(out_data == gbinder_reader_get_data(&reader, NULL));
|
||||
g_assert_cmpuint(out_len, == ,buf_len);
|
||||
g_assert(memcmp(out_data, buf, buf_len) == 0);
|
||||
|
||||
/* Copy the reader */
|
||||
gbinder_reader_copy(&reader2, &reader);
|
||||
|
||||
/* Read both and compare the output */
|
||||
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert((gsize)in_len2 == out_len);
|
||||
g_assert_cmpuint(in_len1, == ,out_len);
|
||||
g_assert(memcmp(in_data2, out_data, in_len2) == 0);
|
||||
|
||||
g_assert((out_data = gbinder_reader_read_byte_array(&reader2, &out_len)));
|
||||
g_assert(gbinder_reader_at_end(&reader2));
|
||||
g_assert((gsize)in_len2 == out_len);
|
||||
g_assert_cmpuint(in_len2, == ,out_len);
|
||||
g_assert(memcmp(in_data2, out_data, in_len2) == 0);
|
||||
|
||||
/* Fetch raw data from the copied reader */
|
||||
g_assert((out_data = gbinder_reader_get_data(&reader2, &out_len)));
|
||||
g_assert(out_data == gbinder_reader_get_data(&reader2, NULL));
|
||||
g_assert_cmpuint(out_len, == ,buf_len);
|
||||
g_assert(memcmp(out_data, buf, buf_len) == 0);
|
||||
|
||||
gbinder_buffer_free(data.buffer);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
@@ -2161,9 +2423,12 @@ int main(int argc, char* argv[])
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func(TEST_("null"), test_null);
|
||||
g_test_add_func(TEST_("empty"), test_empty);
|
||||
g_test_add_func(TEST_("byte"), test_byte);
|
||||
g_test_add_func(TEST_("bool"), test_bool);
|
||||
g_test_add_func(TEST_("int8"), test_int8);
|
||||
g_test_add_func(TEST_("int16"), test_int16);
|
||||
g_test_add_func(TEST_("int32"), test_int32);
|
||||
g_test_add_func(TEST_("int64"), test_int64);
|
||||
g_test_add_func(TEST_("float"), test_float);
|
||||
@@ -2232,6 +2497,7 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_("hidl_string/6"), test_hidl_string6);
|
||||
g_test_add_func(TEST_("hidl_string/7"), test_hidl_string7);
|
||||
g_test_add_func(TEST_("buffer"), test_buffer);
|
||||
g_test_add_func(TEST_("parcelable"), test_parcelable);
|
||||
g_test_add_func(TEST_("object/valid"), test_object);
|
||||
g_test_add_func(TEST_("object/invalid"), test_object_invalid);
|
||||
g_test_add_func(TEST_("object/no_reg"), test_object_no_reg);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -68,7 +68,7 @@ void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj1 = gbinder_object_registry_get_remote(reg,1,TRUE);
|
||||
GBinderRemoteObject* obj2 = gbinder_object_registry_get_remote(reg,2,TRUE);
|
||||
@@ -89,6 +89,7 @@ test_basic(
|
||||
gbinder_remote_object_unref(obj1);
|
||||
gbinder_remote_object_unref(obj2);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -112,15 +113,14 @@ test_dead_run(
|
||||
{
|
||||
const guint h = 1;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, h, TRUE);
|
||||
gulong id = gbinder_remote_object_add_death_handler
|
||||
(obj, test_dead_done, loop);
|
||||
|
||||
test_binder_br_dead_binder(fd, h);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_br_dead_binder(fd, ANY_THREAD, h);
|
||||
test_run(&test_opt, loop);
|
||||
g_assert(gbinder_remote_object_is_dead(obj));
|
||||
|
||||
@@ -128,7 +128,7 @@ test_dead_run(
|
||||
gbinder_remote_object_remove_handler(obj, 0); /* has no effect */
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#include "test_binder.h"
|
||||
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
@@ -44,9 +45,6 @@
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define BINDER_TYPE_BINDER GBINDER_FOURCC('s', 'b', '*', 0x85)
|
||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
|
||||
|
||||
/*==========================================================================*
|
||||
* Dummy GBinderObjectRegistry functions
|
||||
*==========================================================================*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -31,8 +31,10 @@
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#include "test_binder.h"
|
||||
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_remote_request_p.h"
|
||||
@@ -58,9 +60,6 @@ static TestOpt test_opt;
|
||||
#define HIDL_RPC_HEADER \
|
||||
'f', 'o', 'o', 0x00
|
||||
|
||||
#define BINDER_TYPE_BINDER GBINDER_FOURCC('s', 'b', '*', 0x85)
|
||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
@@ -369,6 +368,18 @@ test_to_local(
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const char* default_config_dir;
|
||||
const char* default_config_file;
|
||||
char* conf_dir = g_dir_make_tmp("gbinder-test-remote-request-XXXXXX", NULL);
|
||||
char* conf_file = g_build_filename(conf_dir, "test.conf", NULL);
|
||||
int result;
|
||||
|
||||
/* Point gbinder_config_file to a non-existent file */
|
||||
default_config_dir = gbinder_config_dir;
|
||||
default_config_file = gbinder_config_file;
|
||||
gbinder_config_dir = conf_dir;
|
||||
gbinder_config_file = conf_file;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "basic", test_basic);
|
||||
@@ -378,7 +389,14 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_PREFIX "string16", test_string16);
|
||||
g_test_add_func(TEST_PREFIX "to_local", test_to_local);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
result = g_test_run();
|
||||
|
||||
gbinder_config_dir = default_config_dir;
|
||||
gbinder_config_file = default_config_file;
|
||||
remove(conf_dir);
|
||||
g_free(conf_dir);
|
||||
g_free(conf_file);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -133,9 +133,9 @@ test_setup_ping(
|
||||
{
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_reply(fd, 0, 0, NULL);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -386,8 +386,25 @@ gbinder_servicemanager_aidl_get_type()
|
||||
GType
|
||||
gbinder_servicemanager_aidl2_get_type()
|
||||
{
|
||||
/* Avoid pulling in gbinder_servicemanager_aidl2 object */
|
||||
return TEST_TYPE_DEFSERVICEMANAGER;
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl2 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl3_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl3 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl4_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -400,9 +417,10 @@ test_null(
|
||||
void)
|
||||
{
|
||||
g_assert(!gbinder_servicemanager_new(NULL));
|
||||
g_assert(!gbinder_servicemanager_new_with_type(0, NULL));
|
||||
g_assert(!gbinder_servicemanager_new_with_type(0, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_new_local_object(NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_ref(NULL));
|
||||
g_assert(!gbinder_servicemanager_device(NULL));
|
||||
g_assert(!gbinder_servicemanager_is_present(NULL));
|
||||
g_assert(!gbinder_servicemanager_wait(NULL, 0));
|
||||
g_assert(!gbinder_servicemanager_list(NULL, NULL, NULL));
|
||||
@@ -432,14 +450,15 @@ test_invalid(
|
||||
{
|
||||
int status = 0;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderServiceManager* sm;
|
||||
gulong id = 0;
|
||||
|
||||
test_setup_ping(ipc);
|
||||
g_assert(!gbinder_servicemanager_new2(GBINDER_DEFAULT_HWBINDER, "a", NULL));
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
g_assert(!gbinder_servicemanager_new_with_type(GBINDER_TYPE_LOCAL_OBJECT,
|
||||
NULL));
|
||||
NULL, NULL));
|
||||
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
|
||||
g_assert(!gbinder_servicemanager_list(sm, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_get_service(sm, "foo", NULL, NULL));
|
||||
@@ -465,6 +484,7 @@ test_invalid(
|
||||
gbinder_servicemanager_remove_handlers(sm, &id, 0);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -477,7 +497,7 @@ test_basic(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderServiceManager* sm;
|
||||
GBinderLocalObject* obj;
|
||||
|
||||
@@ -487,13 +507,14 @@ test_basic(
|
||||
obj = gbinder_servicemanager_new_local_object(sm, "foo.bar",
|
||||
test_transact_func, NULL);
|
||||
g_assert(obj);
|
||||
g_assert_cmpstr(gbinder_servicemanager_device(sm), == ,dev);
|
||||
gbinder_local_object_unref(obj);
|
||||
|
||||
g_assert(gbinder_servicemanager_ref(sm) == sm);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -507,7 +528,7 @@ test_legacy(
|
||||
{
|
||||
const char* otherdev = "/dev/otherbinder";
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderServiceManager* sm;
|
||||
|
||||
/* Reset the state */
|
||||
@@ -528,7 +549,7 @@ test_legacy(
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* Legacy default */
|
||||
ipc = gbinder_ipc_new(otherdev);
|
||||
ipc = gbinder_ipc_new(otherdev, NULL);
|
||||
test_setup_ping(ipc);
|
||||
sm = gbinder_servicemanager_new(otherdev);
|
||||
g_assert(TEST_IS_DEFSERVICEMANAGER(sm));
|
||||
@@ -536,7 +557,7 @@ test_legacy(
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_servicemanager_exit();
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -571,7 +592,7 @@ test_config(
|
||||
gbinder_config_file = file;
|
||||
|
||||
/* Unknown device instantiates the default */
|
||||
ipc = gbinder_ipc_new(strange_name);
|
||||
ipc = gbinder_ipc_new(strange_name, NULL);
|
||||
test_setup_ping(ipc);
|
||||
sm = gbinder_servicemanager_new(strange_name);
|
||||
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
|
||||
@@ -579,7 +600,7 @@ test_config(
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* This one was redefined */
|
||||
ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
test_setup_ping(ipc);
|
||||
sm = gbinder_servicemanager_new(GBINDER_DEFAULT_BINDER);
|
||||
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
|
||||
@@ -587,7 +608,7 @@ test_config(
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* This one was not (since name was invalid) */
|
||||
ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
test_setup_ping(ipc);
|
||||
sm = gbinder_servicemanager_new(GBINDER_DEFAULT_HWBINDER);
|
||||
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
|
||||
@@ -595,17 +616,26 @@ test_config(
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* This one points to legacy manager */
|
||||
ipc = gbinder_ipc_new(legacy_name);
|
||||
ipc = gbinder_ipc_new(legacy_name, NULL);
|
||||
test_setup_ping(ipc);
|
||||
sm = gbinder_servicemanager_new(legacy_name);
|
||||
g_assert(TEST_IS_DEFSERVICEMANAGER(sm));
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* Overwrite the legacy manager with "hidl" */
|
||||
ipc = gbinder_ipc_new(legacy_name, "hidl");
|
||||
test_setup_ping(ipc);
|
||||
sm = gbinder_servicemanager_new2(legacy_name, "hidl", "hidl");
|
||||
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* Clear the state */
|
||||
gbinder_servicemanager_exit();
|
||||
gbinder_config_exit();
|
||||
gbinder_config_file = NULL;
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
|
||||
remove(file);
|
||||
remove(dir);
|
||||
@@ -623,12 +653,12 @@ test_not_present(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderServiceManager* sm;
|
||||
|
||||
/* This makes presence detection PING fail */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
g_assert(sm);
|
||||
@@ -636,6 +666,7 @@ test_not_present(
|
||||
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -648,7 +679,7 @@ test_wait(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const glong forever = (test_opt.flags & TEST_FLAG_DEBUG) ?
|
||||
(TEST_TIMEOUT_SEC * 1000) : -1;
|
||||
@@ -657,7 +688,7 @@ test_wait(
|
||||
int count = 0;
|
||||
|
||||
/* This makes presence detection PING fail */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
g_assert(sm);
|
||||
@@ -668,13 +699,13 @@ test_wait(
|
||||
g_assert(id);
|
||||
|
||||
/* Make this wait fail */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
g_assert(!gbinder_servicemanager_wait(sm, 0));
|
||||
|
||||
/* This makes presence detection PING succeed */
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_reply(fd, 0, 0, NULL);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
|
||||
g_assert(gbinder_servicemanager_wait(sm, forever));
|
||||
|
||||
/* The next check succeeds too (without any I/O ) */
|
||||
@@ -686,7 +717,7 @@ test_wait(
|
||||
gbinder_servicemanager_remove_handler(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -699,14 +730,14 @@ test_wait_long(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderServiceManager* sm;
|
||||
gulong id;
|
||||
int count = 0;
|
||||
|
||||
/* This makes presence detection PING fail */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
g_assert(sm);
|
||||
@@ -717,10 +748,10 @@ test_wait_long(
|
||||
g_assert(id);
|
||||
|
||||
/* Make the first presence detection PING fail and second succeed */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_reply_status_later(fd, -1);
|
||||
test_binder_br_transaction_complete_later(fd);
|
||||
test_binder_br_reply_later(fd, 0, 0, NULL);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
test_binder_br_reply_status(fd, TX_THREAD, -1);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
test_binder_br_reply(fd, TX_THREAD, 0, 0, NULL);
|
||||
g_assert(gbinder_servicemanager_wait(sm, TEST_TIMEOUT_SEC * 1000));
|
||||
|
||||
/* The next check succeeds too (without any I/O ) */
|
||||
@@ -732,7 +763,7 @@ test_wait_long(
|
||||
gbinder_servicemanager_remove_handler(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -745,7 +776,7 @@ test_wait_async(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServiceManager* sm;
|
||||
@@ -753,7 +784,7 @@ test_wait_async(
|
||||
int count = 0;
|
||||
|
||||
/* This makes presence detection PING fail */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
g_assert(sm);
|
||||
@@ -766,9 +797,9 @@ test_wait_async(
|
||||
g_assert(id[1]);
|
||||
|
||||
/* Make the first presence detection PING fail and second succeed */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_transaction_complete_later(fd);
|
||||
test_binder_br_reply_later(fd, 0, 0, NULL);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
test_binder_br_transaction_complete(fd, TX_THREAD);
|
||||
test_binder_br_reply(fd, TX_THREAD, 0, 0, NULL);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* The listener must have been invoked exactly once */
|
||||
@@ -776,7 +807,7 @@ test_wait_async(
|
||||
gbinder_servicemanager_remove_all_handlers(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -789,7 +820,7 @@ void
|
||||
test_death_run()
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServiceManager* sm;
|
||||
@@ -810,9 +841,8 @@ test_death_run()
|
||||
g_assert(id[1]);
|
||||
g_assert(id[2]);
|
||||
|
||||
/* Generate death notification (need looper for that) */
|
||||
test_binder_br_dead_binder(fd, 0);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
/* Generate death notification */
|
||||
test_binder_br_dead_binder(fd, ANY_THREAD, 0);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* No registrations must have occured */
|
||||
@@ -824,7 +854,6 @@ test_death_run()
|
||||
gbinder_servicemanager_remove_all_handlers(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -852,11 +881,10 @@ test_reanimate_quit(
|
||||
} else {
|
||||
const int fd = gbinder_driver_fd(sm->client->remote->ipc->driver);
|
||||
|
||||
/* Disable looper and reanimate the object */
|
||||
/* Reanimate the object */
|
||||
GDEBUG("Reanimating...");
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_DISABLE);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_reply(fd, 0, 0, NULL);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -866,7 +894,7 @@ test_reanimate(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServiceManager* sm;
|
||||
@@ -889,9 +917,8 @@ test_reanimate(
|
||||
g_assert(id[1]);
|
||||
g_assert(id[2]);
|
||||
|
||||
/* Generate death notification (need looper for that) */
|
||||
test_binder_br_dead_binder(fd, 0);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
/* Generate death notification */
|
||||
test_binder_br_dead_binder(fd, ANY_THREAD, 0);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* No registrations must have occured */
|
||||
@@ -904,7 +931,6 @@ test_reanimate(
|
||||
gbinder_servicemanager_remove_all_handlers(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -921,9 +947,9 @@ test_reuse(
|
||||
const char* binder_dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* vndbinder_dev = "/dev/vpnbinder";
|
||||
const char* hwbinder_dev = GBINDER_DEFAULT_HWBINDER;
|
||||
GBinderIpc* binder_ipc = gbinder_ipc_new(binder_dev);
|
||||
GBinderIpc* vndbinder_ipc = gbinder_ipc_new(vndbinder_dev);
|
||||
GBinderIpc* hwbinder_ipc = gbinder_ipc_new(hwbinder_dev);
|
||||
GBinderIpc* binder_ipc = gbinder_ipc_new(binder_dev, NULL);
|
||||
GBinderIpc* vndbinder_ipc = gbinder_ipc_new(vndbinder_dev, NULL);
|
||||
GBinderIpc* hwbinder_ipc = gbinder_ipc_new(hwbinder_dev, NULL);
|
||||
GBinderServiceManager* m1;
|
||||
GBinderServiceManager* m2;
|
||||
GBinderServiceManager* vnd1;
|
||||
@@ -963,7 +989,7 @@ test_reuse(
|
||||
gbinder_ipc_unref(binder_ipc);
|
||||
gbinder_ipc_unref(vndbinder_ipc);
|
||||
gbinder_ipc_unref(hwbinder_ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -976,7 +1002,7 @@ test_notify_type(
|
||||
GType t,
|
||||
const char* dev)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderServiceManager* sm;
|
||||
TestHwServiceManager* test;
|
||||
const char* name = "foo";
|
||||
@@ -984,7 +1010,7 @@ test_notify_type(
|
||||
gulong id1, id2;
|
||||
|
||||
test_setup_ping(ipc);
|
||||
sm = gbinder_servicemanager_new_with_type(t, NULL);
|
||||
sm = gbinder_servicemanager_new_with_type(t, NULL, NULL);
|
||||
test = TEST_SERVICEMANAGER2(sm, t);
|
||||
id1 = gbinder_servicemanager_add_registration_handler(sm, name,
|
||||
test_registration_func_inc, &count);
|
||||
@@ -1008,7 +1034,7 @@ test_notify_type(
|
||||
gbinder_servicemanager_remove_handler(sm, id2);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -1044,7 +1070,7 @@ test_list(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServiceManager* sm;
|
||||
TestHwServiceManager* test;
|
||||
@@ -1066,7 +1092,7 @@ test_list(
|
||||
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -1093,7 +1119,7 @@ test_get(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServiceManager* sm;
|
||||
TestHwServiceManager* test;
|
||||
@@ -1130,7 +1156,7 @@ test_get(
|
||||
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -1155,7 +1181,7 @@ test_add(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServiceManager* sm;
|
||||
TestHwServiceManager* test;
|
||||
@@ -1178,7 +1204,7 @@ test_add(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Jolla Ltd.
|
||||
* Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
|
||||
* 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:
|
||||
*
|
||||
@@ -50,14 +50,32 @@ static TestOpt test_opt;
|
||||
GType
|
||||
gbinder_servicemanager_hidl_get_type()
|
||||
{
|
||||
/* Avoid pulling in gbinder_servicemanager_hidl object */
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_hidl */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl2_get_type()
|
||||
{
|
||||
/* Avoid pulling in gbinder_servicemanager_aidl2 object */
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl2 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl3_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl3 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl4_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -80,7 +98,6 @@ typedef GBinderLocalObjectClass ServiceManagerAidlClass;
|
||||
typedef struct service_manager_aidl {
|
||||
GBinderLocalObject parent;
|
||||
GHashTable* objects;
|
||||
gboolean handle_on_looper_thread;
|
||||
} ServiceManagerAidl;
|
||||
|
||||
#define SERVICE_MANAGER_AIDL_TYPE (service_manager_aidl_get_type())
|
||||
@@ -167,18 +184,15 @@ servicemanager_aidl_handler(
|
||||
static
|
||||
ServiceManagerAidl*
|
||||
servicemanager_aidl_new(
|
||||
const char* dev,
|
||||
gboolean handle_on_looper_thread)
|
||||
const char* dev)
|
||||
{
|
||||
ServiceManagerAidl* self = g_object_new(SERVICE_MANAGER_AIDL_TYPE, NULL);
|
||||
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
self->handle_on_looper_thread = handle_on_looper_thread;
|
||||
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
|
||||
servicemanager_aidl_handler, self);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
|
||||
gbinder_ipc_register_local_object(ipc, obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
@@ -193,41 +207,6 @@ servicemanager_aidl_free(
|
||||
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(self));
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
service_manager_aidl_can_handle_transaction(
|
||||
GBinderLocalObject* object,
|
||||
const char* iface,
|
||||
guint code)
|
||||
{
|
||||
ServiceManagerAidl* self = SERVICE_MANAGER_AIDL(object);
|
||||
|
||||
if (self->handle_on_looper_thread && !g_strcmp0(SVCMGR_IFACE, iface)) {
|
||||
return GBINDER_LOCAL_TRANSACTION_LOOPER;
|
||||
} else {
|
||||
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
|
||||
can_handle_transaction(object, iface, code);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
service_manager_aidl_handle_looper_transaction(
|
||||
GBinderLocalObject* object,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
if (!g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE)) {
|
||||
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
|
||||
handle_transaction(object, req, code, flags, status);
|
||||
} else {
|
||||
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
|
||||
handle_looper_transaction(object, req, code, flags, status);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl_finalize(
|
||||
@@ -253,14 +232,7 @@ void
|
||||
service_manager_aidl_class_init(
|
||||
ServiceManagerAidlClass* klass)
|
||||
{
|
||||
GObjectClass* object = G_OBJECT_CLASS(klass);
|
||||
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
|
||||
|
||||
object->finalize = service_manager_aidl_finalize;
|
||||
local_object->can_handle_transaction =
|
||||
service_manager_aidl_can_handle_transaction;
|
||||
local_object->handle_looper_transaction =
|
||||
service_manager_aidl_handle_looper_transaction;
|
||||
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl_finalize;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -311,9 +283,8 @@ void
|
||||
test_get_run()
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
ServiceManagerAidl* smsvc = servicemanager_aidl_new(dev);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* name = "name";
|
||||
@@ -322,7 +293,6 @@ test_get_run()
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(fd, obj, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
|
||||
/* Query the object (it's not there yet) and wait for completion */
|
||||
@@ -351,7 +321,6 @@ test_get_run()
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -393,9 +362,8 @@ void
|
||||
test_list_run()
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
ServiceManagerAidl* smsvc = servicemanager_aidl_new(dev);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* name = "name";
|
||||
@@ -407,7 +375,6 @@ test_list_run()
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(fd, obj, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
|
||||
/* Request the list and wait for completion */
|
||||
@@ -437,7 +404,6 @@ test_list_run()
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, test.loop);
|
||||
|
||||
g_strfreev(test.list);
|
||||
@@ -472,9 +438,8 @@ void
|
||||
test_notify_run()
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
ServiceManagerAidl* svc = servicemanager_aidl_new(other_dev, FALSE);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
ServiceManagerAidl* svc = servicemanager_aidl_new(dev);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* name = "name";
|
||||
@@ -484,7 +449,6 @@ test_notify_run()
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(fd, obj, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
gbinder_ipc_set_max_threads(ipc, 1);
|
||||
|
||||
@@ -508,7 +472,6 @@ test_notify_run()
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -529,9 +492,8 @@ void
|
||||
test_notify2_run()
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, TRUE);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
ServiceManagerAidl* smsvc = servicemanager_aidl_new(dev);
|
||||
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderServiceManager* sm;
|
||||
@@ -542,7 +504,6 @@ test_notify2_run()
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(fd, obj, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
gbinder_ipc_set_max_threads(ipc, 1);
|
||||
|
||||
@@ -575,7 +536,6 @@ test_notify2_run()
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Jolla Ltd.
|
||||
* Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
|
||||
* 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:
|
||||
*
|
||||
@@ -53,7 +53,8 @@ static const char TMP_DIR_TEMPLATE[] =
|
||||
GType
|
||||
gbinder_servicemanager_hidl_get_type()
|
||||
{
|
||||
/* Avoid pulling in gbinder_servicemanager_hidl object */
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_hidl */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -76,7 +77,6 @@ typedef GBinderLocalObjectClass ServiceManagerAidl2Class;
|
||||
typedef struct service_manager_aidl2 {
|
||||
GBinderLocalObject parent;
|
||||
GHashTable* objects;
|
||||
gboolean handle_on_looper_thread;
|
||||
} ServiceManagerAidl2;
|
||||
|
||||
#define SERVICE_MANAGER_AIDL2_TYPE (service_manager_aidl2_get_type())
|
||||
@@ -169,59 +169,21 @@ servicemanager_aidl2_handler(
|
||||
static
|
||||
ServiceManagerAidl2*
|
||||
servicemanager_aidl2_new(
|
||||
const char* dev,
|
||||
gboolean handle_on_looper_thread)
|
||||
const char* dev)
|
||||
{
|
||||
ServiceManagerAidl2* self = g_object_new(SERVICE_MANAGER_AIDL2_TYPE, NULL);
|
||||
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
self->handle_on_looper_thread = handle_on_looper_thread;
|
||||
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
|
||||
servicemanager_aidl2_handler, self);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
|
||||
gbinder_ipc_register_local_object(ipc, obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
service_manager_aidl2_can_handle_transaction(
|
||||
GBinderLocalObject* object,
|
||||
const char* iface,
|
||||
guint code)
|
||||
{
|
||||
ServiceManagerAidl2* self = SERVICE_MANAGER_AIDL2(object);
|
||||
|
||||
if (self->handle_on_looper_thread && !g_strcmp0(SVCMGR_IFACE, iface)) {
|
||||
return GBINDER_LOCAL_TRANSACTION_LOOPER;
|
||||
} else {
|
||||
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
|
||||
can_handle_transaction(object, iface, code);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
service_manager_aidl2_handle_looper_transaction(
|
||||
GBinderLocalObject* object,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
if (!g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE)) {
|
||||
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
|
||||
handle_transaction(object, req, code, flags, status);
|
||||
} else {
|
||||
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
|
||||
handle_looper_transaction(object, req, code, flags, status);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl2_finalize(
|
||||
@@ -247,14 +209,7 @@ void
|
||||
service_manager_aidl2_class_init(
|
||||
ServiceManagerAidl2Class* klass)
|
||||
{
|
||||
GObjectClass* object = G_OBJECT_CLASS(klass);
|
||||
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
|
||||
|
||||
object->finalize = service_manager_aidl2_finalize;
|
||||
local_object->can_handle_transaction =
|
||||
service_manager_aidl2_can_handle_transaction;
|
||||
local_object->handle_looper_transaction =
|
||||
service_manager_aidl2_handle_looper_transaction;
|
||||
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl2_finalize;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -270,6 +225,7 @@ typedef struct test_context {
|
||||
GBinderLocalObject* object;
|
||||
ServiceManagerAidl2* service;
|
||||
GBinderServiceManager* client;
|
||||
GMainLoop* loop;
|
||||
int fd;
|
||||
} TestContext;
|
||||
|
||||
@@ -279,11 +235,6 @@ test_context_init(
|
||||
TestContext* test)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
|
||||
/*
|
||||
* Also set defaults so that both /dev/binder and /dev/binder-private
|
||||
* use the same protocol.
|
||||
*/
|
||||
const char* config =
|
||||
"[Protocol]\n"
|
||||
"Default = aidl2\n"
|
||||
@@ -304,16 +255,13 @@ test_context_init(
|
||||
gbinder_config_dir = test->config_subdir; /* Doesn't exist */
|
||||
gbinder_config_file = test->config_file;
|
||||
|
||||
ipc = gbinder_ipc_new(dev);
|
||||
ipc = gbinder_ipc_new(dev, NULL);
|
||||
test->fd = gbinder_driver_fd(ipc->driver);
|
||||
test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(test->fd, TRUE);
|
||||
|
||||
test->service = servicemanager_aidl2_new(other_dev, TRUE);
|
||||
test->service = servicemanager_aidl2_new(dev);
|
||||
test->client = gbinder_servicemanager_new(dev);
|
||||
test->loop = g_main_loop_new(NULL, FALSE);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
@@ -322,22 +270,47 @@ void
|
||||
test_context_deinit(
|
||||
TestContext* test)
|
||||
{
|
||||
test_binder_unregister_objects(test->fd);
|
||||
test_binder_br_dead_binder_obj(test->fd, test->object);
|
||||
gbinder_local_object_unref(test->object);
|
||||
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
|
||||
gbinder_servicemanager_unref(test->client);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
test_binder_exit_wait(&test_opt, test->loop);
|
||||
remove(test->config_file);
|
||||
remove(test->config_dir);
|
||||
g_free(test->config_file);
|
||||
g_free(test->config_subdir);
|
||||
g_free(test->config_dir);
|
||||
g_main_loop_unref(test->loop);
|
||||
gbinder_config_dir = test->default_config_dir;
|
||||
gbinder_config_file = test->default_config_file;
|
||||
gbinder_config_exit();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_wait_ref_cb(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
GDEBUG("strong_refs %d", obj->strong_refs);
|
||||
if (obj->strong_refs > 0) {
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_wait_ref(
|
||||
TestContext* test)
|
||||
{
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
gulong id = gbinder_local_object_add_strong_refs_changed_handler
|
||||
(test->object, test_context_wait_ref_cb, test->loop);
|
||||
|
||||
test_run(&test_opt, test->loop);
|
||||
gbinder_local_object_remove_handler(test->object, id);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* get
|
||||
*==========================================================================*/
|
||||
@@ -366,12 +339,16 @@ test_get_run()
|
||||
g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
|
||||
g_assert(g_hash_table_contains(test.service->objects, name));
|
||||
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
test_context_wait_ref(&test);
|
||||
|
||||
/* Query the object (this time it must be there) */
|
||||
GDEBUG("Querying '%s' again", name);
|
||||
g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
|
||||
&status));
|
||||
g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
|
||||
|
||||
GDEBUG("Done");
|
||||
test_context_deinit(&test);
|
||||
}
|
||||
|
||||
@@ -409,6 +386,9 @@ test_list_run()
|
||||
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
|
||||
name, test.object), == ,GBINDER_STATUS_OK);
|
||||
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
test_context_wait_ref(&test);
|
||||
|
||||
/* Request the list again */
|
||||
list = gbinder_servicemanager_list_sync(test.client);
|
||||
|
||||
@@ -417,6 +397,7 @@ test_list_run()
|
||||
g_assert_cmpstr(list[0], == ,name);
|
||||
g_strfreev(list);
|
||||
|
||||
GDEBUG("Done");
|
||||
test_context_deinit(&test);
|
||||
}
|
||||
|
||||
|
||||
5
unit/unit_servicemanager_aidl3/Makefile
Normal file
5
unit/unit_servicemanager_aidl3/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_servicemanager_aidl3
|
||||
|
||||
include ../common/Makefile
|
||||
444
unit/unit_servicemanager_aidl3/unit_servicemanager_aidl3.c
Normal file
444
unit/unit_servicemanager_aidl3/unit_servicemanager_aidl3.c
Normal file
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "test_binder.h"
|
||||
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_local_reply.h"
|
||||
#include "gbinder_remote_request.h"
|
||||
#include "gbinder_remote_object.h"
|
||||
#include "gbinder_writer.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_log.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
static const char TMP_DIR_TEMPLATE[] =
|
||||
"gbinder-test-servicemanager_aidl3-XXXXXX";
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_hidl_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_hidl */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Test service manager
|
||||
*==========================================================================*/
|
||||
|
||||
#define SVCMGR_HANDLE (0)
|
||||
static const char SVCMGR_IFACE[] = "android.os.IServiceManager";
|
||||
enum servicemanager_aidl_tx {
|
||||
GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
CHECK_SERVICE_TRANSACTION,
|
||||
ADD_SERVICE_TRANSACTION,
|
||||
LIST_SERVICES_TRANSACTION
|
||||
};
|
||||
|
||||
const char* const servicemanager_aidl_ifaces[] = { SVCMGR_IFACE, NULL };
|
||||
|
||||
typedef GBinderLocalObjectClass ServiceManagerAidl3Class;
|
||||
typedef struct service_manager_aidl3 {
|
||||
GBinderLocalObject parent;
|
||||
GHashTable* objects;
|
||||
} ServiceManagerAidl3;
|
||||
|
||||
#define SERVICE_MANAGER_AIDL3_TYPE (service_manager_aidl3_get_type())
|
||||
#define SERVICE_MANAGER_AIDL3(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
SERVICE_MANAGER_AIDL3_TYPE, ServiceManagerAidl3))
|
||||
G_DEFINE_TYPE(ServiceManagerAidl3, service_manager_aidl3, \
|
||||
GBINDER_TYPE_LOCAL_OBJECT)
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
servicemanager_aidl3_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
ServiceManagerAidl3* self = user_data;
|
||||
GBinderLocalReply* reply = NULL;
|
||||
GBinderReader reader;
|
||||
GBinderRemoteObject* remote_obj;
|
||||
guint32 allow_isolated, dumpsys_priority;
|
||||
char* str;
|
||||
|
||||
g_assert(!flags);
|
||||
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
|
||||
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
|
||||
*status = -1;
|
||||
switch (code) {
|
||||
case GET_SERVICE_TRANSACTION:
|
||||
case CHECK_SERVICE_TRANSACTION:
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
str = gbinder_reader_read_string16(&reader);
|
||||
if (str) {
|
||||
GBinderWriter writer;
|
||||
|
||||
remote_obj = g_hash_table_lookup(self->objects, str);
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_remote_object(&writer, remote_obj);
|
||||
if (remote_obj) {
|
||||
GDEBUG("Found name '%s' => %p", str, remote_obj);
|
||||
} else {
|
||||
GDEBUG("Name '%s' not found", str);
|
||||
}
|
||||
g_free(str);
|
||||
}
|
||||
break;
|
||||
case ADD_SERVICE_TRANSACTION:
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
str = gbinder_reader_read_string16(&reader);
|
||||
remote_obj = gbinder_reader_read_object(&reader);
|
||||
if (str && remote_obj &&
|
||||
gbinder_reader_read_uint32(&reader, &allow_isolated) &&
|
||||
gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
|
||||
GDEBUG("Adding '%s'", str);
|
||||
g_hash_table_replace(self->objects, str, remote_obj);
|
||||
remote_obj = NULL;
|
||||
str = NULL;
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
}
|
||||
g_free(str);
|
||||
gbinder_remote_object_unref(remote_obj);
|
||||
break;
|
||||
case LIST_SERVICES_TRANSACTION:
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
if (gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
|
||||
if (g_hash_table_size(self->objects) == 1) {
|
||||
GList* keys = g_hash_table_get_keys(self->objects);
|
||||
GList* l = g_list_nth(keys, 0);
|
||||
gint32 srv_size = 1;
|
||||
GBinderWriter writer;
|
||||
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_int32(&writer, srv_size);
|
||||
gbinder_writer_append_string16(&writer, l->data);
|
||||
g_list_free(keys);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
} else {
|
||||
GDEBUG("Incorrect number of services %u",
|
||||
g_hash_table_size(self->objects));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GDEBUG("Unhandled command %u", code);
|
||||
break;
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
ServiceManagerAidl3*
|
||||
servicemanager_aidl3_new(
|
||||
const char* dev)
|
||||
{
|
||||
ServiceManagerAidl3* self = g_object_new(SERVICE_MANAGER_AIDL3_TYPE, NULL);
|
||||
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
|
||||
servicemanager_aidl3_handler, self);
|
||||
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
|
||||
gbinder_ipc_register_local_object(ipc, obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl3_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
ServiceManagerAidl3* self = SERVICE_MANAGER_AIDL3(object);
|
||||
|
||||
g_hash_table_destroy(self->objects);
|
||||
G_OBJECT_CLASS(service_manager_aidl3_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl3_init(
|
||||
ServiceManagerAidl3* self)
|
||||
{
|
||||
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
|
||||
(GDestroyNotify) gbinder_remote_object_unref);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl3_class_init(
|
||||
ServiceManagerAidl3Class* klass)
|
||||
{
|
||||
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl3_finalize;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Test context
|
||||
*==========================================================================*/
|
||||
|
||||
typedef struct test_context {
|
||||
const char* default_config_dir;
|
||||
const char* default_config_file;
|
||||
char* config_dir;
|
||||
char* config_subdir;
|
||||
char* config_file;
|
||||
GBinderLocalObject* object;
|
||||
ServiceManagerAidl3* service;
|
||||
GBinderServiceManager* client;
|
||||
GMainLoop* loop;
|
||||
int fd;
|
||||
} TestContext;
|
||||
|
||||
static
|
||||
void
|
||||
test_context_init(
|
||||
TestContext* test)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* config =
|
||||
"[Protocol]\n"
|
||||
"Default = aidl3\n"
|
||||
"/dev/binder = aidl3\n"
|
||||
"[ServiceManager]\n"
|
||||
"Default = aidl3\n"
|
||||
"/dev/binder = aidl3\n";
|
||||
GBinderIpc* ipc;
|
||||
|
||||
memset(test, 0, sizeof(*test));
|
||||
test->default_config_dir = gbinder_config_dir;
|
||||
test->default_config_file = gbinder_config_file;
|
||||
test->config_dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
|
||||
test->config_subdir = g_build_filename(test->config_dir, "d", NULL);
|
||||
test->config_file = g_build_filename(test->config_dir, "test.conf", NULL);
|
||||
g_assert(g_file_set_contents(test->config_file, config, -1, NULL));
|
||||
GDEBUG("Config file %s", test->config_file);
|
||||
gbinder_config_dir = test->config_subdir; /* Doesn't exist */
|
||||
gbinder_config_file = test->config_file;
|
||||
|
||||
ipc = gbinder_ipc_new(dev, NULL);
|
||||
test->fd = gbinder_driver_fd(ipc->driver);
|
||||
test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
|
||||
test->service = servicemanager_aidl3_new(dev);
|
||||
test->client = gbinder_servicemanager_new(dev);
|
||||
test->loop = g_main_loop_new(NULL, FALSE);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_deinit(
|
||||
TestContext* test)
|
||||
{
|
||||
test_binder_br_dead_binder_obj(test->fd, test->object);
|
||||
gbinder_local_object_unref(test->object);
|
||||
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
|
||||
gbinder_servicemanager_unref(test->client);
|
||||
test_binder_exit_wait(&test_opt, test->loop);
|
||||
remove(test->config_file);
|
||||
remove(test->config_dir);
|
||||
g_free(test->config_file);
|
||||
g_free(test->config_subdir);
|
||||
g_free(test->config_dir);
|
||||
g_main_loop_unref(test->loop);
|
||||
gbinder_config_dir = test->default_config_dir;
|
||||
gbinder_config_file = test->default_config_file;
|
||||
gbinder_config_exit();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_wait_ref_cb(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
GDEBUG("strong_refs %d", obj->strong_refs);
|
||||
if (obj->strong_refs > 0) {
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_wait_ref(
|
||||
TestContext* test)
|
||||
{
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
gulong id = gbinder_local_object_add_strong_refs_changed_handler
|
||||
(test->object, test_context_wait_ref_cb, test->loop);
|
||||
|
||||
test_run(&test_opt, test->loop);
|
||||
gbinder_local_object_remove_handler(test->object, id);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* get
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_get_run()
|
||||
{
|
||||
TestContext test;
|
||||
const char* name = "name";
|
||||
int status = -1;
|
||||
|
||||
test_context_init(&test);
|
||||
|
||||
/* Query the object (it's not there yet) */
|
||||
GDEBUG("Querying '%s'", name);
|
||||
g_assert(!gbinder_servicemanager_get_service_sync(test.client,
|
||||
name, &status));
|
||||
g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
|
||||
|
||||
/* Register object */
|
||||
GDEBUG("Registering object '%s' => %p", name, test.object);
|
||||
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
|
||||
name, test.object), == ,GBINDER_STATUS_OK);
|
||||
|
||||
g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
|
||||
g_assert(g_hash_table_contains(test.service->objects, name));
|
||||
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
test_context_wait_ref(&test);
|
||||
|
||||
/* Query the object (this time it must be there) */
|
||||
GDEBUG("Querying '%s' again", name);
|
||||
g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
|
||||
&status));
|
||||
g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
|
||||
|
||||
GDEBUG("Done");
|
||||
test_context_deinit(&test);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_get()
|
||||
{
|
||||
test_run_in_context(&test_opt, test_get_run);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* list
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_list_run()
|
||||
{
|
||||
TestContext test;
|
||||
const char* name = "name";
|
||||
char** list;
|
||||
|
||||
test_context_init(&test);
|
||||
|
||||
/* Request the list */
|
||||
list = gbinder_servicemanager_list_sync(test.client);
|
||||
|
||||
/* There's nothing there yet */
|
||||
g_assert(list);
|
||||
g_assert(!list[0]);
|
||||
g_strfreev(list);
|
||||
|
||||
/* Register object */
|
||||
GDEBUG("Registering object '%s' => %p", name, test.object);
|
||||
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
|
||||
name, test.object), == ,GBINDER_STATUS_OK);
|
||||
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
test_context_wait_ref(&test);
|
||||
|
||||
/* Request the list again */
|
||||
list = gbinder_servicemanager_list_sync(test.client);
|
||||
|
||||
/* Now the name must be there */
|
||||
g_assert_cmpuint(gutil_strv_length(list), == ,1);
|
||||
g_assert_cmpstr(list[0], == ,name);
|
||||
g_strfreev(list);
|
||||
|
||||
GDEBUG("Done");
|
||||
test_context_deinit(&test);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_list()
|
||||
{
|
||||
test_run_in_context(&test_opt, test_list_run);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_(t) "/servicemanager_aidl3/" t
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
g_type_init();
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_("get"), test_get);
|
||||
g_test_add_func(TEST_("list"), test_list);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
5
unit/unit_servicemanager_aidl4/Makefile
Normal file
5
unit/unit_servicemanager_aidl4/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_servicemanager_aidl4
|
||||
|
||||
include ../common/Makefile
|
||||
449
unit/unit_servicemanager_aidl4/unit_servicemanager_aidl4.c
Normal file
449
unit/unit_servicemanager_aidl4/unit_servicemanager_aidl4.c
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Jolla Ltd.
|
||||
* Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 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 "test_binder.h"
|
||||
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_config.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_local_reply.h"
|
||||
#include "gbinder_remote_request.h"
|
||||
#include "gbinder_remote_object.h"
|
||||
#include "gbinder_writer.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_log.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
static const char TMP_DIR_TEMPLATE[] =
|
||||
"gbinder-test-servicemanager_aidl4-XXXXXX";
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_hidl_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_hidl */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Test service manager
|
||||
*==========================================================================*/
|
||||
|
||||
#define SVCMGR_HANDLE (0)
|
||||
static const char SVCMGR_IFACE[] = "android.os.IServiceManager";
|
||||
enum servicemanager_aidl_tx {
|
||||
GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
CHECK_SERVICE_TRANSACTION,
|
||||
ADD_SERVICE_TRANSACTION,
|
||||
LIST_SERVICES_TRANSACTION
|
||||
};
|
||||
|
||||
const char* const servicemanager_aidl_ifaces[] = { SVCMGR_IFACE, NULL };
|
||||
|
||||
typedef GBinderLocalObjectClass ServiceManagerAidl4Class;
|
||||
typedef struct service_manager_aidl4 {
|
||||
GBinderLocalObject parent;
|
||||
GHashTable* objects;
|
||||
} ServiceManagerAidl4;
|
||||
|
||||
#define SERVICE_MANAGER_AIDL4_TYPE (service_manager_aidl4_get_type())
|
||||
#define SERVICE_MANAGER_AIDL4(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
SERVICE_MANAGER_AIDL4_TYPE, ServiceManagerAidl4))
|
||||
G_DEFINE_TYPE(ServiceManagerAidl4, service_manager_aidl4, \
|
||||
GBINDER_TYPE_LOCAL_OBJECT)
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
servicemanager_aidl4_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
ServiceManagerAidl4* self = user_data;
|
||||
GBinderLocalReply* reply = NULL;
|
||||
GBinderReader reader;
|
||||
GBinderRemoteObject* remote_obj;
|
||||
guint32 allow_isolated, dumpsys_priority;
|
||||
char* str;
|
||||
|
||||
g_assert(!flags);
|
||||
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
|
||||
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
|
||||
*status = -1;
|
||||
switch (code) {
|
||||
case GET_SERVICE_TRANSACTION:
|
||||
case CHECK_SERVICE_TRANSACTION:
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
str = gbinder_reader_read_string16(&reader);
|
||||
if (str) {
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
remote_obj = g_hash_table_lookup(self->objects, str);
|
||||
if (str) {
|
||||
GBinderWriter writer;
|
||||
|
||||
remote_obj = g_hash_table_lookup(self->objects, str);
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_remote_object(&writer, remote_obj);
|
||||
if (remote_obj) {
|
||||
GDEBUG("Found name '%s' => %p", str, remote_obj);
|
||||
} else {
|
||||
GDEBUG("Name '%s' not found", str);
|
||||
}
|
||||
g_free(str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ADD_SERVICE_TRANSACTION:
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
str = gbinder_reader_read_string16(&reader);
|
||||
remote_obj = gbinder_reader_read_object(&reader);
|
||||
if (str && remote_obj &&
|
||||
/* This field should be eventually handled at lower level. */
|
||||
gbinder_reader_read_uint32(&reader, NULL) &&
|
||||
gbinder_reader_read_uint32(&reader, &allow_isolated) &&
|
||||
gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
|
||||
GDEBUG("Adding '%s'", str);
|
||||
g_hash_table_replace(self->objects, str, remote_obj);
|
||||
remote_obj = NULL;
|
||||
str = NULL;
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
}
|
||||
g_free(str);
|
||||
gbinder_remote_object_unref(remote_obj);
|
||||
break;
|
||||
case LIST_SERVICES_TRANSACTION:
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
if (gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
|
||||
if (g_hash_table_size(self->objects) == 1) {
|
||||
GList* keys = g_hash_table_get_keys(self->objects);
|
||||
GList* l = g_list_nth(keys, 0);
|
||||
gint32 srv_size = 1;
|
||||
GBinderWriter writer;
|
||||
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_int32(&writer, srv_size);
|
||||
gbinder_writer_append_string16(&writer, l->data);
|
||||
g_list_free(keys);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
} else {
|
||||
GDEBUG("Incorrect number of services %u",
|
||||
g_hash_table_size(self->objects));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GDEBUG("Unhandled command %u", code);
|
||||
break;
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
ServiceManagerAidl4*
|
||||
servicemanager_aidl4_new(
|
||||
const char* dev)
|
||||
{
|
||||
ServiceManagerAidl4* self = g_object_new(SERVICE_MANAGER_AIDL4_TYPE, NULL);
|
||||
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
|
||||
servicemanager_aidl4_handler, self);
|
||||
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
|
||||
gbinder_ipc_register_local_object(ipc, obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl4_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(object);
|
||||
|
||||
g_hash_table_destroy(self->objects);
|
||||
G_OBJECT_CLASS(service_manager_aidl4_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl4_init(
|
||||
ServiceManagerAidl4* self)
|
||||
{
|
||||
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
|
||||
(GDestroyNotify) gbinder_remote_object_unref);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
service_manager_aidl4_class_init(
|
||||
ServiceManagerAidl4Class* klass)
|
||||
{
|
||||
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl4_finalize;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Test context
|
||||
*==========================================================================*/
|
||||
|
||||
typedef struct test_context {
|
||||
const char* default_config_dir;
|
||||
const char* default_config_file;
|
||||
char* config_dir;
|
||||
char* config_subdir;
|
||||
char* config_file;
|
||||
GBinderLocalObject* object;
|
||||
ServiceManagerAidl4* service;
|
||||
GBinderServiceManager* client;
|
||||
GMainLoop* loop;
|
||||
int fd;
|
||||
} TestContext;
|
||||
|
||||
static
|
||||
void
|
||||
test_context_init(
|
||||
TestContext* test)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* config =
|
||||
"[Protocol]\n"
|
||||
"Default = aidl3\n"
|
||||
"/dev/binder = aidl3\n"
|
||||
"[ServiceManager]\n"
|
||||
"Default = aidl4\n"
|
||||
"/dev/binder = aidl4\n";
|
||||
GBinderIpc* ipc;
|
||||
|
||||
memset(test, 0, sizeof(*test));
|
||||
test->default_config_dir = gbinder_config_dir;
|
||||
test->default_config_file = gbinder_config_file;
|
||||
test->config_dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
|
||||
test->config_subdir = g_build_filename(test->config_dir, "d", NULL);
|
||||
test->config_file = g_build_filename(test->config_dir, "test.conf", NULL);
|
||||
g_assert(g_file_set_contents(test->config_file, config, -1, NULL));
|
||||
GDEBUG("Config file %s", test->config_file);
|
||||
gbinder_config_dir = test->config_subdir; /* Doesn't exist */
|
||||
gbinder_config_file = test->config_file;
|
||||
|
||||
ipc = gbinder_ipc_new(dev, NULL);
|
||||
test->fd = gbinder_driver_fd(ipc->driver);
|
||||
test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
|
||||
test->service = servicemanager_aidl4_new(dev);
|
||||
test->client = gbinder_servicemanager_new(dev);
|
||||
test->loop = g_main_loop_new(NULL, FALSE);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_deinit(
|
||||
TestContext* test)
|
||||
{
|
||||
test_binder_unregister_objects(test->fd);
|
||||
gbinder_local_object_unref(test->object);
|
||||
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
|
||||
gbinder_servicemanager_unref(test->client);
|
||||
test_binder_exit_wait(&test_opt, test->loop);
|
||||
remove(test->config_file);
|
||||
remove(test->config_dir);
|
||||
g_free(test->config_file);
|
||||
g_free(test->config_subdir);
|
||||
g_free(test->config_dir);
|
||||
g_main_loop_unref(test->loop);
|
||||
gbinder_config_dir = test->default_config_dir;
|
||||
gbinder_config_file = test->default_config_file;
|
||||
gbinder_config_exit();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_wait_ref_cb(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
GDEBUG("strong_refs %d", obj->strong_refs);
|
||||
if (obj->strong_refs > 0) {
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_context_wait_ref(
|
||||
TestContext* test)
|
||||
{
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
gulong id = gbinder_local_object_add_strong_refs_changed_handler
|
||||
(test->object, test_context_wait_ref_cb, test->loop);
|
||||
|
||||
test_run(&test_opt, test->loop);
|
||||
gbinder_local_object_remove_handler(test->object, id);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* get
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_get_run()
|
||||
{
|
||||
TestContext test;
|
||||
const char* name = "name";
|
||||
int status = -1;
|
||||
|
||||
test_context_init(&test);
|
||||
|
||||
/* Query the object (it's not there yet) */
|
||||
GDEBUG("Querying '%s'", name);
|
||||
g_assert(!gbinder_servicemanager_get_service_sync(test.client,
|
||||
name, &status));
|
||||
g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
|
||||
|
||||
/* Register object */
|
||||
GDEBUG("Registering object '%s' => %p", name, test.object);
|
||||
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
|
||||
name, test.object), == ,GBINDER_STATUS_OK);
|
||||
|
||||
g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
|
||||
g_assert(g_hash_table_contains(test.service->objects, name));
|
||||
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
test_context_wait_ref(&test);
|
||||
|
||||
/* Query the object (this time it must be there) */
|
||||
GDEBUG("Querying '%s' again", name);
|
||||
g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
|
||||
&status));
|
||||
g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
|
||||
|
||||
test_context_deinit(&test);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_get()
|
||||
{
|
||||
test_run_in_context(&test_opt, test_get_run);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* list
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_list_run()
|
||||
{
|
||||
TestContext test;
|
||||
const char* name = "name";
|
||||
char** list;
|
||||
|
||||
test_context_init(&test);
|
||||
|
||||
/* Request the list */
|
||||
list = gbinder_servicemanager_list_sync(test.client);
|
||||
|
||||
/* There's nothing there yet */
|
||||
g_assert(list);
|
||||
g_assert(!list[0]);
|
||||
g_strfreev(list);
|
||||
|
||||
/* Register object */
|
||||
GDEBUG("Registering object '%s' => %p", name, test.object);
|
||||
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
|
||||
name, test.object), == ,GBINDER_STATUS_OK);
|
||||
|
||||
/* Wait until the object gets referenced by servicemanager */
|
||||
test_context_wait_ref(&test);
|
||||
|
||||
/* Request the list again */
|
||||
list = gbinder_servicemanager_list_sync(test.client);
|
||||
|
||||
/* Now the name must be there */
|
||||
g_assert_cmpuint(gutil_strv_length(list), == ,1);
|
||||
g_assert_cmpstr(list[0], == ,name);
|
||||
g_strfreev(list);
|
||||
|
||||
test_context_deinit(&test);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_list()
|
||||
{
|
||||
test_run_in_context(&test_opt, test_list_run);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_(t) "/servicemanager_aidl4/" t
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
g_type_init();
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_("get"), test_get);
|
||||
g_test_add_func(TEST_("list"), test_list);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Jolla Ltd.
|
||||
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2021-2022 Jolla Ltd.
|
||||
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -43,15 +43,13 @@
|
||||
#include <gutil_strv.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
#define MAIN_DEV GBINDER_DEFAULT_HWBINDER
|
||||
#define OTHER_DEV GBINDER_DEFAULT_HWBINDER "-private"
|
||||
#define DEV GBINDER_DEFAULT_HWBINDER
|
||||
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-svcmgr-hidl-XXXXXX";
|
||||
static const char DEFAULT_CONFIG_DATA[] =
|
||||
"[Protocol]\n"
|
||||
MAIN_DEV " = hidl\n"
|
||||
OTHER_DEV " = hidl\n"
|
||||
DEV " = hidl\n"
|
||||
"[ServiceManager]\n"
|
||||
MAIN_DEV " = hidl\n";
|
||||
DEV " = hidl\n";
|
||||
|
||||
typedef struct test_config {
|
||||
char* dir;
|
||||
@@ -61,14 +59,32 @@ typedef struct test_config {
|
||||
GType
|
||||
gbinder_servicemanager_aidl_get_type()
|
||||
{
|
||||
/* Avoid pulling in gbinder_servicemanager_aidl object */
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl2_get_type()
|
||||
{
|
||||
/* Avoid pulling in gbinder_servicemanager_aidl2 object */
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl2 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl3_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl3 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl4_get_type()
|
||||
{
|
||||
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -112,11 +128,10 @@ TestServiceManagerHidl*
|
||||
test_servicemanager_impl_new(
|
||||
const char* dev)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
TestServiceManagerHidl* sm = test_servicemanager_hidl_new(ipc);
|
||||
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
test_binder_register_object(fd, GBINDER_LOCAL_OBJECT(sm),
|
||||
GBINDER_SERVICEMANAGER_HANDLE);
|
||||
gbinder_ipc_unref(ipc);
|
||||
@@ -181,16 +196,14 @@ test_get_run()
|
||||
const char* name = "android.hidl.base@1.0::IBase/test";
|
||||
|
||||
test_config_init(&config, NULL);
|
||||
ipc = gbinder_ipc_new(MAIN_DEV);
|
||||
smsvc = test_servicemanager_impl_new(OTHER_DEV);
|
||||
ipc = gbinder_ipc_new(DEV, NULL);
|
||||
smsvc = test_servicemanager_impl_new(DEV);
|
||||
obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(fd, obj, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
sm = gbinder_servicemanager_new(MAIN_DEV);
|
||||
sm = gbinder_servicemanager_new(DEV);
|
||||
|
||||
/* This one fails because of unexpected name format */
|
||||
g_assert(!gbinder_servicemanager_get_service_sync(sm, "test", NULL));
|
||||
@@ -215,13 +228,11 @@ test_get_run()
|
||||
g_assert(gbinder_servicemanager_get_service(sm, name, test_get_cb, loop));
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
test_binder_unregister_objects(fd);
|
||||
gbinder_local_object_unref(obj);
|
||||
test_servicemanager_hidl_free(smsvc);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
test_config_deinit(&config);
|
||||
g_main_loop_unref(loop);
|
||||
@@ -276,16 +287,14 @@ test_list_run()
|
||||
test.loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
test_config_init(&config, NULL);
|
||||
ipc = gbinder_ipc_new(MAIN_DEV);
|
||||
smsvc = test_servicemanager_impl_new(OTHER_DEV);
|
||||
ipc = gbinder_ipc_new(DEV, NULL);
|
||||
smsvc = test_servicemanager_impl_new(DEV);
|
||||
obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(fd, obj, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
sm = gbinder_servicemanager_new(MAIN_DEV);
|
||||
sm = gbinder_servicemanager_new(DEV);
|
||||
|
||||
/* Request the list and wait for completion */
|
||||
g_assert(gbinder_servicemanager_list(sm, test_list_cb, &test));
|
||||
@@ -308,13 +317,11 @@ test_list_run()
|
||||
g_assert_cmpuint(gutil_strv_length(test.list), == ,1);
|
||||
g_assert_cmpstr(test.list[0], == ,name);
|
||||
|
||||
test_binder_unregister_objects(fd);
|
||||
gbinder_local_object_unref(obj);
|
||||
test_servicemanager_hidl_free(smsvc);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, test.loop);
|
||||
test_config_deinit(&config);
|
||||
|
||||
@@ -404,16 +411,14 @@ test_notify_run()
|
||||
test.loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
test_config_init(&config, NULL);
|
||||
ipc = gbinder_ipc_new(MAIN_DEV);
|
||||
test.smsvc = test_servicemanager_impl_new(OTHER_DEV);
|
||||
ipc = gbinder_ipc_new(DEV, NULL);
|
||||
test.smsvc = test_servicemanager_impl_new(DEV);
|
||||
obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
|
||||
fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
/* Set up binder simulator */
|
||||
test_binder_register_object(fd, obj, AUTO_HANDLE);
|
||||
test_binder_set_passthrough(fd, TRUE);
|
||||
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
|
||||
sm = gbinder_servicemanager_new(MAIN_DEV);
|
||||
sm = gbinder_servicemanager_new(DEV);
|
||||
|
||||
/* This one fails because of invalid names */
|
||||
g_assert(!gbinder_servicemanager_add_registration_handler(sm, NULL,
|
||||
@@ -437,13 +442,11 @@ test_notify_run()
|
||||
test_run(&test_opt, test.loop);
|
||||
gbinder_servicemanager_remove_handler(sm, id);
|
||||
|
||||
test_binder_unregister_objects(fd);
|
||||
gbinder_local_object_unref(obj);
|
||||
test_servicemanager_hidl_free(test.smsvc);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, test.loop);
|
||||
test_config_deinit(&config);
|
||||
g_main_loop_unref(test.loop);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 Jolla Ltd.
|
||||
* Copyright (C) 2019-2021 Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2019-2022 Jolla Ltd.
|
||||
* Copyright (C) 2019-2022 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -62,9 +62,9 @@ test_setup_ping(
|
||||
{
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_reply(fd, 0, 0, NULL);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -145,7 +145,7 @@ test_servicemanager_add_service(
|
||||
}
|
||||
} else {
|
||||
test_binder_br_dead_binder(gbinder_driver_fd(obj->ipc->driver),
|
||||
GBINDER_SERVICEMANAGER_HANDLE);
|
||||
ANY_THREAD, GBINDER_SERVICEMANAGER_HANDLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,6 +234,18 @@ gbinder_servicemanager_aidl2_get_type()
|
||||
return TEST_TYPE_SERVICEMANAGER;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl3_get_type()
|
||||
{
|
||||
return TEST_TYPE_SERVICEMANAGER;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl4_get_type()
|
||||
{
|
||||
return TEST_TYPE_SERVICEMANAGER;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_hidl_get_type()
|
||||
{
|
||||
@@ -250,7 +262,7 @@ test_null(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderServiceManager* sm;
|
||||
|
||||
test_setup_ping(ipc);
|
||||
@@ -277,7 +289,7 @@ test_basic(
|
||||
const char* obj_name = "test";
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
const char* const ifaces[] = { "interface", NULL };
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj;
|
||||
GBinderServiceManager* sm;
|
||||
@@ -299,7 +311,7 @@ test_basic(
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -315,7 +327,7 @@ test_present(
|
||||
const char* obj_name = "test";
|
||||
const char* const ifaces[] = { "interface", NULL };
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj;
|
||||
@@ -333,8 +345,7 @@ test_present(
|
||||
g_assert_cmpstr(sn->name, == ,obj_name);
|
||||
|
||||
/* Immediately generate death notification (need looper for that) */
|
||||
test_binder_br_dead_binder(fd, GBINDER_SERVICEMANAGER_HANDLE);
|
||||
test_binder_set_looper_enabled(fd, TRUE);
|
||||
test_binder_br_dead_binder(fd, ANY_THREAD, GBINDER_SERVICEMANAGER_HANDLE);
|
||||
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
@@ -343,7 +354,6 @@ test_present(
|
||||
gbinder_servicemanager_remove_handler(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -376,7 +386,7 @@ test_not_present(
|
||||
const char* obj_name = "test";
|
||||
const char* const ifaces[] = { "interface", NULL };
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj;
|
||||
@@ -385,7 +395,7 @@ test_not_present(
|
||||
gulong id;
|
||||
|
||||
/* This makes presence detection PING fail */
|
||||
test_binder_br_reply_status(fd, -1);
|
||||
test_binder_br_reply_status(fd, THIS_THREAD, -1);
|
||||
sm = gbinder_servicemanager_new(dev);
|
||||
g_assert(!gbinder_servicemanager_is_present(sm));
|
||||
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
|
||||
@@ -396,8 +406,8 @@ test_not_present(
|
||||
g_assert_cmpstr(sn->name, == ,obj_name);
|
||||
|
||||
/* Make the next presence detection PING succeed */
|
||||
test_binder_br_transaction_complete_later(fd);
|
||||
test_binder_br_reply_later(fd, 0, 0, NULL);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_servicename_unref(sn);
|
||||
@@ -405,7 +415,7 @@ test_not_present(
|
||||
gbinder_servicemanager_remove_handler(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -421,8 +431,7 @@ test_retry(
|
||||
const char* obj_name = "test";
|
||||
const char* const ifaces[] = { "interface", NULL };
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj;
|
||||
GBinderServiceManager* sm;
|
||||
@@ -438,8 +447,6 @@ test_retry(
|
||||
g_assert(sn);
|
||||
g_assert_cmpstr(sn->name, == ,obj_name);
|
||||
|
||||
/* Need looper for death notifications */
|
||||
test_binder_set_looper_enabled(fd, TRUE);
|
||||
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
@@ -448,7 +455,7 @@ test_retry(
|
||||
gbinder_servicemanager_remove_handler(sm, id);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -464,7 +471,7 @@ test_cancel(
|
||||
const char* obj_name = "test";
|
||||
const char* const ifaces[] = { "interface", NULL };
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj;
|
||||
@@ -488,9 +495,8 @@ test_cancel(
|
||||
g_assert(sn);
|
||||
g_assert_cmpstr(sn->name, == ,obj_name);
|
||||
|
||||
/* Immediately generate death notification (need looper for that) */
|
||||
test_binder_br_dead_binder(fd, GBINDER_SERVICEMANAGER_HANDLE);
|
||||
test_binder_set_looper_enabled(fd, TRUE);
|
||||
/* Immediately generate death notification */
|
||||
test_binder_br_dead_binder(fd, ANY_THREAD, GBINDER_SERVICEMANAGER_HANDLE);
|
||||
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
@@ -507,7 +513,6 @@ test_cancel(
|
||||
g_mutex_unlock(&test->mutex);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_exit();
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Jolla Ltd.
|
||||
* Copyright (C) 2018-2021 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:
|
||||
*
|
||||
@@ -52,9 +52,9 @@ test_setup_ping(
|
||||
{
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
|
||||
test_binder_br_noop(fd);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
test_binder_br_reply(fd, 0, 0, NULL);
|
||||
test_binder_br_noop(fd, THIS_THREAD);
|
||||
test_binder_br_transaction_complete(fd, THIS_THREAD);
|
||||
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -200,6 +200,18 @@ gbinder_servicemanager_aidl2_get_type()
|
||||
return TEST_TYPE_SERVICEMANAGER;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl3_get_type()
|
||||
{
|
||||
return TEST_TYPE_SERVICEMANAGER;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_aidl4_get_type()
|
||||
{
|
||||
return TEST_TYPE_SERVICEMANAGER;
|
||||
}
|
||||
|
||||
GType
|
||||
gbinder_servicemanager_hidl_get_type()
|
||||
{
|
||||
@@ -233,7 +245,7 @@ test_basic(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager;
|
||||
GBinderServicePoll* poll;
|
||||
@@ -256,6 +268,7 @@ test_basic(
|
||||
|
||||
gbinder_servicemanager_unref(manager);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -309,7 +322,7 @@ test_notify1(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager;
|
||||
@@ -340,6 +353,7 @@ test_notify1(
|
||||
g_assert(!weakptr);
|
||||
gbinder_servicemanager_unref(manager);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -383,7 +397,7 @@ test_notify2(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager;
|
||||
@@ -418,6 +432,7 @@ test_notify2(
|
||||
g_assert(!weakptr);
|
||||
gbinder_servicemanager_unref(manager);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
@@ -442,7 +457,7 @@ test_already_there(
|
||||
void)
|
||||
{
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager;
|
||||
@@ -466,6 +481,7 @@ test_already_there(
|
||||
g_assert(!weakptr);
|
||||
gbinder_servicemanager_unref(manager);
|
||||
gbinder_ipc_unref(ipc);
|
||||
test_binder_exit_wait(&test_opt, loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user