Compare commits
	
		
			68 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					545f5bc28d | ||
| 
						 | 
					78e006f1cf | ||
| 
						 | 
					3c9cc1711a | ||
| 
						 | 
					71aa3acc08 | ||
| 
						 | 
					eee26c5e98 | ||
| 
						 | 
					736a29aa4c | ||
| 
						 | 
					0d7105edbe | ||
| 
						 | 
					4420c7b2ae | ||
| 
						 | 
					52726a07b0 | ||
| 
						 | 
					12b9fd49ad | ||
| 
						 | 
					e75959e389 | ||
| 
						 | 
					9d35ca22fb | ||
| 
						 | 
					3e0d0005ce | ||
| 
						 | 
					29718f921f | ||
| 
						 | 
					99b2dd85c1 | ||
| 
						 | 
					cf5417d5db | ||
| 
						 | 
					03f214eb24 | ||
| 
						 | 
					6508a73dcd | ||
| 
						 | 
					1100d8ede1 | ||
| 
						 | 
					f89469b1a5 | ||
| 
						 | 
					fcf2ef0ea4 | ||
| 
						 | 
					f9202cab37 | ||
| 
						 | 
					49729d95c9 | ||
| 
						 | 
					11765cd80d | ||
| 
						 | 
					4820b2971f | ||
| 
						 | 
					0623fb85db | ||
| 
						 | 
					e655d8992a | ||
| 
						 | 
					44e57ea98d | ||
| 
						 | 
					e3f705c4cc | ||
| 
						 | 
					6f0e8a693d | ||
| 
						 | 
					c7fab6373b | ||
| 
						 | 
					9aded94555 | ||
| 
						 | 
					b5bab2431e | ||
| 
						 | 
					509faccba0 | ||
| 
						 | 
					a89dcd2702 | ||
| 
						 | 
					62b9b30865 | ||
| 
						 | 
					4a913590d9 | ||
| 
						 | 
					1ee872aaf2 | ||
| 
						 | 
					00e9d8ac6f | ||
| 
						 | 
					b032e151a2 | ||
| 
						 | 
					b8edc9221a | ||
| 
						 | 
					05634757d7 | ||
| 
						 | 
					03ef78c9fd | ||
| 
						 | 
					84efc32ac0 | ||
| 
						 | 
					88388de696 | ||
| 
						 | 
					daa062d981 | ||
| 
						 | 
					85db18f663 | ||
| 
						 | 
					af796828a4 | ||
| 
						 | 
					885d27c12c | ||
| 
						 | 
					38f156a8ba | ||
| 
						 | 
					d7eacd455f | ||
| 
						 | 
					b1a3dc5c64 | ||
| 
						 | 
					98ad09e803 | ||
| 
						 | 
					c94ccbd8bf | ||
| 
						 | 
					5874c88559 | ||
| 
						 | 
					b0c3b6017f | ||
| 
						 | 
					4f82e82081 | ||
| 
						 | 
					51eefbf566 | ||
| 
						 | 
					ec76cb3930 | ||
| 
						 | 
					9a0d0a7894 | ||
| 
						 | 
					32b3d4455a | ||
| 
						 | 
					09e9a9d5c1 | ||
| 
						 | 
					83b04757c6 | ||
| 
						 | 
					c636814500 | ||
| 
						 | 
					2592ea60ce | ||
| 
						 | 
					f04e21b462 | ||
| 
						 | 
					d739912faa | ||
| 
						 | 
					c2263874ec | 
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							@@ -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>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								LICENSE
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								Makefile
									
									
									
									
									
								
							@@ -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
									
									
								
							
							
						
						
									
										77
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -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
									
									
								
							
							
						
						
									
										6
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										8
									
								
								misc/coverity_model.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
