Compare commits
	
		
			60 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					c22eafe49e | ||
| 
						 | 
					66122a2ce6 | ||
| 
						 | 
					c1ff25f6ae | ||
| 
						 | 
					af3c23a18f | ||
| 
						 | 
					5a14796c4c | ||
| 
						 | 
					3bb8a38f5f | ||
| 
						 | 
					f29f0b5a1b | ||
| 
						 | 
					2da1c7b5ca | ||
| 
						 | 
					8348bc76bd | ||
| 
						 | 
					a97a153c94 | ||
| 
						 | 
					94ddc9f0e5 | ||
| 
						 | 
					370d2dedb3 | ||
| 
						 | 
					58c9a7fe93 | ||
| 
						 | 
					3742e2ca8e | ||
| 
						 | 
					ede15da9e2 | ||
| 
						 | 
					771444a8ac | ||
| 
						 | 
					956fa90cbf | ||
| 
						 | 
					17ff87510c | ||
| 
						 | 
					552fc4f172 | ||
| 
						 | 
					4b179477ad | ||
| 
						 | 
					8419a53f23 | ||
| 
						 | 
					865a29d1dd | ||
| 
						 | 
					93fbb5b238 | ||
| 
						 | 
					1a9408f65c | ||
| 
						 | 
					14399b112f | ||
| 
						 | 
					754fa5bcda | ||
| 
						 | 
					0b43f88700 | ||
| 
						 | 
					5822a40c39 | ||
| 
						 | 
					ca5f3ad0be | ||
| 
						 | 
					3398afd701 | ||
| 
						 | 
					3c828b453a | ||
| 
						 | 
					9d95a622f4 | ||
| 
						 | 
					78dd0563e6 | ||
| 
						 | 
					5fd5b423c1 | ||
| 
						 | 
					2acec3f7ce | ||
| 
						 | 
					59dee397f0 | ||
| 
						 | 
					e196c66264 | ||
| 
						 | 
					8f62f4d65c | ||
| 
						 | 
					8583a72d11 | ||
| 
						 | 
					381446eb4f | ||
| 
						 | 
					eabf5683f4 | ||
| 
						 | 
					f4712be3b5 | ||
| 
						 | 
					08f701c96b | ||
| 
						 | 
					8c5618aaab | ||
| 
						 | 
					1bc2efd724 | ||
| 
						 | 
					066464f3af | ||
| 
						 | 
					f5b399d775 | ||
| 
						 | 
					6e127bd184 | ||
| 
						 | 
					95277d1b3d | ||
| 
						 | 
					e0c56c1226 | ||
| 
						 | 
					5e3df46da9 | ||
| 
						 | 
					393006f051 | ||
| 
						 | 
					e10e3df1eb | ||
| 
						 | 
					86ba34dc67 | ||
| 
						 | 
					b0b5595f20 | ||
| 
						 | 
					757908cd6c | ||
| 
						 | 
					e6ca4b50ec | ||
| 
						 | 
					97831a65da | ||
| 
						 | 
					5798434ead | ||
| 
						 | 
					54b1149a75 | 
							
								
								
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							@@ -7,3 +7,5 @@ Rinigus <rinigus.git@gmail.com>
 | 
			
		||||
George Hopkins <george-hopkins@null.net>
 | 
			
		||||
Bart Ribbers <bribbers@disroot.org>
 | 
			
		||||
Gary Wang <gary.wang@canonical.com>
 | 
			
		||||
Eugenio Paolantonio <me@medesimo.eu>
 | 
			
		||||
Alessandro Astone <ales.astone@gmail.com>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 | 
			
		||||
You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
VERSION_MAJOR = 1
 | 
			
		||||
VERSION_MINOR = 1
 | 
			
		||||
VERSION_RELEASE = 14
 | 
			
		||||
VERSION_RELEASE = 25
 | 
			
		||||
 | 
			
		||||
# Version for pkg-config
 | 
			
		||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
			
		||||
@@ -105,6 +105,7 @@ SRC += \
 | 
			
		||||
  gbinder_servicemanager_aidl.c \
 | 
			
		||||
  gbinder_servicemanager_aidl2.c \
 | 
			
		||||
  gbinder_servicemanager_aidl3.c \
 | 
			
		||||
  gbinder_servicemanager_aidl4.c \
 | 
			
		||||
  gbinder_servicemanager_hidl.c
 | 
			
		||||
 | 
			
		||||
SRC += \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README
									
									
									
									
									
								
							@@ -5,7 +5,7 @@ Key features:
 | 
			
		||||
1. Integration with GLib event loop
 | 
			
		||||
2. Detection of 32 vs 64 bit kernel at runtime
 | 
			
		||||
3. Asynchronous transactions that don't block the event thread
 | 
			
		||||
4. Stable service manager and low-level transation APIs
 | 
			
		||||
4. Stable service manager and low-level transaction APIs
 | 
			
		||||
 | 
			
		||||
Android keeps changing both low-level RPC and service manager
 | 
			
		||||
protocols from version to version. To counter that, libgbinder
 | 
			
		||||
@@ -22,8 +22,8 @@ directory is scanned for .conf files, the file list is sorted, files are
 | 
			
		||||
loaded one by one, overwriting the entries loaded from /etc/gbinder.conf
 | 
			
		||||
or from the previously processed file.
 | 
			
		||||
 | 
			
		||||
Known protocol and service manager variants are aidl, aidl2 and hidl.
 | 
			
		||||
This list is expected to expand further in the future. The default
 | 
			
		||||
Known protocol and service manager variants are aidl, aidl2, aidl3 and
 | 
			
		||||
hidl. This list is expected to expand further in the future. The default
 | 
			
		||||
configuration is as follows:
 | 
			
		||||
 | 
			
		||||
  [Protocol]
 | 
			
		||||
@@ -36,9 +36,11 @@ configuration is as follows:
 | 
			
		||||
  /dev/binder = aidl
 | 
			
		||||
  /dev/hwbinder = hidl
 | 
			
		||||
 | 
			
		||||
Alternatively, one can specify the desired Android API level:
 | 
			
		||||
Alternatively and preferably, one can specify the desired Android API
 | 
			
		||||
level:
 | 
			
		||||
 | 
			
		||||
  [General]
 | 
			
		||||
  ApiLevel = 29
 | 
			
		||||
 | 
			
		||||
and let libgbinder pick the appropriate preset.
 | 
			
		||||
and let libgbinder pick the appropriate preset. Full list of presets can
 | 
			
		||||
be found in src/gbinder_config.c
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										69
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,72 @@
 | 
			
		||||
libgbinder (1.1.25) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Handle RPC protocol change at run time
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Tue, 19 Jul 2022 02:02:41 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.24) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Bumped debhelper compat level to 7
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 14 Jul 2022 01:32:11 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.23) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Fixed Debian build dependencies
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 23 Jun 2022 20:09:35 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.22) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Added support for Android 12 (API level 31)
 | 
			
		||||
  * Made binder device configurable for binder-dump
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 22 Jun 2022 17:02:20 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.21) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Properly finalize GBinderIpc and GBinderServicePoll
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Mon, 20 Jun 2022 18:53:26 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.20) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Made RPC protocol selectable at runtime
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sat, 11 Jun 2022 02:49:49 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.19) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Added reader and writer for aidl parcelables
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sun, 20 Feb 2022 03:26:24 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.18) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Disassociate auto-created proxies to stop them from piling up
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sat, 08 Jan 2022 15:35:56 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.17) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Don't release remote proxy handle too early (sometimes hever)
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Fri, 07 Jan 2022 14:43:51 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.16) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Make sure stale object pointers don't hang around
 | 
			
		||||
  * Properly shut down remote object inside the proxy
 | 
			
		||||
  * Read ref_count from GObject atomically
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Mon, 03 Jan 2022 13:58:44 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.15) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Added readers and writers for int8 and int16
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Mon, 27 Dec 2021 15:13:23 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder (1.1.14) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Support for FMQ (Fast Message Queues)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							@@ -1 +1 @@
 | 
			
		||||
5
 | 
			
		||||
7
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -2,7 +2,7 @@ Source: libgbinder
 | 
			
		||||
Section: libs
 | 
			
		||||
Priority: optional
 | 
			
		||||
Maintainer: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.52), flex, bison
 | 
			
		||||
Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.0), libglibutil-dev (>= 1.0.52), flex, bison
 | 
			
		||||
Standards-Version: 3.8.4
 | 
			
		||||
 | 
			
		||||
Package: libgbinder
 | 
			
		||||
@@ -14,7 +14,7 @@ Description: Binder client library
 | 
			
		||||
Package: libgbinder-dev
 | 
			
		||||
Section: libdevel
 | 
			
		||||
Architecture: any
 | 
			
		||||
