Compare commits

...

68 Commits

Author SHA1 Message Date
Slava Monich
545f5bc28d Version 1.1.39 2024-05-05 20:09:11 +03:00
Slava Monich
78e006f1cf Acknowledge Martin's contribution 2024-05-05 20:08:23 +03:00
Slava Monich
3c9cc1711a [spec] Cleaned up macro syntax 2024-04-30 20:25:43 +03:00
Slava Monich
71aa3acc08 [spec] Restore compatibility with rpm < 4.12 (again) 2024-04-30 02:42:25 +03:00
Slava Monich
eee26c5e98 [spec] Restore compatibility with rpm < 4.12 2024-04-30 02:18:18 +03:00
Slava Monich
736a29aa4c Merge pull request #128 from mer-hybris/jb61933
Utilize make_build macro
2024-04-29 19:54:51 +03:00
Martin Kampas
0d7105edbe [gbinder] Utilize make_build macro. JB#61933
Allow the build system to override the way make is invoked.

Cannot use make_install equally as that does not allow to pass
additional arguments to make.
2024-04-16 13:36:50 +02:00
Slava Monich
4420c7b2ae Merge pull request #126 from mer-hybris/jb61912
Eliminate defects found by Coverity
2024-04-12 04:51:00 +03:00
Martin Kampas
52726a07b0 [gbinder] Add model file for Coverity. JB#61912
Eliminate false positive. Help Coverity see there is no resource leak
(CID 444479).
2024-04-11 12:59:39 +02:00
Martin Kampas
12b9fd49ad [gbinder] Avoid double-checked locking in gbinder_ipc_looper_check. JB#61912
Data race condition detected by Coverity (CID 444481, CID 444483).

According to Slava the effect of this particular optimization is
negligible, so let's simply drop it to make Coverity happy.
2024-04-11 12:57:13 +02:00
Martin Kampas
e75959e389 [gbinder] Explicitly ignore return value. JB#61912
Recognized by Coverity (CID 444485) that this is the single call to
gbinder_driver_write out of the total of 9, where the return value is
not checked.

This change is implemented just to make Coverity happy.  The compiler
does not complain.
2024-04-11 12:45:33 +02:00
Slava Monich
9d35ca22fb Merge pull request #127 from monich/set_data
Remove unnecessary checks for NULL
2024-04-11 13:09:34 +03:00
Slava Monich
3e0d0005ce [gbinder] Remove unnecessary checks for NULL. JB#61912
And fix potential use after free.
2024-04-11 03:29:28 +03:00
Slava Monich
29718f921f Version 1.1.38 2024-03-02 02:13:19 +02:00
Slava Monich
99b2dd85c1 [unit] Test byte array padding. JB#42956 2024-03-02 02:09:44 +02:00
Slava Monich
cf5417d5db [gbinder] Housekeeping 2024-03-02 02:01:11 +02:00
Slava Monich
03f214eb24 [gbinder] Fixed FF padding 2024-03-02 01:59:43 +02:00
Slava Monich
6508a73dcd Merge pull request #124 from mer-hybris/bytearraypad 2024-03-02 01:46:57 +02:00
Andrew Branson
1100d8ede1 [gbinder] Byte array padding
Android aligns byte array reads and writes to 4 bytes and pads with 0xFF.
Not accounting for this causes misalignment issues on further reading.
2024-03-01 10:09:41 +01:00
Slava Monich
f89469b1a5 Version 1.1.37 2024-02-26 16:25:25 +02:00
Slava Monich
fcf2ef0ea4 Merge pull request #123 from Tomin1/jb61613
Fix gbinder_driver_reply_data return value
2024-02-26 16:18:55 +02:00
Tomi Leppänen
f9202cab37 [gbinder] Fix gbinder_driver_reply_data return value. Fixes JB#61613
Previously this always returned 1. Drop the first comparison so status
can be negative and errors will return 0.

Signed-off-by: Tomi Leppänen <tomi.leppanen@jolla.com>
2024-02-26 10:54:39 +02:00
Slava Monich
49729d95c9 Version 1.1.36 2024-02-10 05:05:39 +02:00
Slava Monich
11765cd80d [unit] Added test for surrogate pairs 2024-02-10 05:00:25 +02:00
Slava Monich
4820b2971f [gbinder] Housekeeping 2024-02-10 04:57:24 +02:00
Slava Monich
0623fb85db [license] Freshened up the license 2024-02-10 04:54:52 +02:00
Slava Monich
e655d8992a Merge pull request #122 from mer-hybris/jb61524
Calculate correct size for UTF-16 buffer in advance.
2024-02-10 04:49:11 +02:00
Andrew Branson
44e57ea98d [gbinder] Calculate correct size for UTF-16 buffer in advance. Fixes JB#61524
In UTF-16, code points U+010000 to U+10FFFF are encoded using 'surrogate
pairs' where 32 bits are actually used. If a string is mostly emojis,
that can end up larger than the len*2 bytes assumed padded_len.
Convert the string to UTF-16 before allocating the extra buffer size so
it will be correct.
2024-02-09 17:29:19 +01:00
Slava Monich
e3f705c4cc Merge pull request #120 from JamiKettunen/cross-pkgconf
[build] Support pkg-config cross-compilation
2023-12-01 03:44:46 +02:00
Jami Kettunen
6f0e8a693d [build] Support pkg-config cross-compilation
Previously to cross-compile one would need to add a pkg-config
executable in $PATH wrapping all the search paths required; now one can
e.g.

  make PKG_CONFIG=foreign-arch-target-pkg-config

with the wrapper executable being separate and allowing programs for
host to also be built if needed for example.
2023-11-30 20:54:40 +02:00
Slava Monich
c7fab6373b Version 1.1.35 2023-11-23 01:45:18 +02:00
Slava Monich
9aded94555 Merge pull request #119 from monich/test_config
Make unit tests independent on system config
2023-11-23 01:38:15 +02:00
Slava Monich
b5bab2431e [unit] Make unit tests independent on system config. JB#42956
System gbinder config shouldn't break unit tests.
2023-11-19 18:41:26 +02:00
Slava Monich
509faccba0 Merge pull request #117 from JamiKettunen/make-var
[build] Use MAKE var instead of explicitly calling make
2023-09-11 02:13:30 +03:00
Jami Kettunen
a89dcd2702 [build] Use MAKE var instead of explicitly calling make
There are multiple make implementations and nothing guarantees that the
make executable is gmake, which is what this Makefile requires.
2023-09-08 15:20:10 +03:00
Slava Monich
62b9b30865 Version 1.1.34 2023-04-30 06:10:45 +03:00
Slava Monich
4a913590d9 [gbinder] Require glib 2.32 2023-04-30 06:07:16 +03:00
Slava Monich
1ee872aaf2 Merge pull request #115 from Tomin1/jb60671_fix
Use correct suffix for 16-bit strings
2023-04-30 05:26:55 +03:00
Tomi Leppänen
00e9d8ac6f [binder-call] Use correct suffix for 16-bit strings. Fixes JB#60671
Signed-off-by: Tomi Leppänen <tomi.leppanen@jolla.com>
2023-04-27 11:44:12 +03:00
Slava Monich
b032e151a2 Version 1.1.33 2023-02-26 03:15:39 +02:00
Slava Monich
b8edc9221a Merge pull request #114 from monich/int32_vs_byte
Fix gbinder_writer_type_byte and gbinder_writer_type_int32 descriptors
2023-02-26 03:10:44 +02:00
Slava Monich
05634757d7 [unit] Added tests for byte and int32 type descriptors. JB#42956 2023-02-25 02:59:47 +02:00
Slava Monich
03ef78c9fd [gbinder] Fixed GBinderWriterType for byte and int32. JB#42956 2023-02-25 02:58:33 +02:00
Slava Monich
84efc32ac0 Version 1.1.32 2023-01-23 11:49:21 +02:00
Slava Monich
88388de696 [license] Freshened up copyright 2023-01-23 11:46:19 +02:00
Slava Monich
daa062d981 Merge pull request #113 from monich/unit-tests
Improve reliability of unit tests
2023-01-23 11:27:39 +02:00
Slava Monich
85db18f663 [unit] Handle servicemanager requests on looper thread. JB#42956
Because tests are using synchronous calls blocking the main thread,
2023-01-23 01:29:58 +02:00
Slava Monich
af796828a4 [unit] Fixed possible deadlock in proxy_object test. JB#42956
The /proxy_object/param test could be deadlocked by gbinder_ipc_exit()
blocking the main thread and waiting for all client threads to terminate
one of which waiting for the transaction (the one getting cancelled) to
complete on the main thread blocked by gbinder_ipc_exit().

The deadlock is avoided by making sure that both transactions get completed
before gbinder_ipc_exit() is called.
2023-01-22 04:35:22 +02:00
Slava Monich
885d27c12c Version 1.1.31 2023-01-04 19:14:49 +02:00
Slava Monich
38f156a8ba Merge pull request #110 from monich/binder-test
Refactor binder simulation used by unit tests
2023-01-04 19:02:48 +02:00
Slava Monich
d7eacd455f [unit] Refactored binder simulation. JB#42956
The old one was way too hackish and prone to race conditions.
This one is more accurate and hopefully more reliable.
2023-01-04 14:42:19 +02:00
Slava Monich
b1a3dc5c64 [gbinder] Improved handling of multiple gbinder_ipc_exit() calls
Needed primarily for unit testing.
2023-01-03 12:49:04 +02:00
Slava Monich
98ad09e803 Merge pull request #112 from monich/big-endian
Fix serialization issues on big-endian systems
2023-01-03 12:42:44 +02:00
Slava Monich
c94ccbd8bf [gbinder] Fixed serialization issues on big-endian. JB#42956
Note that libhwbinder and libbinder encode TRUE value differently
on big-endian machines (0x01 becomes either first or last of 4 bytes)
but reading uint32 and comparing it with zero works in either case.
2023-01-03 01:56:18 +02:00
Slava Monich
5874c88559 Version 1.1.30 2022-12-04 19:51:04 +02:00
Slava Monich
b0c3b6017f Merge pull request #109 from monich/ptr_cookie
Fix return value from binder_ptr_cookie encoder
2022-12-04 19:46:23 +02:00
Slava Monich
4f82e82081 [gbinder] Fix return value from binder_ptr_cookie encoder. JB#42956
It was resulting in broken BC_ACQUIRE_DONE commands being sent to
the driver. That's not nice.
2022-12-04 19:41:24 +02:00
Slava Monich
51eefbf566 Version 1.1.29 2022-11-25 00:03:04 +02:00
Slava Monich
ec76cb3930 Merge pull request #106 from monich/vec
gbinder_writer_append_struct_vec
2022-11-24 23:41:11 +02:00
Slava Monich
9a0d0a7894 [gbinder] Added gbinder_writer_append_struct_vec(). JB#42956
Appends top-level vec<type>. Allocates GBinderHidlVec for that,
but unlike gbinder_writer_append_hidl_vec(), doesn't copy the
contents of the vector.
2022-11-24 19:48:24 +02:00
Slava Monich
32b3d4455a Version 1.1.28 2022-11-22 18:22:37 +02:00
Slava Monich
09e9a9d5c1 Merge pull request #103 from monich/minus
Allow to pass negative number as a parameter
2022-11-22 18:12:34 +02:00
Slava Monich
83b04757c6 Merge pull request #105 from monich/pie
Compile executables with -fPIE
2022-11-22 18:12:09 +02:00
Slava Monich
c636814500 [test] Compile executables with -fPIE. JB#42956 2022-11-20 18:02:58 +02:00
Slava Monich
2592ea60ce Merge pull request #104 from monich/spec
Tweak the spec file
2022-11-20 05:18:12 +02:00
Slava Monich
f04e21b462 [packaging] Tweak the spec file. JB#42956
1. Some packaging guides suggest not to do rm -rf %{buildroot}
2. Own the directory containing the header files, not just the files
2022-11-20 01:17:19 +02:00
Slava Monich
d739912faa [binder-call] Allow to pass negative number as a parameter. JB#59412
Note that the user would have to use  "--" flag to stop GOptionContext
from parsing negative numbers as command line options.
2022-11-19 21:48:54 +02:00
Slava Monich
c2263874ec [binder-call] Removed unused app_options field 2022-11-19 21:43:32 +02:00
60 changed files with 2908 additions and 3725 deletions

View File

@@ -9,3 +9,4 @@ Bart Ribbers <bribbers@disroot.org>
Gary Wang <gary.wang@canonical.com>
Eugenio Paolantonio <me@medesimo.eu>
Alessandro Astone <ales.astone@gmail.com>
Martin Kampas <martin.kampas@seafarix.com>