typedef struct gbinder_remote_request GBinderRemoteRequest;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_request_unref(
 | 
			
		||||
    GBinderRemoteRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    __coverity_free__(req);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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*
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 $@
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -36,7 +36,6 @@
 | 
			
		||||
 | 
			
		||||
typedef struct app_options {
 | 
			
		||||
    char* dev;
 | 
			
		||||
    char* iface;
 | 
			
		||||
    gboolean oneway;
 | 
			
		||||
    gboolean aidl;
 | 
			
		||||
    gint transaction;
 | 
			
		||||
 
 | 
			
		||||
@@ -55,11 +55,11 @@ char* handle_str8(char* text) {
 | 
			
		||||
"}"                                 { return('}'); }
 | 
			
		||||
"["                                 { return('['); }
 | 
			
		||||
"]"                                 { return(']'); }
 | 
			
		||||
{D}*{INT8_SUFFIX}                   { cmdlinelval.int8_value = atoi(yytext); return(INT8_VALUE); }
 | 
			
		||||
{D}*{INT64_SUFFIX}                  { cmdlinelval.int64_value = atol(yytext); return(INT64_VALUE); }
 | 
			
		||||
{D}*                                { cmdlinelval.int32_value = atoi(yytext); return(INT32_VALUE); }
 | 
			
		||||
{D}+"."{D}*{INT64_SUFFIX}           { cmdlinelval.double_value = atof(yytext); return(DOUBLE_VALUE); }
 | 
			
		||||
{D}+"."{D}*                         { cmdlinelval.float_value = atof(yytext); return(FLOAT_VALUE); }
 | 
			
		||||
-?{D}+{INT8_SUFFIX}                 { cmdlinelval.int8_value = atoi(yytext); return(INT8_VALUE); }
 | 
			
		||||
-?{D}+{INT64_SUFFIX}                { cmdlinelval.int64_value = atol(yytext); return(INT64_VALUE); }
 | 
			
		||||
-?{D}+                              { cmdlinelval.int32_value = atoi(yytext); return(INT32_VALUE); }
 | 
			
		||||
-?{D}+"."{D}*{INT64_SUFFIX}         { cmdlinelval.double_value = atof(yytext); return(DOUBLE_VALUE); }
 | 
			
		||||
-?{D}+"."{D}*                       { cmdlinelval.float_value = atof(yytext); return(FLOAT_VALUE); }
 | 
			
		||||
"reply"                             { return(REPLY); }
 | 
			
		||||
\".*\"{HSTRING_SUFFIX}              { cmdlinelval.hstring_value = handle_str(yytext); return(HSTRING_VALUE); }
 | 
			
		||||
\".*\"{UTF16_SUFFIX}                { cmdlinelval.string16_value = handle_str(yytext); return(STRING16_VALUE); }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,140 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: all debug release clean cleaner
 | 
			
		||||
.PHONY: libgbinder-release libgbinder-debug
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Required packages
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default target
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
all: debug release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Executable
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
EXE = binder-client
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Sources
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC = $(EXE).c
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Directories
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC_DIR = .
 | 
			
		||||
BUILD_DIR = build
 | 
			
		||||
LIB_DIR = ../..
 | 
			
		||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
 | 
			
		||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Tools and flags
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
CC ?= $(CROSS_COMPILE)gcc
 | 
			
		||||
LD = $(CC)
 | 
			
		||||
WARNINGS = -Wall
 | 
			
		||||
INCLUDES = -I$(LIB_DIR)/include
 | 
			
		||||
BASE_FLAGS = -fPIC
 | 
			
		||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
 | 
			
		||||
  $(shell pkg-config --cflags $(PKGS))
 | 
			
		||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
 | 
			
		||||
QUIET_MAKE = make --no-print-directory
 | 
			
		||||
DEBUG_FLAGS = -g
 | 
			
		||||
RELEASE_FLAGS =
 | 
			
		||||
 | 
			
		||||
ifndef KEEP_SYMBOLS
 | 
			
		||||
KEEP_SYMBOLS = 0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
RELEASE_FLAGS += -g
 | 
			
		||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
 | 
			
		||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
 | 
			
		||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
			
		||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Files
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
 | 
			
		||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
			
		||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
 | 
			
		||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
 | 
			
		||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
 | 
			
		||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
 | 
			
		||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
 | 
			
		||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Dependencies
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
 | 
			
		||||
ifneq ($(MAKECMDGOALS),clean)
 | 
			
		||||
ifneq ($(strip $(DEPS)),)
 | 
			
		||||
-include $(DEPS)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Rules
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
 | 
			
		||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
 | 
			
		||||
 | 
			
		||||
debug: libgbinder-debug $(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
release: libgbinder-release $(RELEASE_EXE)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *~
 | 
			
		||||
	rm -fr $(BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
cleaner: clean
 | 
			
		||||
	@make -C $(LIB_DIR) clean
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
 | 
			
		||||
	$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
 | 
			
		||||
	$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
 | 
			
		||||
ifeq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
	strip $@
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
libgbinder-debug:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
 | 
			
		||||
 | 
			
		||||
libgbinder-release:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -1,140 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: all debug release clean cleaner
 | 
			
		||||
.PHONY: libgbinder-release libgbinder-debug
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Required packages
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default target
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
all: debug release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Executable
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
EXE = binder-dump
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Sources
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC = $(EXE).c
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Directories
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC_DIR = .
 | 
			
		||||
BUILD_DIR = build
 | 
			
		||||
LIB_DIR = ../..
 | 
			
		||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
 | 
			
		||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Tools and flags
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
CC ?= $(CROSS_COMPILE)gcc
 | 
			
		||||
LD = $(CC)
 | 
			
		||||
WARNINGS = -Wall
 | 
			
		||||
INCLUDES = -I$(LIB_DIR)/include
 | 
			
		||||
BASE_FLAGS = -fPIC
 | 
			
		||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
 | 
			
		||||
  $(shell pkg-config --cflags $(PKGS))
 | 
			
		||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
 | 
			
		||||
QUIET_MAKE = make --no-print-directory
 | 
			
		||||
DEBUG_FLAGS = -g
 | 
			
		||||
RELEASE_FLAGS =
 | 
			
		||||
 | 
			
		||||
ifndef KEEP_SYMBOLS
 | 
			
		||||
KEEP_SYMBOLS = 0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
RELEASE_FLAGS += -g
 | 
			
		||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
 | 
			
		||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
 | 
			
		||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
			
		||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Files
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
 | 
			
		||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
			
		||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
 | 
			
		||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
 | 
			
		||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
 | 
			
		||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
 | 
			
		||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
 | 
			
		||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Dependencies
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
 | 
			
		||||
ifneq ($(MAKECMDGOALS),clean)
 | 
			
		||||
ifneq ($(strip $(DEPS)),)
 | 
			
		||||
-include $(DEPS)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Rules
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
 | 
			
		||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
 | 
			
		||||
 | 
			
		||||
debug: libgbinder-debug $(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
release: libgbinder-release $(RELEASE_EXE)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *~
 | 
			
		||||
	rm -fr $(BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
cleaner: clean
 | 
			
		||||
	@make -C $(LIB_DIR) clean
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
 | 
			
		||||
	$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
 | 
			
		||||
	$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
 | 
			
		||||
ifeq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
	strip $@
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
libgbinder-debug:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
 | 
			
		||||
 | 
			
		||||
libgbinder-release:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -1,154 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: all debug release clean cleaner
 | 
			
		||||
.PHONY: libgbinder-release libgbinder-debug
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Required packages
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default target
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
all: debug release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Executable
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
EXE = binder-list
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Sources
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC = $(EXE).c
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Directories
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC_DIR = .
 | 
			
		||||
BUILD_DIR = build
 | 
			
		||||
LIB_DIR = ../..
 | 
			
		||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
 | 
			
		||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Tools and flags
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
CC ?= $(CROSS_COMPILE)gcc
 | 
			
		||||
LD = $(CC)
 | 
			
		||||
WARNINGS = -Wall
 | 
			
		||||
INCLUDES = -I$(LIB_DIR)/include
 | 
			
		||||
BASE_FLAGS = -fPIC
 | 
			
		||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
 | 
			
		||||
  $(shell pkg-config --cflags $(PKGS))
 | 
			
		||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
 | 
			
		||||
QUIET_MAKE = make --no-print-directory
 | 
			
		||||
DEBUG_FLAGS = -g
 | 
			
		||||
RELEASE_FLAGS =
 | 
			
		||||
 | 
			
		||||
ifndef KEEP_SYMBOLS
 | 
			
		||||
KEEP_SYMBOLS = 0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
RELEASE_FLAGS += -g
 | 
			
		||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
 | 
			
		||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
 | 
			
		||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
			
		||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Files
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
 | 
			
		||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
			
		||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
 | 
			
		||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
 | 
			
		||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
 | 
			
		||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
 | 
			
		||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
 | 
			
		||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Dependencies
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
 | 
			
		||||
ifneq ($(MAKECMDGOALS),clean)
 | 
			
		||||
ifneq ($(strip $(DEPS)),)
 | 
			
		||||
-include $(DEPS)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Rules
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
 | 
			
		||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
 | 
			
		||||
 | 
			
		||||
debug: libgbinder-debug $(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
release: libgbinder-release $(RELEASE_EXE)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *~
 | 
			
		||||
	rm -fr $(BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
cleaner: clean
 | 
			
		||||
	@make -C $(LIB_DIR) clean
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
 | 
			
		||||
	$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
 | 
			
		||||
	$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
 | 
			
		||||
ifeq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
	strip $@
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
libgbinder-debug:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
 | 
			
		||||
 | 
			
		||||
libgbinder-release:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Install
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
INSTALL = install
 | 
			
		||||
 | 
			
		||||
INSTALL_BIN_DIR = $(DESTDIR)/usr/bin
 | 
			
		||||
 | 
			
		||||
install: release $(INSTALL_BIN_DIR)
 | 
			
		||||
	$(INSTALL) -m 755 $(RELEASE_EXE) $(INSTALL_BIN_DIR)
 | 
			
		||||
 | 
			
		||||
$(INSTALL_BIN_DIR):
 | 
			
		||||
	$(INSTALL) -d $@
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -1,154 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: all debug release clean cleaner
 | 
			
		||||
.PHONY: libgbinder-release libgbinder-debug
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Required packages
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default target
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
all: debug release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Executable
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
EXE = binder-ping
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Sources
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC = $(EXE).c
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Directories
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC_DIR = .
 | 
			
		||||
BUILD_DIR = build
 | 
			
		||||
LIB_DIR = ../..
 | 
			
		||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
 | 
			
		||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Tools and flags
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
CC ?= $(CROSS_COMPILE)gcc
 | 
			
		||||
LD = $(CC)
 | 
			
		||||
WARNINGS = -Wall
 | 
			
		||||
INCLUDES = -I$(LIB_DIR)/include
 | 
			
		||||
BASE_FLAGS = -fPIC
 | 
			
		||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
 | 
			
		||||
  $(shell pkg-config --cflags $(PKGS))
 | 
			
		||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
 | 
			
		||||
QUIET_MAKE = make --no-print-directory
 | 
			
		||||
DEBUG_FLAGS = -g
 | 
			
		||||
RELEASE_FLAGS =
 | 
			
		||||
 | 
			
		||||
ifndef KEEP_SYMBOLS
 | 
			
		||||
KEEP_SYMBOLS = 0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
RELEASE_FLAGS += -g
 | 
			
		||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
 | 
			
		||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
 | 
			
		||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
			
		||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Files
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
 | 
			
		||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
			
		||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
 | 
			
		||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
 | 
			
		||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
 | 
			
		||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
 | 
			
		||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
 | 
			
		||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Dependencies
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
 | 
			
		||||
ifneq ($(MAKECMDGOALS),clean)
 | 
			
		||||
ifneq ($(strip $(DEPS)),)
 | 
			
		||||
-include $(DEPS)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Rules
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
 | 
			
		||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
 | 
			
		||||
 | 
			
		||||
debug: libgbinder-debug $(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
release: libgbinder-release $(RELEASE_EXE)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *~
 | 
			
		||||
	rm -fr $(BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
cleaner: clean
 | 
			
		||||
	@make -C $(LIB_DIR) clean
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
 | 
			
		||||
	$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
 | 
			
		||||
	$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
 | 
			
		||||
ifeq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
	strip $@
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
libgbinder-debug:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
 | 
			
		||||
 | 
			
		||||
libgbinder-release:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Install
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
INSTALL = install
 | 
			
		||||
 | 
			
		||||
INSTALL_BIN_DIR = $(DESTDIR)/usr/bin
 | 
			
		||||
 | 
			
		||||
install: release $(INSTALL_BIN_DIR)
 | 
			
		||||
	$(INSTALL) -m 755 $(RELEASE_EXE) $(INSTALL_BIN_DIR)
 | 
			
		||||
 | 
			
		||||
$(INSTALL_BIN_DIR):
 | 
			
		||||
	$(INSTALL) -d $@
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -1,140 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: all debug release clean cleaner
 | 
			
		||||
.PHONY: libgbinder-release libgbinder-debug
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Required packages
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default target
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
all: debug release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Executable
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
EXE = binder-service
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Sources
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC = $(EXE).c
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Directories
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC_DIR = .
 | 
			
		||||
BUILD_DIR = build
 | 
			
		||||
LIB_DIR = ../..
 | 
			
		||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
 | 
			
		||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Tools and flags
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
CC ?= $(CROSS_COMPILE)gcc
 | 
			
		||||
LD = $(CC)
 | 
			
		||||
WARNINGS = -Wall
 | 
			
		||||
INCLUDES = -I$(LIB_DIR)/include
 | 
			
		||||
BASE_FLAGS = -fPIC
 | 
			
		||||
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
 | 
			
		||||
  $(shell pkg-config --cflags $(PKGS))
 | 
			
		||||
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
 | 
			
		||||
QUIET_MAKE = make --no-print-directory
 | 
			
		||||
DEBUG_FLAGS = -g
 | 
			
		||||
RELEASE_FLAGS =
 | 
			
		||||
 | 
			
		||||
ifndef KEEP_SYMBOLS
 | 
			
		||||
KEEP_SYMBOLS = 0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
RELEASE_FLAGS += -g
 | 
			
		||||
SUBMAKE_OPTS += KEEP_SYMBOLS=1
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
 | 
			
		||||
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
 | 
			
		||||
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
			
		||||
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Files
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
 | 
			
		||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
			
		||||
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
 | 
			
		||||
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
 | 
			
		||||
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
 | 
			
		||||
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
 | 
			
		||||
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
 | 
			
		||||
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Dependencies
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
 | 
			
		||||
ifneq ($(MAKECMDGOALS),clean)
 | 
			
		||||
ifneq ($(strip $(DEPS)),)
 | 
			
		||||
-include $(DEPS)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Rules
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
 | 
			
		||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
 | 
			
		||||
 | 
			
		||||
debug: libgbinder-debug $(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
release: libgbinder-release $(RELEASE_EXE)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *~
 | 
			
		||||
	rm -fr $(BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
cleaner: clean
 | 
			
		||||
	@make -C $(LIB_DIR) clean
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
 | 
			
		||||
	$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
 | 
			
		||||
	$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
 | 
			
		||||
ifeq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
	strip $@
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
libgbinder-debug:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
 | 
			
		||||
 | 
			
		||||
libgbinder-release:
 | 
			
		||||
	@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										155
									
								
								test/common/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								test/common/Makefile
									
									
									
									
									
										Normal 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 $@
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
											
										
									
								
							@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -277,9 +277,10 @@ test_servicemanager_hidl_add(
 | 
			
		||||
        const char* sep = strrchr(instance, '/');
 | 
			
		||||
 | 
			
		||||
        GDEBUG("Adding '%s'", instance);
 | 
			
		||||
        /* Transfer remote_obj reference to the hashtable */
 | 
			
		||||
        g_hash_table_replace(self->objects, g_strdup(instance), remote_obj);
 | 
			
		||||
        if (sep) {
 | 
			
		||||
            /* Alread know the interface */
 | 
			
		||||
            /* Already know the interface */
 | 
			
		||||
            char* iface = g_strndup(instance, sep - instance);
 | 
			
		||||
 | 
			
		||||
            test_servicemanager_hidl_notify_all(self, iface, sep + 1, FALSE);
 | 
			
		||||
@@ -350,7 +351,7 @@ test_servicemanager_hidl_register_for_notifications(
 | 
			
		||||
    iface = gbinder_reader_read_hidl_string_c(&reader);
 | 
			
		||||
    instance = gbinder_reader_read_hidl_string_c(&reader);
 | 
			
		||||
    watcher = gbinder_reader_read_object(&reader);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
    if (watcher) {
 | 
			
		||||
        GBinderClient* wc = gbinder_client_new(watcher, NOTIFICATION_IFACE);
 | 
			
		||||
        GHashTableIter it;
 | 
			
		||||
@@ -481,6 +482,38 @@ test_servicemanager_hidl_lookup(
 | 
			
		||||
    return object;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
test_servicemanager_hidl_remove(
 | 
			
		||||
    TestServiceManagerHidl* self,
 | 
			
		||||
    const char* fqname)
 | 
			
		||||
{
 | 
			
		||||
    gboolean removed = FALSE;
 | 
			
		||||
 | 
			
		||||
    if (self) {
 | 
			
		||||
        GBinderRemoteObject* obj;
 | 
			
		||||
 | 
			
		||||
        /* Lock */
 | 
			
		||||
        g_mutex_lock(&self->mutex);
 | 
			
		||||
        obj = g_hash_table_lookup(self->objects, fqname);
 | 
			
		||||
        if (obj) {
 | 
			
		||||
            GHashTableIter it;
 | 
			
		||||
            gpointer key, value;
 | 
			
		||||
 | 
			
		||||
            g_hash_table_iter_init(&it, self->objects);
 | 
			
		||||
            while (g_hash_table_iter_next(&it, &key, &value)) {
 | 
			
		||||
                if (value == obj) {
 | 
			
		||||
                    GDEBUG("Removed name '%s' => %p", (char*) key, value);
 | 
			
		||||
                    g_hash_table_iter_remove(&it);
 | 
			
		||||
                    removed = TRUE;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        g_mutex_unlock(&self->mutex);
 | 
			
		||||
        /* Unlock */
 | 
			
		||||
    }
 | 
			
		||||
    return removed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internals
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -58,6 +58,11 @@ test_servicemanager_hidl_lookup(
 | 
			
		||||
    TestServiceManagerHidl* self,
 | 
			
		||||
    const char* name);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
test_servicemanager_hidl_remove(
 | 
			
		||||
    TestServiceManagerHidl* self,
 | 
			
		||||
    const char* fqname);
 | 
			
		||||
 | 
			
		||||
#endif /* TEST_SERVICEMANAGER_HIDL_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user