Depends: libgbinder (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Depends: libgbinder (= ${binary:Version}), libglibutil-dev (>= 1.0.52)
 | 
			
		||||
Description: Development files for libgbinder
 | 
			
		||||
 | 
			
		||||
Package: libgbinder-tools
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 | 
			
		||||
You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -65,6 +65,26 @@ gbinder_reader_read_bool(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gboolean* value);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_int8(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gint8* value); /* Since 1.1.15 */
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_uint8(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    guint8* value); /* Since 1.1.15 */
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_int16(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gint16* value); /* Since 1.1.15 */
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_uint16(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    guint16* value); /* Since 1.1.15 */
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_int32(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
@@ -122,6 +142,11 @@ gbinder_reader_read_buffer(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_parcelable(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* size); /* Since 1.1.19 */
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_struct1(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -76,7 +76,15 @@ void
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new(
 | 
			
		||||
    const char* dev);
 | 
			
		||||
    const char* dev)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new2(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* sm_protocol,
 | 
			
		||||
    const char* rpc_protocol) /* Since 1.1.20 */
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_defaultservicemanager_new(
 | 
			
		||||
@@ -193,7 +201,7 @@ gbinder_servicemanager_remove_handlers(
 | 
			
		||||
    gulong* ids,
 | 
			
		||||
    guint count); /* Since 1.0.25 */
 | 
			
		||||
 | 
			
		||||
#define gbinder_servicemanager_remove_all_handlers(r,ids) \
 | 
			
		||||
#define gbinder_servicemanager_remove_all_handlers(sm,ids) \
 | 
			
		||||
    gbinder_servicemanager_remove_handlers(sm, ids, G_N_ELEMENTS(ids))
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -55,6 +55,16 @@ struct gbinder_parent {
 | 
			
		||||
    guint32 offset;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_int8(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    guint8 value); /* Since 1.1.15 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_int16(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    guint16 value); /* Since 1.1.15 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_int32(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
@@ -138,6 +148,12 @@ gbinder_writer_append_buffer_object(
 | 
			
		||||
    const void* buf,
 | 
			
		||||
    gsize len);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_parcelable(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    const void* buf,
 | 
			
		||||
    gsize len); /* Since 1.1.19 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_vec(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
Name: libgbinder
 | 
			
		||||
 | 
			
		||||
Version: 1.1.14
 | 
			
		||||
Version: 1.1.25
 | 
			
		||||
Release: 0
 | 
			
		||||
Summary: Binder client library
 | 
			
		||||
License: BSD
 | 
			
		||||
 
 | 
			
		||||
@@ -133,9 +133,24 @@ static const GBinderConfigPresetGroup gbinder_config_30[] = {
 | 
			
		||||
    { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* API level 31 */
 | 
			
		||||
 | 
			
		||||
static const GBinderConfigPresetEntry gbinder_config_31_servicemanager[] = {
 | 
			
		||||
    { "/dev/binder", "aidl4" },
 | 
			
		||||
    { "/dev/vndbinder", "aidl4" },
 | 
			
		||||
    { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const GBinderConfigPresetGroup gbinder_config_31[] = {
 | 
			
		||||
    { GBINDER_CONFIG_GROUP_PROTOCOL, gbinder_config_30_protocol },
 | 
			
		||||
    { GBINDER_CONFIG_GROUP_SERVICEMANAGER, gbinder_config_31_servicemanager },
 | 
			
		||||
    { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Presets sorted by API level in descending order */
 | 
			
		||||
 | 
			
		||||
static const GBinderConfigPreset gbinder_config_presets[] = {
 | 
			
		||||
    { 31, gbinder_config_31 },
 | 
			
		||||
    { 30, gbinder_config_30 },
 | 
			
		||||
    { 29, gbinder_config_29 },
 | 
			
		||||
    { 28, gbinder_config_28 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -82,6 +82,7 @@ struct gbinder_driver {
 | 
			
		||||
    void* vm;
 | 
			
		||||
    gsize vmsize;
 | 
			
		||||
    char* dev;
 | 
			
		||||
    const char* name;
 | 
			
		||||
    const GBinderIo* io;
 | 
			
		||||
    const GBinderRpcProtocol* protocol;
 | 
			
		||||
};
 | 
			
		||||
@@ -169,6 +170,14 @@ gbinder_driver_verbose_transaction_data(
 | 
			
		||||
                    GVERBOSE("> %s %d (%u bytes, %u objects)", name,
 | 
			
		||||
                        tx->status, (guint)tx->size, n);
 | 
			
		||||
                }
 | 
			
		||||
            } else if (tx->code) {
 | 
			
		||||
                if (tx->target) {
 | 
			
		||||
                    GVERBOSE("> %s %p 0x%08x (%u bytes, %u objects)", name,
 | 
			
		||||
                        tx->target, tx->code, (guint)tx->size, n);
 | 
			
		||||
                } else {
 | 
			
		||||
                    GVERBOSE("> %s 0x%08x (%u bytes, %u objects)", name,
 | 
			
		||||
                        tx->code, (guint)tx->size, n);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (tx->target) {
 | 
			
		||||
                    GVERBOSE("> %s %p (%u bytes, %u objects)", name,
 | 
			
		||||
@@ -187,6 +196,14 @@ gbinder_driver_verbose_transaction_data(
 | 
			
		||||
                    GVERBOSE("> %s %d (%u bytes)", name, tx->status, (guint)
 | 
			
		||||
                        tx->size);
 | 
			
		||||
                }
 | 
			
		||||
            } else if (tx->code) {
 | 
			
		||||
                if (tx->target) {
 | 
			
		||||
                    GVERBOSE("> %s %p 0x%08x (%u bytes)", name,
 | 
			
		||||
                        tx->target, tx->code, (guint)tx->size);
 | 
			
		||||
                } else {
 | 
			
		||||
                    GVERBOSE("> %s 0x%08x (%u bytes)", name,
 | 
			
		||||
                        tx->code, (guint)tx->size);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (tx->target) {
 | 
			
		||||
                    GVERBOSE("> %s %p (%u bytes)", name, tx->target, (guint)
 | 
			
		||||
@@ -549,7 +566,8 @@ gbinder_driver_handle_transaction(
 | 
			
		||||
                tx.flags, &txstatus);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        GWARN("Unhandled transaction %s 0x%08x", iface, tx.code);
 | 
			
		||||
        GWARN("Unhandled transaction %s 0x%08x from %s", iface, tx.code,
 | 
			
		||||
            self->name);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -879,6 +897,9 @@ gbinder_driver_new(
 | 
			
		||||
                    self->vm = vm;
 | 
			
		||||
                    self->vmsize = vmsize;
 | 
			
		||||
                    self->dev = g_strdup(dev);
 | 
			
		||||
                    self->name = self->dev + /* Shorter version for logging */
 | 
			
		||||
                        (g_str_has_prefix(self->dev, "/dev/") ? 5 : 0);
 | 
			
		||||
 | 
			
		||||
                    if (gbinder_system_ioctl(fd, BINDER_SET_MAX_THREADS,
 | 
			
		||||
                        &max_threads) < 0) {
 | 
			
		||||
                        GERR("%s failed to set max threads (%u): %s", dev,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -58,11 +58,13 @@
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_ipc_looper GBinderIpcLooper;
 | 
			
		||||
typedef GObjectClass GBinderIpcClass;
 | 
			
		||||
 | 
			
		||||
struct gbinder_ipc_priv {
 | 
			
		||||
    GBinderIpc* self;
 | 
			
		||||
    GThreadPool* tx_pool;
 | 
			
		||||
    GHashTable* tx_table;
 | 
			
		||||
    char* dev;
 | 
			
		||||
    char* key;
 | 
			
		||||
    const char* name;
 | 
			
		||||
    GBinderObjectRegistry object_registry;
 | 
			
		||||
@@ -78,11 +80,12 @@ struct gbinder_ipc_priv {
 | 
			
		||||
    GBinderIpcLooper* blocked_loopers;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef GObjectClass GBinderIpcClass;
 | 
			
		||||
#define PARENT_CLASS gbinder_ipc_parent_class
 | 
			
		||||
#define THIS_TYPE gbinder_ipc_get_type()
 | 
			
		||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GBinderIpc)
 | 
			
		||||
 | 
			
		||||
GType THIS_TYPE GBINDER_INTERNAL;
 | 
			
		||||
G_DEFINE_TYPE(GBinderIpc, gbinder_ipc, G_TYPE_OBJECT)
 | 
			
		||||
#define GBINDER_TYPE_IPC (gbinder_ipc_get_type())
 | 
			
		||||
#define GBINDER_IPC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
			
		||||
        GBINDER_TYPE_IPC, GBinderIpc))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Binder requests are blocking, worker threads are needed in order to
 | 
			
		||||
@@ -207,9 +210,6 @@ typedef struct gbinder_ipc_tx_custom {
 | 
			
		||||
    GDestroyNotify fn_custom_destroy;
 | 
			
		||||
} GBinderIpcTxCustom;
 | 
			
		||||
 | 
			
		||||
GBINDER_INLINE_FUNC const char* gbinder_ipc_name(GBinderIpc* self)
 | 
			
		||||
    { return self->priv->name; }
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderIpcLooper*
 | 
			
		||||
gbinder_ipc_looper_new(
 | 
			
		||||
@@ -266,6 +266,15 @@ gbinder_ipc_wait(
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
char*
 | 
			
		||||
gbinder_ipc_make_key(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* protocol)
 | 
			
		||||
{
 | 
			
		||||
    return g_strdup_printf("%s:%s", protocol, dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * GBinderIpcLooperTx
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -1115,6 +1124,23 @@ gbinder_ipc_tx_handler_transact(
 | 
			
		||||
 * GBinderObjectRegistry
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_invalidate_local_object_locked(
 | 
			
		||||
    GBinderIpc* self,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpcPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    if (priv->local_objects && g_hash_table_remove(priv->local_objects, obj)) {
 | 
			
		||||
        GVERBOSE_("%p %s", obj, gbinder_ipc_name(self));
 | 
			
		||||
        if (g_hash_table_size(priv->local_objects) == 0) {
 | 
			
		||||
            g_hash_table_unref(priv->local_objects);
 | 
			
		||||
            priv->local_objects = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_invalidate_remote_handle_locked(
 | 
			
		||||
@@ -1140,6 +1166,20 @@ gbinder_ipc_invalidate_remote_handle_locked(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_invalidate_local_object(
 | 
			
		||||
    GBinderIpc* self,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpcPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    /* Lock */
 | 
			
		||||
    g_mutex_lock(&priv->local_objects_mutex);
 | 
			
		||||
    gbinder_ipc_invalidate_local_object_locked(self, obj);
 | 
			
		||||
    g_mutex_unlock(&priv->local_objects_mutex);
 | 
			
		||||
    /* Unlock */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_invalidate_remote_handle(
 | 
			
		||||
    GBinderIpc* self,
 | 
			
		||||
@@ -1183,14 +1223,8 @@ gbinder_ipc_local_object_disposed(
 | 
			
		||||
 | 
			
		||||
    /* Lock */
 | 
			
		||||
    g_mutex_lock(&priv->local_objects_mutex);
 | 
			
		||||
    if (obj->object.ref_count == 1 && priv->local_objects) {
 | 
			
		||||
        if (g_hash_table_remove(priv->local_objects, obj)) {
 | 
			
		||||
            GVERBOSE_("%p %s", obj, gbinder_ipc_name(self));
 | 
			
		||||
            if (g_hash_table_size(priv->local_objects) == 0) {
 | 
			
		||||
                g_hash_table_unref(priv->local_objects);
 | 
			
		||||
                priv->local_objects = NULL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    if (g_atomic_int_get(&obj->object.ref_count) == 1) {
 | 
			
		||||
        gbinder_ipc_invalidate_local_object_locked(self, obj);
 | 
			
		||||
    }
 | 
			
		||||
    g_mutex_unlock(&priv->local_objects_mutex);
 | 
			
		||||
    /* Unlock */
 | 
			
		||||
@@ -1203,9 +1237,32 @@ gbinder_ipc_remote_object_disposed(
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpcPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Check of ref_count for 1 makes it possible (albeit quite unlikely)
 | 
			
		||||
     * that GBinderRemoteObject still remains in remote_objects table
 | 
			
		||||
     * when it's being finalized.
 | 
			
		||||
     *
 | 
			
		||||
     * For this to happen, other thread must re-reference GBinderRemoteObject
 | 
			
		||||
     * right before we grab the lock here (making ref_count greater than 1)
 | 
			
		||||
     * and then release that reference before g_object_unref() re-checks the
 | 
			
		||||
     * refcount.
 | 
			
		||||
     *
 | 
			
		||||
     * That's why another gbinder_ipc_invalidate_remote_handle() call from
 | 
			
		||||
     * gbinder_remote_object_finalize() is necessary to make sure that stale
 | 
			
		||||
     * object pointer isn't stored in the hashtable.
 | 
			
		||||
     *
 | 
			
		||||
     * We still have to invalidate the handle here because it's the last
 | 
			
		||||
     * point when GObject can be legitimately re-referenced and brought
 | 
			
		||||
     * back to life. Which means that GBinderIpc mutex has to acquired
 | 
			
		||||
     * twice during GBinderRemoteObject destruction.
 | 
			
		||||
     *
 | 
			
		||||
     * The same applies to GBinderLocalObject too, except that it calls
 | 
			
		||||
     * gbinder_ipc_invalidate_local_object() from its finalize() handler.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /* Lock */
 | 
			
		||||
    g_mutex_lock(&priv->remote_objects_mutex);
 | 
			
		||||
    if (obj->object.ref_count == 1) {
 | 
			
		||||
    if (g_atomic_int_get(&obj->object.ref_count) == 1) {
 | 
			
		||||
        gbinder_ipc_invalidate_remote_handle_locked(self, obj->handle);
 | 
			
		||||
    }
 | 
			
		||||
    g_mutex_unlock(&priv->remote_objects_mutex);
 | 
			
		||||
@@ -1250,10 +1307,10 @@ gbinder_ipc_priv_get_local_object(
 | 
			
		||||
            if (obj) {
 | 
			
		||||
                gbinder_local_object_ref(obj);
 | 
			
		||||
            } else {
 | 
			
		||||
                GWARN("Unknown local object %p", pointer);
 | 
			
		||||
                GWARN("Unknown local object %p %s", pointer, priv->name);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            GWARN("Unknown local object %p", pointer);
 | 
			
		||||
            GWARN("Unknown local object %p %s", pointer, priv->name);
 | 
			
		||||
        }
 | 
			
		||||
        g_mutex_unlock(&priv->local_objects_mutex);
 | 
			
		||||
        /* Unlock */
 | 
			
		||||
@@ -1297,6 +1354,8 @@ gbinder_ipc_priv_get_remote_object(
 | 
			
		||||
        }
 | 
			
		||||
        GVERBOSE_("%p handle %u %s", obj, handle, gbinder_ipc_name(self));
 | 
			
		||||
        g_hash_table_replace(priv->remote_objects, key, obj);
 | 
			
		||||
    } else {
 | 
			
		||||
        GWARN("Unknown handle %u %s", handle, priv->name);
 | 
			
		||||
    }
 | 
			
		||||
    g_mutex_unlock(&priv->remote_objects_mutex);
 | 
			
		||||
    /* Unlock */
 | 
			
		||||
@@ -1794,20 +1853,25 @@ const GBinderIpcSyncApi gbinder_ipc_sync_main = {
 | 
			
		||||
 | 
			
		||||
GBinderIpc*
 | 
			
		||||
gbinder_ipc_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* protocol_name)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* self = NULL;
 | 
			
		||||
    const GBinderRpcProtocol* protocol;
 | 
			
		||||
    char* key;
 | 
			
		||||
    const GBinderRpcProtocol* protocol = (protocol_name ?
 | 
			
		||||
        gbinder_rpc_protocol_by_name(protocol_name) : NULL);
 | 
			
		||||
 | 
			
		||||
    if (!dev || !dev[0]) dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    protocol = gbinder_rpc_protocol_for_device(dev); /* Never returns NULL */
 | 
			
		||||
    if (!protocol) protocol = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    key = gbinder_ipc_make_key(dev, protocol->name);
 | 
			
		||||
 | 
			
		||||
    /* Lock */
 | 
			
		||||
    pthread_mutex_lock(&gbinder_ipc_mutex);
 | 
			
		||||
    if (gbinder_ipc_table) {
 | 
			
		||||
        self = g_hash_table_lookup(gbinder_ipc_table, dev);
 | 
			
		||||
        self = g_hash_table_lookup(gbinder_ipc_table, key);
 | 
			
		||||
    }
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_free(key);
 | 
			
		||||
        gbinder_ipc_ref(self);
 | 
			
		||||
    } else {
 | 
			
		||||
        GBinderDriver* driver = gbinder_driver_new(dev, protocol);
 | 
			
		||||
@@ -1815,10 +1879,11 @@ gbinder_ipc_new(
 | 
			
		||||
        if (driver) {
 | 
			
		||||
            GBinderIpcPriv* priv;
 | 
			
		||||
 | 
			
		||||
            self = g_object_new(GBINDER_TYPE_IPC, NULL);
 | 
			
		||||
            self = g_object_new(THIS_TYPE, NULL);
 | 
			
		||||
            priv = self->priv;
 | 
			
		||||
            self->driver = driver;
 | 
			
		||||
            self->dev = priv->key = g_strdup(dev);
 | 
			
		||||
            self->dev = priv->dev = g_strdup(dev);
 | 
			
		||||
            priv->key = key;
 | 
			
		||||
            self->priv->object_registry.io = gbinder_driver_io(driver);
 | 
			
		||||
            /* gbinder_ipc_dispose will remove iself from the table */
 | 
			
		||||
            if (!gbinder_ipc_table) {
 | 
			
		||||
@@ -1826,8 +1891,10 @@ gbinder_ipc_new(
 | 
			
		||||
            }
 | 
			
		||||
            g_hash_table_replace(gbinder_ipc_table, priv->key, self);
 | 
			
		||||
            /* With "/dev/" prefix, it may be too long to be a thread name */
 | 
			
		||||
            priv->name = priv->key +
 | 
			
		||||
                (g_str_has_prefix(priv->key, "/dev/") ? 5 : 0);
 | 
			
		||||
            priv->name = self->dev +
 | 
			
		||||
                (g_str_has_prefix(priv->dev, "/dev/") ? 5 : 0);
 | 
			
		||||
        } else {
 | 
			
		||||
            g_free(key);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pthread_mutex_unlock(&gbinder_ipc_mutex);
 | 
			
		||||
@@ -1840,7 +1907,7 @@ gbinder_ipc_ref(
 | 
			
		||||
    GBinderIpc* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        g_object_ref(GBINDER_IPC(self));
 | 
			
		||||
        g_object_ref(THIS(self));
 | 
			
		||||
        return self;
 | 
			
		||||
    } else {
 | 
			
		||||
        return NULL;
 | 
			
		||||
@@ -1852,10 +1919,17 @@ gbinder_ipc_unref(
 | 
			
		||||
    GBinderIpc* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        g_object_unref(GBINDER_IPC(self));
 | 
			
		||||
        g_object_unref(THIS(self));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
gbinder_ipc_name(
 | 
			
		||||
    GBinderIpc* self)
 | 
			
		||||
{
 | 
			
		||||
    return G_LIKELY(self) ? self->priv->name : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderObjectRegistry*
 | 
			
		||||
gbinder_ipc_object_registry(
 | 
			
		||||
    GBinderIpc* self)
 | 
			
		||||
@@ -1983,7 +2057,7 @@ gbinder_ipc_init(
 | 
			
		||||
        .get_local = gbinder_ipc_object_registry_get_local,
 | 
			
		||||
        .get_remote = gbinder_ipc_object_registry_get_remote
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpcPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self, GBINDER_TYPE_IPC,
 | 
			
		||||
    GBinderIpcPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self, THIS_TYPE,
 | 
			
		||||
        GBinderIpcPriv);
 | 
			
		||||
 | 
			
		||||
    g_mutex_init(&priv->looper_mutex);
 | 
			
		||||
@@ -2034,7 +2108,7 @@ void
 | 
			
		||||
gbinder_ipc_dispose(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* self = GBINDER_IPC(object);
 | 
			
		||||
    GBinderIpc* self = THIS(object);
 | 
			
		||||
 | 
			
		||||
    GVERBOSE_("%s", self->dev);
 | 
			
		||||
    /* Lock */
 | 
			
		||||
@@ -2058,7 +2132,7 @@ gbinder_ipc_dispose(
 | 
			
		||||
    /* Unlock */
 | 
			
		||||
 | 
			
		||||
    gbinder_ipc_stop_loopers(self);
 | 
			
		||||
    G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -2066,7 +2140,7 @@ void
 | 
			
		||||
gbinder_ipc_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* self = GBINDER_IPC(object);
 | 
			
		||||
    GBinderIpc* self = THIS(object);
 | 
			
		||||
    GBinderIpcPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    GASSERT(!priv->local_objects);
 | 
			
		||||
@@ -2080,8 +2154,9 @@ gbinder_ipc_finalize(
 | 
			
		||||
    GASSERT(!g_hash_table_size(priv->tx_table));
 | 
			
		||||
    g_hash_table_unref(priv->tx_table);
 | 
			
		||||
    gbinder_driver_unref(self->driver);
 | 
			
		||||
    g_free(priv->dev);
 | 
			
		||||
    g_free(priv->key);
 | 
			
		||||
    G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -2117,7 +2192,7 @@ gbinder_ipc_exit()
 | 
			
		||||
    /* Unlock */
 | 
			
		||||
 | 
			
		||||
    for (i = ipcs; i; i = i->next) {
 | 
			
		||||
        GBinderIpc* ipc = GBINDER_IPC(i->data);
 | 
			
		||||
        GBinderIpc* ipc = THIS(i->data);
 | 
			
		||||
        GBinderIpcPriv* priv = ipc->priv;
 | 
			
		||||
        GThreadPool* pool = priv->tx_pool;
 | 
			
		||||
        GSList* local_objs = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -100,7 +100,8 @@ extern const GBinderIpcSyncApi gbinder_ipc_sync_worker GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
GBinderIpc*
 | 
			
		||||
gbinder_ipc_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* protocol)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
GBinderIpc*
 | 
			
		||||
@@ -113,6 +114,11 @@ gbinder_ipc_unref(
 | 
			
		||||
    GBinderIpc* ipc)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
gbinder_ipc_name(
 | 
			
		||||
    GBinderIpc* ipc)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_looper_check(
 | 
			
		||||
    GBinderIpc* ipc)
 | 
			
		||||
@@ -149,7 +155,7 @@ gbinder_ipc_register_local_object(
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
gbinder_ipc_get_service_manager(
 | 
			
		||||
    GBinderIpc* self)
 | 
			
		||||
    GBinderIpc* ipc)
 | 
			
		||||
    GBINDER_INTERNAL
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
@@ -196,21 +202,27 @@ gbinder_ipc_cancel(
 | 
			
		||||
/* Internal for GBinderLocalObject */
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_local_object_disposed(
 | 
			
		||||
    GBinderIpc* self,
 | 
			
		||||
    GBinderIpc* ipc,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_invalidate_local_object(
 | 
			
		||||
    GBinderIpc* ipc,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
/* Internal for GBinderRemoteObject */
 | 
			
		||||
void
 | 
			
		||||
gbinder_ipc_remote_object_disposed(
 | 
			
		||||
    GBinderIpc* self,
 | 
			
		||||
    GBinderIpc* ipc,
 | 
			
		||||
    GBinderRemoteObject* obj)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
/* Needed by unit tests */
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_ipc_set_max_threads(
 | 
			
		||||
    GBinderIpc* self,
 | 
			
		||||
    GBinderIpc* ipc,
 | 
			
		||||
    gint max_threads)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -644,6 +644,7 @@ gbinder_local_object_finalize(
 | 
			
		||||
    GBinderLocalObjectPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    GASSERT(!self->strong_refs);
 | 
			
		||||
    gbinder_ipc_invalidate_local_object(self->ipc, self);
 | 
			
		||||
    gbinder_ipc_unref(self->ipc);
 | 
			
		||||
    g_strfreev(priv->ifaces);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -60,11 +60,9 @@ struct gbinder_proxy_tx {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct gbinder_proxy_object_priv {
 | 
			
		||||
    gulong remote_death_id;
 | 
			
		||||
    gboolean acquired;
 | 
			
		||||
    gboolean dropped;
 | 
			
		||||
    GBinderProxyTx* tx;
 | 
			
		||||
    GMutex mutex; /* Protects the hashtable below */
 | 
			
		||||
    GHashTable* subproxies;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE(GBinderProxyObject, gbinder_proxy_object, \
 | 
			
		||||
@@ -76,79 +74,12 @@ G_DEFINE_TYPE(GBinderProxyObject, gbinder_proxy_object, \
 | 
			
		||||
#define THIS_TYPE GBINDER_TYPE_PROXY_OBJECT
 | 
			
		||||
#define PARENT_CLASS gbinder_proxy_object_parent_class
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_proxy_object_subproxy_gone(
 | 
			
		||||
    gpointer proxy,
 | 
			
		||||
    GObject* subproxy)
 | 
			
		||||
{
 | 
			
		||||
    GBinderProxyObject* self = THIS(proxy);
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    /* Lock */
 | 
			
		||||
    g_mutex_lock(&priv->mutex);
 | 
			
		||||
    g_hash_table_remove(priv->subproxies, subproxy);
 | 
			
		||||
    if (g_hash_table_size(priv->subproxies) == 0) {
 | 
			
		||||
        g_hash_table_unref(priv->subproxies);
 | 
			
		||||
        priv->subproxies = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    g_mutex_unlock(&priv->mutex);
 | 
			
		||||
    /* Unlock */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_proxy_object_drop_subproxies(
 | 
			
		||||
    GBinderProxyObject* self)
 | 
			
		||||
{
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
    GSList* list = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Lock */
 | 
			
		||||
    g_mutex_lock(&priv->mutex);
 | 
			
		||||
    if (priv->subproxies) {
 | 
			
		||||
        GHashTableIter it;
 | 
			
		||||
        gpointer value;
 | 
			
		||||
 | 
			
		||||
        g_hash_table_iter_init(&it, priv->subproxies);
 | 
			
		||||
        while (g_hash_table_iter_next(&it, NULL, &value)) {
 | 
			
		||||
            list = g_slist_append(list, gbinder_local_object_ref(value));
 | 
			
		||||
            g_object_weak_unref(G_OBJECT(value),
 | 
			
		||||
                gbinder_proxy_object_subproxy_gone, self);
 | 
			
		||||
        }
 | 
			
		||||
        g_hash_table_destroy(priv->subproxies);
 | 
			
		||||
        priv->subproxies = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    g_mutex_unlock(&priv->mutex);
 | 
			
		||||
    /* Unlock */
 | 
			
		||||
 | 
			
		||||
    /* Drop (and possibly destroy) the objects outside of the lock */
 | 
			
		||||
    g_slist_free_full(list, (GDestroyNotify) gbinder_local_object_drop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_proxy_remote_death_proc(
 | 
			
		||||
    GBinderRemoteObject* obj,
 | 
			
		||||
    void* proxy)
 | 
			
		||||
{
 | 
			
		||||
    GBinderProxyObject* self = THIS(proxy);
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("Remote object %u died on %s", obj->handle, obj->ipc->dev);
 | 
			
		||||
    gbinder_remote_object_remove_handler(obj, priv->remote_death_id);
 | 
			
		||||
    priv->remote_death_id = 0;
 | 
			
		||||
    /* Drop the implicit reference */
 | 
			
		||||
    gbinder_local_object_unref(&self->parent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Converter
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_proxy_object_converter {
 | 
			
		||||
    GBinderObjectConverter pub;
 | 
			
		||||
    GBinderProxyObject* proxy;
 | 
			
		||||
    GBinderIpc* remote;
 | 
			
		||||
    GBinderIpc* local;
 | 
			
		||||
} GBinderProxyObjectConverter;
 | 
			
		||||
@@ -182,8 +113,6 @@ gbinder_proxy_object_converter_handle_to_local(
 | 
			
		||||
    guint32 handle)
 | 
			
		||||
{
 | 
			
		||||
    GBinderProxyObjectConverter* c = gbinder_proxy_object_converter_cast(pub);
 | 
			
		||||
    GBinderProxyObject* proxy = c->proxy;
 | 
			
		||||
    GBinderProxyObjectPriv* priv = proxy->priv;
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(c->remote);
 | 
			
		||||
    GBinderRemoteObject* remote = gbinder_object_registry_get_remote(reg,
 | 
			
		||||
        handle, REMOTE_REGISTRY_CAN_CREATE /* but don't acquire */);
 | 
			
		||||
@@ -192,32 +121,7 @@ gbinder_proxy_object_converter_handle_to_local(
 | 
			
		||||
 | 
			
		||||
    if (!local && !remote->dead) {
 | 
			
		||||
        /* GBinderProxyObject will reference GBinderRemoteObject */
 | 
			
		||||
        GBinderProxyObject* subp = gbinder_proxy_object_new(c->local, remote);
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Auto-created proxies may get spontaneously destroyed and
 | 
			
		||||
         * not necessarily on the UI thread.
 | 
			
		||||
         */
 | 
			
		||||
        subp->priv->remote_death_id = gbinder_remote_object_add_death_handler
 | 
			
		||||
            (remote, gbinder_proxy_remote_death_proc, subp);
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Remote keeps an implicit reference to this auto-created
 | 
			
		||||
         * proxy. The reference gets released when the remote object
 | 
			
		||||
         * dies, i.e. by gbinder_proxy_remote_death_proc().
 | 
			
		||||
         */
 | 
			
		||||
        gbinder_local_object_ref(local = GBINDER_LOCAL_OBJECT(subp));
 | 
			
		||||
 | 
			
		||||
        /* Lock */
 | 
			
		||||
        g_mutex_lock(&priv->mutex);
 | 
			
		||||
        if (!priv->subproxies) {
 | 
			
		||||
            priv->subproxies = g_hash_table_new(g_direct_hash, g_direct_equal);
 | 
			
		||||
        }
 | 
			
		||||
        g_hash_table_insert(priv->subproxies, subp, subp);
 | 
			
		||||
        g_object_weak_ref(G_OBJECT(subp),
 | 
			
		||||
            gbinder_proxy_object_subproxy_gone, proxy);
 | 
			
		||||
        g_mutex_unlock(&priv->mutex);
 | 
			
		||||
        /* Unlock */
 | 
			
		||||
        local = &gbinder_proxy_object_new(c->local, remote)->parent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Release the reference returned by gbinder_object_registry_get_remote */
 | 
			
		||||
@@ -241,7 +145,6 @@ gbinder_proxy_object_converter_init(
 | 
			
		||||
    GBinderIpc* dest = proxy->parent.ipc;
 | 
			
		||||
 | 
			
		||||
    memset(convert, 0, sizeof(*convert));
 | 
			
		||||
    convert->proxy = proxy;
 | 
			
		||||
    convert->remote = remote;
 | 
			
		||||
    convert->local = local;
 | 
			
		||||
    pub->f = &gbinder_converter_fn;
 | 
			
		||||
@@ -346,7 +249,7 @@ gbinder_proxy_object_handle_transaction(
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
    GBinderRemoteObject* remote = self->remote;
 | 
			
		||||
 | 
			
		||||
    if (!priv->dropped && !gbinder_remote_object_is_dead(remote)) {
 | 
			
		||||
    if (!priv->dropped && !remote->dead) {
 | 
			
		||||
        GBinderLocalRequest* fwd;
 | 
			
		||||
        GBinderProxyTx* tx = g_slice_new0(GBinderProxyTx);
 | 
			
		||||
        GBinderProxyObjectConverter convert;
 | 
			
		||||
@@ -374,6 +277,7 @@ gbinder_proxy_object_handle_transaction(
 | 
			
		||||
        gbinder_local_request_unref(fwd);
 | 
			
		||||
        *status = GBINDER_STATUS_OK;
 | 
			
		||||
    } else {
 | 
			
		||||
        GVERBOSE_("dropped: %d dead:%d", priv->dropped, remote->dead);
 | 
			
		||||
        *status = (-EBADMSG);
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
@@ -397,33 +301,16 @@ gbinder_proxy_object_acquire(
 | 
			
		||||
{
 | 
			
		||||
    GBinderProxyObject* self = THIS(object);
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
    GBinderRemoteObject* remote = self->remote;
 | 
			
		||||
 | 
			
		||||
    if (priv->remote_death_id && !object->strong_refs) {
 | 
			
		||||
        GBinderRemoteObject* remote = self->remote;
 | 
			
		||||
 | 
			
		||||
        /* First strong ref, acquire the attached remote object */
 | 
			
		||||
    if (!remote->dead && !priv->dropped && !priv->acquired) {
 | 
			
		||||
        /* Not acquired yet */
 | 
			
		||||
        priv->acquired = TRUE;
 | 
			
		||||
        gbinder_driver_acquire(remote->ipc->driver, remote->handle);
 | 
			
		||||
    }
 | 
			
		||||
    GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->acquire(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_proxy_object_release(
 | 
			
		||||
    GBinderLocalObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderProxyObject* self = THIS(object);
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    if (priv->remote_death_id && object->strong_refs == 1) {
 | 
			
		||||
        GBinderRemoteObject* remote = self->remote;
 | 
			
		||||
 | 
			
		||||
        /* Last strong ref, release the attached remote object */
 | 
			
		||||
        gbinder_driver_release(remote->ipc->driver, remote->handle);
 | 
			
		||||
    }
 | 
			
		||||
    GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->release(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_proxy_object_drop(
 | 
			
		||||
@@ -433,7 +320,6 @@ gbinder_proxy_object_drop(
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    priv->dropped = TRUE;
 | 
			
		||||
    gbinder_proxy_object_drop_subproxies(self);
 | 
			
		||||
    GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->drop(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -459,6 +345,8 @@ gbinder_proxy_object_new(
 | 
			
		||||
        if (object) {
 | 
			
		||||
            GBinderProxyObject* self = THIS(object);
 | 
			
		||||
 | 
			
		||||
            GDEBUG("Proxy %p %s => %u %s created", self, gbinder_ipc_name(src),
 | 
			
		||||
                remote->handle, gbinder_ipc_name(remote->ipc));
 | 
			
		||||
            self->remote = gbinder_remote_object_ref(remote);
 | 
			
		||||
            return self;
 | 
			
		||||
        }
 | 
			
		||||
@@ -477,11 +365,25 @@ gbinder_proxy_object_finalize(
 | 
			
		||||
{
 | 
			
		||||
    GBinderProxyObject* self = THIS(object);
 | 
			
		||||
    GBinderProxyObjectPriv* priv = self->priv;
 | 
			
		||||
    GBinderLocalObject* local = &self->parent;
 | 
			
		||||
    GBinderRemoteObject* remote = self->remote;
 | 
			
		||||
 | 
			
		||||
    gbinder_proxy_object_drop_subproxies(self);
 | 
			
		||||
    gbinder_remote_object_remove_handler(self->remote, priv->remote_death_id);
 | 
			
		||||
    gbinder_remote_object_unref(self->remote);
 | 
			
		||||
    g_mutex_clear(&priv->mutex);
 | 
			
		||||
    /*
 | 
			
		||||
     * gbinder_local_object_finalize() will also try to do the same thing
 | 
			
		||||
     * i.e. invalidate self but proxy objects need to do it before releasing
 | 
			
		||||
     * the handle, to leave no room for race conditions. That's not very good
 | 
			
		||||
     * because it grabs ipc-wide mutex but shouldn'd have much of an impact
 | 
			
		||||
     * on the performance because finalizing a proxy is not supposed to be a
 | 
			
		||||
     * frequent operation.
 | 
			
		||||
     */
 | 
			
		||||
    gbinder_ipc_invalidate_local_object(local->ipc, local);
 | 
			
		||||
    if (priv->acquired) {
 | 
			
		||||
        gbinder_driver_release(remote->ipc->driver, remote->handle);
 | 
			
		||||
    }
 | 
			
		||||
    GDEBUG("Proxy %p %s => %u %s gone", self,
 | 
			
		||||
        gbinder_ipc_name(self->parent.ipc), remote->handle,
 | 
			
		||||
        gbinder_ipc_name(remote->ipc));
 | 
			
		||||
    gbinder_remote_object_unref(remote);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -494,7 +396,6 @@ gbinder_proxy_object_init(
 | 
			
		||||
        THIS_TYPE, GBinderProxyObjectPriv);
 | 
			
		||||
 | 
			
		||||
    self->priv = priv;
 | 
			
		||||
    g_mutex_init(&priv->mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -509,7 +410,6 @@ gbinder_proxy_object_class_init(
 | 
			
		||||
    klass->can_handle_transaction = gbinder_proxy_object_can_handle_transaction;
 | 
			
		||||
    klass->handle_transaction = gbinder_proxy_object_handle_transaction;
 | 
			
		||||
    klass->acquire = gbinder_proxy_object_acquire;
 | 
			
		||||
    klass->release = gbinder_proxy_object_release;
 | 
			
		||||
    klass->drop = gbinder_proxy_object_drop;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -138,6 +138,62 @@ gbinder_reader_read_bool(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_int8(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gint8* value) /* Since 1.1.15 */
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_reader_read_uint8(reader, (guint8*)value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_uint8(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    guint8* value) /* Since 1.1.15 */
 | 
			
		||||
{
 | 
			
		||||
    /* Primitive values are supposed to be padded to 4-byte boundary */
 | 
			
		||||
    if (value) {
 | 
			
		||||
        guint32 padded;
 | 
			
		||||
 | 
			
		||||
        if (gbinder_reader_read_uint32(reader, &padded)) {
 | 
			
		||||
            *value = (guint8)padded;
 | 
			
		||||
            return TRUE;
 | 
			
		||||
        } else {
 | 
			
		||||
            return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        return gbinder_reader_read_uint32(reader, NULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_int16(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gint16* value) /* Since 1.1.15 */
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_reader_read_uint16(reader, (guint16*)value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_uint16(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    guint16* value) /* Since 1.1.15 */
 | 
			
		||||
{
 | 
			
		||||
    /* Primitive values are supposed to be padded to 4-byte boundary */
 | 
			
		||||
    if (value) {
 | 
			
		||||
        guint32 padded;
 | 
			
		||||
 | 
			
		||||
        if (gbinder_reader_read_uint32(reader, &padded)) {
 | 
			
		||||
            *value = (guint16)padded;
 | 
			
		||||
            return TRUE;
 | 
			
		||||
        } else {
 | 
			
		||||
            return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        return gbinder_reader_read_uint32(reader, NULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_int32(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
@@ -364,6 +420,40 @@ gbinder_reader_skip_buffer(
 | 
			
		||||
    return gbinder_reader_read_buffer_object(reader, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is supposed to be used to read aidl parcelables, and is not
 | 
			
		||||
 * guaranteed to work on any other kind of parcelable.
 | 
			
		||||
 */
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_parcelable(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* size) /* Since 1.1.19 */
 | 
			
		||||
{
 | 
			
		||||
    guint32 non_null, payload_size = 0;
 | 
			
		||||
 | 
			
		||||
    if (gbinder_reader_read_uint32(reader, &non_null) && non_null &&
 | 
			
		||||
        gbinder_reader_read_uint32(reader, &payload_size) &&
 | 
			
		||||
        payload_size >= sizeof(payload_size)) {
 | 
			
		||||
        GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
			
		||||
 | 
			
		||||
        payload_size -= sizeof(payload_size);
 | 
			
		||||
        if (p->ptr + payload_size <= p->end) {
 | 
			
		||||
            const void* out = p->ptr;
 | 
			
		||||
 | 
			
		||||
            /* Success */
 | 
			
		||||
            p->ptr += payload_size;
 | 
			
		||||
            if (size) {
 | 
			
		||||
                *size = payload_size;
 | 
			
		||||
            }
 | 
			
		||||
            return out;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (size) {
 | 
			
		||||
        *size = 0;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Helper for gbinder_reader_read_hidl_struct() macro */
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_struct1(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -149,6 +149,7 @@ gbinder_remote_object_commit_suicide(
 | 
			
		||||
        GBinderRemoteObjectPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
        self->dead = TRUE;
 | 
			
		||||
        gbinder_driver_clear_death_notification(driver, self);
 | 
			
		||||
        if (priv->acquired) {
 | 
			
		||||
            priv->acquired = FALSE;
 | 
			
		||||
            /* Release the dead node */
 | 
			
		||||
@@ -294,6 +295,7 @@ gbinder_remote_object_finalize(
 | 
			
		||||
    GBinderIpc* ipc = self->ipc;
 | 
			
		||||
    GBinderDriver* driver = ipc->driver;
 | 
			
		||||
 | 
			
		||||
    gbinder_ipc_invalidate_remote_handle(ipc, self->handle);
 | 
			
		||||
    if (!self->dead) {
 | 
			
		||||
        gbinder_driver_clear_death_notification(driver, self);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -379,6 +379,13 @@ gbinder_rpc_protocol_for_device(
 | 
			
		||||
    return gbinder_rpc_protocol_default;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const GBinderRpcProtocol*
 | 
			
		||||
gbinder_rpc_protocol_by_name(
 | 
			
		||||
    const char* protocol_name)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_rpc_protocol_find(protocol_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,11 @@ struct gbinder_rpc_protocol {
 | 
			
		||||
        char** iface);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const GBinderRpcProtocol*
 | 
			
		||||
gbinder_rpc_protocol_by_name(
 | 
			
		||||
    const char* protocol_name)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
/* Returns one of the above based on the device name */
 | 
			
		||||
const GBinderRpcProtocol*
 | 
			
		||||
gbinder_rpc_protocol_for_device(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -83,11 +83,12 @@ static const GBinderServiceManagerType gbinder_servicemanager_types[] = {
 | 
			
		||||
    { "aidl", gbinder_servicemanager_aidl_get_type },
 | 
			
		||||
    { "aidl2", gbinder_servicemanager_aidl2_get_type },
 | 
			
		||||
    { "aidl3", gbinder_servicemanager_aidl3_get_type },
 | 
			
		||||
    { "aidl4", gbinder_servicemanager_aidl4_get_type },
 | 
			
		||||
    { "hidl", gbinder_servicemanager_hidl_get_type }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SERVICEMANAGER_TYPE_AIDL (gbinder_servicemanager_types + 0)
 | 
			
		||||
#define SERVICEMANAGER_TYPE_HIDL (gbinder_servicemanager_types + 3)
 | 
			
		||||
#define SERVICEMANAGER_TYPE_HIDL (gbinder_servicemanager_types + 4)
 | 
			
		||||
#define SERVICEMANAGER_TYPE_DEFAULT SERVICEMANAGER_TYPE_AIDL
 | 
			
		||||
 | 
			
		||||
static GHashTable* gbinder_servicemanager_map = NULL;
 | 
			
		||||
@@ -519,7 +520,8 @@ gbinder_servicemanager_exit(
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new_with_type(
 | 
			
		||||
    GType type,
 | 
			
		||||
    const char* dev)
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* rpc_protocol)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManager* self = NULL;
 | 
			
		||||
    GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
 | 
			
		||||
@@ -528,7 +530,7 @@ gbinder_servicemanager_new_with_type(
 | 
			
		||||
        GBinderIpc* ipc;
 | 
			
		||||
 | 
			
		||||
        if (!dev) dev = klass->default_device;
 | 
			
		||||
        ipc = gbinder_ipc_new(dev);
 | 
			
		||||
        ipc = gbinder_ipc_new(dev, rpc_protocol);
 | 
			
		||||
        if (ipc) {
 | 
			
		||||
            /* Create a (possibly) dead service manager object */
 | 
			
		||||
            GBinderRemoteObject* object = gbinder_ipc_get_service_manager(ipc);
 | 
			
		||||
@@ -620,25 +622,36 @@ GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    if (dev) {
 | 
			
		||||
        const GBinderServiceManagerType* type = NULL;
 | 
			
		||||
    return gbinder_servicemanager_new2(dev, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new2(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* sm_protocol,
 | 
			
		||||
    const char* rpc_protocol) /* Since 1.1.20 */
 | 
			
		||||
{
 | 
			
		||||
    if (!dev) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    } else if (!sm_protocol) {
 | 
			
		||||
        const GBinderServiceManagerType* type;
 | 
			
		||||
 | 
			
		||||
        /* One-time initialization */
 | 
			
		||||
        if (!gbinder_servicemanager_map) {
 | 
			
		||||
            const GBinderServiceManagerType* t;
 | 
			
		||||
 | 
			
		||||
            /* One-time initialization */
 | 
			
		||||
            gbinder_servicemanager_map = gbinder_servicemanager_load_config();
 | 
			
		||||
 | 
			
		||||
            /* "Default" is a special value stored in a special variable */
 | 
			
		||||
            t = g_hash_table_lookup(gbinder_servicemanager_map, CONF_DEFAULT);
 | 
			
		||||
            if (t) {
 | 
			
		||||
            type = g_hash_table_lookup(gbinder_servicemanager_map,
 | 
			
		||||
                CONF_DEFAULT);
 | 
			
		||||
            if (type) {
 | 
			
		||||
                g_hash_table_remove(gbinder_servicemanager_map, CONF_DEFAULT);
 | 
			
		||||
                gbinder_servicemanager_default = t;
 | 
			
		||||
                gbinder_servicemanager_default = type;
 | 
			
		||||
            } else {
 | 
			
		||||
                gbinder_servicemanager_default = SERVICEMANAGER_TYPE_DEFAULT;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* If no protocol is specified, pick one up based on the device name */
 | 
			
		||||
        type = g_hash_table_lookup(gbinder_servicemanager_map, dev);
 | 
			
		||||
        if (type) {
 | 
			
		||||
            GDEBUG("Using %s service manager for %s", type->name, dev);
 | 
			
		||||
@@ -646,9 +659,21 @@ gbinder_servicemanager_new(
 | 
			
		||||
            type = gbinder_servicemanager_default;
 | 
			
		||||
            GDEBUG("Using default service manager %s for %s", type->name, dev);
 | 
			
		||||
        }
 | 
			
		||||
        return gbinder_servicemanager_new_with_type(type->get_type(), dev);
 | 
			
		||||
        return gbinder_servicemanager_new_with_type(type->get_type(), dev,
 | 
			
		||||
            rpc_protocol);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* If protocol name is specified, it must be a valid one */
 | 
			
		||||
        const GBinderServiceManagerType* type =
 | 
			
		||||
            gbinder_servicemanager_value_map(sm_protocol);
 | 
			
		||||
 | 
			
		||||
        if (type) {
 | 
			
		||||
            return gbinder_servicemanager_new_with_type(type->get_type(), dev,
 | 
			
		||||
                rpc_protocol);
 | 
			
		||||
        } else {
 | 
			
		||||
            GWARN("Unknown servicemanager protocol %s", sm_protocol);
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalObject*
 | 
			
		||||
@@ -1016,7 +1041,7 @@ gbinder_defaultservicemanager_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_servicemanager_new_with_type
 | 
			
		||||
        (gbinder_servicemanager_aidl_get_type(), dev);
 | 
			
		||||
        (gbinder_servicemanager_aidl_get_type(), dev, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
@@ -1024,7 +1049,7 @@ gbinder_hwservicemanager_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_servicemanager_new_with_type
 | 
			
		||||
        (gbinder_servicemanager_hidl_get_type(), dev);
 | 
			
		||||
        (gbinder_servicemanager_hidl_get_type(), dev, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 
 | 
			
		||||
@@ -66,6 +66,13 @@ enum gbinder_servicemanager_aidl_calls {
 | 
			
		||||
    LIST_SERVICES_TRANSACTION
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum gbinder_stability_level {
 | 
			
		||||
    UNDECLARED = 0,
 | 
			
		||||
    VENDOR = 0b000011,
 | 
			
		||||
    SYSTEM = 0b001100,
 | 
			
		||||
    VINTF = 0b111111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DUMP_FLAG_PRIORITY_DEFAULT (0x08)
 | 
			
		||||
#define DUMP_FLAG_PRIORITY_ALL     (0x0f)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_aidl.h"
 | 
			
		||||
#include "gbinder_servicemanager_aidl_p.h"
 | 
			
		||||
#include "gbinder_client_p.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
 | 
			
		||||
@@ -50,14 +50,6 @@ G_DEFINE_TYPE(GBinderServiceManagerAidl3,
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS gbinder_servicemanager_aidl3_parent_class
 | 
			
		||||
 | 
			
		||||
enum gbinder_stability_level {
 | 
			
		||||
    UNDECLARED = 0,
 | 
			
		||||
    VENDOR = 0b000011,
 | 
			
		||||
    SYSTEM = 0b001100,
 | 
			
		||||
    VINTF = 0b111111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
gbinder_servicemanager_aidl3_get_service(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
@@ -84,28 +76,6 @@ gbinder_servicemanager_aidl3_get_service(
 | 
			
		||||
    return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_servicemanager_aidl3_add_service_req(
 | 
			
		||||
    GBinderClient* client,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_string16(req, name);
 | 
			
		||||
    gbinder_local_request_append_local_object(req, obj);
 | 
			
		||||
    /*
 | 
			
		||||
     * Starting from Android 11, to add a service, Android framework requires
 | 
			
		||||
     * an additional field `stability` when reading a strong binder.
 | 
			
		||||
     */
 | 
			
		||||
    gbinder_local_request_append_int32(req, SYSTEM);
 | 
			
		||||
    gbinder_local_request_append_int32(req, 0);
 | 
			
		||||
    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
char**
 | 
			
		||||
gbinder_servicemanager_aidl3_list(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
@@ -148,6 +118,27 @@ gbinder_servicemanager_aidl3_list(
 | 
			
		||||
    return (char**)g_ptr_array_free(list, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_servicemanager_aidl3_add_service_req(
 | 
			
		||||
    GBinderClient* client,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_string16(req, name);
 | 
			
		||||
    gbinder_local_request_append_local_object(req, obj);
 | 
			
		||||
    /*
 | 
			
		||||
     * Starting from Android 11, to add a service, Android framework requires
 | 
			
		||||
     * an additional field `stability` when reading a strong binder.
 | 
			
		||||
     */
 | 
			
		||||
    gbinder_local_request_append_int32(req, SYSTEM);
 | 
			
		||||
    gbinder_local_request_append_int32(req, 0);
 | 
			
		||||
    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_aidl3_init(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								src/gbinder_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/gbinder_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
 | 
			
		||||
 * Copyright (C) 2021 Madhushan Nishantha <jlmadushan@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_aidl_p.h"
 | 
			
		||||
#include "gbinder_client_p.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
#include "binder.h"
 | 
			
		||||
 | 
			
		||||
#include <gbinder_local_request.h>
 | 
			
		||||
#include <gbinder_remote_reply.h>
 | 
			
		||||
 | 
			
		||||
/* Variant of AIDL servicemanager appeared in Android 12 (API level 31) */
 | 
			
		||||
 | 
			
		||||
typedef GBinderServiceManagerAidl GBinderServiceManagerAidl4;
 | 
			
		||||
typedef GBinderServiceManagerAidlClass GBinderServiceManagerAidl4Class;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE(GBinderServiceManagerAidl4,
 | 
			
		||||
    gbinder_servicemanager_aidl4,
 | 
			
		||||
    GBINDER_TYPE_SERVICEMANAGER_AIDL)
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS gbinder_servicemanager_aidl4_parent_class
 | 
			
		||||
 | 
			
		||||
#define BINDER_WIRE_FORMAT_VERSION (1)
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_servicemanager_aidl4_add_service_req(
 | 
			
		||||
    GBinderClient* client,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(client);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_string16(req, name);
 | 
			
		||||
    gbinder_local_request_append_local_object(req, obj);
 | 
			
		||||
    /*
 | 
			
		||||
     * When reading nullable strong binder, from Android 12, the format of
 | 
			
		||||
     * the `stability` field passed on the wire was changed and evolved to
 | 
			
		||||
     * `struct Category`, which consists of the following members with 4 bytes long.
 | 
			
		||||
     *
 | 
			
		||||
     * struct Category {
 | 
			
		||||
     *   uint8_t version;
 | 
			
		||||
     *   uint8_t reserved[2];
 | 
			
		||||
     *   Level level;        <- bitmask of Stability::Level
 | 
			
		||||
     * }
 | 
			
		||||
     */
 | 
			
		||||
    gbinder_local_request_append_int32(req, B_PACK_CHARS(SYSTEM, 0, 0, BINDER_WIRE_FORMAT_VERSION));
 | 
			
		||||
    gbinder_local_request_append_int32(req, 0);
 | 
			
		||||
    gbinder_local_request_append_int32(req, DUMP_FLAG_PRIORITY_DEFAULT);
 | 
			
		||||
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_aidl4_init(
 | 
			
		||||
    GBinderServiceManagerAidl* self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_aidl4_class_init(
 | 
			
		||||
    GBinderServiceManagerAidl4Class* cls)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManagerClass* manager = GBINDER_SERVICEMANAGER_CLASS(cls);
 | 
			
		||||
    cls->add_service_req = gbinder_servicemanager_aidl4_add_service_req;
 | 
			
		||||
    manager->list = gbinder_servicemanager_aidl3_list;
 | 
			
		||||
    manager->get_service = gbinder_servicemanager_aidl3_get_service;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								src/gbinder_servicemanager_aidl_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/gbinder_servicemanager_aidl_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021 Gary Wang <gary.wang@canonical.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
 | 
			
		||||
#define GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_aidl.h"
 | 
			
		||||
 | 
			
		||||
char**
 | 
			
		||||
gbinder_servicemanager_aidl3_list(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
    const GBinderIpcSyncApi* api)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
gbinder_servicemanager_aidl3_get_service(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    int* status,
 | 
			
		||||
    const GBinderIpcSyncApi* api)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_SERVICEMANAGER_AIDL_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -90,7 +90,8 @@ GType gbinder_servicemanager_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new_with_type(
 | 
			
		||||
    GType type,
 | 
			
		||||
    const char* dev)
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* rpc_protocol)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -111,6 +112,7 @@ gbinder_servicemanager_exit(
 | 
			
		||||
GType gbinder_servicemanager_aidl_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_aidl2_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_aidl3_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_aidl4_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
GType gbinder_servicemanager_hidl_get_type(void) GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -50,10 +50,12 @@ struct gbinder_servicepoll {
 | 
			
		||||
    GBinderEventLoopTimeout* timer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS gbinder_servicepoll_parent_class
 | 
			
		||||
#define THIS_TYPE gbinder_servicepoll_get_type()
 | 
			
		||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GBinderServicePoll)
 | 
			
		||||
 | 
			
		||||
GType THIS_TYPE GBINDER_INTERNAL;
 | 
			
		||||
G_DEFINE_TYPE(GBinderServicePoll, gbinder_servicepoll, G_TYPE_OBJECT)
 | 
			
		||||
#define GBINDER_TYPE_SERVICEPOLL (gbinder_servicepoll_get_type())
 | 
			
		||||
#define GBINDER_SERVICEPOLL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
			
		||||
        GBINDER_TYPE_SERVICEPOLL, GBinderServicePoll))
 | 
			
		||||
 | 
			
		||||
enum gbinder_servicepoll_signal {
 | 
			
		||||
    SIGNAL_NAME_ADDED,
 | 
			
		||||
@@ -76,7 +78,7 @@ gbinder_servicepoll_list(
 | 
			
		||||
    char** services,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServicePoll* self = GBINDER_SERVICEPOLL(user_data);
 | 
			
		||||
    GBinderServicePoll* self = THIS(user_data);
 | 
			
		||||
 | 
			
		||||
    gbinder_servicepoll_ref(self);
 | 
			
		||||
    self->list_id = 0;
 | 
			
		||||
@@ -122,7 +124,7 @@ gboolean
 | 
			
		||||
gbinder_servicepoll_timer(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServicePoll* self = GBINDER_SERVICEPOLL(user_data);
 | 
			
		||||
    GBinderServicePoll* self = THIS(user_data);
 | 
			
		||||
 | 
			
		||||
    if (!self->list_id) {
 | 
			
		||||
        self->list_id = gbinder_servicemanager_list(self->manager,
 | 
			
		||||
@@ -136,7 +138,7 @@ GBinderServicePoll*
 | 
			
		||||
gbinder_servicepoll_create(
 | 
			
		||||
    GBinderServiceManager* manager)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServicePoll* self = g_object_new(GBINDER_TYPE_SERVICEPOLL, NULL);
 | 
			
		||||
    GBinderServicePoll* self = g_object_new(THIS_TYPE, NULL);
 | 
			
		||||
 | 
			
		||||
    self->manager = gbinder_servicemanager_ref(manager);
 | 
			
		||||
    self->list_id = gbinder_servicemanager_list(manager,
 | 
			
		||||
@@ -171,7 +173,7 @@ gbinder_servicepoll_ref(
 | 
			
		||||
    GBinderServicePoll* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        g_object_ref(GBINDER_SERVICEPOLL(self));
 | 
			
		||||
        g_object_ref(THIS(self));
 | 
			
		||||
        return self;
 | 
			
		||||
    } else {
 | 
			
		||||
        return NULL;
 | 
			
		||||
@@ -183,7 +185,7 @@ gbinder_servicepoll_unref(
 | 
			
		||||
    GBinderServicePoll* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        g_object_unref(GBINDER_SERVICEPOLL(self));
 | 
			
		||||
        g_object_unref(THIS(self));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -240,12 +242,13 @@ void
 | 
			
		||||
gbinder_servicepoll_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServicePoll* self = GBINDER_SERVICEPOLL(object);
 | 
			
		||||
    GBinderServicePoll* self = THIS(object);
 | 
			
		||||
 | 
			
		||||
    gbinder_timeout_remove(self->timer);
 | 
			
		||||
    gbinder_servicemanager_cancel(self->manager, self->list_id);
 | 
			
		||||
    gbinder_servicemanager_unref(self->manager);
 | 
			
		||||
    g_strfreev(self->list);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -213,12 +213,34 @@ gbinder_writer_data_append_bool(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    gboolean value)
 | 
			
		||||
{
 | 
			
		||||
    guint8 padded[4];
 | 
			
		||||
    /* Primitive values are padded to 4-byte boundary */
 | 
			
		||||
    gbinder_writer_data_append_int32(data, value != FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    /* Boolean values are padded to 4-byte boundary */
 | 
			
		||||
    padded[0] = (value != FALSE);
 | 
			
		||||
    padded[1] = padded[2] = padded[3] = 0;
 | 
			
		||||
    g_byte_array_append(data->bytes, padded, sizeof(padded));
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_int8(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
    guint8 value) /* Since 1.1.15 */
 | 
			
		||||
{
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_int16(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
    guint16 value) /* Since 1.1.15 */
 | 
			
		||||
{
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -661,24 +683,21 @@ gbinder_writer_data_append_fds(
 | 
			
		||||
    const GBinderFds *fds,
 | 
			
		||||
    const GBinderParent* parent)
 | 
			
		||||
{
 | 
			
		||||
    /* If the pointer is null only write zero size */
 | 
			
		||||
    if (!fds) {
 | 
			
		||||
    if (fds) {
 | 
			
		||||
        /* Size, fds data buffer and fd_array_object */
 | 
			
		||||
        const gsize fds_total = sizeof(GBinderFds) +
 | 
			
		||||
            sizeof(int) * (fds->num_fds + fds->num_ints);
 | 
			
		||||
        GBinderParent fds_parent;
 | 
			
		||||
 | 
			
		||||
        gbinder_writer_data_append_int64(data, fds_total);
 | 
			
		||||
        fds_parent.index = gbinder_writer_data_append_buffer_object(data,
 | 
			
		||||
            fds, fds_total, parent);
 | 
			
		||||
        fds_parent.offset = sizeof(GBinderFds);
 | 
			
		||||
        gbinder_writer_data_append_fda_object(data, fds, &fds_parent);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* If the pointer is null only write zero size */
 | 
			
		||||
        gbinder_writer_data_append_int64(data, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Write the fds information: size, fds data buffer and fd_array_object */
 | 
			
		||||
    const gsize fds_total = sizeof(GBinderFds) +
 | 
			
		||||
        sizeof(int) * (fds->num_fds + fds->num_ints);
 | 
			
		||||
    GBinderParent fds_parent;
 | 
			
		||||
 | 
			
		||||
    gbinder_writer_data_append_int64(data, fds_total);
 | 
			
		||||
 | 
			
		||||
    fds_parent.index = gbinder_writer_data_append_buffer_object(data,
 | 
			
		||||
        fds, fds_total, parent);
 | 
			
		||||
    fds_parent.offset = sizeof(GBinderFds);
 | 
			
		||||
 | 
			
		||||
    gbinder_writer_data_append_fda_object(data, fds, &fds_parent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
guint
 | 
			
		||||
@@ -735,6 +754,51 @@ gbinder_writer_data_append_buffer_object(
 | 
			
		||||
    return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is supposed to be used to write aidl parcelables, and is not
 | 
			
		||||
 * guaranteed to work on any other kind of parcelable.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_parcelable(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
    const void* buf,
 | 
			
		||||
    gsize len) /* Since 1.1.19 */
 | 
			
		||||
{
 | 
			
		||||
    GBinderWriterData* data = gbinder_writer_data(self);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(data)) {
 | 
			
		||||
        gbinder_writer_data_append_parcelable(data, buf, len);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is compatible with aidl parcelables, and is not guaranteed to work
 | 
			
		||||
 * with any other kind of parcelable.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_parcelable(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    const void* ptr,
 | 
			
		||||
    gsize size)
 | 
			
		||||
{
 | 
			
		||||
    if (ptr) {
 | 
			
		||||
        /* Non-null */
 | 
			
		||||
        gbinder_writer_data_append_int32(data, 1);
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Write the parcelable size, taking in account the size of this
 | 
			
		||||
         * integer as well.
 | 
			
		||||
         */
 | 
			
		||||
        gbinder_writer_data_append_int32(data, size + sizeof(gint32));
 | 
			
		||||
 | 
			
		||||
        /* Append the parcelable data */
 | 
			
		||||
        g_byte_array_append(data->bytes, ptr, size);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Null */
 | 
			
		||||
        gbinder_writer_data_append_int32(data, 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_string(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
@@ -1017,6 +1081,7 @@ gbinder_writer_data_append_fmq_descriptor(
 | 
			
		||||
    const gsize fds_total = sizeof(GBinderFds) +
 | 
			
		||||
        sizeof(int) * (desc->data.fds->num_fds + desc->data.fds->num_ints);
 | 
			
		||||
    GBinderFds* fds = gutil_memdup(desc->data.fds, fds_total);
 | 
			
		||||
 | 
			
		||||
    mqdesc->data.fds = fds;
 | 
			
		||||
    data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, fds);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -130,6 +130,13 @@ gbinder_writer_data_append_buffer_object(
 | 
			
		||||
    const GBinderParent* parent)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_parcelable(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    const void* ptr,
 | 
			
		||||
    gsize size)
 | 
			
		||||
    GBINDER_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_vec(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
 
 | 
			
		||||
@@ -171,6 +171,8 @@ app_init(
 | 
			
		||||
          app_log_verbose, "Enable verbose output", NULL },
 | 
			
		||||
        { "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
 | 
			
		||||
          app_log_quiet, "Be quiet", NULL },
 | 
			
		||||
        { "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
 | 
			
		||||
          "Binder device [" DEV_DEFAULT "]", "DEVICE" },
 | 
			
		||||
        { NULL }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -187,7 +189,7 @@ app_init(
 | 
			
		||||
    if (g_option_context_parse(options, &argc, &argv, &error)) {
 | 
			
		||||
        char* help;
 | 
			
		||||
 | 
			
		||||
        opt->dev = g_strdup(DEV_DEFAULT);
 | 
			
		||||
        if (!opt->dev || !opt->dev[0]) opt->dev = g_strdup(DEV_DEFAULT);
 | 
			
		||||
        switch (argc) {
 | 
			
		||||
        case 2:
 | 
			
		||||
            opt->service = argv[1];
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ all:
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl2 $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl3 $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_aidl4 $*
 | 
			
		||||
	@$(MAKE) -C unit_servicemanager_hidl $*
 | 
			
		||||
	@$(MAKE) -C unit_servicename $*
 | 
			
		||||
	@$(MAKE) -C unit_servicepoll $*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -55,6 +55,7 @@ static GHashTable* test_fd_map = NULL;
 | 
			
		||||
static GHashTable* test_node_map = NULL;
 | 
			
		||||
static GPrivate test_looper = G_PRIVATE_INIT(NULL);
 | 
			
		||||
static GPrivate test_tx_state = G_PRIVATE_INIT(NULL);
 | 
			
		||||
static guint32 last_auto_handle = 0;
 | 
			
		||||
 | 
			
		||||
G_LOCK_DEFINE_STATIC(test_binder);
 | 
			
		||||
static GMainLoop* test_binder_exit_loop = NULL;
 | 
			
		||||
@@ -125,6 +126,7 @@ typedef struct test_binder_node TestBinderNode;
 | 
			
		||||
struct test_binder_node {
 | 
			
		||||
    int fd;
 | 
			
		||||
    char* path;
 | 
			
		||||
    const char* name;
 | 
			
		||||
    TestBinder* binder;
 | 
			
		||||
    TestBinderNode* other;
 | 
			
		||||
    TEST_LOOPER looper_enabled;
 | 
			
		||||
@@ -146,7 +148,6 @@ typedef struct test_binder {
 | 
			
		||||
    GHashTable* object_map; /* GBinderLocalObject* => handle */
 | 
			
		||||
    GHashTable* handle_map; /* handle => GBinderLocalObject* */
 | 
			
		||||
    TestBinderSubmitThread* submit_thread;
 | 
			
		||||
    guint32 last_auto_handle;
 | 
			
		||||
    GMutex mutex;
 | 
			
		||||
    gboolean passthrough;
 | 
			
		||||
    TestBinderNode node[2];
 | 
			
		||||
@@ -437,13 +438,16 @@ test_binder_register_object_locked(
 | 
			
		||||
    g_assert(!g_hash_table_contains(binder->object_map, obj));
 | 
			
		||||
    g_assert(!g_hash_table_contains(binder->handle_map, GINT_TO_POINTER(h)));
 | 
			
		||||
    if (h == AUTO_HANDLE) {
 | 
			
		||||
        h = ++(binder->last_auto_handle);
 | 
			
		||||
        h = ++last_auto_handle;
 | 
			
		||||
        while (g_hash_table_contains(binder->handle_map, GINT_TO_POINTER(h)) ||
 | 
			
		||||
            g_hash_table_contains(binder->object_map, GINT_TO_POINTER(h))) {
 | 
			
		||||
            h = ++(binder->last_auto_handle);
 | 
			
		||||
            h = ++last_auto_handle;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (last_auto_handle < h) {
 | 
			
		||||
        /* Avoid re-using handles, to make debugging easier */
 | 
			
		||||
        last_auto_handle = h;
 | 
			
		||||
    }
 | 
			
		||||
    GDEBUG("Object %p <=> handle %u", obj, h);
 | 
			
		||||
    GDEBUG("Object %p <=> handle %u %s", obj, h, binder->node[0].name);
 | 
			
		||||
    g_hash_table_insert(binder->handle_map, GINT_TO_POINTER(h), obj);
 | 
			
		||||
    g_hash_table_insert(binder->object_map, obj, GINT_TO_POINTER(h));
 | 
			
		||||
    g_object_weak_ref(G_OBJECT(obj), test_binder_local_object_gone, binder);
 | 
			
		||||
@@ -463,10 +467,10 @@ test_io_passthough_handle_to_object(
 | 
			
		||||
        gpointer obj = g_hash_table_lookup(binder->handle_map, key);
 | 
			
		||||
 | 
			
		||||
        GDEBUG("Handle %u => object %p %s", (guint) handle, obj,
 | 
			
		||||
            binder->node[0].path);
 | 
			
		||||
            binder->node[0].name);
 | 
			
		||||
        return GPOINTER_TO_SIZE(obj);
 | 
			
		||||
    }
 | 
			
		||||
    GDEBUG("Unexpected handle %u %s", (guint) handle, binder->node[0].path);
 | 
			
		||||
    GDEBUG("Unexpected handle %u %s", (guint) handle, binder->node[0].name);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -484,13 +488,13 @@ test_io_passthough_object_to_handle(
 | 
			
		||||
        guint64 handle = GPOINTER_TO_SIZE(value);
 | 
			
		||||
 | 
			
		||||
        GDEBUG("Object %p => handle %u %s", key, (guint) handle,
 | 
			
		||||
            binder->node[0].path);
 | 
			
		||||
            binder->node[0].name);
 | 
			
		||||
        return handle;
 | 
			
		||||
    } else if (key) {
 | 
			
		||||
        GDEBUG("Auto-registering object %p %s", key, binder->node[0].path);
 | 
			
		||||
        GDEBUG("Auto-registering object %p %s", key, binder->node[0].name);
 | 
			
		||||
        return test_binder_register_object_locked(binder, key, AUTO_HANDLE);
 | 
			
		||||
    } else {
 | 
			
		||||
        GDEBUG("Unexpected object %p %s", key, binder->node[0].path);
 | 
			
		||||
        GDEBUG("Unexpected object %p %s", key, binder->node[0].name);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -565,7 +569,7 @@ test_binder_node_read(
 | 
			
		||||
        const guint32 cmd = node->next_cmd[0];
 | 
			
		||||
        const guint total = 4 + _IOC_SIZE(cmd);
 | 
			
		||||
 | 
			
		||||
        /* Alread have one ready */
 | 
			
		||||
        /* Already have one ready */
 | 
			
		||||
        if (!(test_binder_cmd_read_flags(cmd) & flags)) {
 | 
			
		||||
            GDEBUG("Cmd 0x%08x not for %d", cmd, gettid());
 | 
			
		||||
            *bytes_read = 0;
 | 
			
		||||
@@ -667,7 +671,7 @@ test_tx_state_acquire(
 | 
			
		||||
    while (g_atomic_pointer_get(&node->tx_state) != my_tx_state &&
 | 
			
		||||
        !g_atomic_pointer_compare_and_exchange(&node->tx_state, NULL,
 | 
			
		||||
         my_tx_state)) {
 | 
			
		||||
        GDEBUG("Thread %d is waiting to become a transacton thread",
 | 
			
		||||
        GDEBUG("Thread %d is waiting to become a transaction thread",
 | 
			
		||||
            my_tx_state->tid);
 | 
			
		||||
        test_io_short_wait();
 | 
			
		||||
    }
 | 
			
		||||
@@ -696,7 +700,7 @@ test_tx_state_release(
 | 
			
		||||
        my_tx_state->depth--;
 | 
			
		||||
        my_tx_state->stack = g_renew(TEST_TX_STATE, my_tx_state->stack,
 | 
			
		||||
            my_tx_state->depth);
 | 
			
		||||
        GDEBUG("Thread %d is still a transacton thread", my_tx_state->tid);
 | 
			
		||||
        GDEBUG("Thread %d is still a transaction thread", my_tx_state->tid);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -843,6 +847,8 @@ test_io_passthough_write_64(
 | 
			
		||||
                        buffer->buffer = GPOINTER_TO_SIZE(copy);
 | 
			
		||||
                        g_hash_table_replace(fd->destroy_map, copy, NULL);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    GDEBUG("Unexpected object type 0x%08x", *obj_ptr);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            g_hash_table_replace(fd->destroy_map, data_offsets, NULL);
 | 
			
		||||
@@ -1594,6 +1600,7 @@ test_binder_fd_new(
 | 
			
		||||
    binder_fd->node = node;
 | 
			
		||||
    binder_fd->fd = dup(node->fd);
 | 
			
		||||
    binder_fd->destroy_map = g_hash_table_new(g_direct_hash, g_direct_equal);
 | 
			
		||||
    GDEBUG("fd %d => %d", binder_fd->fd, node->fd);
 | 
			
		||||
    return binder_fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1602,11 +1609,12 @@ gbinder_system_open(
 | 
			
		||||
    const char* path,
 | 
			
		||||
    int flags)
 | 
			
		||||
{
 | 
			
		||||
    static const char path_prefix[] = "/dev/";
 | 
			
		||||
    static const char binder_suffix[] = "binder";
 | 
			
		||||
    static const char binder_private_suffix[] = "binder-private";
 | 
			
		||||
    static const char private_suffix[] = "-private";
 | 
			
		||||
 | 
			
		||||
    if (path && g_str_has_prefix(path, "/dev/") &&
 | 
			
		||||
    if (path && g_str_has_prefix(path, path_prefix) &&
 | 
			
		||||
        (g_str_has_suffix(path, binder_suffix) ||
 | 
			
		||||
         g_str_has_suffix(path, binder_private_suffix))) {
 | 
			
		||||
        TestBinderFd* fd;
 | 
			
		||||
@@ -1631,7 +1639,7 @@ gbinder_system_open(
 | 
			
		||||
                node = binder->node + PRIVATE;
 | 
			
		||||
                node->path = g_strdup(path);
 | 
			
		||||
                binder->node[PUBLIC].path = g_strndup(path,
 | 
			
		||||
                    strlen(path) - strlen(private_suffix) - 1);
 | 
			
		||||
                    strlen(path) - strlen(private_suffix));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!test_node_map) {
 | 
			
		||||
@@ -1644,6 +1652,7 @@ gbinder_system_open(
 | 
			
		||||
                this_node->binder = binder;
 | 
			
		||||
                this_node->fd = fds[i];
 | 
			
		||||
                this_node->other = binder->node + ((i + 1) % 2);
 | 
			
		||||
                this_node->name = this_node->path + strlen(path_prefix);
 | 
			
		||||
                g_hash_table_replace(test_node_map, this_node->path, this_node);
 | 
			
		||||
            }
 | 
			
		||||
            binder->object_map = g_hash_table_new
 | 
			
		||||
@@ -1651,8 +1660,8 @@ gbinder_system_open(
 | 
			
		||||
            binder->handle_map = g_hash_table_new
 | 
			
		||||
                (g_direct_hash, g_direct_equal);
 | 
			
		||||
            GDEBUG("Created %s (%d) <=> %s (%d) binder",
 | 
			
		||||
                binder->node[0].path, binder->node[0].fd,
 | 
			
		||||
                binder->node[1].path, binder->node[1].fd);
 | 
			
		||||
                binder->node[0].name, binder->node[0].fd,
 | 
			
		||||
                binder->node[1].name, binder->node[1].fd);
 | 
			
		||||
        }
 | 
			
		||||
        fd = test_binder_fd_new(node);
 | 
			
		||||
        if (!test_fd_map) {
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,10 @@ test_run_in_context(
 | 
			
		||||
/* Helper macros */
 | 
			
		||||
 | 
			
		||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 | 
			
		||||
#  define TEST_INT8_BYTES_4(v) \
 | 
			
		||||
    (guint8)(v), 0, 0, 0
 | 
			
		||||
#  define TEST_INT16_BYTES_4(v) \
 | 
			
		||||
    (guint8)(v), (guint8)((v) >> 8), 0, 0
 | 
			
		||||
#  define TEST_INT16_BYTES(v) \
 | 
			
		||||
    (guint8)(v), (guint8)((v) >> 8)
 | 
			
		||||
#  define TEST_INT32_BYTES(v) \
 | 
			
		||||
@@ -91,6 +95,10 @@ test_run_in_context(
 | 
			
		||||
    (guint8)(((guint64)(v)) >> 32), (guint8)(((guint64)(v)) >> 40), \
 | 
			
		||||
    (guint8)(((guint64)(v)) >> 48), (guint8)(((guint64)(v)) >> 56)
 | 
			
		||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
 | 
			
		||||
#  define TEST_INT8_BYTES_4(v) \
 | 
			
		||||
    0, 0, 0, (guint8)(v)
 | 
			
		||||
#  define TEST_INT16_BYTES_4(v) \
 | 
			
		||||
    0, 0, (guint8)((v) >> 8), (guint8)(v)
 | 
			
		||||
#  define TEST_INT16_BYTES(v) \
 | 
			
		||||
    (guint8)((v) >> 8), (guint8)(v)
 | 
			
		||||
#  define TEST_INT32_BYTES(v) \
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ unit_servicemanager \
 | 
			
		||||
unit_servicemanager_aidl \
 | 
			
		||||
unit_servicemanager_aidl2 \
 | 
			
		||||
unit_servicemanager_aidl3 \
 | 
			
		||||
unit_servicemanager_aidl4 \
 | 
			
		||||
unit_servicemanager_hidl \
 | 
			
		||||
unit_servicename \
 | 
			
		||||
unit_servicepoll \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -183,7 +183,7 @@ TestServiceManagerHidl*
 | 
			
		||||
test_servicemanager_impl_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    TestServiceManagerHidl* sm = test_servicemanager_hidl_new(ipc);
 | 
			
		||||
 | 
			
		||||
@@ -357,10 +357,10 @@ test_basic_run(
 | 
			
		||||
    test.loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
    /* obj (DEST) <=> bridge <=> (SRC) mirror */
 | 
			
		||||
    src_ipc = gbinder_ipc_new(SRC_DEV);
 | 
			
		||||
    src_priv_ipc = gbinder_ipc_new(SRC_PRIV_DEV);
 | 
			
		||||
    dest_ipc = gbinder_ipc_new(DEST_DEV);
 | 
			
		||||
    dest_priv_ipc = gbinder_ipc_new(DEST_PRIV_DEV);
 | 
			
		||||
    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);
 | 
			
		||||
    src_fd = gbinder_driver_fd(src_ipc->driver);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -55,7 +55,7 @@ test_client_new(
 | 
			
		||||
    guint h,
 | 
			
		||||
    const char* iface)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, h, TRUE);
 | 
			
		||||
    GBinderClient* client = gbinder_client_new(obj, iface);
 | 
			
		||||
@@ -99,7 +99,7 @@ void
 | 
			
		||||
test_basic(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, 0, TRUE);
 | 
			
		||||
    const char* iface = "foo";
 | 
			
		||||
@@ -125,7 +125,7 @@ void
 | 
			
		||||
test_interfaces(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, 0, TRUE);
 | 
			
		||||
    static const GBinderClientIfaceInfo ifaces[] = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2020-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -231,6 +231,7 @@ test_dirs(
 | 
			
		||||
    char* file1 = g_build_filename(subdir, "a.conf", NULL);
 | 
			
		||||
    char* file2 = g_build_filename(subdir, "b.conf", NULL);
 | 
			
		||||
    char* file3 = g_build_filename(subdir, "c.conf", NULL);
 | 
			
		||||
    char* file4 = g_build_filename(subdir, "d.conf", NULL);
 | 
			
		||||
    char* random_file = g_build_filename(subdir, "foo", NULL);
 | 
			
		||||
    static const char garbage[] = "foo";
 | 
			
		||||
    static const char config[] =
 | 
			
		||||
@@ -252,6 +253,11 @@ test_dirs(
 | 
			
		||||
        "/dev/binder3 = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder3 = aidl3\n";
 | 
			
		||||
    static const char config4[] =
 | 
			
		||||
        "[Protocol]\n"
 | 
			
		||||
        "/dev/binder4 = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder4 = aidl4\n";
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpint(mkdir(subdir, 0700), == ,0);
 | 
			
		||||
    g_assert_cmpint(mkdir(notafile, 0700), == ,0);
 | 
			
		||||
@@ -259,6 +265,7 @@ test_dirs(
 | 
			
		||||
    g_assert(g_file_set_contents(file1, config1, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(file2, config2, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(file3, config3, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(file4, config4, -1, NULL));
 | 
			
		||||
    g_assert(g_file_set_contents(random_file, garbage, -1, NULL));
 | 
			
		||||
 | 
			
		||||
    /* Reset the state */
 | 
			
		||||
@@ -271,10 +278,12 @@ test_dirs(
 | 
			
		||||
    g_assert(k);
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/hbinder",b), == ,"hidl");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/hwbinder",b), == ,"hidl");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Remove the default file and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
@@ -284,9 +293,11 @@ test_dirs(
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/hwbinder",b), == ,"hidl");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Damage one of the files and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
@@ -297,8 +308,10 @@ test_dirs(
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Disallow access to one of the files and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
@@ -309,14 +322,27 @@ test_dirs(
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder",b), == ,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder3",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b), == ,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder",b),==,"aidl2");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder3",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Delete the remaining files and try again */
 | 
			
		||||
    /* Leave only one file (file4) in the subdirectory */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
    g_assert_cmpint(remove(file1), == ,0);
 | 
			
		||||
    g_assert_cmpint(remove(file2), == ,0);
 | 
			
		||||
    g_assert_cmpint(remove(file3), == ,0);
 | 
			
		||||
    k = gbinder_config_get();
 | 
			
		||||
    g_assert(k);
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hbinder",b));
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/hwbinder",b));
 | 
			
		||||
    g_assert(!test_value(k,"Protocol","/dev/binder3",b));
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"Protocol","/dev/binder4",b),==,"aidl3");
 | 
			
		||||
    g_assert_cmpstr(test_value(k,"ServiceManager","/dev/binder4",b),==,"aidl4");
 | 
			
		||||
 | 
			
		||||
    /* Delete the remaining file and try again */
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
    g_assert_cmpint(remove(file4), == ,0);
 | 
			
		||||
    g_assert(!gbinder_config_get());
 | 
			
		||||
 | 
			
		||||
    /* Undo all the damage */
 | 
			
		||||
@@ -329,6 +355,7 @@ test_dirs(
 | 
			
		||||
    g_free(file1);
 | 
			
		||||
    g_free(file2);
 | 
			
		||||
    g_free(file3);
 | 
			
		||||
    g_free(file4);
 | 
			
		||||
    g_free(random_file);
 | 
			
		||||
 | 
			
		||||
    remove(notafile);
 | 
			
		||||
@@ -495,6 +522,20 @@ static const TestPresetsData test_presets_data [] = {
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder = aidl3\n"
 | 
			
		||||
        "/dev/vndbinder = aidl3\n"
 | 
			
		||||
    },{
 | 
			
		||||
        "31",
 | 
			
		||||
 | 
			
		||||
        "[General]\n"
 | 
			
		||||
        "ApiLevel = 31",
 | 
			
		||||
 | 
			
		||||
        "[General]\n"
 | 
			
		||||
        "ApiLevel = 31\n"
 | 
			
		||||
        "[Protocol]\n"
 | 
			
		||||
        "/dev/binder = aidl3\n"
 | 
			
		||||
        "/dev/vndbinder = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "/dev/binder = aidl4\n"
 | 
			
		||||
        "/dev/vndbinder = aidl4\n"
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
 | 
			
		||||
#include "test_binder.h"
 | 
			
		||||
 | 
			
		||||
#include "gbinder_config.h"
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_handler.h"
 | 
			
		||||
#include "gbinder_local_request_p.h"
 | 
			
		||||
@@ -140,12 +141,31 @@ test_local_request(
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    const char* default_config_dir;
 | 
			
		||||
    const char* default_config_file;
 | 
			
		||||
    char* config_dir = g_dir_make_tmp("gbinder-test-driver-XXXXXX", NULL);
 | 
			
		||||
    char* config_file = g_build_filename(config_dir, "test.conf", NULL);
 | 
			
		||||
    int result;
 | 
			
		||||
 | 
			
		||||
    /* Point gbinder_config_file to a non-existent file */
 | 
			
		||||
    default_config_dir = gbinder_config_dir;
 | 
			
		||||
    default_config_file = gbinder_config_file;
 | 
			
		||||
    gbinder_config_dir = config_dir;
 | 
			
		||||
    gbinder_config_file = config_file;
 | 
			
		||||
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "basic", test_basic);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "noop", test_noop);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "local_request", test_local_request);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
    result = g_test_run();
 | 
			
		||||
 | 
			
		||||
    gbinder_config_dir = default_config_dir;
 | 
			
		||||
    gbinder_config_file = default_config_file;
 | 
			
		||||
    remove(config_dir);
 | 
			
		||||
    g_free(config_dir);
 | 
			
		||||
    g_free(config_file);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -79,26 +79,25 @@ void
 | 
			
		||||
test_null(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* null = NULL;
 | 
			
		||||
    int status = INT_MAX;
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_ipc_ref(null));
 | 
			
		||||
    gbinder_ipc_unref(null);
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_main.sync_reply(null, 0, 0, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_main.sync_reply(null, 0, 0, NULL, &status));
 | 
			
		||||
    g_assert(!gbinder_ipc_ref(NULL));
 | 
			
		||||
    gbinder_ipc_unref(NULL);
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_main.sync_reply(NULL, 0, 0, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_main.sync_reply(NULL, 0, 0, NULL, &status));
 | 
			
		||||
    g_assert_cmpint(status, == ,-EINVAL);
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_worker.sync_reply(null, 0, 0, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_worker.sync_reply(null, 0, 0, NULL, &status));
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_worker.sync_reply(NULL, 0, 0, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_sync_worker.sync_reply(NULL, 0, 0, NULL, &status));
 | 
			
		||||
    g_assert_cmpint(status, == ,-EINVAL);
 | 
			
		||||
    g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(null, 0, 0, NULL), == ,
 | 
			
		||||
    g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(NULL, 0, 0, NULL), == ,
 | 
			
		||||
        -EINVAL);
 | 
			
		||||
    g_assert_cmpint(gbinder_ipc_sync_worker.sync_oneway(null, 0, 0, NULL), == ,
 | 
			
		||||
    g_assert_cmpint(gbinder_ipc_sync_worker.sync_oneway(NULL, 0, 0, NULL), == ,
 | 
			
		||||
        -EINVAL);
 | 
			
		||||
    g_assert(!gbinder_ipc_transact(null, 0, 0, 0, NULL, NULL, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_transact_custom(null, NULL, NULL, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_object_registry(null));
 | 
			
		||||
    gbinder_ipc_looper_check(null);
 | 
			
		||||
    gbinder_ipc_cancel(null, 0);
 | 
			
		||||
    g_assert(!gbinder_ipc_transact(NULL, 0, 0, 0, NULL, NULL, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_transact_custom(NULL, NULL, NULL, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_object_registry(NULL));
 | 
			
		||||
    gbinder_ipc_looper_check(NULL);
 | 
			
		||||
    gbinder_ipc_cancel(NULL, 0);
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_object_registry_ref(NULL));
 | 
			
		||||
    gbinder_object_registry_unref(NULL);
 | 
			
		||||
@@ -120,13 +119,23 @@ test_basic_find_none(
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_basic_find(
 | 
			
		||||
    GBinderLocalObject* obj,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    return obj == user_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_basic(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj;
 | 
			
		||||
 | 
			
		||||
    g_assert(ipc);
 | 
			
		||||
    g_assert(ipc2);
 | 
			
		||||
@@ -136,16 +145,45 @@ test_basic(
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_ipc_find_local_object(NULL, test_basic_find_none, NULL));
 | 
			
		||||
    g_assert(!gbinder_ipc_find_local_object(ipc, test_basic_find_none, NULL));
 | 
			
		||||
    obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    g_assert(obj);
 | 
			
		||||
    g_assert(!gbinder_ipc_find_local_object(ipc, test_basic_find_none, NULL));
 | 
			
		||||
    g_assert(gbinder_ipc_find_local_object(ipc, test_basic_find, obj) == obj);
 | 
			
		||||
    gbinder_local_object_unref(obj); /* Above call added a reference */
 | 
			
		||||
    gbinder_local_object_unref(obj);
 | 
			
		||||
 | 
			
		||||
    /* Second gbinder_ipc_new returns the same (default) object */
 | 
			
		||||
    g_assert(gbinder_ipc_new(NULL) == ipc);
 | 
			
		||||
    g_assert(gbinder_ipc_new("") == ipc);
 | 
			
		||||
    g_assert(gbinder_ipc_new(NULL, NULL) == ipc);
 | 
			
		||||
    g_assert(gbinder_ipc_new("", NULL) == ipc);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
 | 
			
		||||
    /* Invalid path */
 | 
			
		||||
    g_assert(!gbinder_ipc_new("invalid path"));
 | 
			
		||||
    g_assert(!gbinder_ipc_new("invalid path", NULL));
 | 
			
		||||
 | 
			
		||||
    gbinder_ipc_exit();
 | 
			
		||||
    test_binder_exit_wait(&test_opt, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * protocol
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_protocol(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    /* GBinderIpc objects are identified by device + protocol combination */
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, "aidl");
 | 
			
		||||
    GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, "hidl");
 | 
			
		||||
 | 
			
		||||
    g_assert(ipc);
 | 
			
		||||
    g_assert(ipc2);
 | 
			
		||||
    g_assert(ipc != ipc2);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
    gbinder_ipc_unref(ipc2);
 | 
			
		||||
 | 
			
		||||
    gbinder_ipc_exit();
 | 
			
		||||
    test_binder_exit_wait(&test_opt, NULL);
 | 
			
		||||
@@ -173,7 +211,7 @@ void
 | 
			
		||||
test_async_oneway(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -200,7 +238,7 @@ void
 | 
			
		||||
test_sync_oneway(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -222,7 +260,7 @@ void
 | 
			
		||||
test_sync_reply_ok_status(
 | 
			
		||||
    int* status)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -279,7 +317,7 @@ void
 | 
			
		||||
test_sync_reply_error(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -348,7 +386,7 @@ void
 | 
			
		||||
test_transact_ok(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -407,7 +445,7 @@ void
 | 
			
		||||
test_transact_dead(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -455,7 +493,7 @@ void
 | 
			
		||||
test_transact_failed(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -505,7 +543,7 @@ void
 | 
			
		||||
test_transact_status(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
@@ -548,7 +586,7 @@ void
 | 
			
		||||
test_transact_custom(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    gulong id = gbinder_ipc_transact_custom(ipc, NULL,
 | 
			
		||||
        test_transact_custom_done, NULL, loop);
 | 
			
		||||
@@ -580,7 +618,7 @@ void
 | 
			
		||||
test_transact_custom2(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    gulong id = gbinder_ipc_transact_custom(ipc, NULL, NULL,
 | 
			
		||||
        test_transact_custom_destroy, loop);
 | 
			
		||||
@@ -613,7 +651,7 @@ void
 | 
			
		||||
test_transact_custom3(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    /* Reusing test_transact_cancel_done and test_transact_cancel_destroy */
 | 
			
		||||
    gulong id = gbinder_ipc_transact_custom(ipc, test_transact_custom3_exec,
 | 
			
		||||
@@ -663,7 +701,7 @@ void
 | 
			
		||||
test_transact_cancel(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel_exec,
 | 
			
		||||
        test_transact_cancel_done, test_transact_cancel_destroy, loop);
 | 
			
		||||
@@ -709,7 +747,7 @@ void
 | 
			
		||||
test_transact_cancel2(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    /* Reusing test_transact_cancel_done and test_transact_cancel_destroy */
 | 
			
		||||
    gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel2_exec,
 | 
			
		||||
@@ -759,7 +797,7 @@ void
 | 
			
		||||
test_transact_2way_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    const char* dev = gbinder_driver_dev(ipc->driver);
 | 
			
		||||
@@ -844,7 +882,7 @@ void
 | 
			
		||||
test_transact_unhandled_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderDriver* driver = ipc->driver;
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_driver_local_request_new_ping(driver);
 | 
			
		||||
@@ -905,7 +943,7 @@ void
 | 
			
		||||
test_transact_incoming_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    const char* dev = gbinder_driver_dev(ipc->driver);
 | 
			
		||||
@@ -986,7 +1024,7 @@ void
 | 
			
		||||
test_transact_status_reply_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    const char* dev = gbinder_driver_dev(ipc->driver);
 | 
			
		||||
@@ -1103,7 +1141,7 @@ void
 | 
			
		||||
test_transact_async_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    const char* dev = gbinder_driver_dev(ipc->driver);
 | 
			
		||||
@@ -1186,7 +1224,7 @@ void
 | 
			
		||||
test_transact_async_sync_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    const char* dev = gbinder_driver_dev(ipc->driver);
 | 
			
		||||
@@ -1250,7 +1288,7 @@ void
 | 
			
		||||
test_drop_remote_refs_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -1301,7 +1339,7 @@ void
 | 
			
		||||
test_cancel_on_exit(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(ipc->driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -1334,6 +1372,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("null"), test_null);
 | 
			
		||||
    g_test_add_func(TEST_("basic"), test_basic);
 | 
			
		||||
    g_test_add_func(TEST_("protocol"), test_protocol);
 | 
			
		||||
    g_test_add_func(TEST_("async_oneway"), test_async_oneway);
 | 
			
		||||
    g_test_add_func(TEST_("sync_oneway"), test_sync_oneway);
 | 
			
		||||
    g_test_add_func(TEST_("sync_reply_ok"), test_sync_reply_ok);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
#include "test_binder.h"
 | 
			
		||||
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_config.h"
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_ipc.h"
 | 
			
		||||
#include "gbinder_local_object_p.h"
 | 
			
		||||
@@ -152,7 +153,7 @@ test_basic(
 | 
			
		||||
{
 | 
			
		||||
    const char* const ifaces_foo[] = { "foo", NULL };
 | 
			
		||||
    const char* const ifaces_bar[] = { "bar", NULL };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderLocalObject* foo;
 | 
			
		||||
    GBinderLocalObject* bar;
 | 
			
		||||
@@ -201,7 +202,7 @@ test_ping(
 | 
			
		||||
    int status = INT_MAX;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
@@ -247,7 +248,7 @@ test_interface(
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    const char* const ifaces[] = { "x", NULL };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces, NULL, NULL);
 | 
			
		||||
@@ -296,7 +297,7 @@ test_hidl_ping(
 | 
			
		||||
    int status = INT_MAX;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
@@ -346,7 +347,7 @@ test_get_descriptor(
 | 
			
		||||
    int status = INT_MAX;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
@@ -402,7 +403,7 @@ test_descriptor_chain(
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    const char* const ifaces[] = { "android.hidl.base@1.0::IBase", NULL };
 | 
			
		||||
    const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces, NULL, NULL);
 | 
			
		||||
@@ -476,7 +477,7 @@ test_custom_iface(
 | 
			
		||||
    int count = 0, status = INT_MAX;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces,
 | 
			
		||||
@@ -583,7 +584,7 @@ test_reply_status(
 | 
			
		||||
    int count = 0, status = 0;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot, 0, 0);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces,
 | 
			
		||||
@@ -624,7 +625,7 @@ void
 | 
			
		||||
test_increfs_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -675,7 +676,7 @@ void
 | 
			
		||||
test_decrefs_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -726,7 +727,7 @@ void
 | 
			
		||||
test_acquire_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -777,7 +778,7 @@ void
 | 
			
		||||
test_release_run(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
@@ -815,6 +816,18 @@ test_release(
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    const char* default_config_dir;
 | 
			
		||||
    const char* default_config_file;
 | 
			
		||||
    char* config_dir = g_dir_make_tmp("gbinder-test-local-object-XXXXXX", NULL);
 | 
			
		||||
    char* config_file = g_build_filename(config_dir, "test.conf", NULL);
 | 
			
		||||
    int result;
 | 
			
		||||
 | 
			
		||||
    /* Point gbinder_config_file to a non-existent file */
 | 
			
		||||
    default_config_dir = gbinder_config_dir;
 | 
			
		||||
    default_config_file = gbinder_config_file;
 | 
			
		||||
    gbinder_config_dir = config_dir;
 | 
			
		||||
    gbinder_config_file = config_file;
 | 
			
		||||
 | 
			
		||||
    G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
 | 
			
		||||
    g_type_init();
 | 
			
		||||
    G_GNUC_END_IGNORE_DEPRECATIONS;
 | 
			
		||||
@@ -833,7 +846,14 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "acquire", test_acquire);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "release", test_release);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
    result = g_test_run();
 | 
			
		||||
 | 
			
		||||
    gbinder_config_dir = default_config_dir;
 | 
			
		||||
    gbinder_config_file = default_config_file;
 | 
			
		||||
    remove(config_dir);
 | 
			
		||||
    g_free(config_dir);
 | 
			
		||||
    g_free(config_file);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -426,7 +426,7 @@ test_local_object(
 | 
			
		||||
    GBinderLocalReply* reply;
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GUtilIntArray* offsets;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(NULL);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(NULL, NULL);
 | 
			
		||||
    const char* const ifaces[] = { "android.hidl.base@1.0::IBase", NULL };
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, ifaces, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2020 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -184,6 +184,9 @@ test_device(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const GBinderRpcProtocol* p;
 | 
			
		||||
    TestConfig config;
 | 
			
		||||
 | 
			
		||||
    test_config_init(&config, "");
 | 
			
		||||
 | 
			
		||||
    p = gbinder_rpc_protocol_for_device(NULL);
 | 
			
		||||
    g_assert(p);
 | 
			
		||||
@@ -196,6 +199,8 @@ test_device(
 | 
			
		||||
    p = gbinder_rpc_protocol_for_device(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    g_assert(p);
 | 
			
		||||
    g_assert_cmpstr(p->name, == ,"hidl");
 | 
			
		||||
 | 
			
		||||
    test_config_cleanup(&config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 *
 | 
			
		||||
@@ -198,8 +198,8 @@ test_basic_run(
 | 
			
		||||
    int fd_obj, fd_proxy, n = 0;
 | 
			
		||||
 | 
			
		||||
    test_config_init(&config, NULL);
 | 
			
		||||
    ipc_proxy = gbinder_ipc_new(DEV);
 | 
			
		||||
    ipc_obj = gbinder_ipc_new(DEV_PRIV);
 | 
			
		||||
    ipc_proxy = gbinder_ipc_new(DEV, NULL);
 | 
			
		||||
    ipc_obj = gbinder_ipc_new(DEV_PRIV, 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);
 | 
			
		||||
@@ -362,10 +362,10 @@ test_param_run(
 | 
			
		||||
    int fd_obj, fd_proxy, n = 0;
 | 
			
		||||
 | 
			
		||||
    test_config_init(&config, NULL);
 | 
			
		||||
    ipc_obj = gbinder_ipc_new(DEV);
 | 
			
		||||
    ipc_remote_obj = gbinder_ipc_new(DEV_PRIV);
 | 
			
		||||
    ipc_proxy = gbinder_ipc_new(DEV2);
 | 
			
		||||
    ipc_remote_proxy = gbinder_ipc_new(DEV2_PRIV);
 | 
			
		||||
    ipc_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);
 | 
			
		||||
    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);
 | 
			
		||||
@@ -438,7 +438,7 @@ test_param(
 | 
			
		||||
 | 
			
		||||
typedef struct test_obj_data {
 | 
			
		||||
    GMainLoop* loop;
 | 
			
		||||
    GBinderLocalObject* tmp_proxy;
 | 
			
		||||
    GBinderLocalObject* obj2;
 | 
			
		||||
    gboolean obj_call_handled;
 | 
			
		||||
    gboolean obj_call_finished;
 | 
			
		||||
    gboolean obj2_call_handled;
 | 
			
		||||
@@ -539,9 +539,9 @@ test_obj_cb(
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
 | 
			
		||||
    /* Make sure temporary proxy won't get destroyed too early */
 | 
			
		||||
    test->tmp_proxy = test_binder_object(gbinder_driver_fd(obj->ipc->driver),
 | 
			
		||||
    test->obj2 = test_binder_object(gbinder_driver_fd(obj->ipc->driver),
 | 
			
		||||
        obj2->handle);
 | 
			
		||||
    g_assert(test->tmp_proxy);
 | 
			
		||||
    g_assert(test->obj2);
 | 
			
		||||
 | 
			
		||||
    /* Call remote object */
 | 
			
		||||
    client2 = gbinder_client_new(obj2, TEST_IFACE2);
 | 
			
		||||
@@ -599,39 +599,55 @@ test_obj_run(
 | 
			
		||||
    GBinderRemoteObject* remote_obj;
 | 
			
		||||
    GBinderRemoteObject* remote_proxy;
 | 
			
		||||
    GBinderClient* proxy_client;
 | 
			
		||||
    GBinderIpc* ipc_remote_obj;
 | 
			
		||||
    GBinderIpc* ipc_obj;
 | 
			
		||||
    GBinderIpc* ipc_proxy;
 | 
			
		||||
    GBinderIpc* ipc_remote_proxy;
 | 
			
		||||
    GBinderLocalRequest* req;
 | 
			
		||||
    int fd_obj, fd_proxy;
 | 
			
		||||
    int fd_remote_obj, fd_obj, fd_proxy, fd_remote_proxy;
 | 
			
		||||
 | 
			
		||||
    test_config_init(&config, NULL);
 | 
			
		||||
    memset(&test, 0, sizeof(test));
 | 
			
		||||
    test.loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
    ipc_proxy = gbinder_ipc_new(DEV);
 | 
			
		||||
    ipc_obj = gbinder_ipc_new(DEV_PRIV);
 | 
			
		||||
    fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
 | 
			
		||||
    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);
 | 
			
		||||
    obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_obj_cb, &test);
 | 
			
		||||
    obj2 = gbinder_local_object_new(ipc_obj, TEST_IFACES2, test_obj2_cb, &test);
 | 
			
		||||
    remote_obj = gbinder_remote_object_new(ipc_proxy,
 | 
			
		||||
    fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
 | 
			
		||||
    fd_remote_proxy = gbinder_driver_fd(ipc_remote_proxy->driver);
 | 
			
		||||
 | 
			
		||||
    obj = gbinder_local_object_new(ipc_remote_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(DEV_PRIV) => proxy (DEV) => obj (DEV) => DEV_PRIV */
 | 
			
		||||
    g_assert(!gbinder_proxy_object_new(NULL, remote_obj));
 | 
			
		||||
    /* remote_proxy(DEV2_PRIV) => proxy (DEV) => obj(DEV2_PRIV) */
 | 
			
		||||
    g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
 | 
			
		||||
    remote_proxy = gbinder_remote_object_new(ipc_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);
 | 
			
		||||
 | 
			
		||||
    /* Pass object reference via proxy */
 | 
			
		||||
    obj2 = gbinder_local_object_new(ipc_remote_proxy, TEST_IFACES2, test_obj2_cb, &test);
 | 
			
		||||
    GDEBUG("obj2 %p", obj2);
 | 
			
		||||
    req = gbinder_client_new_request(proxy_client);
 | 
			
		||||
    gbinder_local_request_append_int32(req, TX_PARAM1);
 | 
			
		||||
    gbinder_local_request_append_local_object(req, obj2);
 | 
			
		||||
@@ -646,19 +662,24 @@ test_obj_run(
 | 
			
		||||
    g_assert(test.obj_call_finished);
 | 
			
		||||
    g_assert(test.obj2_call_handled);
 | 
			
		||||
    g_assert(test.obj2_call_finished);
 | 
			
		||||
    g_assert(test.tmp_proxy);
 | 
			
		||||
    gbinder_local_object_unref(test.tmp_proxy);
 | 
			
		||||
    g_assert(test.obj2);
 | 
			
		||||
    gbinder_local_object_unref(test.obj2);
 | 
			
		||||
 | 
			
		||||
    test_binder_unregister_objects(fd_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_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);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -39,6 +39,8 @@
 | 
			
		||||
#include "gbinder_remote_object_p.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_misc.h>
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
@@ -65,6 +67,20 @@ typedef struct binder_buffer_object_64 {
 | 
			
		||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
 | 
			
		||||
G_STATIC_ASSERT(sizeof(BinderObject64) == BUFFER_OBJECT_SIZE_64);
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_init_reader(
 | 
			
		||||
    GBinderDriver* driver,
 | 
			
		||||
    GBinderReaderData* data,
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    const void* bytes,
 | 
			
		||||
    gsize size)
 | 
			
		||||
{
 | 
			
		||||
    data->buffer = gbinder_buffer_new(driver, gutil_memdup(bytes, size),
 | 
			
		||||
        size, NULL);
 | 
			
		||||
    gbinder_reader_init(reader, data, 0, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -108,6 +124,8 @@ test_empty(
 | 
			
		||||
    g_assert(!gbinder_reader_bytes_remaining(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_byte(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_bool(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_int8(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_int16(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_int32(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_uint32(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_int64(&reader, NULL));
 | 
			
		||||
@@ -117,6 +135,7 @@ test_empty(
 | 
			
		||||
    g_assert(!gbinder_reader_read_object(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_nullable_object(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_buffer(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_parcelable(&reader, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_struct1(&reader, 1));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec(&reader, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec(&reader, &count, &elemsize));
 | 
			
		||||
@@ -176,8 +195,8 @@ void
 | 
			
		||||
test_bool(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const guint8 in_true[4] = { 0x01, 0xff, 0xff, 0xff };
 | 
			
		||||
    const guint8 in_false[4] = { 0x00, 0xff, 0xff, 0xff };
 | 
			
		||||
    const guint8 in_true[] = { TEST_INT8_BYTES_4(TRUE) };
 | 
			
		||||
    const guint8 in_false[] = { TEST_INT8_BYTES_4(FALSE) };
 | 
			
		||||
    gboolean out = FALSE;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
@@ -216,6 +235,108 @@ test_bool(
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * int8
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_int8(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const guint8 in = 42;
 | 
			
		||||
    const guint8 in4[] = { TEST_INT8_BYTES_4(42) };
 | 
			
		||||
    guint8 out1 = 0;
 | 
			
		||||
    gint8 out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
    g_assert(driver);
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
 | 
			
		||||
    /* Not enough data */
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
 | 
			
		||||
        sizeof(in), NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in));
 | 
			
		||||
    g_assert(!gbinder_reader_read_uint8(&reader, &out1));
 | 
			
		||||
    g_assert(!gbinder_reader_at_end(&reader));
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
 | 
			
		||||
    /* Enough data */
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, g_memdup(in4, sizeof(in4)),
 | 
			
		||||
        sizeof(in4), NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in4));
 | 
			
		||||
    g_assert(gbinder_reader_read_uint8(&reader, &out1));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert_cmpuint(in, == ,out1);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in4));
 | 
			
		||||
    g_assert(gbinder_reader_read_int8(&reader, &out2));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert_cmpint(in, == ,out2);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in4));
 | 
			
		||||
    g_assert(gbinder_reader_read_int8(&reader, NULL));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * int16
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_int16(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const guint16 in = 42;
 | 
			
		||||
    const guint8 in4[] = { TEST_INT16_BYTES_4(42) };
 | 
			
		||||
    guint16 out1 = 0;
 | 
			
		||||
    gint16 out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
    g_assert(driver);
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
 | 
			
		||||
    /* Not enough data */
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
 | 
			
		||||
        sizeof(in), NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in));
 | 
			
		||||
    g_assert(!gbinder_reader_read_uint16(&reader, &out1));
 | 
			
		||||
    g_assert(!gbinder_reader_at_end(&reader));
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
 | 
			
		||||
    /* Enough data */
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, g_memdup(in4, sizeof(in4)),
 | 
			
		||||
        sizeof(in4), NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in4));
 | 
			
		||||
    g_assert(gbinder_reader_read_uint16(&reader, &out1));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert_cmpuint(in, == ,out1);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in4));
 | 
			
		||||
    g_assert(gbinder_reader_read_int16(&reader, &out2));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert_cmpint(in, == ,out2);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(in4));
 | 
			
		||||
    g_assert(gbinder_reader_read_int16(&reader, NULL));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * int32
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -648,7 +769,7 @@ test_hidl_struct(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlStruct* test = test_data;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(test->in, test->in_size), test->in_size, NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -852,7 +973,7 @@ test_hidl_vec(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlVec* test = test_data;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(test->in, test->in_size), test->in_size, NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -958,7 +1079,7 @@ test_hidl_string_err(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlStringErr* test = test_data;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(test->in, test->in_size), test->in_size, NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -992,7 +1113,7 @@ test_hidl_string_err_skip(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlStringErr* test = test_data;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(test->in, test->in_size), test->in_size, NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -1037,7 +1158,7 @@ test_fd_ok(
 | 
			
		||||
        TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -1077,7 +1198,7 @@ test_fd_shortbuf(
 | 
			
		||||
        TEST_INT32_BYTES(BINDER_TYPE_FD),
 | 
			
		||||
        TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -1111,7 +1232,7 @@ test_fd_badtype(
 | 
			
		||||
        TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -1154,7 +1275,7 @@ test_dupfd_ok(
 | 
			
		||||
        TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -1201,7 +1322,7 @@ test_dupfd_badtype(
 | 
			
		||||
        TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -1244,7 +1365,7 @@ test_dupfd_badfd(
 | 
			
		||||
        TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -1283,7 +1404,7 @@ test_hidl_string(
 | 
			
		||||
    guint bufcount,
 | 
			
		||||
    const char* result)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver, g_memdup(input, size),
 | 
			
		||||
        size, NULL);
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
@@ -1554,7 +1675,7 @@ test_buffer(
 | 
			
		||||
        TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(0), TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
@@ -1588,6 +1709,98 @@ test_buffer(
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * parcelable
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_parcelable(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const guint8 input_null_header[] = {
 | 
			
		||||
        TEST_INT32_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    const guint8 input_broken_header[] = {
 | 
			
		||||
        TEST_INT32_BYTES(1),
 | 
			
		||||
        TEST_INT32_BYTES(1)
 | 
			
		||||
    };
 | 
			
		||||
    const guint8 input_non_null_header[] = {
 | 
			
		||||
        TEST_INT32_BYTES(1),
 | 
			
		||||
        /* Size must be size of itself + payload */
 | 
			
		||||
        TEST_INT32_BYTES(sizeof(gint32) * 3)
 | 
			
		||||
    };
 | 
			
		||||
    const guint8 input_non_null_payload[] = {
 | 
			
		||||
        TEST_INT32_BYTES(10),
 | 
			
		||||
        TEST_INT32_BYTES(20)
 | 
			
		||||
    };
 | 
			
		||||
    gpointer in;
 | 
			
		||||
    gsize in_size, out_size;
 | 
			
		||||
    const void* out = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
    g_assert(driver);
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
 | 
			
		||||
    /* Missing payload */
 | 
			
		||||
    test_init_reader(driver, &data, &reader,
 | 
			
		||||
        TEST_ARRAY_AND_SIZE(input_non_null_header));
 | 
			
		||||
    out = gbinder_reader_read_parcelable(&reader, &out_size);
 | 
			
		||||
    g_assert(!out);
 | 
			
		||||
    g_assert_cmpuint(out_size, == ,0);
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
 | 
			
		||||
    /* Broken headers */
 | 
			
		||||
    test_init_reader(driver, &data, &reader, input_broken_header, 4);
 | 
			
		||||
    out = gbinder_reader_read_parcelable(&reader, &out_size);
 | 
			
		||||
    g_assert(!out);
 | 
			
		||||
    g_assert_cmpuint(out_size, == ,0);
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
 | 
			
		||||
    test_init_reader(driver, &data, &reader,
 | 
			
		||||
        TEST_ARRAY_AND_SIZE(input_broken_header));
 | 
			
		||||
    out = gbinder_reader_read_parcelable(&reader, &out_size);
 | 
			
		||||
    g_assert(!out);
 | 
			
		||||
    g_assert_cmpuint(out_size, == ,0);
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
 | 
			
		||||
    /* Null */
 | 
			
		||||
    test_init_reader(driver, &data, &reader,
 | 
			
		||||
        TEST_ARRAY_AND_SIZE(input_null_header));
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(input_null_header));
 | 
			
		||||
    out = gbinder_reader_read_parcelable(&reader, &out_size);
 | 
			
		||||
    g_assert(!out);
 | 
			
		||||
    g_assert_cmpuint(out_size, == ,0);
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
 | 
			
		||||
    /* Non-null */
 | 
			
		||||
    in_size = sizeof(input_non_null_header) + sizeof(input_non_null_payload);
 | 
			
		||||
    in = g_malloc(in_size);
 | 
			
		||||
    memcpy(in, &input_non_null_header, sizeof(input_non_null_header));
 | 
			
		||||
    memcpy(in + sizeof(input_non_null_header), &input_non_null_payload,
 | 
			
		||||
        sizeof(input_non_null_payload));
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, in, in_size, NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, in_size);
 | 
			
		||||
    out = gbinder_reader_read_parcelable(&reader, &out_size);
 | 
			
		||||
    g_assert(memcmp(&input_non_null_payload, out,
 | 
			
		||||
        sizeof(input_non_null_payload)) == 0);
 | 
			
		||||
    g_assert_cmpuint(out_size, == ,sizeof(input_non_null_payload));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
 | 
			
		||||
    /* And verify NULL tolerance for the size parameter */
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, in_size);
 | 
			
		||||
    out = gbinder_reader_read_parcelable(&reader, NULL);
 | 
			
		||||
    g_assert(memcmp(&input_non_null_payload, out,
 | 
			
		||||
        sizeof(input_non_null_payload)) == 0);
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * object
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -1602,7 +1815,7 @@ test_object(
 | 
			
		||||
        TEST_INT32_BYTES(BINDER_TYPE_HANDLE), TEST_INT32_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(1 /* handle*/), TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
@@ -1660,7 +1873,7 @@ test_object_invalid(
 | 
			
		||||
        TEST_INT32_BYTES(42 /* invalid type */), TEST_INT32_BYTES(0),
 | 
			
		||||
        TEST_INT64_BYTES(1 /* handle*/), TEST_INT64_BYTES(0)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
 | 
			
		||||
        g_memdup(input, sizeof(input)), sizeof(input), NULL);
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
@@ -1694,7 +1907,7 @@ test_vec(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    /* Using 64-bit I/O */
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    BinderObject64 obj;
 | 
			
		||||
@@ -1747,7 +1960,7 @@ test_hidl_string_vec(
 | 
			
		||||
    gsize size,
 | 
			
		||||
    const char* const* result)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(ipc->driver, g_memdup(input, size),
 | 
			
		||||
        size, NULL);
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
@@ -2199,6 +2412,8 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_("empty"), test_empty);
 | 
			
		||||
    g_test_add_func(TEST_("byte"), test_byte);
 | 
			
		||||
    g_test_add_func(TEST_("bool"), test_bool);
 | 
			
		||||
    g_test_add_func(TEST_("int8"), test_int8);
 | 
			
		||||
    g_test_add_func(TEST_("int16"), test_int16);
 | 
			
		||||
    g_test_add_func(TEST_("int32"), test_int32);
 | 
			
		||||
    g_test_add_func(TEST_("int64"), test_int64);
 | 
			
		||||
    g_test_add_func(TEST_("float"), test_float);
 | 
			
		||||
@@ -2267,6 +2482,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_("hidl_string/6"), test_hidl_string6);
 | 
			
		||||
    g_test_add_func(TEST_("hidl_string/7"), test_hidl_string7);
 | 
			
		||||
    g_test_add_func(TEST_("buffer"), test_buffer);
 | 
			
		||||
    g_test_add_func(TEST_("parcelable"), test_parcelable);
 | 
			
		||||
    g_test_add_func(TEST_("object/valid"), test_object);
 | 
			
		||||
    g_test_add_func(TEST_("object/invalid"), test_object_invalid);
 | 
			
		||||
    g_test_add_func(TEST_("object/no_reg"), test_object_no_reg);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -68,7 +68,7 @@ void
 | 
			
		||||
test_basic(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    GBinderRemoteObject* obj1 = gbinder_object_registry_get_remote(reg,1,TRUE);
 | 
			
		||||
    GBinderRemoteObject* obj2 = gbinder_object_registry_get_remote(reg,2,TRUE);
 | 
			
		||||
@@ -112,7 +112,7 @@ test_dead_run(
 | 
			
		||||
{
 | 
			
		||||
    const guint h = 1;
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, h, TRUE);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_config.h"
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_reader.h"
 | 
			
		||||
#include "gbinder_remote_request_p.h"
 | 
			
		||||
@@ -369,6 +370,18 @@ test_to_local(
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    const char* default_config_dir;
 | 
			
		||||
    const char* default_config_file;
 | 
			
		||||
    char* conf_dir = g_dir_make_tmp("gbinder-test-remote-request-XXXXXX", NULL);
 | 
			
		||||
    char* conf_file = g_build_filename(conf_dir, "test.conf", NULL);
 | 
			
		||||
    int result;
 | 
			
		||||
 | 
			
		||||
    /* Point gbinder_config_file to a non-existent file */
 | 
			
		||||
    default_config_dir = gbinder_config_dir;
 | 
			
		||||
    default_config_file = gbinder_config_file;
 | 
			
		||||
    gbinder_config_dir = conf_dir;
 | 
			
		||||
    gbinder_config_file = conf_file;
 | 
			
		||||
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "null", test_null);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "basic", test_basic);
 | 
			
		||||
@@ -378,7 +391,14 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "string16", test_string16);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "to_local", test_to_local);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
    result = g_test_run();
 | 
			
		||||
 | 
			
		||||
    gbinder_config_dir = default_config_dir;
 | 
			
		||||
    gbinder_config_file = default_config_file;
 | 
			
		||||
    remove(conf_dir);
 | 
			
		||||
    g_free(conf_dir);
 | 
			
		||||
    g_free(conf_file);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -399,6 +399,14 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    /* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -409,7 +417,7 @@ test_null(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    g_assert(!gbinder_servicemanager_new(NULL));
 | 
			
		||||
    g_assert(!gbinder_servicemanager_new_with_type(0, NULL));
 | 
			
		||||
    g_assert(!gbinder_servicemanager_new_with_type(0, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_servicemanager_new_local_object(NULL, NULL, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_servicemanager_ref(NULL));
 | 
			
		||||
    g_assert(!gbinder_servicemanager_device(NULL));
 | 
			
		||||
@@ -442,14 +450,15 @@ test_invalid(
 | 
			
		||||
{
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    gulong id = 0;
 | 
			
		||||
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    g_assert(!gbinder_servicemanager_new2(GBINDER_DEFAULT_HWBINDER, "a", NULL));
 | 
			
		||||
    sm = gbinder_servicemanager_new(dev);
 | 
			
		||||
    g_assert(!gbinder_servicemanager_new_with_type(GBINDER_TYPE_LOCAL_OBJECT,
 | 
			
		||||
        NULL));
 | 
			
		||||
        NULL, NULL));
 | 
			
		||||
    g_assert(TEST_IS_HWSERVICEMANAGER(sm));
 | 
			
		||||
    g_assert(!gbinder_servicemanager_list(sm, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_servicemanager_get_service(sm, "foo", NULL, NULL));
 | 
			
		||||
@@ -487,7 +496,7 @@ test_basic(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    GBinderLocalObject* obj;
 | 
			
		||||
 | 
			
		||||
@@ -518,7 +527,7 @@ test_legacy(
 | 
			
		||||
{
 | 
			
		||||
    const char* otherdev = "/dev/otherbinder";
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
 | 
			
		||||
    /* Reset the state */
 | 
			
		||||
@@ -539,7 +548,7 @@ test_legacy(
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
 | 
			
		||||
    /* Legacy default */
 | 
			
		||||
    ipc = gbinder_ipc_new(otherdev);
 | 
			
		||||
    ipc = gbinder_ipc_new(otherdev, NULL);
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    sm = gbinder_servicemanager_new(otherdev);
 | 
			
		||||
    g_assert(TEST_IS_DEFSERVICEMANAGER(sm));
 | 
			
		||||
@@ -582,7 +591,7 @@ test_config(
 | 
			
		||||
    gbinder_config_file = file;
 | 
			
		||||
 | 
			
		||||
    /* Unknown device instantiates the default */
 | 
			
		||||
    ipc = gbinder_ipc_new(strange_name);
 | 
			
		||||
    ipc = gbinder_ipc_new(strange_name, NULL);
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    sm = gbinder_servicemanager_new(strange_name);
 | 
			
		||||
    g_assert(TEST_IS_HWSERVICEMANAGER(sm));
 | 
			
		||||
@@ -590,7 +599,7 @@ test_config(
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
 | 
			
		||||
    /* This one was redefined */
 | 
			
		||||
    ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    sm = gbinder_servicemanager_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    g_assert(TEST_IS_HWSERVICEMANAGER(sm));
 | 
			
		||||
@@ -598,7 +607,7 @@ test_config(
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
 | 
			
		||||
    /* This one was not (since name was invalid) */
 | 
			
		||||
    ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    sm = gbinder_servicemanager_new(GBINDER_DEFAULT_HWBINDER);
 | 
			
		||||
    g_assert(TEST_IS_HWSERVICEMANAGER(sm));
 | 
			
		||||
@@ -606,13 +615,21 @@ test_config(
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
 | 
			
		||||
    /* This one points to legacy manager */
 | 
			
		||||
    ipc = gbinder_ipc_new(legacy_name);
 | 
			
		||||
    ipc = gbinder_ipc_new(legacy_name, NULL);
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    sm = gbinder_servicemanager_new(legacy_name);
 | 
			
		||||
    g_assert(TEST_IS_DEFSERVICEMANAGER(sm));
 | 
			
		||||
    gbinder_servicemanager_unref(sm);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
 | 
			
		||||
    /* Overwrite the legacy manager with "hidl" */
 | 
			
		||||
    ipc = gbinder_ipc_new(legacy_name, "hidl");
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    sm = gbinder_servicemanager_new2(legacy_name, "hidl", "hidl");
 | 
			
		||||
    g_assert(TEST_IS_HWSERVICEMANAGER(sm));
 | 
			
		||||
    gbinder_servicemanager_unref(sm);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
 | 
			
		||||
    /* Clear the state */
 | 
			
		||||
    gbinder_servicemanager_exit();
 | 
			
		||||
    gbinder_config_exit();
 | 
			
		||||
@@ -634,7 +651,7 @@ test_not_present(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
 | 
			
		||||
@@ -659,7 +676,7 @@ test_wait(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    const glong forever = (test_opt.flags & TEST_FLAG_DEBUG) ?
 | 
			
		||||
        (TEST_TIMEOUT_SEC * 1000) : -1;
 | 
			
		||||
@@ -710,7 +727,7 @@ test_wait_long(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    gulong id;
 | 
			
		||||
@@ -756,7 +773,7 @@ test_wait_async(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
@@ -800,7 +817,7 @@ void
 | 
			
		||||
test_death_run()
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
@@ -877,7 +894,7 @@ test_reanimate(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
@@ -932,9 +949,9 @@ test_reuse(
 | 
			
		||||
    const char* binder_dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    const char* vndbinder_dev = "/dev/vpnbinder";
 | 
			
		||||
    const char* hwbinder_dev = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    GBinderIpc* binder_ipc = gbinder_ipc_new(binder_dev);
 | 
			
		||||
    GBinderIpc* vndbinder_ipc = gbinder_ipc_new(vndbinder_dev);
 | 
			
		||||
    GBinderIpc* hwbinder_ipc = gbinder_ipc_new(hwbinder_dev);
 | 
			
		||||
    GBinderIpc* binder_ipc = gbinder_ipc_new(binder_dev, NULL);
 | 
			
		||||
    GBinderIpc* vndbinder_ipc = gbinder_ipc_new(vndbinder_dev, NULL);
 | 
			
		||||
    GBinderIpc* hwbinder_ipc = gbinder_ipc_new(hwbinder_dev, NULL);
 | 
			
		||||
    GBinderServiceManager* m1;
 | 
			
		||||
    GBinderServiceManager* m2;
 | 
			
		||||
    GBinderServiceManager* vnd1;
 | 
			
		||||
@@ -987,7 +1004,7 @@ test_notify_type(
 | 
			
		||||
    GType t,
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    TestHwServiceManager* test;
 | 
			
		||||
    const char* name = "foo";
 | 
			
		||||
@@ -995,7 +1012,7 @@ test_notify_type(
 | 
			
		||||
    gulong id1, id2;
 | 
			
		||||
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
    sm = gbinder_servicemanager_new_with_type(t, NULL);
 | 
			
		||||
    sm = gbinder_servicemanager_new_with_type(t, NULL, NULL);
 | 
			
		||||
    test = TEST_SERVICEMANAGER2(sm, t);
 | 
			
		||||
    id1 = gbinder_servicemanager_add_registration_handler(sm, name,
 | 
			
		||||
        test_registration_func_inc, &count);
 | 
			
		||||
@@ -1055,7 +1072,7 @@ test_list(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    TestHwServiceManager* test;
 | 
			
		||||
@@ -1104,7 +1121,7 @@ test_get(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    TestHwServiceManager* test;
 | 
			
		||||
@@ -1166,7 +1183,7 @@ test_add(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    TestHwServiceManager* test;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2020-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -71,6 +71,14 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    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
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -182,7 +190,7 @@ servicemanager_aidl_new(
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl* self = g_object_new(SERVICE_MANAGER_AIDL_TYPE, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
 | 
			
		||||
    self->handle_on_looper_thread = handle_on_looper_thread;
 | 
			
		||||
@@ -322,7 +330,7 @@ test_get_run()
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
@@ -404,7 +412,7 @@ test_list_run()
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
@@ -483,7 +491,7 @@ test_notify_run()
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    ServiceManagerAidl* svc = servicemanager_aidl_new(other_dev, FALSE);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
@@ -540,7 +548,7 @@ test_notify2_run()
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, TRUE);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2020-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -175,7 +175,7 @@ servicemanager_aidl2_new(
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl2* self = g_object_new(SERVICE_MANAGER_AIDL2_TYPE, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
 | 
			
		||||
    self->handle_on_looper_thread = handle_on_looper_thread;
 | 
			
		||||
@@ -305,7 +305,7 @@ test_context_init(
 | 
			
		||||
    gbinder_config_dir = test->config_subdir; /* Doesn't exist */
 | 
			
		||||
    gbinder_config_file = test->config_file;
 | 
			
		||||
 | 
			
		||||
    ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    test->fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2020-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -193,7 +193,7 @@ servicemanager_aidl3_new(
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl3* self = g_object_new(SERVICE_MANAGER_AIDL3_TYPE, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
 | 
			
		||||
    self->handle_on_looper_thread = handle_on_looper_thread;
 | 
			
		||||
@@ -323,7 +323,7 @@ test_context_init(
 | 
			
		||||
    gbinder_config_dir = test->config_subdir; /* Doesn't exist */
 | 
			
		||||
    gbinder_config_file = test->config_file;
 | 
			
		||||
 | 
			
		||||
    ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    test->fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								unit/unit_servicemanager_aidl4/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_servicemanager_aidl4/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_servicemanager_aidl4
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										488
									
								
								unit/unit_servicemanager_aidl4/unit_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										488
									
								
								unit/unit_servicemanager_aidl4/unit_servicemanager_aidl4.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,488 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2020-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_binder.h"
 | 
			
		||||
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_config.h"
 | 
			
		||||
#include "gbinder_ipc.h"
 | 
			
		||||
#include "gbinder_reader.h"
 | 
			
		||||
#include "gbinder_servicemanager_p.h"
 | 
			
		||||
#include "gbinder_rpc_protocol.h"
 | 
			
		||||
#include "gbinder_local_object_p.h"
 | 
			
		||||
#include "gbinder_local_reply.h"
 | 
			
		||||
#include "gbinder_remote_request.h"
 | 
			
		||||
#include "gbinder_remote_object.h"
 | 
			
		||||
#include "gbinder_writer.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_strv.h>
 | 
			
		||||
#include <gutil_log.h>
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
static const char TMP_DIR_TEMPLATE[] =
 | 
			
		||||
    "gbinder-test-servicemanager_aidl4-XXXXXX";
 | 
			
		||||
 | 
			
		||||
enum gbinder_stability_level {
 | 
			
		||||
    UNDECLARED = 0,
 | 
			
		||||
    VENDOR = 0b000011,
 | 
			
		||||
    SYSTEM = 0b001100,
 | 
			
		||||
    VINTF = 0b111111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_hidl_get_type()
 | 
			
		||||
{
 | 
			
		||||
    /* Dummy function to avoid pulling in gbinder_servicemanager_hidl */
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Test service manager
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define SVCMGR_HANDLE (0)
 | 
			
		||||
static const char SVCMGR_IFACE[] = "android.os.IServiceManager";
 | 
			
		||||
enum servicemanager_aidl_tx {
 | 
			
		||||
    GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
 | 
			
		||||
    CHECK_SERVICE_TRANSACTION,
 | 
			
		||||
    ADD_SERVICE_TRANSACTION,
 | 
			
		||||
    LIST_SERVICES_TRANSACTION
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char* const servicemanager_aidl_ifaces[] = { SVCMGR_IFACE, NULL };
 | 
			
		||||
 | 
			
		||||
typedef GBinderLocalObjectClass ServiceManagerAidl4Class;
 | 
			
		||||
typedef struct service_manager_aidl4 {
 | 
			
		||||
    GBinderLocalObject parent;
 | 
			
		||||
    GHashTable* objects;
 | 
			
		||||
    gboolean handle_on_looper_thread;
 | 
			
		||||
} ServiceManagerAidl4;
 | 
			
		||||
 | 
			
		||||
#define SERVICE_MANAGER_AIDL4_TYPE (service_manager_aidl4_get_type())
 | 
			
		||||
#define SERVICE_MANAGER_AIDL4(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
			
		||||
        SERVICE_MANAGER_AIDL4_TYPE, ServiceManagerAidl4))
 | 
			
		||||
G_DEFINE_TYPE(ServiceManagerAidl4, service_manager_aidl4, \
 | 
			
		||||
        GBINDER_TYPE_LOCAL_OBJECT)
 | 
			
		||||
 | 
			
		||||
/* This is the format of stability passed on the wire. */
 | 
			
		||||
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,
 | 
			
		||||
    GBinderRemoteRequest* req,
 | 
			
		||||
    guint code,
 | 
			
		||||
    guint flags,
 | 
			
		||||
    int* status,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl4* self = user_data;
 | 
			
		||||
    GBinderLocalReply* reply = NULL;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderRemoteObject* remote_obj;
 | 
			
		||||
    guint32 allow_isolated, dumpsys_priority;
 | 
			
		||||
    char* str;
 | 
			
		||||
    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;
 | 
			
		||||
    switch (code) {
 | 
			
		||||
    case GET_SERVICE_TRANSACTION:
 | 
			
		||||
    case CHECK_SERVICE_TRANSACTION:
 | 
			
		||||
        gbinder_remote_request_init_reader(req, &reader);
 | 
			
		||||
        str = gbinder_reader_read_string16(&reader);
 | 
			
		||||
        if (str) {
 | 
			
		||||
            reply = gbinder_local_object_new_reply(obj);
 | 
			
		||||
            remote_obj = g_hash_table_lookup(self->objects, str);
 | 
			
		||||
            if (remote_obj) {
 | 
			
		||||
                GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
                GDEBUG("Found name '%s' => %p", str, remote_obj);
 | 
			
		||||
                gbinder_local_reply_init_writer(reply, &writer);
 | 
			
		||||
                gbinder_writer_append_int32(&writer, UNDECLARED);
 | 
			
		||||
                gbinder_writer_append_remote_object(&writer, remote_obj);
 | 
			
		||||
            } else {
 | 
			
		||||
                GDEBUG("Name '%s' not found", str);
 | 
			
		||||
                gbinder_local_reply_append_int32(reply, GBINDER_STATUS_OK);
 | 
			
		||||
            }
 | 
			
		||||
            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 == SYSTEM &&
 | 
			
		||||
            category.version == 1 &&
 | 
			
		||||
            gbinder_reader_read_uint32(&reader, &allow_isolated) &&
 | 
			
		||||
            gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
 | 
			
		||||
            GDEBUG("Adding '%s'", str);
 | 
			
		||||
            g_hash_table_replace(self->objects, str, remote_obj);
 | 
			
		||||
            remote_obj = NULL;
 | 
			
		||||
            str = NULL;
 | 
			
		||||
            reply = gbinder_local_object_new_reply(obj);
 | 
			
		||||
            *status = GBINDER_STATUS_OK;
 | 
			
		||||
        }
 | 
			
		||||
        g_free(str);
 | 
			
		||||
        gbinder_remote_object_unref(remote_obj);
 | 
			
		||||
        break;
 | 
			
		||||
    case LIST_SERVICES_TRANSACTION:
 | 
			
		||||
        gbinder_remote_request_init_reader(req, &reader);
 | 
			
		||||
        if (gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
 | 
			
		||||
            if (g_hash_table_size(self->objects) == 1) {
 | 
			
		||||
                GList* keys = g_hash_table_get_keys(self->objects);
 | 
			
		||||
                GList* l = g_list_nth(keys, 0);
 | 
			
		||||
                gint32 srv_size = 1;
 | 
			
		||||
                GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
                reply = gbinder_local_object_new_reply(obj);
 | 
			
		||||
                gbinder_local_reply_init_writer(reply, &writer);
 | 
			
		||||
                gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
 | 
			
		||||
                gbinder_writer_append_int32(&writer, srv_size);
 | 
			
		||||
                gbinder_writer_append_string16(&writer, l->data);
 | 
			
		||||
                g_list_free(keys);
 | 
			
		||||
                *status = GBINDER_STATUS_OK;
 | 
			
		||||
            } else {
 | 
			
		||||
                GDEBUG("Incorrect number of services %u",
 | 
			
		||||
                    g_hash_table_size(self->objects));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        GDEBUG("Unhandled command %u", code);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return reply;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
ServiceManagerAidl4*
 | 
			
		||||
servicemanager_aidl4_new(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    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,
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
service_manager_aidl4_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(object);
 | 
			
		||||
 | 
			
		||||
    g_hash_table_destroy(self->objects);
 | 
			
		||||
    G_OBJECT_CLASS(service_manager_aidl4_parent_class)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
service_manager_aidl4_init(
 | 
			
		||||
    ServiceManagerAidl4* self)
 | 
			
		||||
{
 | 
			
		||||
    self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
 | 
			
		||||
        (GDestroyNotify) gbinder_remote_object_unref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
service_manager_aidl4_class_init(
 | 
			
		||||
    ServiceManagerAidl4Class* klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass* object = G_OBJECT_CLASS(klass);
 | 
			
		||||
    GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Test context
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_context {
 | 
			
		||||
    const char* default_config_dir;
 | 
			
		||||
    const char* default_config_file;
 | 
			
		||||
    char* config_dir;
 | 
			
		||||
    char* config_subdir;
 | 
			
		||||
    char* config_file;
 | 
			
		||||
    GBinderLocalObject* object;
 | 
			
		||||
    ServiceManagerAidl4* service;
 | 
			
		||||
    GBinderServiceManager* client;
 | 
			
		||||
    int fd;
 | 
			
		||||
} TestContext;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
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"
 | 
			
		||||
        "/dev/binder = aidl3\n"
 | 
			
		||||
        "[ServiceManager]\n"
 | 
			
		||||
        "Default = aidl4\n"
 | 
			
		||||
        "/dev/binder = aidl4\n";
 | 
			
		||||
    GBinderIpc* ipc;
 | 
			
		||||
 | 
			
		||||
    memset(test, 0, sizeof(*test));
 | 
			
		||||
    test->default_config_dir = gbinder_config_dir;
 | 
			
		||||
    test->default_config_file = gbinder_config_file;
 | 
			
		||||
    test->config_dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
 | 
			
		||||
    test->config_subdir = g_build_filename(test->config_dir, "d", NULL);
 | 
			
		||||
    test->config_file = g_build_filename(test->config_dir, "test.conf", NULL);
 | 
			
		||||
    g_assert(g_file_set_contents(test->config_file, config, -1, NULL));
 | 
			
		||||
    GDEBUG("Config file %s", test->config_file);
 | 
			
		||||
    gbinder_config_dir = test->config_subdir; /* Doesn't exist */
 | 
			
		||||
    gbinder_config_file = test->config_file;
 | 
			
		||||
 | 
			
		||||
    ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    test->fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    /* 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->client = gbinder_servicemanager_new(dev);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_context_deinit(
 | 
			
		||||
    TestContext* test)
 | 
			
		||||
{
 | 
			
		||||
    test_binder_unregister_objects(test->fd);
 | 
			
		||||
    gbinder_local_object_unref(test->object);
 | 
			
		||||
    gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
 | 
			
		||||
    gbinder_servicemanager_unref(test->client);
 | 
			
		||||
    gbinder_ipc_exit();
 | 
			
		||||
    test_binder_exit_wait(&test_opt, NULL);
 | 
			
		||||
    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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * get
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_get_run()
 | 
			
		||||
{
 | 
			
		||||
    TestContext test;
 | 
			
		||||
    const char* name = "name";
 | 
			
		||||
    int status = -1;
 | 
			
		||||
 | 
			
		||||
    test_context_init(&test);
 | 
			
		||||
 | 
			
		||||
    /* Query the object (it's not there yet) */
 | 
			
		||||
    GDEBUG("Querying '%s'", name);
 | 
			
		||||
    g_assert(!gbinder_servicemanager_get_service_sync(test.client,
 | 
			
		||||
        name, &status));
 | 
			
		||||
    g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    /* Register object */
 | 
			
		||||
    GDEBUG("Registering object '%s' => %p", name, test.object);
 | 
			
		||||
    g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
 | 
			
		||||
        name, test.object), == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
 | 
			
		||||
    g_assert(g_hash_table_contains(test.service->objects, name));
 | 
			
		||||
 | 
			
		||||
    /* Query the object (this time it must be there) */
 | 
			
		||||
    GDEBUG("Querying '%s' again", name);
 | 
			
		||||
    g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
 | 
			
		||||
        &status));
 | 
			
		||||
    g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    test_context_deinit(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_get()
 | 
			
		||||
{
 | 
			
		||||
    test_run_in_context(&test_opt, test_get_run);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * list
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_list_run()
 | 
			
		||||
{
 | 
			
		||||
    TestContext test;
 | 
			
		||||
    const char* name = "name";
 | 
			
		||||
    char** list;
 | 
			
		||||
 | 
			
		||||
    test_context_init(&test);
 | 
			
		||||
 | 
			
		||||
    /* Request the list */
 | 
			
		||||
    list = gbinder_servicemanager_list_sync(test.client);
 | 
			
		||||
 | 
			
		||||
    /* There's nothing there yet */
 | 
			
		||||
    g_assert(list);
 | 
			
		||||
    g_assert(!list[0]);
 | 
			
		||||
    g_strfreev(list);
 | 
			
		||||
 | 
			
		||||
    /* Register object */
 | 
			
		||||
    GDEBUG("Registering object '%s' => %p", name, test.object);
 | 
			
		||||
    g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
 | 
			
		||||
        name, test.object), == ,GBINDER_STATUS_OK);
 | 
			
		||||
 | 
			
		||||
    /* Request the list again */
 | 
			
		||||
    list = gbinder_servicemanager_list_sync(test.client);
 | 
			
		||||
 | 
			
		||||
    /* Now the name must be there */
 | 
			
		||||
    g_assert_cmpuint(gutil_strv_length(list), == ,1);
 | 
			
		||||
    g_assert_cmpstr(list[0], == ,name);
 | 
			
		||||
    g_strfreev(list);
 | 
			
		||||
 | 
			
		||||
    test_context_deinit(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_list()
 | 
			
		||||
{
 | 
			
		||||
    test_run_in_context(&test_opt, test_list_run);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define TEST_(t) "/servicemanager_aidl4/" t
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
 | 
			
		||||
    g_type_init();
 | 
			
		||||
    G_GNUC_END_IGNORE_DEPRECATIONS;
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("get"), test_get);
 | 
			
		||||
    g_test_add_func(TEST_("list"), test_list);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -82,6 +82,14 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    /* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -122,7 +130,7 @@ TestServiceManagerHidl*
 | 
			
		||||
test_servicemanager_impl_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    TestServiceManagerHidl* sm = test_servicemanager_hidl_new(ipc);
 | 
			
		||||
 | 
			
		||||
@@ -191,7 +199,7 @@ test_get_run()
 | 
			
		||||
    const char* name = "android.hidl.base@1.0::IBase/test";
 | 
			
		||||
 | 
			
		||||
    test_config_init(&config, NULL);
 | 
			
		||||
    ipc = gbinder_ipc_new(MAIN_DEV);
 | 
			
		||||
    ipc = gbinder_ipc_new(MAIN_DEV, NULL);
 | 
			
		||||
    smsvc = test_servicemanager_impl_new(OTHER_DEV);
 | 
			
		||||
    obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
@@ -286,7 +294,7 @@ test_list_run()
 | 
			
		||||
    test.loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
    test_config_init(&config, NULL);
 | 
			
		||||
    ipc = gbinder_ipc_new(MAIN_DEV);
 | 
			
		||||
    ipc = gbinder_ipc_new(MAIN_DEV, NULL);
 | 
			
		||||
    smsvc = test_servicemanager_impl_new(OTHER_DEV);
 | 
			
		||||
    obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
@@ -414,7 +422,7 @@ test_notify_run()
 | 
			
		||||
    test.loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
    test_config_init(&config, NULL);
 | 
			
		||||
    ipc = gbinder_ipc_new(MAIN_DEV);
 | 
			
		||||
    ipc = gbinder_ipc_new(MAIN_DEV, NULL);
 | 
			
		||||
    test.smsvc = test_servicemanager_impl_new(OTHER_DEV);
 | 
			
		||||
    obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
 | 
			
		||||
    fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2019-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2019-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2019-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -240,6 +240,12 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_hidl_get_type()
 | 
			
		||||
{
 | 
			
		||||
@@ -256,7 +262,7 @@ test_null(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
 | 
			
		||||
    test_setup_ping(ipc);
 | 
			
		||||
@@ -283,7 +289,7 @@ test_basic(
 | 
			
		||||
    const char* obj_name = "test";
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    const char* const ifaces[] = { "interface", NULL };
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderLocalObject* obj;
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
@@ -321,7 +327,7 @@ test_present(
 | 
			
		||||
    const char* obj_name = "test";
 | 
			
		||||
    const char* const ifaces[] = { "interface", NULL };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderLocalObject* obj;
 | 
			
		||||
@@ -382,7 +388,7 @@ test_not_present(
 | 
			
		||||
    const char* obj_name = "test";
 | 
			
		||||
    const char* const ifaces[] = { "interface", NULL };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderLocalObject* obj;
 | 
			
		||||
@@ -427,7 +433,7 @@ test_retry(
 | 
			
		||||
    const char* obj_name = "test";
 | 
			
		||||
    const char* const ifaces[] = { "interface", NULL };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    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;
 | 
			
		||||
@@ -470,7 +476,7 @@ test_cancel(
 | 
			
		||||
    const char* obj_name = "test";
 | 
			
		||||
    const char* const ifaces[] = { "interface", NULL };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(ipc->driver);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderLocalObject* obj;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -206,6 +206,12 @@ gbinder_servicemanager_aidl3_get_type()
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_aidl4_get_type()
 | 
			
		||||
{
 | 
			
		||||
    return TEST_TYPE_SERVICEMANAGER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gbinder_servicemanager_hidl_get_type()
 | 
			
		||||
{
 | 
			
		||||
@@ -239,7 +245,7 @@ test_basic(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GBinderServicePoll* weakptr = NULL;
 | 
			
		||||
    GBinderServiceManager* manager;
 | 
			
		||||
    GBinderServicePoll* poll;
 | 
			
		||||
@@ -315,7 +321,7 @@ test_notify1(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServicePoll* weakptr = NULL;
 | 
			
		||||
    GBinderServiceManager* manager;
 | 
			
		||||
@@ -389,7 +395,7 @@ test_notify2(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServicePoll* weakptr = NULL;
 | 
			
		||||
    GBinderServiceManager* manager;
 | 
			
		||||
@@ -448,7 +454,7 @@ test_already_there(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    GBinderServicePoll* weakptr = NULL;
 | 
			
		||||
    GBinderServiceManager* manager;
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,10 @@ test_null(
 | 
			
		||||
    gsize size = 1;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_init_writer(NULL, &writer);
 | 
			
		||||
    gbinder_writer_append_int8(NULL, 0);
 | 
			
		||||
    gbinder_writer_append_int8(&writer, 0);
 | 
			
		||||
    gbinder_writer_append_int16(NULL, 0);
 | 
			
		||||
    gbinder_writer_append_int16(&writer, 0);
 | 
			
		||||
    gbinder_writer_append_int32(NULL, 0);
 | 
			
		||||
    gbinder_writer_append_int32(&writer, 0);
 | 
			
		||||
    gbinder_writer_append_int64(NULL, 0);
 | 
			
		||||
@@ -96,6 +100,7 @@ test_null(
 | 
			
		||||
    gbinder_writer_append_buffer_object(&writer, NULL, 0);
 | 
			
		||||
    gbinder_writer_append_buffer_object_with_parent(NULL, NULL, 0, NULL);
 | 
			
		||||
    gbinder_writer_append_buffer_object_with_parent(&writer, NULL, 0, NULL);
 | 
			
		||||
    gbinder_writer_append_parcelable(NULL, NULL, 0);
 | 
			
		||||
    gbinder_writer_append_local_object(NULL, NULL);
 | 
			
		||||
    gbinder_writer_append_local_object(&writer, NULL);
 | 
			
		||||
    gbinder_writer_append_remote_object(NULL, NULL);
 | 
			
		||||
@@ -164,6 +169,60 @@ test_cleanup(
 | 
			
		||||
    g_assert_cmpint(cleanup_count, == ,2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * int8
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_int8(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char encoded[] = {
 | 
			
		||||
        TEST_INT8_BYTES_4(0x80)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_int8(&writer, 0x80);
 | 
			
		||||
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert_cmpuint(data->bytes->len, == ,sizeof(encoded));
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data, encoded, data->bytes->len));
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * int16
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_int16(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char encoded[] = {
 | 
			
		||||
        TEST_INT16_BYTES_4(0x80ff)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_int16(&writer, 0x80ff);
 | 
			
		||||
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert_cmpuint(data->bytes->len, == ,sizeof(encoded));
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data, encoded, data->bytes->len));
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * int32
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -283,9 +342,9 @@ test_bool(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char encoded[] = {
 | 
			
		||||
        0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
        0x01, 0x00, 0x00, 0x00,
 | 
			
		||||
        0x01, 0x00, 0x00, 0x00
 | 
			
		||||
        TEST_INT8_BYTES_4(0),
 | 
			
		||||
        TEST_INT8_BYTES_4(1),
 | 
			
		||||
        TEST_INT8_BYTES_4(1)
 | 
			
		||||
    };
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
@@ -804,6 +863,53 @@ test_parent(
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * parcelable
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_parcelable(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const guint8 encoded_non_null[] = {
 | 
			
		||||
        TEST_INT32_BYTES(1),
 | 
			
		||||
        TEST_INT32_BYTES(sizeof(TestData) + sizeof(gint32)),
 | 
			
		||||
        TEST_INT32_BYTES(10)
 | 
			
		||||
    };
 | 
			
		||||
    const gint32 test_null_value = 0;
 | 
			
		||||
    GBinderLocalRequest* req;
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
    TestData test_data;
 | 
			
		||||
 | 
			
		||||
    test_data.x = 10;
 | 
			
		||||
 | 
			
		||||
    /* Non-null */
 | 
			
		||||
    req = gbinder_local_request_new(&gbinder_io_32, NULL);
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_parcelable(&writer, &test_data, sizeof(test_data));
 | 
			
		||||
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert(data->bytes->len == sizeof(encoded_non_null));
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data, &encoded_non_null, data->bytes->len));
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    /* Null */
 | 
			
		||||
    req = gbinder_local_request_new(&gbinder_io_32, NULL);
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_parcelable(&writer, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert(data->bytes->len == sizeof(test_null_value));
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data, &test_null_value, data->bytes->len));
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * fd
 | 
			
		||||
 * fd_invalid
 | 
			
		||||
@@ -1063,6 +1169,8 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("null"), test_null);
 | 
			
		||||
    g_test_add_func(TEST_("cleanup"), test_cleanup);
 | 
			
		||||
    g_test_add_func(TEST_("int8"), test_int8);
 | 
			
		||||
    g_test_add_func(TEST_("int16"), test_int16);
 | 
			
		||||
    g_test_add_func(TEST_("int32"), test_int32);
 | 
			
		||||
    g_test_add_func(TEST_("int64"), test_int64);
 | 
			
		||||
    g_test_add_func(TEST_("float"), test_float);
 | 
			
		||||
@@ -1117,6 +1225,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
 | 
			
		||||
    g_test_add_func(TEST_("buffer"), test_buffer);
 | 
			
		||||
    g_test_add_func(TEST_("parent"), test_parent);
 | 
			
		||||
    g_test_add_func(TEST_("parcelable"), test_parcelable);
 | 
			
		||||
    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