View File

@@ -1,7 +1,5 @@
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:
Copyright (C) 2018-2024 Jolla Ltd.
Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@@ -16,7 +16,7 @@
VERSION_MAJOR = 1
VERSION_MINOR = 1
VERSION_RELEASE = 27
VERSION_RELEASE = 39
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
@@ -50,10 +50,10 @@ RELEASE_DEPS = libglibutil_release
.PHONY: libglibutil_debug libglibutil_release
libglibutil_debug:
make -C $(LIBGLIBUTIL_PATH) debug
$(MAKE) -C $(LIBGLIBUTIL_PATH) debug
libglibutil_release:
make -C $(LIBGLIBUTIL_PATH) release
$(MAKE) -C $(LIBGLIBUTIL_PATH) release
endif
@@ -126,16 +126,19 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
# Tools and flags
#
PKG_CONFIG ?= pkg-config
CC ?= $(CROSS_COMPILE)gcc
STRIP ?= strip
LD = $(CC)
WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
DEFINES += -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED
INCLUDES += -I$(INCLUDE_DIR)
BASE_FLAGS = -fPIC
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
-MMD -MP $(shell pkg-config --cflags $(PKGS))
-MMD -MP $(shell $(PKG_CONFIG) --cflags $(PKGS))
FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \
$(shell pkg-config --libs $(PKGS)) -lpthread
$(shell $(PKG_CONFIG) --libs $(PKGS)) -lpthread
DEBUG_FLAGS = -g
RELEASE_FLAGS =
COVERAGE_FLAGS = -g
@@ -235,8 +238,8 @@ print_release_path:
@echo $(RELEASE_BUILD_DIR)
clean:
make -C test clean
make -C unit clean
$(MAKE) -C test clean
$(MAKE) -C unit clean
rm -fr test/coverage/results test/coverage/*.gcov
rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
rm -fr $(BUILD_DIR) RPMS installroot
@@ -246,7 +249,7 @@ clean:
rm -f debian/libgbinder.install debian/libgbinder-dev.install
test:
make -C unit test
$(MAKE) -C unit test
$(BUILD_DIR):
mkdir -p $@

77
debian/changelog vendored
View File

@@ -1,3 +1,80 @@
libgbinder (1.1.39) unstable; urgency=low
* Eliminate defects found by Coverity
-- Slava Monich <slava@monich.com> Sun, 05 May 2024 20:03:44 +0300
libgbinder (1.1.38) unstable; urgency=low
* Fixed byte array padding
-- Slava Monich <slava@monich.com> Sat, 02 Mar 2024 02:11:50 +0200
libgbinder (1.1.37) unstable; urgency=low
* Fixed gbinder_driver_reply_data return value
-- Slava Monich <slava@monich.com> Mon, 26 Feb 2024 16:22:29 +0200
libgbinder (1.1.36) unstable; urgency=low
* Support pkg-config cross-compilation
* Fixed handling of UTF-16 surrogate pairs
-- Slava Monich <slava@monich.com> Sat, 10 Feb 2024 05:04:13 +0200
libgbinder (1.1.35) unstable; urgency=low
* Make unit tests independent on system config
* Use MAKE var instead of explicitly calling make
-- Slava Monich <slava@monich.com> Thu, 23 Nov 2023 01:42:56 +0200
libgbinder (1.1.34) unstable; urgency=low
* Fixed binder-call help message
* Require glib 2.32
-- Slava Monich <slava@monich.com> Sun, 30 Apr 2023 06:04:38 +0300
libgbinder (1.1.33) unstable; urgency=low
* Fixed GBinderWriterType for byte and int32
-- Slava Monich <slava@monich.com> Sun, 26 Feb 2023 03:13:49 +0200
libgbinder (1.1.32) unstable; urgency=low
* Improved reliability of unit tests
-- Slava Monich <slava@monich.com> Mon, 23 Jan 2023 11:48:00 +0200
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()

6
debian/copyright vendored
View File

@@ -1,7 +1,5 @@
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:
Copyright (C) 2018-2024 Jolla Ltd.
Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@@ -137,6 +137,13 @@ gbinder_writer_append_struct(
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,

8
misc/coverity_model.c Normal file
View File

@@ -0,0 +1,8 @@
typedef struct gbinder_remote_request GBinderRemoteRequest;
void
gbinder_remote_request_unref(
GBinderRemoteRequest* req)
{
__coverity_free__(req);
}

View File

@@ -1,15 +1,16 @@
Name: libgbinder
Version: 1.1.27
Version: 1.1.39
Release: 0
Summary: Binder client library
License: BSD
URL: https://github.com/mer-hybris/libgbinder
Source: %{name}-%{version}.tar.bz2
%define glib_version 2.32
%define libglibutil_version 1.0.52
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(glib-2.0) >= %{glib_version}
BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}
BuildRequires: pkgconfig
BuildRequires: bison
@@ -19,6 +20,10 @@ BuildRequires: flex
BuildRequires: pkgconfig(rpm)
%define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?)
# make_build macro appeared in rpm 4.12
%{!?make_build: %define make_build make %{_smp_mflags}}
Requires: glib2 >= %{glib_version}
Requires: libglibutil >= %{libglibutil_version}
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
@@ -29,6 +34,7 @@ C interfaces for Android binder
%package devel
Summary: Development library for %{name}
Requires: %{name} = %{version}
Requires: pkgconfig(glib-2.0) >= %{glib_version}
%description devel
This package contains the development library for %{name}.
@@ -37,14 +43,13 @@ This package contains the development library for %{name}.
%setup -q
%build
make %{_smp_mflags} LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
make -C test/binder-bridge KEEP_SYMBOLS=1 release
make -C test/binder-list KEEP_SYMBOLS=1 release
make -C test/binder-ping KEEP_SYMBOLS=1 release
make -C test/binder-call KEEP_SYMBOLS=1 release
%make_build LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
%make_build -C test/binder-bridge -j1 KEEP_SYMBOLS=1 release
%make_build -C test/binder-list -j1 KEEP_SYMBOLS=1 release
%make_build -C test/binder-ping -j1 KEEP_SYMBOLS=1 release
%make_build -C test/binder-call -j1 KEEP_SYMBOLS=1 release
%install
rm -rf %{buildroot}
make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev
make -C test/binder-bridge DESTDIR=%{buildroot} install
make -C test/binder-list DESTDIR=%{buildroot} install
@@ -67,6 +72,7 @@ make -C unit test
%files devel
%defattr(-,root,root,-)
%dir %{_includedir}/gbinder
%{_libdir}/pkgconfig/*.pc
%{_libdir}/%{name}.so
%{_includedir}/gbinder/*.h

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -506,7 +506,7 @@ gbinder_driver_reply_data(
write.ptr = (uintptr_t)buf;
write.size = len;
write.consumed = 0;
status = gbinder_driver_write(self, &write) >= 0;
status = gbinder_driver_write(self, &write);
g_free(offsets_buf);
return status >= 0;
@@ -813,7 +813,7 @@ gbinder_driver_txstatus(
gbinder_driver_verbose_transaction_data("BR_REPLY", &tx);
/* Transfer data ownership to the reply */
if (tx.data && tx.size) {
if (tx.data && tx.size && reply) {
GBinderBuffer* buf = gbinder_buffer_new(self,
tx.data, tx.size, tx.objects);
@@ -1173,7 +1173,7 @@ gbinder_driver_free_buffer(
write.ptr = (uintptr_t)wbuf;
write.size = len;
write.consumed = 0;
gbinder_driver_write(self, &write);
(void) gbinder_driver_write(self, &write);
}
}

View File

@@ -289,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 */

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,7 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#define _GNU_SOURCE /* pthread_*_np */
#include "gbinder_ipc.h"
@@ -906,28 +905,25 @@ gbinder_ipc_looper_check(
{
if (G_LIKELY(self)) {
GBinderIpcPriv* priv = self->priv;
GBinderIpcLooper* new_looper = NULL;
/* Lock */
g_mutex_lock(&priv->looper_mutex);
if (!priv->primary_loopers) {
GBinderIpcLooper* looper;
priv->primary_loopers = gbinder_ipc_looper_new(self);
new_looper = priv->primary_loopers;
if (new_looper) {
gbinder_ipc_looper_ref(new_looper);
}
}
g_mutex_unlock(&priv->looper_mutex);
/* Unlock */
/* Lock */
g_mutex_lock(&priv->looper_mutex);
if (!priv->primary_loopers) {
priv->primary_loopers = gbinder_ipc_looper_new(self);
}
looper = priv->primary_loopers;
if (looper) {
gbinder_ipc_looper_ref(looper);
}
g_mutex_unlock(&priv->looper_mutex);
/* Unlock */
/* We are not ready to accept incoming transactions until
* looper has started. We may need to wait a bit. */
if (looper) {
gbinder_ipc_looper_start(looper);
gbinder_ipc_looper_unref(looper);
}
/* We are not ready to accept incoming transactions until
* looper has started. We may need to wait a bit. */
if (new_looper) {
gbinder_ipc_looper_start(new_looper);
gbinder_ipc_looper_unref(new_looper);
}
}
}
@@ -2194,7 +2190,6 @@ gbinder_ipc_exit()
for (i = ipcs; i; i = i->next) {
GBinderIpc* ipc = THIS(i->data);
GBinderIpcPriv* priv = ipc->priv;
GThreadPool* pool = priv->tx_pool;
GSList* local_objs = NULL;
GSList* tx_keys = NULL;
GSList* k;
@@ -2205,8 +2200,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,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,8 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_driver.h"
#include "gbinder_ipc.h"
#include "gbinder_buffer_p.h"

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2021-2022 Jolla Ltd.
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2021-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,8 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_proxy_object.h"
#include "gbinder_local_object_p.h"
#include "gbinder_local_request.h"

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Jolla Ltd.
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -124,17 +124,24 @@ gbinder_reader_read_bool(
GBinderReader* reader,
gboolean* value)
{
GBinderReaderPriv* p = gbinder_reader_cast(reader);
/*
* 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;
/* Boolean values are supposed to be padded to 4-byte boundary */
if (gbinder_reader_can_read(p, 4)) {
if (value) {
*value = (p->ptr[0] != 0);
if (gbinder_reader_read_uint32(reader, &padded)) {
*value = (padded != 0);
return TRUE;
} else {
return FALSE;
}
p->ptr += 4;
return TRUE;
} else {
return FALSE;
return gbinder_reader_read_uint32(reader, NULL);
}
}
@@ -151,18 +158,17 @@ gbinder_reader_read_uint8(
GBinderReader* reader,
guint8* value) /* Since 1.1.15 */
{
/* Primitive values are supposed to be padded to 4-byte boundary */
if (value) {
guint32 padded;
GBinderReaderPriv* p = gbinder_reader_cast(reader);
if (gbinder_reader_read_uint32(reader, &padded)) {
*value = (guint8)padded;
return TRUE;
} else {
return FALSE;
/* Primitive values are supposed to be padded to 4-byte boundary */
if (gbinder_reader_can_read(p, 4)) {
if (value) {
*value = p->ptr[0];
}
p->ptr += 4;
return TRUE;
} else {
return gbinder_reader_read_uint32(reader, NULL);
return FALSE;
}
}
@@ -179,18 +185,17 @@ gbinder_reader_read_uint16(
GBinderReader* reader,
guint16* value) /* Since 1.1.15 */
{
/* Primitive values are supposed to be padded to 4-byte boundary */
if (value) {
guint32 padded;
GBinderReaderPriv* p = gbinder_reader_cast(reader);
if (gbinder_reader_read_uint32(reader, &padded)) {
*value = (guint16)padded;
return TRUE;
} else {
return FALSE;
/* 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;
} else {
return gbinder_reader_read_uint32(reader, NULL);
return FALSE;
}
}
@@ -765,7 +770,8 @@ gbinder_reader_read_byte_array(
*len = (gsize)*ptr;
p->ptr += sizeof(*ptr);
data = p->ptr;
p->ptr += *len;
/* Android aligns byte array reads and writes to 4 bytes */
p->ptr += G_ALIGN4(*len);
}
}
return data;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,8 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_driver.h"
#include "gbinder_ipc.h"
#include "gbinder_remote_object_p.h"

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -73,15 +73,12 @@ gbinder_remote_reply_set_data(
GBinderRemoteReply* self,
GBinderBuffer* buffer)
{
if (G_LIKELY(self)) {
GBinderReaderData* data = &self->data;
/* The caller checks the pointer for NULL */
GBinderReaderData* data = &self->data;
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
} else {
gbinder_buffer_free(buffer);
}
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
}
GBinderRemoteReply*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -162,29 +162,25 @@ gbinder_remote_request_set_data(
guint32 txcode,
GBinderBuffer* buffer)
{
/* The caller never passes NULL req */
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
GBinderReaderData* data = &self->data;
GBinderReader reader;
if (G_LIKELY(self)) {
GBinderReaderData* data = &self->data;
GBinderReader reader;
g_free(self->iface2);
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
g_free(self->iface2);
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
data->objects = gbinder_buffer_objects(buffer);
/* Parse RPC header */
gbinder_remote_request_init_reader2(self, &reader);
self->iface = self->protocol->read_rpc_header(&reader, txcode,
&self->iface2);
if (self->iface) {
self->header_size = gbinder_reader_bytes_read(&reader);
} else {
/* No RPC header */
self->header_size = 0;
}
/* Parse RPC header */
gbinder_remote_request_init_reader2(self, &reader);
self->iface = self->protocol->read_rpc_header(&reader, txcode,
&self->iface2);
if (self->iface) {
self->header_size = gbinder_reader_bytes_read(&reader);
} else {
gbinder_buffer_free(buffer);
/* No RPC header */
self->header_size = 0;
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,8 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_servicemanager_p.h"
#include "gbinder_client_p.h"
#include "gbinder_config.h"

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,8 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_servicemanager_aidl.h"
#include "gbinder_servicepoll.h"
#include "gbinder_eventloop_p.h"

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Jolla Ltd.
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -52,8 +52,8 @@ 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 };
const GBinderWriterType gbinder_writer_type_byte = { "byte", 1, NULL };
const GBinderWriterType gbinder_writer_type_int32 = { "int32", 4, NULL };
static const GBinderWriterField gbinder_writer_type_hidl_string_f[] = {
{
"hidl_string.data.str", 0, NULL,
@@ -212,6 +212,23 @@ gbinder_writer_bytes_written(
return G_LIKELY(data) ? data->bytes->len : 0;
}
static
void
gbinder_writer_data_append_padded(
GByteArray* buf,
const void* data,
guint size)
{
/* Primitive values are padded to 4-byte boundary */
const guint padded_size = 4;
guint8* ptr;
g_byte_array_set_size(buf, buf->len + padded_size);
ptr = buf->data + (buf->len - padded_size);
memcpy(ptr, data, size);
memset(ptr + size, 0, padded_size - size);
}
void
gbinder_writer_append_bool(
GBinderWriter* self,
@@ -229,8 +246,9 @@ gbinder_writer_data_append_bool(
GBinderWriterData* data,
gboolean value)
{
/* Primitive values are padded to 4-byte boundary */
gbinder_writer_data_append_int32(data, value != FALSE);
const guint8 b = (value != FALSE);
gbinder_writer_data_append_padded(data->bytes, &b, sizeof(b));
}
void
@@ -241,8 +259,7 @@ gbinder_writer_append_int8(
GBinderWriterData* data = gbinder_writer_data(self);
if (G_LIKELY(data)) {
/* Primitive values are padded to 4-byte boundary */
gbinder_writer_data_append_int32(data, value);
gbinder_writer_data_append_padded(data->bytes, &value, sizeof(value));
}
}
@@ -254,8 +271,7 @@ gbinder_writer_append_int16(
GBinderWriterData* data = gbinder_writer_data(self);
if (G_LIKELY(data)) {
/* Primitive values are padded to 4-byte boundary */
gbinder_writer_data_append_int32(data, value);
gbinder_writer_data_append_padded(data->bytes, &value, sizeof(value));
}
}
@@ -507,37 +523,37 @@ gbinder_writer_data_append_string16_len(
gsize padded_len = G_ALIGN4((len+1)*2);
guint32* len_ptr;
gunichar2* utf16_ptr;
gunichar2* utf16 = NULL;
/* Create utf-16 string to make sure of its size */
if (len > 0) {
glong utf16_len = 0;
utf16 = g_utf8_to_utf16(utf8, num_bytes, NULL, &utf16_len, NULL);
if (utf16) {
len = utf16_len;
padded_len = G_ALIGN4((len+1)*2);
}
}
/* Preallocate space */
g_byte_array_set_size(buf, old_size + padded_len + 4);
len_ptr = (guint32*)(buf->data + old_size);
utf16_ptr = (gunichar2*)(len_ptr + 1);
/* TODO: this could be optimized for ASCII strings, i.e. if
* len equals num_bytes */
if (len > 0) {
glong utf16_len = 0;
gunichar2* utf16 = g_utf8_to_utf16(utf8, num_bytes, NULL,
&utf16_len, NULL);
if (utf16) {
len = utf16_len;
padded_len = G_ALIGN4((len+1)*2);
memcpy(utf16_ptr, utf16, (len+1)*2);
g_free(utf16);
}
/* Copy string */
if (utf16) {
memcpy(utf16_ptr, utf16, len*2);
g_free(utf16);
}
/* Actual length */
*len_ptr = len;
/* Zero padding */
if (padded_len - (len + 1)*2) {
memset(utf16_ptr + (len + 1), 0, padded_len - (len + 1)*2);
if (padded_len > len*2) {
memset(utf16_ptr + len, 0, padded_len - len*2);
}
/* Correct the packet size if necessaary */
g_byte_array_set_size(buf, old_size + padded_len + 4);
} else if (utf8) {
/* Empty string */
gbinder_writer_data_append_string16_empty(data);
@@ -800,6 +816,39 @@ gbinder_writer_append_struct(
}
}
/*
* 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,
@@ -1154,19 +1203,29 @@ gbinder_writer_append_byte_array(
GASSERT(len >= 0);
if (G_LIKELY(data)) {
GByteArray* buf = data->bytes;
void* ptr;
gsize padded_len;
guint8* ptr;
if (!byte_array) {
len = 0;
}
g_byte_array_set_size(buf, buf->len + sizeof(len) + len);
ptr = buf->data + (buf->len - sizeof(len) - len);
/*
* Android aligns byte array reads and writes to 4 bytes and
* pads with 0xFF.
*/
padded_len = G_ALIGN4(len);
g_byte_array_set_size(buf, buf->len + sizeof(len) + padded_len);
ptr = buf->data + (buf->len - sizeof(len) - padded_len);
if (len > 0) {
*((gint32*)ptr) = len;
ptr += sizeof(len);
memcpy(ptr, byte_array, len);
/* FF padding */
if (padded_len > len) {
memset(ptr + len, 0xff, padded_len - len);
}
} else {
*((gint32*)ptr) = -1;
}

View File

@@ -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 = ashmem-test
#
# 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

View File

@@ -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

View File

@@ -45,15 +45,17 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
# Tools and flags
#
PKG_CONFIG ?= pkg-config
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
DEFINES += -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED
INCLUDES = -I$(LIB_DIR)/include -I$(GEN_DIR) -I$(SRC_DIR)
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
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 =
@@ -119,7 +121,7 @@ clean:
rm -fr $(BUILD_DIR)
cleaner: clean
@make -C $(LIB_DIR) clean
@$(MAKE) -C $(LIB_DIR) clean
$(DEBUG_BUILD_DIR):
mkdir -p $@

View File

@@ -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;
}
@@ -731,7 +742,7 @@ app_init(
"\t[0-9]*.[0-9]* for a 32-bit float\n"
"\t[0-9]*.[0-9]*L for a 64-bit double\n"
"\t\"[.*]\" for an 8-bit aidl string\n"
"\t\"[.*]\"L for an utf16 aidl string\n"
"\t\"[.*]\"u for an utf16 aidl string\n"
"\t\"[.*]\"h for an 8-bit hidl string\n"
"\t{ VALUE1 VALUE2 ... VALUEN } for a struct containing VALUE1, VALUE2, etc., where\n"
"\t all of these values can be any of the possible values described here.\n"
@@ -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;
}

View File

@@ -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;

View File

@@ -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); }

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

155
test/common/Makefile Normal file
View File

@@ -0,0 +1,155 @@
# -*- 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
#
PKG_CONFIG ?= pkg-config
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
DEFINES += -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED
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 $@

View File

@@ -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

View File

@@ -37,10 +37,10 @@ RELEASE_DEPS = libglibutil_release
.PHONY: libglibutil_debug libglibutil_release
libglibutil_debug:
make -C $(LIBGLIBUTIL_PATH) debug
$(MAKE) -C $(LIBGLIBUTIL_PATH) debug
libglibutil_release:
make -C $(LIBGLIBUTIL_PATH) release
$(MAKE) -C $(LIBGLIBUTIL_PATH) release
endif
@@ -66,18 +66,21 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
# Tools and flags
#
PKG_CONFIG ?= pkg-config
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS += -Wall -Wno-deprecated-declarations
DEFINES += -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED
INCLUDES += -I$(COMMON_DIR) -I$(LIB_DIR)/src -I$(LIB_DIR)/include
BASE_FLAGS = -fPIC
BASE_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS)
BASE_CFLAGS = $(BASE_FLAGS) $(CFLAGS)
FULL_CFLAGS = $(BASE_CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
$(shell pkg-config --cflags $(PKGS))
$(shell $(PKG_CONFIG) --cflags $(PKGS))
FULL_LDFLAGS = $(BASE_LDFLAGS)
LIBS = $(shell pkg-config --libs $(PKGS)) -lpthread
QUIET_MAKE = make --no-print-directory
LIBS = $(shell $(PKG_CONFIG) --libs $(PKGS)) -lpthread
QUIET_MAKE = $(MAKE) --no-print-directory
DEBUG_FLAGS = -g
RELEASE_FLAGS =
COVERAGE_FLAGS = -g
@@ -156,7 +159,7 @@ unitclean:
clean: unitclean
cleaner: unitclean
@make -C $(LIB_DIR) clean
@$(MAKE) -C $(LIB_DIR) clean
test_banner:
@echo "===========" $(EXE) "=========== "

File diff suppressed because it is too large Load Diff

View File

@@ -45,56 +45,72 @@
#define BINDER_OBJECT_SIZE_32 (16)
#define BINDER_OBJECT_SIZE_64 (24)
typedef struct test_binder TestBinder;
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);
@@ -102,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);
@@ -109,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(

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.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:
*
@@ -40,6 +40,13 @@ typedef struct test_opt {
int flags;
} TestOpt;
typedef struct test_config {
const char* default_config_dir;
const char* default_config_file;
char* config_dir;
char* non_existent_config_file;
} TestConfig;
/* Should be invoked after g_test_init */
void
test_init(
@@ -47,6 +54,16 @@ test_init(
int argc,
char* argv[]);
/* Creates empty test config dir */
void
test_config_init(
TestConfig* config,
const char* template);
void
test_config_cleanup(
TestConfig* config);
/* Run loop with a timeout */
void
test_run(

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -32,6 +32,9 @@
#include "test_common.h"
#include "gbinder_config.h"
#include "gbinder_rpc_protocol.h"
#include <gutil_log.h>
typedef struct test_quit_later_data{
@@ -191,6 +194,49 @@ test_init(
gutil_log_timestamp = FALSE;
}
/*
* Unit tests shouldn't depend on the system gbinder config. This is
* achieved by pointing gbinder_config_file to a non-existent file
* and gbinder_config_dir to an empty directory (where individual
* tests may create their own config files when they need it)
*/
void
test_config_init(
TestConfig* config,
const char* template)
{
config->config_dir = g_dir_make_tmp("gbinder-test-driver-XXXXXX", NULL);
g_assert(config->config_dir);
config->non_existent_config_file = g_build_filename(config->config_dir,
"non-existent.conf", NULL);
/* Point gbinder_config_file to a non-existent file */
config->default_config_dir = gbinder_config_dir;
config->default_config_file = gbinder_config_file;
gbinder_config_dir = config->config_dir;
gbinder_config_file = config->non_existent_config_file;
/* Reset the state */
gbinder_rpc_protocol_exit();
gbinder_config_exit();
}
void
test_config_cleanup(
TestConfig* config)
{
gbinder_config_dir = config->default_config_dir;
gbinder_config_file = config->default_config_file;
remove(config->config_dir);
g_free(config->config_dir);
g_free(config->non_existent_config_file);
memset(config, 0, sizeof(*config));
/* Reset the state */
gbinder_rpc_protocol_exit();
gbinder_config_exit();
}
/*
* Local Variables:
* mode: C

View File

@@ -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
*==========================================================================*/

View File

@@ -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 */
/*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2021-2023 Slava Monich <slava@monich.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
@@ -69,115 +67,10 @@ static const char DEFAULT_CONFIG_DATA[] =
"[ServiceManager]\n"
"Default = hidl\n";
typedef struct test_config {
char* dir;
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
*==========================================================================*/
static
void
test_config_init(
TestConfig* config,
char* config_data)
{
config->dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
config->file = g_build_filename(config->dir, "test.conf", NULL);
g_assert(g_file_set_contents(config->file, config_data ? config_data :
DEFAULT_CONFIG_DATA, -1, NULL));
gbinder_config_exit();
gbinder_config_dir = config->dir;
gbinder_config_file = config->file;
GDEBUG("Wrote config to %s", config->file);
}
static
void
test_config_deinit(
TestConfig* config)
{
gbinder_config_exit();
remove(config->file);
g_free(config->file);
remove(config->dir);
g_free(config->dir);
}
static
TestServiceManagerHidl*
test_servicemanager_impl_new(
@@ -187,7 +80,6 @@ test_servicemanager_impl_new(
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);
@@ -333,46 +225,34 @@ test_basic_run(
void)
{
TestBasic test;
TestConfig config;
TestServiceManagerHidl* dest_impl;
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);
memset(&test, 0, sizeof(test));
test.loop = g_main_loop_new(NULL, FALSE);
/* obj (DEST) <=> bridge <=> (SRC) mirror */
src_ipc = gbinder_ipc_new(SRC_DEV, NULL);
src_priv_ipc = gbinder_ipc_new(SRC_PRIV_DEV, NULL);
dest_ipc = gbinder_ipc_new(DEST_DEV, NULL);
dest_priv_ipc = gbinder_ipc_new(DEST_PRIV_DEV, NULL);
test.src_impl = test_servicemanager_impl_new(SRC_PRIV_DEV);
dest_impl = test_servicemanager_impl_new(DEST_PRIV_DEV);
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 +267,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 +278,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,42 +294,39 @@ 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);
}
@@ -482,14 +346,31 @@ test_basic(
int main(int argc, char* argv[])
{
TestConfig test_config;
char* config_file;
int result;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
g_test_init(&argc, &argv, NULL);
g_test_add_func(TEST_("null"), test_null);
g_test_add_func(TEST_("basic"), test_basic);
test_init(&test_opt, argc, argv);
return g_test_run();
test_config_init(&test_config, TMP_DIR_TEMPLATE);
config_file = g_build_filename(test_config.config_dir, "test.conf", NULL);
g_assert(g_file_set_contents(config_file, DEFAULT_CONFIG_DATA, -1, NULL));
GDEBUG("Config file %s", config_file);
gbinder_config_file = config_file;
result = g_test_run();
remove(config_file);
g_free(config_file);
test_config_cleanup(&test_config);
return result;
}
/*

View File

@@ -114,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);
}
/*==========================================================================*
@@ -175,6 +176,7 @@ test_interfaces(
gbinder_remote_object_unref(obj);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -189,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);
}
/*==========================================================================*
@@ -220,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));
@@ -232,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);
}
@@ -251,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);
}
/*==========================================================================*
@@ -291,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);
@@ -323,6 +326,7 @@ test_sync_reply(
test_sync_reply_tx(client, NULL);
gbinder_client_unref(client);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -393,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);
@@ -424,6 +429,7 @@ test_reply(
test_reply_tx(client, NULL, done, destroy);
gbinder_client_unref(client);
test_binder_exit_wait(&test_opt, NULL);
}
static

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.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,7 +32,6 @@
#include "test_binder.h"
#include "gbinder_config.h"
#include "gbinder_driver.h"
#include "gbinder_handler.h"
#include "gbinder_local_request_p.h"
@@ -42,6 +41,7 @@
#include <poll.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-driver-XXXXXX";
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
@@ -82,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);
}
/*==========================================================================*
@@ -98,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);
}
/*==========================================================================*
@@ -131,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);
}
/*==========================================================================*
@@ -141,30 +144,17 @@ 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);
TestConfig test_config;
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);
test_config_init(&test_config, TMP_DIR_TEMPLATE);
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);
test_config_cleanup(&test_config);
return result;
}

View File

@@ -180,7 +180,6 @@ test_basic(
/* Invalid path */
g_assert(!gbinder_ipc_new("invalid path", NULL));
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
@@ -203,7 +202,6 @@ test_protocol(
gbinder_ipc_unref(ipc);
gbinder_ipc_unref(ipc2);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
@@ -235,7 +233,7 @@ test_async_oneway(
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);
@@ -259,11 +257,10 @@ test_sync_oneway(
GBinderLocalRequest* req = test_local_request_new(ipc);
const int fd = gbinder_driver_fd(ipc->driver);
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);
}
@@ -291,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);
@@ -307,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);
}
@@ -341,26 +337,27 @@ test_sync_reply_error(
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);
}
@@ -414,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);
@@ -430,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);
}
@@ -464,8 +460,8 @@ test_transact_dead(
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);
@@ -477,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);
}
@@ -511,8 +506,8 @@ test_transact_failed(
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);
@@ -524,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);
}
@@ -560,8 +554,8 @@ test_transact_status(
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);
@@ -573,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);
}
@@ -671,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);
}
@@ -721,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);
}
@@ -767,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);
}
@@ -831,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 */
@@ -855,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);
}
@@ -895,10 +885,6 @@ test_transact_unhandled_run(
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,
@@ -907,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);
}
@@ -971,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 */
@@ -989,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);
}
@@ -1049,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 */
@@ -1062,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);
}
@@ -1165,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 */
@@ -1178,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);
}
@@ -1247,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 */
@@ -1260,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);
}
@@ -1301,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);
@@ -1350,7 +1326,7 @@ test_cancel_on_exit(
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);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.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,7 +33,6 @@
#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"
@@ -51,6 +50,7 @@
#include <errno.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-local-object-XXXXXX";
/* android.hidl.base@1.0::IBase */
#define TEST_BASE_INTERFACE_BYTES \
@@ -188,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);
}
/*==========================================================================*
@@ -233,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);
}
/*==========================================================================*
@@ -282,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);
}
/*==========================================================================*
@@ -332,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);
}
/*==========================================================================*
@@ -385,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);
}
/*==========================================================================*
@@ -436,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);
}
/*==========================================================================*
@@ -546,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);
}
/*==========================================================================*
@@ -603,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);
}
/*==========================================================================*
@@ -634,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);
}
@@ -685,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);
}
@@ -736,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);
}
@@ -786,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);
}
@@ -816,18 +820,9 @@ 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);
TestConfig test_config;
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;
@@ -846,13 +841,9 @@ 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);
test_config_init(&test_config, TMP_DIR_TEMPLATE);
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);
test_config_cleanup(&test_config);
return result;
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -43,6 +43,8 @@
#include "gbinder_rpc_protocol.h"
#include "gbinder_writer.h"
#include <gutil_log.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-protocol-XXXXXX";
@@ -121,57 +123,49 @@ static const TestHeaderData test_header_tests[] = {
test_header_hidl, 1 }
};
typedef struct test_config {
char* dir;
char* file;
} TestConfig;
typedef struct test_context {
TestConfig config;
char* config_file;
} TestContext;
static
void
test_config_init(
TestConfig* test,
test_context_init(
TestContext* test,
const char* config)
{
test->dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
test->file = g_build_filename(test->dir, "test.conf", NULL);
/* Reset the state */
gbinder_rpc_protocol_exit();
gbinder_config_exit();
memset(test, 0, sizeof(*test));
test_config_init(&test->config, TMP_DIR_TEMPLATE);
test->config_file = g_build_filename(test->config.config_dir,
"test.conf", NULL);
/* Write the config */
g_assert(g_file_set_contents(test->file, config, -1, NULL));
gbinder_config_file = test->file;
g_assert(g_file_set_contents(test->config_file, config, -1, NULL));
GDEBUG("Config file %s", test->config_file);
gbinder_config_file = test->config_file;
}
static
void
test_config_init2(
TestConfig* test,
test_context_init2(
TestContext* test,
const char* dev,
const char* prot)
{
char* config = g_strconcat("[Protocol]\n", dev, " = ", prot, "\n", NULL);
test_config_init(test, config);
test_context_init(test, config);
g_free(config);
}
static
void
test_config_cleanup(
TestConfig* test)
test_context_cleanup(
TestContext* test)
{
/* Undo the damage */
gbinder_rpc_protocol_exit();
gbinder_config_exit();
gbinder_config_file = NULL;
remove(test->file);
g_free(test->file);
remove(test->dir);
g_free(test->dir);
remove(test->config_file);
g_free(test->config_file);
test_config_cleanup(&test->config);
}
/*==========================================================================*
@@ -184,9 +178,9 @@ test_device(
void)
{
const GBinderRpcProtocol* p;
TestConfig config;
TestContext context;
test_config_init(&config, "");
test_context_init(&context, "");
p = gbinder_rpc_protocol_for_device(NULL);
g_assert(p);
@@ -200,7 +194,7 @@ test_device(
g_assert(p);
g_assert_cmpstr(p->name, == ,"hidl");
test_config_cleanup(&config);
test_context_cleanup(&context);
}
/*==========================================================================*
@@ -213,9 +207,9 @@ test_config1(
void)
{
const GBinderRpcProtocol* p;
TestConfig config;
TestContext context;
test_config_init(&config,
test_context_init(&context,
"[Protocol]\n"
"/dev/binder = hidl\n" /* Redefined name for /dev/binder */
"/dev/hwbinder = foo\n"); /* Invalid protocol name */
@@ -236,7 +230,7 @@ test_config1(
g_assert(p);
g_assert_cmpstr(p->name, == ,"aidl");
test_config_cleanup(&config);
test_context_cleanup(&context);
}
/*==========================================================================*
@@ -249,9 +243,9 @@ test_config2(
void)
{
const GBinderRpcProtocol* p;
TestConfig config;
TestContext context;
test_config_init(&config,
test_context_init(&context,
"[Protocol]\n"
"Default = hidl\n"
"/dev/vndbinder = hidl\n"
@@ -278,7 +272,7 @@ test_config2(
g_assert(p);
g_assert_cmpstr(p->name, == ,"hidl");
test_config_cleanup(&config);
test_context_cleanup(&context);
}
/*==========================================================================*
@@ -291,9 +285,9 @@ test_config3(
void)
{
const GBinderRpcProtocol* p;
TestConfig config;
TestContext context;
test_config_init(&config,
test_context_init(&context,
"[Whatever]\n"
"/dev/hwbinder = aidl\n"); /* Ignored, wrong section */
@@ -310,7 +304,7 @@ test_config3(
g_assert(p);
g_assert_cmpstr(p->name, == ,"aidl");
test_config_cleanup(&config);
test_context_cleanup(&context);
}
/*==========================================================================*
@@ -324,9 +318,9 @@ test_no_header1(
{
const TestData* test = test_data;
GBinderRemoteRequest* req;
TestConfig config;
TestContext context;
test_config_init2(&config, test->dev, test->prot);
test_context_init2(&context, test->dev, test->prot);
req = gbinder_remote_request_new(NULL, gbinder_rpc_protocol_for_device
(GBINDER_DEFAULT_BINDER), 0, 0);
@@ -334,7 +328,7 @@ test_no_header1(
g_assert(!gbinder_remote_request_interface(req));
gbinder_remote_request_unref(req);
test_config_cleanup(&config);
test_context_cleanup(&context);
}
/*==========================================================================*
@@ -350,9 +344,9 @@ test_no_header2(
const GBinderRpcProtocol* p;
GBinderDriver* driver;
GBinderRemoteRequest* req;
TestConfig config;
TestContext context;
test_config_init2(&config, test->dev, test->prot);
test_context_init2(&context, test->dev, test->prot);
p = gbinder_rpc_protocol_for_device(test->dev);
driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, p);
@@ -365,7 +359,7 @@ test_no_header2(
g_assert(!gbinder_remote_request_interface(req));
gbinder_remote_request_unref(req);
gbinder_driver_unref(driver);
test_config_cleanup(&config);
test_context_cleanup(&context);
}
static const TestData test_no_header_data[] = {
@@ -388,9 +382,9 @@ test_write_header(
GBinderLocalRequest* req;
GBinderOutputData* data;
GBinderWriter writer;
TestConfig config;
TestContext context;
test_config_init2(&config, test->dev, test->prot);
test_context_init2(&context, test->dev, test->prot);
prot = gbinder_rpc_protocol_for_device(test->dev);
req = gbinder_local_request_new(&gbinder_io_32,
@@ -402,7 +396,7 @@ test_write_header(
g_assert(!memcmp(data->bytes->data, test->header, test->header_size));
gbinder_local_request_unref(req);
test_config_cleanup(&config);
test_context_cleanup(&context);
}
/*==========================================================================*
@@ -417,9 +411,9 @@ test_read_header(
const TestHeaderData* test = test_data;
GBinderDriver* driver;
GBinderRemoteRequest* req;
TestConfig config;
TestContext context;
test_config_init2(&config, test->dev, test->prot);
test_context_init2(&context, test->dev, test->prot);
driver = gbinder_driver_new(test->dev, NULL);
req = gbinder_remote_request_new(NULL, gbinder_rpc_protocol_for_device
@@ -431,7 +425,7 @@ test_read_header(
gbinder_remote_request_unref(req);
gbinder_driver_unref(driver);
test_config_cleanup(&config);
test_context_cleanup(&context);
}
/*==========================================================================*

View File

@@ -1,6 +1,6 @@
/*
* 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 +50,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,
@@ -68,9 +66,9 @@ enum test_tx_codes {
#define TX_PARAM_DONT_REPLY 0x22220000
#define TX_RESULT 0x03030303
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-proxy-XXXXXX";
const char TEST_IFACE[] = "test@1.0::ITest";
const char TEST_IFACE2[] = "test@1.0::ITest2";
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-proxy_object-XXXXXX";
static const char TEST_IFACE[] = "test@1.0::ITest";
static const char TEST_IFACE2[] = "test@1.0::ITest2";
static const char* TEST_IFACES[] = { TEST_IFACE, NULL };
static const char* TEST_IFACES2[] = { TEST_IFACE2, NULL };
static const char DEFAULT_CONFIG_DATA[] =
@@ -79,46 +77,6 @@ static const char DEFAULT_CONFIG_DATA[] =
"[ServiceManager]\n"
"Default = hidl\n";
typedef struct test_config {
char* dir;
char* file;
} TestConfig;
/*==========================================================================*
* Common
*==========================================================================*/
static
void
test_config_init(
TestConfig* config,
char* config_data)
{
config->dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
config->file = g_build_filename(config->dir, "test.conf", NULL);
g_assert(g_file_set_contents(config->file, config_data ? config_data :
DEFAULT_CONFIG_DATA, -1, NULL));
gbinder_config_exit();
gbinder_config_dir = config->dir;
gbinder_config_file = config->file;
GDEBUG("Wrote config to %s", config->file);
}
static
void
test_config_deinit(
TestConfig* config)
{
gbinder_config_exit();
remove(config->file);
g_free(config->file);
remove(config->dir);
g_free(config->dir);
}
/*==========================================================================*
* null
*==========================================================================*/
@@ -186,42 +144,30 @@ void
test_basic_run(
void)
{
TestConfig config;
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, NULL);
ipc_obj = gbinder_ipc_new(DEV_PRIV, 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,13 +178,10 @@ 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);
}
@@ -259,6 +202,7 @@ gboolean
test_param_cancel(
gpointer req)
{
GDEBUG("Cancelling request");
gbinder_remote_request_complete(req, NULL, -ECANCELED);
return G_SOURCE_REMOVE;
}
@@ -303,6 +247,20 @@ test_param_cb(
}
}
static
void
test_param_canceled(
GBinderClient* client,
GBinderRemoteReply* reply,
int status,
void* loop)
{
g_assert(!reply);
g_assert_cmpint(status, == ,-ECANCELED);
GDEBUG("Transaction cancelled");
g_main_loop_quit((GMainLoop*)loop);
}
static
void
test_param_reply(
@@ -311,35 +269,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
@@ -347,81 +289,61 @@ void
test_param_run(
void)
{
TestConfig config;
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);
GMainLoop* loop2 = g_main_loop_new(NULL, FALSE);
int fd_obj, fd_proxy, n = 0;
test_config_init(&config, NULL);
ipc_obj = gbinder_ipc_new(DEV, NULL);
ipc_remote_obj = gbinder_ipc_new(DEV_PRIV, NULL);
ipc_proxy = gbinder_ipc_new(DEV2, NULL);
ipc_remote_proxy = gbinder_ipc_new(DEV2_PRIV, 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,
NULL, NULL);
gbinder_client_transact(client, TX_CODE, 0, req, test_param_canceled,
NULL, loop2);
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);
test_run(&test_opt, loop);
/* Depending on how callbacks are scheduled, n could be 1 or 2 */
g_assert_cmpint(n, > ,0);
test_run(&test_opt, loop2);
g_assert_cmpint(n, == ,2);
test_binder_unregister_objects(fd_obj);
test_binder_unregister_objects(fd_proxy);
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);
g_main_loop_unref(loop2);
}
static
@@ -591,68 +513,43 @@ void
test_obj_run(
void)
{
TestConfig config;
TestObj test;
GBinderLocalObject* obj;
GBinderLocalObject* obj2;
GBinderProxyObject* proxy;
GBinderRemoteObject* remote_obj;
GBinderRemoteObject* remote_proxy;
GBinderClient* proxy_client;
GBinderIpc* ipc_remote_obj;
GBinderClient* client;
GBinderIpc* ipc_obj;
GBinderIpc* ipc_proxy;
GBinderIpc* ipc_remote_proxy;
GBinderLocalRequest* req;
int fd_remote_obj, fd_obj, fd_proxy, fd_remote_proxy;
int fd_obj, fd_proxy;
test_config_init(&config, NULL);
memset(&test, 0, sizeof(test));
test.loop = g_main_loop_new(NULL, FALSE);
ipc_remote_obj = gbinder_ipc_new(DEV_PRIV, NULL);
ipc_obj = gbinder_ipc_new(DEV, NULL);
ipc_proxy = gbinder_ipc_new(DEV2, NULL);
ipc_remote_proxy = gbinder_ipc_new(DEV2_PRIV, NULL);
fd_remote_obj = gbinder_driver_fd(ipc_remote_obj->driver);
fd_obj = gbinder_driver_fd(ipc_obj->driver);
ipc_obj = gbinder_ipc_new(DEV, NULL);
fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
fd_remote_proxy = gbinder_driver_fd(ipc_remote_proxy->driver);
fd_obj = gbinder_driver_fd(ipc_obj->driver);
obj = gbinder_local_object_new(ipc_remote_obj, TEST_IFACES,
test_obj_cb, &test);
obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_obj_cb, &test);
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(DEV2_PRIV) => proxy (DEV) => obj(DEV2_PRIV) */
g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
GDEBUG("proxy %p", proxy);
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_remote_obj, TRUE);
test_binder_set_passthrough(fd_obj, TRUE);
test_binder_set_passthrough(fd_proxy, TRUE);
test_binder_set_passthrough(fd_remote_proxy, TRUE);
test_binder_set_looper_enabled(fd_remote_obj, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_obj, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_proxy, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_remote_proxy, TEST_LOOPER_ENABLE);
client = gbinder_client_new(proxy->remote, TEST_IFACE);
/* Pass object reference via proxy */
obj2 = gbinder_local_object_new(ipc_remote_proxy, TEST_IFACES2, test_obj2_cb, &test);
obj2 = gbinder_local_object_new(ipc_obj, TEST_IFACES2, test_obj2_cb, &test);
GDEBUG("obj2 %p", obj2);
req = gbinder_client_new_request(proxy_client);
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);
@@ -665,24 +562,17 @@ test_obj_run(
g_assert(test.obj2);
gbinder_local_object_unref(test.obj2);
test_binder_unregister_objects(fd_remote_obj);
test_binder_unregister_objects(fd_obj);
test_binder_unregister_objects(fd_proxy);
test_binder_unregister_objects(fd_remote_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_ipc_unref(ipc_remote_obj);
gbinder_client_unref(client);
gbinder_ipc_unref(ipc_obj);
gbinder_ipc_unref(ipc_proxy);
gbinder_ipc_unref(ipc_remote_proxy);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, test.loop);
test_config_deinit(&config);
g_main_loop_unref(test.loop);
}
@@ -702,6 +592,10 @@ test_obj(
int main(int argc, char* argv[])
{
TestConfig test_config;
char* config_file;
int result;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
@@ -710,8 +604,20 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("basic"), test_basic);
g_test_add_func(TEST_("param"), test_param);
g_test_add_func(TEST_("obj"), test_obj);
test_init(&test_opt, argc, argv);
return g_test_run();
test_config_init(&test_config, TMP_DIR_TEMPLATE);
config_file = g_build_filename(test_config.config_dir, "test.conf", NULL);
g_assert(g_file_set_contents(config_file, DEFAULT_CONFIG_DATA, -1, NULL));
GDEBUG("Config file %s", config_file);
gbinder_config_file = config_file;
result = g_test_run();
remove(config_file);
g_free(config_file);
test_config_cleanup(&test_config);
return result;
}
/*

View File

@@ -1,6 +1,7 @@
/*
* 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"
@@ -59,12 +61,9 @@ 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
@@ -176,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));
@@ -215,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);
@@ -244,8 +243,8 @@ void
test_int8(
void)
{
const guint8 in = 42;
const guint8 in4[] = { TEST_INT8_BYTES_4(42) };
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);
@@ -296,7 +295,7 @@ test_int16(
void)
{
const guint16 in = 42;
const guint8 in4[] = { TEST_INT16_BYTES_4(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);
@@ -789,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);
}
/*==========================================================================*
@@ -1024,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);
}
/*==========================================================================*
@@ -1105,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
@@ -1139,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);
}
/*==========================================================================*
@@ -1182,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);
}
/*==========================================================================*
@@ -1213,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);
}
/*==========================================================================*
@@ -1256,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);
}
/*==========================================================================*
@@ -1303,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);
}
/*==========================================================================*
@@ -1346,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);
}
/*==========================================================================*
@@ -1389,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);
}
/*==========================================================================*
@@ -1429,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
@@ -1707,6 +1717,7 @@ test_buffer(
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1813,7 +1824,8 @@ 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, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
@@ -1833,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);
}
/*==========================================================================*
@@ -1895,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);
}
/*==========================================================================*
@@ -1947,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);
}
/*==========================================================================*
@@ -1983,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);
@@ -2002,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

View File

@@ -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);
}
/*==========================================================================*
@@ -119,8 +120,7 @@ test_dead_run(
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);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -95,7 +95,6 @@ test_null(
g_assert(!gbinder_remote_reply_ref(NULL));
gbinder_remote_reply_unref(NULL);
gbinder_remote_reply_set_data(NULL, NULL);
gbinder_remote_reply_init_reader(NULL, &reader);
g_assert(gbinder_reader_at_end(&reader));
g_assert(gbinder_remote_reply_is_empty(NULL));

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2024 Slava Monich <slava@monich.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,6 +47,7 @@
#include <gutil_intarray.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-remote-request-XXXXXX";
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
@@ -73,7 +74,6 @@ test_null(
g_assert(!gbinder_remote_request_ref(NULL));
gbinder_remote_request_unref(NULL);
gbinder_remote_request_set_data(NULL, 0, NULL);
gbinder_remote_request_init_reader(NULL, &reader);
gbinder_remote_request_block(NULL);
gbinder_remote_request_complete(NULL, NULL, 0);
@@ -368,18 +368,9 @@ 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);
TestConfig test_config;
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);
@@ -389,13 +380,9 @@ 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);
test_config_init(&test_config, TMP_DIR_TEMPLATE);
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);
test_config_cleanup(&test_config);
return result;
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2023 Slava Monich <slava@monich.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,7 +40,6 @@
#include "gbinder_local_object_p.h"
#include "gbinder_servicemanager_p.h"
#include "gbinder_object_registry.h"
#include "gbinder_rpc_protocol.h"
#include <gutil_strv.h>
#include <gutil_macros.h>
@@ -133,9 +132,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);
}
/*==========================================================================*
@@ -484,6 +483,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);
}
/*==========================================================================*
@@ -499,7 +499,9 @@ test_basic(
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GBinderServiceManager* sm;
GBinderLocalObject* obj;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -513,7 +515,8 @@ test_basic(
gbinder_servicemanager_unref(sm);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
test_config_cleanup(&config);
}
/*==========================================================================*
@@ -529,12 +532,9 @@ test_legacy(
const char* dev = GBINDER_DEFAULT_HWBINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
GBinderServiceManager* sm;
TestConfig config;
/* Reset the state */
gbinder_servicemanager_exit();
gbinder_config_exit();
gbinder_config_file = NULL;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_hwservicemanager_new(dev);
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
@@ -556,7 +556,8 @@ test_legacy(
gbinder_ipc_unref(ipc);
gbinder_servicemanager_exit();
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
test_config_cleanup(&config);
}
/*==========================================================================*
@@ -572,8 +573,8 @@ test_config(
GBinderServiceManager* sm;
const char* strange_name = "/dev/notbinder";
const char* legacy_name = "/dev/legacybinder";
char* dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
char* file = g_build_filename(dir, "test.conf", NULL);
TestConfig test;
char* file;
static const char config[] =
"[ServiceManager]\n"
@@ -582,12 +583,12 @@ test_config(
"/dev/hwbinder = foo\n" /* Invalid name */
"/dev/legacybinder = aidl\n";
/* Reset the state */
gbinder_servicemanager_exit();
gbinder_config_exit();
test_config_init(&test, TMP_DIR_TEMPLATE);
file = g_build_filename(test.config_dir, "test.conf", NULL);
/* Write the config file */
g_assert(g_file_set_contents(file, config, -1, NULL));
GDEBUG("Config file %s", file);
gbinder_config_file = file;
/* Unknown device instantiates the default */
@@ -632,13 +633,10 @@ test_config(
/* Clear the state */
gbinder_servicemanager_exit();
gbinder_config_exit();
gbinder_config_file = NULL;
test_binder_exit_wait(&test_opt, NULL);
remove(file);
remove(dir);
g_free(file);
g_free(dir);
test_config_cleanup(&test);
}
/*==========================================================================*
@@ -654,9 +652,12 @@ test_not_present(
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GBinderServiceManager* sm;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
/* 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);
@@ -664,6 +665,8 @@ test_not_present(
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
test_config_cleanup(&config);
}
/*==========================================================================*
@@ -683,9 +686,12 @@ test_wait(
GBinderServiceManager* sm;
gulong id;
int count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
/* 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);
@@ -696,13 +702,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 ) */
@@ -714,7 +720,8 @@ 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);
test_config_cleanup(&config);
}
/*==========================================================================*
@@ -732,9 +739,12 @@ test_wait_long(
GBinderServiceManager* sm;
gulong id;
int count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
/* 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);
@@ -745,10 +755,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 ) */
@@ -760,7 +770,8 @@ 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);
test_config_cleanup(&config);
}
/*==========================================================================*
@@ -779,9 +790,12 @@ test_wait_async(
GBinderServiceManager* sm;
gulong id[2];
int count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
/* 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);
@@ -794,9 +808,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 */
@@ -804,7 +818,8 @@ 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);
test_config_cleanup(&config);
g_main_loop_unref(loop);
}
@@ -823,7 +838,9 @@ test_death_run()
GBinderServiceManager* sm;
gulong id[3];
int count = 0, reg_count = 0;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -838,9 +855,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 */
@@ -852,8 +868,8 @@ 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);
test_config_cleanup(&config);
g_main_loop_unref(loop);
}
@@ -880,11 +896,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);
}
}
@@ -900,8 +915,10 @@ test_reanimate(
GBinderServiceManager* sm;
gulong id[3];
int count = 0, reg_count = 0;
TestConfig config;
/* Create live service manager */
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -917,9 +934,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 */
@@ -932,8 +948,8 @@ 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);
test_config_cleanup(&config);
g_main_loop_unref(loop);
}
@@ -958,7 +974,9 @@ test_reuse(
GBinderServiceManager* vnd2;
GBinderServiceManager* hw1;
GBinderServiceManager* hw2;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(binder_ipc);
test_setup_ping(vndbinder_ipc);
test_setup_ping(hwbinder_ipc);
@@ -991,7 +1009,8 @@ 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);
test_config_cleanup(&config);
}
/*==========================================================================*
@@ -1010,7 +1029,9 @@ test_notify_type(
const char* name = "foo";
int count = 0;
gulong id1, id2;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new_with_type(t, NULL, NULL);
test = TEST_SERVICEMANAGER2(sm, t);
@@ -1036,7 +1057,8 @@ 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);
test_config_cleanup(&config);
}
static
@@ -1078,7 +1100,9 @@ test_list(
TestHwServiceManager* test;
char** list;
gulong id;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
test = TEST_SERVICEMANAGER(sm);
@@ -1094,7 +1118,8 @@ test_list(
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
test_config_cleanup(&config);
g_main_loop_unref(loop);
}
@@ -1128,7 +1153,9 @@ test_get(
int status = -1;
GBinderLocalObject* obj;
gulong id;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
test = TEST_SERVICEMANAGER(sm);
@@ -1158,7 +1185,8 @@ test_get(
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
test_config_cleanup(&config);
g_main_loop_unref(loop);
}
@@ -1189,7 +1217,9 @@ test_add(
TestHwServiceManager* test;
GBinderLocalObject* obj;
gulong id;
TestConfig config;
test_config_init(&config, TMP_DIR_TEMPLATE);
test_setup_ping(ipc);
sm = gbinder_servicemanager_new(dev);
test = TEST_SERVICEMANAGER(sm);
@@ -1206,7 +1236,8 @@ 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);
test_config_cleanup(&config);
g_main_loop_unref(loop);
}

View File

@@ -1,6 +1,6 @@
/*
* 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:
*
@@ -36,7 +36,6 @@
#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"
@@ -46,6 +45,8 @@
#include <gutil_log.h>
static TestOpt test_opt;
static const char TMP_DIR_TEMPLATE[] =
"gbinder-test-servicemanager_aidl-XXXXXX";
GType
gbinder_servicemanager_hidl_get_type()
@@ -98,7 +99,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidlClass;
typedef struct service_manager_aidl {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl;
#define SERVICE_MANAGER_AIDL_TYPE (service_manager_aidl_get_type())
@@ -110,23 +111,23 @@ G_DEFINE_TYPE(ServiceManagerAidl, service_manager_aidl, \
static
GBinderLocalReply*
servicemanager_aidl_handler(
GBinderLocalObject* obj,
ServiceManagerAidl* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl* self = user_data;
GBinderLocalObject* obj = &self->parent;
GBinderLocalReply* reply = NULL;
GBinderReader reader;
GBinderRemoteObject* remote_obj;
guint32 num;
char* str;
g_assert(!flags);
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
*status = -1;
/* Lock */
g_mutex_lock(&self->mutex);
switch (code) {
case GET_SERVICE_TRANSACTION:
case CHECK_SERVICE_TRANSACTION:
@@ -179,71 +180,39 @@ servicemanager_aidl_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl*
servicemanager_aidl_new(
const char* dev,
gboolean handle_on_looper_thread)
{
ServiceManagerAidl* self = g_object_new(SERVICE_MANAGER_AIDL_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
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);
return self;
}
static
void
servicemanager_aidl_free(
ServiceManagerAidl* self)
{
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,
servicemanager_aidl_handle_looper_transaction(
GBinderLocalObject* obj,
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);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl_handler(SERVICE_MANAGER_AIDL(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -253,6 +222,7 @@ service_manager_aidl_finalize(
{
ServiceManagerAidl* self = SERVICE_MANAGER_AIDL(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl_parent_class)->finalize(object);
}
@@ -262,6 +232,7 @@ void
service_manager_aidl_init(
ServiceManagerAidl* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -271,14 +242,29 @@ void
service_manager_aidl_class_init(
ServiceManagerAidlClass* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl_finalize;
klass->can_handle_transaction =
servicemanager_aidl_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl_handle_looper_transaction;
}
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;
static
ServiceManagerAidl*
servicemanager_aidl_new(
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, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -329,9 +315,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, NULL);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
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";
@@ -340,7 +325,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 */
@@ -365,11 +349,10 @@ test_get_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(smsvc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(smsvc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -411,9 +394,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, NULL);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
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";
@@ -425,7 +407,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 */
@@ -451,11 +432,10 @@ test_list_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(smsvc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(smsvc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, test.loop);
g_strfreev(test.list);
@@ -490,9 +470,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, NULL);
ServiceManagerAidl* svc = servicemanager_aidl_new(other_dev, FALSE);
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";
@@ -502,7 +481,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);
@@ -522,11 +500,10 @@ test_notify_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(svc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(svc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -547,9 +524,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, NULL);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, TRUE);
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;
@@ -560,7 +536,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);
@@ -589,11 +564,10 @@ test_notify2_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(smsvc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(smsvc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -613,6 +587,9 @@ test_notify2()
int main(int argc, char* argv[])
{
TestConfig config;
int result;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
@@ -622,7 +599,10 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("notify"), test_notify);
g_test_add_func(TEST_("notify2"), test_notify2);
test_init(&test_opt, argc, argv);
return g_test_run();
test_config_init(&config, TMP_DIR_TEMPLATE);
result = g_test_run();
test_config_cleanup(&config);
return result;
}
/*

View File

@@ -1,6 +1,6 @@
/*
* 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:
*
@@ -37,7 +37,6 @@
#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"
@@ -58,6 +57,22 @@ gbinder_servicemanager_hidl_get_type()
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;
}
/*==========================================================================*
* Test service manager
*==========================================================================*/
@@ -77,7 +92,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidl2Class;
typedef struct service_manager_aidl2 {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl2;
#define SERVICE_MANAGER_AIDL2_TYPE (service_manager_aidl2_get_type())
@@ -89,24 +104,23 @@ G_DEFINE_TYPE(ServiceManagerAidl2, service_manager_aidl2, \
static
GBinderLocalReply*
servicemanager_aidl2_handler(
GBinderLocalObject* obj,
ServiceManagerAidl2* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl2* self = user_data;
GBinderLocalObject* obj = &self->parent;
GBinderLocalReply* reply = NULL;
GBinderReader reader;
GBinderRemoteObject* remote_obj;
guint32 num, 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;
/* Lock */
g_mutex_lock(&self->mutex);
switch (code) {
case GET_SERVICE_TRANSACTION:
case CHECK_SERVICE_TRANSACTION:
@@ -164,63 +178,39 @@ servicemanager_aidl2_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl2*
servicemanager_aidl2_new(
const char* dev,
gboolean handle_on_looper_thread)
{
ServiceManagerAidl2* self = g_object_new(SERVICE_MANAGER_AIDL2_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
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,
servicemanager_aidl2_handle_looper_transaction(
GBinderLocalObject* obj,
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);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl2_handler(SERVICE_MANAGER_AIDL2(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl2_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -230,6 +220,7 @@ service_manager_aidl2_finalize(
{
ServiceManagerAidl2* self = SERVICE_MANAGER_AIDL2(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl2_parent_class)->finalize(object);
}
@@ -239,6 +230,7 @@ void
service_manager_aidl2_init(
ServiceManagerAidl2* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -248,14 +240,29 @@ void
service_manager_aidl2_class_init(
ServiceManagerAidl2Class* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl2_finalize;
klass->can_handle_transaction =
servicemanager_aidl2_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl2_handle_looper_transaction;
}
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;
static
ServiceManagerAidl2*
servicemanager_aidl2_new(
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, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -263,14 +270,12 @@ service_manager_aidl2_class_init(
*==========================================================================*/
typedef struct test_context {
const char* default_config_dir;
const char* default_config_file;
char* config_dir;
char* config_subdir;
TestConfig config;
char* config_file;
GBinderLocalObject* object;
ServiceManagerAidl2* service;
GBinderServiceManager* client;
GMainLoop* loop;
int fd;
} TestContext;
@@ -280,11 +285,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"
@@ -295,26 +295,20 @@ test_context_init(
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);
test_config_init(&test->config, TMP_DIR_TEMPLATE);
test->config_file = g_build_filename(test->config.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);
/* 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);
}
@@ -323,20 +317,40 @@ 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_local_object_unref(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);
gbinder_config_dir = test->default_config_dir;
gbinder_config_file = test->default_config_file;
gbinder_config_exit();
g_main_loop_unref(test->loop);
test_config_cleanup(&test->config);
}
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);
}
/*==========================================================================*
@@ -367,12 +381,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);
}
@@ -410,6 +428,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);
@@ -418,6 +439,7 @@ test_list_run()
g_assert_cmpstr(list[0], == ,name);
g_strfreev(list);
GDEBUG("Done");
test_context_deinit(&test);
}

View File

@@ -1,6 +1,6 @@
/*
* 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:
*
@@ -37,7 +37,6 @@
#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"
@@ -59,6 +58,22 @@ gbinder_servicemanager_hidl_get_type()
return 0;
}
GType
gbinder_servicemanager_aidl2_get_type()
{
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl2 */
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;
}
/*==========================================================================*
* Test service manager
*==========================================================================*/
@@ -78,7 +93,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidl3Class;
typedef struct service_manager_aidl3 {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl3;
#define SERVICE_MANAGER_AIDL3_TYPE (service_manager_aidl3_get_type())
@@ -90,24 +105,23 @@ G_DEFINE_TYPE(ServiceManagerAidl3, service_manager_aidl3, \
static
GBinderLocalReply*
servicemanager_aidl3_handler(
GBinderLocalObject* obj,
ServiceManagerAidl3* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl3* self = user_data;
GBinderLocalObject* obj = &self->parent;
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;
/* Lock */
g_mutex_lock(&self->mutex);
switch (code) {
case GET_SERVICE_TRANSACTION:
case CHECK_SERVICE_TRANSACTION:
@@ -173,63 +187,39 @@ servicemanager_aidl3_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl3*
servicemanager_aidl3_new(
const char* dev,
gboolean handle_on_looper_thread)
{
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);
self->handle_on_looper_thread = handle_on_looper_thread;
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
servicemanager_aidl3_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_aidl3_can_handle_transaction(
GBinderLocalObject* object,
const char* iface,
guint code)
{
ServiceManagerAidl3* self = SERVICE_MANAGER_AIDL3(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_aidl3_parent_class)->
can_handle_transaction(object, iface, code);
}
}
static
GBinderLocalReply*
service_manager_aidl3_handle_looper_transaction(
GBinderLocalObject* object,
servicemanager_aidl3_handle_looper_transaction(
GBinderLocalObject* obj,
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_aidl3_parent_class)->
handle_transaction(object, req, code, flags, status);
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
handle_looper_transaction(object, req, code, flags, status);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl3_handler(SERVICE_MANAGER_AIDL3(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl3_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -239,6 +229,7 @@ service_manager_aidl3_finalize(
{
ServiceManagerAidl3* self = SERVICE_MANAGER_AIDL3(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl3_parent_class)->finalize(object);
}
@@ -248,6 +239,7 @@ void
service_manager_aidl3_init(
ServiceManagerAidl3* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -257,14 +249,29 @@ void
service_manager_aidl3_class_init(
ServiceManagerAidl3Class* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl3_finalize;
klass->can_handle_transaction =
servicemanager_aidl3_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl3_handle_looper_transaction;
}
object->finalize = service_manager_aidl3_finalize;
local_object->can_handle_transaction =
service_manager_aidl3_can_handle_transaction;
local_object->handle_looper_transaction =
service_manager_aidl3_handle_looper_transaction;
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,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -272,14 +279,12 @@ service_manager_aidl3_class_init(
*==========================================================================*/
typedef struct test_context {
const char* default_config_dir;
const char* default_config_file;
char* config_dir;
char* config_subdir;
TestConfig config;
char* config_file;
GBinderLocalObject* object;
ServiceManagerAidl3* service;
GBinderServiceManager* client;
GMainLoop* loop;
int fd;
} TestContext;
@@ -289,11 +294,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 = aidl3\n"
@@ -304,26 +304,20 @@ test_context_init(
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);
test_config_init(&test->config, TMP_DIR_TEMPLATE);
test->config_file = g_build_filename(test->config.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);
/* Set up binder simulator */
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
test_binder_set_passthrough(test->fd, TRUE);
test->service = servicemanager_aidl3_new(other_dev, TRUE);
test->service = servicemanager_aidl3_new(dev);
test->client = gbinder_servicemanager_new(dev);
test->loop = g_main_loop_new(NULL, FALSE);
gbinder_ipc_unref(ipc);
}
@@ -332,20 +326,40 @@ 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_local_object_unref(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);
gbinder_config_dir = test->default_config_dir;
gbinder_config_file = test->default_config_file;
gbinder_config_exit();
g_main_loop_unref(test->loop);
test_config_cleanup(&test->config);
}
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);
}
/*==========================================================================*
@@ -376,12 +390,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);
}
@@ -419,6 +437,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);
@@ -427,6 +448,7 @@ test_list_run()
g_assert_cmpstr(list[0], == ,name);
g_strfreev(list);
GDEBUG("Done");
test_context_deinit(&test);
}

View File

@@ -1,6 +1,6 @@
/*
* 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:
*
@@ -37,7 +37,6 @@
#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"
@@ -59,6 +58,14 @@ gbinder_servicemanager_hidl_get_type()
return 0;
}
GType
gbinder_servicemanager_aidl2_get_type()
{
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl2 */
g_assert_not_reached();
return 0;
}
/*==========================================================================*
* Test service manager
*==========================================================================*/
@@ -78,7 +85,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidl4Class;
typedef struct service_manager_aidl4 {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl4;
#define SERVICE_MANAGER_AIDL4_TYPE (service_manager_aidl4_get_type())
@@ -87,75 +94,55 @@ typedef struct service_manager_aidl4 {
G_DEFINE_TYPE(ServiceManagerAidl4, service_manager_aidl4, \
GBINDER_TYPE_LOCAL_OBJECT)
/* This should be eventually handled at lower level. */
typedef struct category {
/*
* This is the version of the wire protocol associated with the host
* process of a particular binder. As the wire protocol changes, if
* sending a transaction to a binder with an old version, the Parcel
* class must write parcels according to the version documented here.
*/
gint8 version;
gint8 reserved[2];
gint8 level; /* bitmask of Stability::Level */
} Category;
static
GBinderLocalReply*
servicemanager_aidl4_handler(
GBinderLocalObject* obj,
ServiceManagerAidl4* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl4* self = user_data;
GBinderLocalObject* obj = &self->parent;
GBinderLocalReply* reply = NULL;
GBinderReader reader;
GBinderRemoteObject* remote_obj;
guint32 allow_isolated, dumpsys_priority;
char* str;
Category category;
g_assert(!flags);
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
*status = -1;
/* Lock */
g_mutex_lock(&self->mutex);
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);
GBinderWriter writer;
remote_obj = g_hash_table_lookup(self->objects, str);
if (str) {
GBinderWriter writer;
reply = gbinder_local_object_new_reply(obj);
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);
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);
gbinder_reader_read_uint32(&reader, (guint32*)&category);
if (str && remote_obj &&
category.level == GBINDER_STABILITY_SYSTEM &&
category.version == 1 &&
/* 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);
@@ -194,63 +181,39 @@ servicemanager_aidl4_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl4*
servicemanager_aidl4_new(
const char* dev,
gboolean handle_on_looper_thread)
{
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);
self->handle_on_looper_thread = handle_on_looper_thread;
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
servicemanager_aidl4_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_aidl4_can_handle_transaction(
GBinderLocalObject* object,
const char* iface,
guint code)
{
ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(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_aidl4_parent_class)->
can_handle_transaction(object, iface, code);
}
}
static
GBinderLocalReply*
service_manager_aidl4_handle_looper_transaction(
GBinderLocalObject* object,
servicemanager_aidl4_handle_looper_transaction(
GBinderLocalObject* obj,
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_aidl4_parent_class)->
handle_transaction(object, req, code, flags, status);
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
handle_looper_transaction(object, req, code, flags, status);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl4_handler(SERVICE_MANAGER_AIDL4(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl4_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -260,6 +223,7 @@ service_manager_aidl4_finalize(
{
ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl4_parent_class)->finalize(object);
}
@@ -269,6 +233,7 @@ void
service_manager_aidl4_init(
ServiceManagerAidl4* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -278,14 +243,29 @@ void
service_manager_aidl4_class_init(
ServiceManagerAidl4Class* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl4_finalize;
klass->can_handle_transaction =
servicemanager_aidl4_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl4_handle_looper_transaction;
}
object->finalize = service_manager_aidl4_finalize;
local_object->can_handle_transaction =
service_manager_aidl4_can_handle_transaction;
local_object->handle_looper_transaction =
service_manager_aidl4_handle_looper_transaction;
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,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -293,14 +273,12 @@ service_manager_aidl4_class_init(
*==========================================================================*/
typedef struct test_context {
const char* default_config_dir;
const char* default_config_file;
char* config_dir;
char* config_subdir;
TestConfig config;
char* config_file;
GBinderLocalObject* object;
ServiceManagerAidl4* service;
GBinderServiceManager* client;
GMainLoop* loop;
int fd;
} TestContext;
@@ -310,11 +288,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 = aidl3\n"
@@ -325,26 +298,20 @@ test_context_init(
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);
test_config_init(&test->config, TMP_DIR_TEMPLATE);
test->config_file = g_build_filename(test->config.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);
/* Set up binder simulator */
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
test_binder_set_passthrough(test->fd, TRUE);
test->service = servicemanager_aidl4_new(other_dev, TRUE);
test->service = servicemanager_aidl4_new(dev);
test->client = gbinder_servicemanager_new(dev);
test->loop = g_main_loop_new(NULL, FALSE);
gbinder_ipc_unref(ipc);
}
@@ -355,18 +322,38 @@ test_context_deinit(
{
test_binder_unregister_objects(test->fd);
gbinder_local_object_unref(test->object);
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
gbinder_local_object_unref(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);
gbinder_config_dir = test->default_config_dir;
gbinder_config_file = test->default_config_file;
gbinder_config_exit();
g_main_loop_unref(test->loop);
test_config_cleanup(&test->config);
}
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);
}
/*==========================================================================*
@@ -397,6 +384,9 @@ 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,
@@ -440,6 +430,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);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2021-2023 Slava Monich <slava@monich.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,20 +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";
typedef struct test_config {
char* dir;
char* file;
} TestConfig;
DEV " = hidl\n";
GType
gbinder_servicemanager_aidl_get_type()
@@ -94,37 +87,6 @@ gbinder_servicemanager_aidl4_get_type()
* Common
*==========================================================================*/
static
void
test_config_init(
TestConfig* config,
char* config_data)
{
config->dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
config->file = g_build_filename(config->dir, "test.conf", NULL);
g_assert(g_file_set_contents(config->file, config_data ? config_data :
DEFAULT_CONFIG_DATA, -1, NULL));
gbinder_config_exit();
gbinder_config_dir = config->dir;
gbinder_config_file = config->file;
GDEBUG("Wrote config to %s", config->file);
}
static
void
test_config_deinit(
TestConfig* config)
{
gbinder_config_exit();
remove(config->file);
g_free(config->file);
remove(config->dir);
g_free(config->dir);
}
static
TestServiceManagerHidl*
test_servicemanager_impl_new(
@@ -134,7 +96,6 @@ test_servicemanager_impl_new(
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);
@@ -189,7 +150,6 @@ static
void
test_get_run()
{
TestConfig config;
GBinderIpc* ipc;
TestServiceManagerHidl* smsvc;
GBinderLocalObject* obj;
@@ -198,17 +158,14 @@ test_get_run()
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
const char* name = "android.hidl.base@1.0::IBase/test";
test_config_init(&config, NULL);
ipc = gbinder_ipc_new(MAIN_DEV, NULL);
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));
@@ -233,15 +190,12 @@ 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);
}
@@ -282,7 +236,6 @@ void
test_list_run()
{
TestList test;
TestConfig config;
GBinderIpc* ipc;
TestServiceManagerHidl* smsvc;
GBinderLocalObject* obj;
@@ -293,17 +246,14 @@ test_list_run()
memset(&test, 0, sizeof(test));
test.loop = g_main_loop_new(NULL, FALSE);
test_config_init(&config, NULL);
ipc = gbinder_ipc_new(MAIN_DEV, NULL);
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));
@@ -326,15 +276,12 @@ 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);
g_strfreev(test.list);
g_main_loop_unref(test.loop);
@@ -410,7 +357,6 @@ void
test_notify_run()
{
TestNotify test;
TestConfig config;
GBinderIpc* ipc;
GBinderLocalObject* obj;
int fd;
@@ -421,17 +367,14 @@ test_notify_run()
memset(&test, 0, sizeof(test));
test.loop = g_main_loop_new(NULL, FALSE);
test_config_init(&config, NULL);
ipc = gbinder_ipc_new(MAIN_DEV, NULL);
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,
@@ -455,15 +398,12 @@ 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);
}
@@ -482,6 +422,10 @@ test_notify()
int main(int argc, char* argv[])
{
TestConfig test_config;
char* config_file;
int result;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
@@ -489,8 +433,20 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("get"), test_get);
g_test_add_func(TEST_("list"), test_list);
g_test_add_func(TEST_("notify"), test_notify);
test_init(&test_opt, argc, argv);
return g_test_run();
test_config_init(&test_config, TMP_DIR_TEMPLATE);
config_file = g_build_filename(test_config.config_dir, "test.conf", NULL);
g_assert(g_file_set_contents(config_file, DEFAULT_CONFIG_DATA, -1, NULL));
GDEBUG("Config file %s", config_file);
gbinder_config_file = config_file;
result = g_test_run();
remove(config_file);
g_free(config_file);
test_config_cleanup(&test_config);
return result;
}
/*

View File

@@ -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);
}
}
}
@@ -311,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);
}
@@ -345,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);
@@ -355,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);
}
@@ -397,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);
@@ -408,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);
@@ -417,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);
}
@@ -434,7 +432,6 @@ test_retry(
const char* const ifaces[] = { "interface", NULL };
const char* dev = GBINDER_DEFAULT_BINDER;
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;
GBinderServiceManager* sm;
@@ -450,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);
@@ -460,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);
}
@@ -500,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);
@@ -519,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);
}

View File

@@ -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);
}
/*==========================================================================*
@@ -268,6 +268,7 @@ test_basic(
gbinder_servicemanager_unref(manager);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -352,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);
}
@@ -430,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);
}
@@ -478,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);
}

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2018-2024 Slava Monich <slava@monich.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:
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,15 +33,20 @@
#include "test_common.h"
#include "test_binder.h"
#include "gbinder_buffer_p.h"
#include "gbinder_config.h"
#include "gbinder_fmq_p.h"
#include "gbinder_local_request_p.h"
#include "gbinder_rpc_protocol.h"
#include "gbinder_output_data.h"
#include "gbinder_reader_p.h"
#include "gbinder_writer_p.h"
#include "gbinder_ipc.h"
#include "gbinder_io.h"
#include <gutil_intarray.h>
#include <gutil_macros.h>
#include <gutil_misc.h>
#include <gutil_log.h>
#include <unistd.h>
@@ -78,10 +83,7 @@ test_local_request_new_64()
*==========================================================================*/
typedef struct test_context {
const char* default_config_dir;
const char* default_config_file;
char* config_dir;
char* config_subdir;
TestConfig config;
char* config_file;
} TestContext;
@@ -92,20 +94,17 @@ test_context_init(
const char* prot)
{
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);
gbinder_config_dir = test->config_subdir; /* Doesn't exist */
gbinder_config_file = test->config_file;
test_config_init(&test->config, TMP_DIR_TEMPLATE);
if (prot) {
char* config = g_strdup_printf("[Protocol]\n"
GBINDER_DEFAULT_BINDER " = %s", prot);
test->config_file = g_build_filename(test->config.config_dir,
"test.conf", NULL);
GDEBUG("Config file %s", test->config_file);
g_assert(g_file_set_contents(test->config_file, config, -1, NULL));
g_free(config);
gbinder_config_file = test->config_file;
}
}
@@ -114,15 +113,11 @@ void
test_context_deinit(
TestContext* test)
{
remove(test->config_file);
remove(test->config_dir);
g_free(test->config_file);
g_free(test->config_subdir);
g_free(test->config_dir);
gbinder_config_dir = test->default_config_dir;
gbinder_config_file = test->default_config_file;
gbinder_config_exit();
gbinder_rpc_protocol_exit();
if (test->config_file) {
remove(test->config_file);
g_free(test->config_file);
}
test_config_cleanup(&test->config);
}
/*==========================================================================*
@@ -252,9 +247,7 @@ void
test_int8(
void)
{
const char encoded[] = {
TEST_INT8_BYTES_4(0x80)
};
const char encoded[] = { 0x80, 0x00, 0x00, 0x00 };
GBinderLocalRequest* req = test_local_request_new();
GBinderOutputData* data;
GBinderWriter writer;
@@ -279,9 +272,7 @@ void
test_int16(
void)
{
const char encoded[] = {
TEST_INT16_BYTES_4(0x80ff)
};
const char encoded[] = { TEST_INT16_BYTES(0x80ff), 0x00, 0x00 };
GBinderLocalRequest* req = test_local_request_new();
GBinderOutputData* data;
GBinderWriter writer;
@@ -417,8 +408,8 @@ test_bool(
{
const char encoded[] = {
TEST_INT8_BYTES_4(0),
TEST_INT8_BYTES_4(1),
TEST_INT8_BYTES_4(1)
0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00
};
GBinderLocalRequest* req = test_local_request_new();
GBinderOutputData* data;
@@ -527,11 +518,23 @@ static const guint8 string16_tests_data_xy[] = {
0x00, 0x00, 0x00, 0x00
};
static const guint8 string16_tests_data_surrogates[] = {
TEST_INT32_BYTES(8),
TEST_INT16_BYTES(0xd83d), TEST_INT16_BYTES(0xde00),
TEST_INT16_BYTES(0xd83d), TEST_INT16_BYTES(0xde01),
TEST_INT16_BYTES(0xd83d), TEST_INT16_BYTES(0xde02),
TEST_INT16_BYTES(0xd83d), TEST_INT16_BYTES(0xde03),
0x00, 0x00, 0x00, 0x00
};
static const TestString16Data test_string16_tests[] = {
{ "null", NULL, TEST_ARRAY_AND_SIZE(string16_tests_data_null) },
{ "empty", "", TEST_ARRAY_AND_SIZE(string16_tests_data_empty) },
{ "1", "x", TEST_ARRAY_AND_SIZE(string16_tests_data_x) },
{ "2", "xy", TEST_ARRAY_AND_SIZE(string16_tests_data_xy) }
{ "2", "xy", TEST_ARRAY_AND_SIZE(string16_tests_data_xy) },
{ "surrogates", "\xF0\x9F\x98\x80" "\xF0\x9F\x98\x81"
"\xF0\x9F\x98\x82" "\xF0\x9F\x98\x83",
TEST_ARRAY_AND_SIZE(string16_tests_data_surrogates) }
};
static
@@ -549,7 +552,7 @@ test_string16(
data = gbinder_local_request_data(req);
g_assert(!gbinder_output_data_offsets(data));
g_assert(!gbinder_output_data_buffers_size(data));
g_assert(data->bytes->len == test->output_len);
g_assert_cmpuint(data->bytes->len, == ,test->output_len);
g_assert(!memcmp(data->bytes->data, test->output, test->output_len));
gbinder_local_request_unref(req);
}
@@ -1112,6 +1115,18 @@ test_struct(
g_assert_cmpuint(offsets->data[0], == ,0);
gbinder_local_request_unref(req);
/* Write vec<TestStruct> in a different way */
req = test_local_request_new();
gbinder_local_request_init_writer(req, &writer);
gbinder_writer_append_struct_vec(&writer, &test_struct, 1, &test_struct_t);
data = gbinder_local_request_data(req);
offsets = gbinder_output_data_offsets(data);
g_assert(offsets);
g_assert_cmpuint(offsets->count, == ,5);
g_assert_cmpuint(offsets->data[0], == ,0);
gbinder_local_request_unref(req);
/* Corner cases */
req = test_local_request_new();
gbinder_local_request_init_writer(req, &writer);
@@ -1138,6 +1153,108 @@ test_struct(
gbinder_local_request_unref(req);
}
/*==========================================================================*
* struct_vec
*==========================================================================*/
static
void
test_struct_vec(
void)
{
/* vec<byte> */
static const GBinderWriterField vec_byte_ptr_f[] = {
{
"ptr", GBINDER_HIDL_VEC_BUFFER_OFFSET, &gbinder_writer_type_byte,
gbinder_writer_field_hidl_vec_write_buf, NULL
},
GBINDER_WRITER_FIELD_END()
};
static const GBinderWriterType vec_byte_t = {
GBINDER_WRITER_STRUCT_NAME_AND_SIZE(GBinderHidlVec), vec_byte_ptr_f
};
/* vec<int32> */
static const GBinderWriterField vec_int32_ptr_f[] = {
{
"ptr", GBINDER_HIDL_VEC_BUFFER_OFFSET, &gbinder_writer_type_int32,
gbinder_writer_field_hidl_vec_write_buf, NULL
},
GBINDER_WRITER_FIELD_END()
};
static const GBinderWriterType vec_int32_t = {
GBINDER_WRITER_STRUCT_NAME_AND_SIZE(GBinderHidlVec), vec_int32_ptr_f
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderLocalRequest* req = gbinder_local_request_new(gbinder_ipc_io(ipc),
gbinder_ipc_protocol(ipc), NULL);
GBinderOutputData* writer_data;
GBinderReaderData reader_data;
GBinderWriter writer;
GBinderReader reader;
GUtilIntArray* offsets;
GBinderHidlVec vec_byte, vec_int32;
gsize count, elemsize;
const void* vec_data;
guint i;
static const guint8 vec_byte_data[] = { 0x01, 0x02 };
static const guint32 vec_int32_data[] = { 42 };
memset(&vec_byte, 0, sizeof(vec_byte));
vec_byte.data.ptr = vec_byte_data;
vec_byte.count = G_N_ELEMENTS(vec_byte_data);
memset(&vec_int32, 0, sizeof(vec_int32));
vec_int32.data.ptr = vec_int32_data;
vec_int32.count = G_N_ELEMENTS(vec_int32_data);
gbinder_local_request_init_writer(req, &writer);
gbinder_writer_append_struct(&writer, &vec_byte, &vec_byte_t, NULL);
gbinder_writer_append_struct(&writer, &vec_int32, &vec_int32_t, NULL);
writer_data = gbinder_local_request_data(req);
offsets = gbinder_output_data_offsets(writer_data);
g_assert(offsets);
g_assert_cmpuint(offsets->count, == ,4);
/* Set up the reader */
memset(&reader_data, 0, sizeof(reader_data));
reader_data.reg = gbinder_ipc_object_registry(ipc);
reader_data.objects = g_new0(void*, offsets->count + 1);
reader_data.buffer = gbinder_buffer_new(ipc->driver,
gutil_memdup(writer_data->bytes->data, writer_data->bytes->len),
writer_data->bytes->len, reader_data.objects);
for (i = 0; i < offsets->count; i++) {
reader_data.objects[i] = reader_data.buffer->data + offsets->data[i];
}
/* Read those vectors back */
gbinder_reader_init(&reader, &reader_data, 0, writer_data->bytes->len);
/* vec<byte> */
vec_data = gbinder_reader_read_hidl_vec(&reader, &count, &elemsize);
g_assert(vec_data);
g_assert_cmpuint(count, == ,G_N_ELEMENTS(vec_byte_data));
g_assert_cmpuint(elemsize, == ,sizeof(vec_byte_data[0]));
g_assert(!memcmp(vec_data, vec_byte_data, sizeof(vec_byte_data)));
/* vec<int32> */
vec_data = gbinder_reader_read_hidl_vec(&reader, &count, &elemsize);
g_assert(vec_data);
g_assert_cmpuint(count, == ,G_N_ELEMENTS(vec_int32_data));
g_assert_cmpuint(elemsize, == ,sizeof(vec_int32_data[0]));
g_assert(!memcmp(vec_data, vec_int32_data, sizeof(vec_int32_data)));
gbinder_buffer_free(reader_data.buffer);
gbinder_local_request_unref(req);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* fd
* fd_invalid
@@ -1294,7 +1411,7 @@ test_byte_array(
GBinderOutputData* data;
GBinderWriter writer;
const char in_data[] = "abcd1234";
const char in_data[] = "abcd12";
gint32 in_len = sizeof(in_data) - 1;
gint32 null_len = -1;
@@ -1327,7 +1444,7 @@ test_byte_array(
data = gbinder_local_request_data(req);
g_assert(!gbinder_output_data_offsets(data));
g_assert(!gbinder_output_data_buffers_size(data));
g_assert(data->bytes->len == sizeof(in_len) + in_len);
g_assert(data->bytes->len == sizeof(in_len) + G_ALIGN4(in_len));
g_assert(!memcmp(data->bytes->data, &in_len, sizeof(in_len)));
g_assert(!memcmp(data->bytes->data + sizeof(in_len), in_data, in_len));
gbinder_local_request_unref(req);
@@ -1475,6 +1592,7 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("parent"), test_parent);
g_test_add_func(TEST_("parcelable"), test_parcelable);
g_test_add_func(TEST_("struct"), test_struct);
g_test_add_func(TEST_("struct_vec"), test_struct_vec);
g_test_add_func(TEST_("fd"), test_fd);
g_test_add_func(TEST_("fd_invalid"), test_fd_invalid);
g_test_add_func(TEST_("fd_close_error"), test_fd_close_error);