Compare commits
	
		
			39 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d855d695db | ||
| 
						 | 
					922cc82029 | ||
| 
						 | 
					80498378f2 | ||
| 
						 | 
					51856865df | ||
| 
						 | 
					d26dcca37e | ||
| 
						 | 
					5ac02fcb2e | ||
| 
						 | 
					110cd65779 | ||
| 
						 | 
					67e665b619 | ||
| 
						 | 
					d1c431c370 | ||
| 
						 | 
					2167a82c73 | ||
| 
						 | 
					d113d3bf4a | ||
| 
						 | 
					b2206adae5 | ||
| 
						 | 
					8075cce1b1 | ||
| 
						 | 
					29e4c79f75 | ||
| 
						 | 
					3b299d3345 | ||
| 
						 | 
					7421fff380 | ||
| 
						 | 
					694aad637b | ||
| 
						 | 
					c8c7222e06 | ||
| 
						 | 
					9c6e31ef41 | ||
| 
						 | 
					6a8d5c0c6e | ||
| 
						 | 
					96ca10396b | ||
| 
						 | 
					61cef824e8 | ||
| 
						 | 
					972517d32d | ||
| 
						 | 
					217a03642a | ||
| 
						 | 
					f14783b8cf | ||
| 
						 | 
					4f75c6e37b | ||
| 
						 | 
					4eb3b66a0e | ||
| 
						 | 
					6b74d5faed | ||
| 
						 | 
					10d72ec42c | ||
| 
						 | 
					9eae4ef819 | ||
| 
						 | 
					b3657e396f | ||
| 
						 | 
					a69885d05f | ||
| 
						 | 
					306d08112b | ||
| 
						 | 
					b489becf51 | ||
| 
						 | 
					8a27829af3 | ||
| 
						 | 
					d67b73502e | ||
| 
						 | 
					4ecf3ae24d | ||
| 
						 | 
					d0542e759d | ||
| 
						 | 
					ffa44ac5b3 | 
							
								
								
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							@@ -1,2 +1,4 @@
 | 
			
		||||
Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
Matti Lehtimäki <matti.lehtimaki@gmail.com>
 | 
			
		||||
Franz-Josef Haider <franz.haider@jolla.com>
 | 
			
		||||
Juho Hämäläinen <juho.hamalainen@jolla.com>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -24,7 +24,7 @@ all: debug release pkgconfig
 | 
			
		||||
 | 
			
		||||
VERSION_MAJOR = 1
 | 
			
		||||
VERSION_MINOR = 0
 | 
			
		||||
VERSION_RELEASE = 6
 | 
			
		||||
VERSION_RELEASE = 14
 | 
			
		||||
 | 
			
		||||
# Version for pkg-config
 | 
			
		||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								README
									
									
									
									
									
								
							@@ -1 +1,7 @@
 | 
			
		||||
GLib-style interface to binder (Android IPC mechanism)
 | 
			
		||||
 | 
			
		||||
Provides:
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,59 @@
 | 
			
		||||
libgbinder (1.0.14) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Changed bool padding from 0xff to 0x00
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Tue, 27 Nov 2018 17:20:18 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.13) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Support for service registration notifications
 | 
			
		||||
  * Make sure looper is started before gbinder_ipc_looper_new() returns
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sat, 17 Nov 2018 01:52:28 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.12) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Add byte array reader and writer
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 31 Oct 2018 17:04:38 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.11) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Use BINDER_TYPE_WEAK_HANDLE for NULL objects
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 24 Oct 2018 18:57:28 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.10) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Fixed dependencies for unit tests
 | 
			
		||||
  * Plugged memory leak in unit_reader
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 10 Oct 2018 14:44:44 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.9) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Respect strong refs to GBinderLocalObject
 | 
			
		||||
  * Added gbinder_reader_read_hidl_struct macro
 | 
			
		||||
  * Added gbinder_reader_read_hidl_type_vec macro
 | 
			
		||||
  * Added gbinder_reader_read_hidl_byte_vec macro
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Mon, 08 Oct 2018 11:41:33 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.8) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Added gbinder_writer_append_hidl_vec()
 | 
			
		||||
  * Added Added gbinder_reader_read_hidl_vec()
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Tue, 25 Sep 2018 01:08:54 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.7) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Added gbinder_remote_request_copy_to_local()
 | 
			
		||||
  * Added gbinder_remote_reply_copy_to_local()
 | 
			
		||||
  * Make sure RPC protocol matches servicemanager type
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sun, 23 Sep 2018 22:47:16 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder (1.0.6) unstable; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Fixed GBinderServiceManager lifecycle management
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -2,13 +2,13 @@ Source: libgbinder
 | 
			
		||||
Section: libs
 | 
			
		||||
Priority: optional
 | 
			
		||||
Maintainer: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.29)
 | 
			
		||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.34)
 | 
			
		||||
Standards-Version: 3.8.4
 | 
			
		||||
 | 
			
		||||
Package: libgbinder
 | 
			
		||||
Section: libs
 | 
			
		||||
Architecture: any
 | 
			
		||||
Depends: libglibutil (>= 1.0.29), ${shlibs:Depends}, ${misc:Depends}
 | 
			
		||||
Depends: libglibutil (>= 1.0.34), ${shlibs:Depends}, ${misc:Depends}
 | 
			
		||||
Description: Binder client library
 | 
			
		||||
 | 
			
		||||
Package: libgbinder-dev
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -113,6 +113,31 @@ gbinder_reader_read_buffer(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_struct1(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize size); /* since 1.0.9 */
 | 
			
		||||
 | 
			
		||||
#define gbinder_reader_read_hidl_struct(reader,type) \
 | 
			
		||||
    ((const type*)gbinder_reader_read_hidl_struct1(reader, sizeof(type)))
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_vec(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* count,
 | 
			
		||||
    gsize* elemsize);
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_vec1(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* count,
 | 
			
		||||
    guint expected_elemsize); /* since 1.0.9 */
 | 
			
		||||
 | 
			
		||||
#define gbinder_reader_read_hidl_type_vec(reader,type,count) \
 | 
			
		||||
    ((const type*)gbinder_reader_read_hidl_vec1(reader, count, sizeof(type)))
 | 
			
		||||
#define gbinder_reader_read_hidl_byte_vec(reader,count) /* vec<uint8_t> */ \
 | 
			
		||||
    gbinder_reader_read_hidl_type_vec(reader,guint8,count)
 | 
			
		||||
 | 
			
		||||
char*
 | 
			
		||||
gbinder_reader_read_hidl_string(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
@@ -144,6 +169,11 @@ gboolean
 | 
			
		||||
gbinder_reader_skip_string16(
 | 
			
		||||
    GBinderReader* reader);
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_byte_array(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* len); /* since 1.0.12 */
 | 
			
		||||
 | 
			
		||||
gsize
 | 
			
		||||
gbinder_reader_bytes_read(
 | 
			
		||||
    GBinderReader* reader);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -50,6 +50,11 @@ gbinder_remote_reply_init_reader(
 | 
			
		||||
    GBinderRemoteReply* reply,
 | 
			
		||||
    GBinderReader* reader);
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
gbinder_remote_reply_copy_to_local(
 | 
			
		||||
    GBinderRemoteReply* reply) /* since 1.0.6 */
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
/* Convenience function to decode replies with just one data item */
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -62,6 +62,11 @@ uid_t
 | 
			
		||||
gbinder_remote_request_sender_euid(
 | 
			
		||||
    GBinderRemoteRequest* req); /* since 1.0.2 */
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_remote_request_copy_to_local(
 | 
			
		||||
    GBinderRemoteRequest* req) /* since 1.0.6 */
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
/* Convenience function to decode requests with just one data item */
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -61,6 +61,13 @@ void
 | 
			
		||||
    int status,
 | 
			
		||||
    void* user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*GBinderServiceManagerRegistrationFunc)(
 | 
			
		||||
    GBinderServiceManager* sm,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    void* user_data);
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new(
 | 
			
		||||
    const char* dev);
 | 
			
		||||
@@ -130,6 +137,18 @@ gbinder_servicemanager_cancel(
 | 
			
		||||
    GBinderServiceManager* sm,
 | 
			
		||||
    gulong id);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
gbinder_servicemanager_add_registration_handler(
 | 
			
		||||
    GBinderServiceManager* sm,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderServiceManagerRegistrationFunc func,
 | 
			
		||||
    void* user_data); /* Since 1.0.13 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_remove_handler(
 | 
			
		||||
    GBinderServiceManager* sm,
 | 
			
		||||
    gulong id); /* Since 1.0.13 */
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_SERVICEMANAGER_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -121,6 +121,13 @@ gbinder_writer_append_buffer_object(
 | 
			
		||||
    const void* buf,
 | 
			
		||||
    gsize len);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_vec(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize); /* since 1.0.8 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_string(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
@@ -142,6 +149,12 @@ gbinder_writer_append_remote_object(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    GBinderRemoteObject* obj);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_byte_array(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
    const void* byte_array,
 | 
			
		||||
    gint32 len); /* since 1.0.12 */
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_WRITER_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
Name: libgbinder
 | 
			
		||||
Version: 1.0.6
 | 
			
		||||
Version: 1.0.14
 | 
			
		||||
Release: 0
 | 
			
		||||
Summary: Binder client library
 | 
			
		||||
Group: Development/Libraries
 | 
			
		||||
License: BSD
 | 
			
		||||
URL: https://github.com/mer-hybris/libgbinder
 | 
			
		||||
Source: %{name}-%{version}.tar.bz2
 | 
			
		||||
Requires: libglibutil >= 1.0.29
 | 
			
		||||
Requires: libglibutil >= 1.0.34
 | 
			
		||||
BuildRequires: pkgconfig(glib-2.0)
 | 
			
		||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.29
 | 
			
		||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.34
 | 
			
		||||
Requires(post): /sbin/ldconfig
 | 
			
		||||
Requires(postun): /sbin/ldconfig
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -36,12 +36,12 @@
 | 
			
		||||
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_buffer_memory {
 | 
			
		||||
struct gbinder_buffer_memory {
 | 
			
		||||
    gint refcount;
 | 
			
		||||
    void* buffer;
 | 
			
		||||
    gsize size;
 | 
			
		||||
    GBinderDriver* driver;
 | 
			
		||||
} GBinderBufferMemory;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_buffer_priv {
 | 
			
		||||
    GBinderBuffer pub;
 | 
			
		||||
@@ -81,7 +81,6 @@ gbinder_buffer_memory_free(
 | 
			
		||||
    g_slice_free(GBinderBufferMemory, self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderBufferMemory*
 | 
			
		||||
gbinder_buffer_memory_ref(
 | 
			
		||||
    GBinderBufferMemory* self)
 | 
			
		||||
@@ -93,7 +92,6 @@ gbinder_buffer_memory_ref(
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_buffer_memory_unref(
 | 
			
		||||
    GBinderBufferMemory* self)
 | 
			
		||||
@@ -155,10 +153,30 @@ gbinder_buffer_new_with_parent(
 | 
			
		||||
    gsize size)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_buffer_alloc(parent ?
 | 
			
		||||
        gbinder_buffer_memory_ref(gbinder_buffer_cast(parent)->memory) : NULL,
 | 
			
		||||
        gbinder_buffer_memory_ref(gbinder_buffer_memory(parent)) : NULL,
 | 
			
		||||
        data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gconstpointer
 | 
			
		||||
gbinder_buffer_data(
 | 
			
		||||
    GBinderBuffer* self,
 | 
			
		||||
    gsize* size)
 | 
			
		||||
{
 | 
			
		||||
    GBinderBufferMemory* memory = gbinder_buffer_memory(self);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(memory)) {
 | 
			
		||||
        if (size) {
 | 
			
		||||
            *size = memory->size;
 | 
			
		||||
        }
 | 
			
		||||
        return memory->buffer;
 | 
			
		||||
    } else {
 | 
			
		||||
        if (size) {
 | 
			
		||||
            *size = 0;
 | 
			
		||||
        }
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderDriver*
 | 
			
		||||
gbinder_buffer_driver(
 | 
			
		||||
    GBinderBuffer* self)
 | 
			
		||||
@@ -173,6 +191,22 @@ gbinder_buffer_driver(
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const GBinderIo*
 | 
			
		||||
gbinder_buffer_io(
 | 
			
		||||
    GBinderBuffer* buf)
 | 
			
		||||
{
 | 
			
		||||
    GBinderDriver* driver = gbinder_buffer_driver(buf);
 | 
			
		||||
 | 
			
		||||
    return driver ? gbinder_driver_io(driver) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderBufferMemory*
 | 
			
		||||
gbinder_buffer_memory(
 | 
			
		||||
    GBinderBuffer* self)
 | 
			
		||||
{
 | 
			
		||||
    return G_LIKELY(self) ? gbinder_buffer_cast(self)->memory : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -53,8 +53,26 @@ GBinderDriver*
 | 
			
		||||
gbinder_buffer_driver(
 | 
			
		||||
    GBinderBuffer* buf);
 | 
			
		||||
 | 
			
		||||
#define gbinder_buffer_io(buf) \
 | 
			
		||||
    gbinder_driver_io(gbinder_buffer_driver(buf))
 | 
			
		||||
GBinderBufferMemory*
 | 
			
		||||
gbinder_buffer_memory(
 | 
			
		||||
    GBinderBuffer* buf);
 | 
			
		||||
 | 
			
		||||
gconstpointer
 | 
			
		||||
gbinder_buffer_data(
 | 
			
		||||
    GBinderBuffer* buf,
 | 
			
		||||
    gsize* size);
 | 
			
		||||
 | 
			
		||||
const GBinderIo*
 | 
			
		||||
gbinder_buffer_io(
 | 
			
		||||
    GBinderBuffer* buf);
 | 
			
		||||
 | 
			
		||||
GBinderBufferMemory*
 | 
			
		||||
gbinder_buffer_memory_ref(
 | 
			
		||||
    GBinderBufferMemory* mem);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_buffer_memory_unref(
 | 
			
		||||
    GBinderBufferMemory* mem);
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_BUFFER_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_p.h"
 | 
			
		||||
#include "gbinder_rpc_protocol.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gbinder_client.h>
 | 
			
		||||
@@ -150,6 +151,17 @@ gbinder_defaultservicemanager_add_service(
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBINDER_SERVICEMANAGER_NAME_CHECK
 | 
			
		||||
gbinder_defaultservicemanager_check_name(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name)
 | 
			
		||||
{
 | 
			
		||||
    /* Old servicemanager doesn't support notifications, those would
 | 
			
		||||
     * have to be emulated with polling. Is it necessary though? */
 | 
			
		||||
    return GBINDER_SERVICEMANAGER_NAME_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_defaultservicemanager_init(
 | 
			
		||||
@@ -165,10 +177,13 @@ gbinder_defaultservicemanager_class_init(
 | 
			
		||||
    klass->handle = DEFAULTSERVICEMANAGER_HANDLE;
 | 
			
		||||
    klass->iface = DEFAULTSERVICEMANAGER_IFACE;
 | 
			
		||||
    klass->default_device = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    klass->rpc_protocol = &gbinder_rpc_protocol_binder;
 | 
			
		||||
 | 
			
		||||
    klass->list = gbinder_defaultservicemanager_list;
 | 
			
		||||
    klass->get_service = gbinder_defaultservicemanager_get_service;
 | 
			
		||||
    klass->add_service = gbinder_defaultservicemanager_add_service;
 | 
			
		||||
    klass->check_name = gbinder_defaultservicemanager_check_name;
 | 
			
		||||
    /* No need for other watch callbacks */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -672,7 +672,8 @@ gbinder_driver_txstatus(
 | 
			
		||||
 | 
			
		||||
GBinderDriver*
 | 
			
		||||
gbinder_driver_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const GBinderRpcProtocol* protocol)
 | 
			
		||||
{
 | 
			
		||||
    const int fd = gbinder_system_open(dev, O_RDWR | O_CLOEXEC);
 | 
			
		||||
    if (fd >= 0) {
 | 
			
		||||
@@ -711,8 +712,10 @@ gbinder_driver_new(
 | 
			
		||||
                        GERR("%s failed to set max threads (%u): %s", dev,
 | 
			
		||||
                            max_threads, strerror(errno));
 | 
			
		||||
                    }
 | 
			
		||||
                    /* Choose the protocol based on the device name */
 | 
			
		||||
                    self->protocol = gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
                    /* Choose the protocol based on the device name
 | 
			
		||||
                     * if none is explicitely specified */
 | 
			
		||||
                    self->protocol = protocol ? protocol :
 | 
			
		||||
                        gbinder_rpc_protocol_for_device(dev);
 | 
			
		||||
                    return self;
 | 
			
		||||
                } else {
 | 
			
		||||
                    GERR("%s failed to mmap: %s", dev, strerror(errno));
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -39,7 +39,8 @@ struct pollfd;
 | 
			
		||||
 | 
			
		||||
GBinderDriver*
 | 
			
		||||
gbinder_driver_new(
 | 
			
		||||
    const char* dev);
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const GBinderRpcProtocol* protocol);
 | 
			
		||||
 | 
			
		||||
GBinderDriver*
 | 
			
		||||
gbinder_driver_ref(
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -31,23 +31,40 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_servicemanager_p.h"
 | 
			
		||||
#include "gbinder_rpc_protocol.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gbinder_client.h>
 | 
			
		||||
#include <gbinder_local_object.h>
 | 
			
		||||
#include <gbinder_local_request.h>
 | 
			
		||||
#include <gbinder_remote_reply.h>
 | 
			
		||||
#include <gbinder_remote_request.h>
 | 
			
		||||
#include <gbinder_reader.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
typedef GBinderServiceManager GBinderHwServiceManager;
 | 
			
		||||
typedef struct gbinder_hwservicemanager_watch {
 | 
			
		||||
    char* name;
 | 
			
		||||
    GBinderLocalObject* callback;
 | 
			
		||||
} GBinderHwServiceManagerWatch;
 | 
			
		||||
 | 
			
		||||
typedef GBinderServiceManagerClass GBinderHwServiceManagerClass;
 | 
			
		||||
typedef struct gbinder_hwservicemanager {
 | 
			
		||||
    GBinderServiceManager manager;
 | 
			
		||||
    GHashTable* watch_table;
 | 
			
		||||
} GBinderHwServiceManager;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE(GBinderHwServiceManager,
 | 
			
		||||
    gbinder_hwservicemanager,
 | 
			
		||||
    GBINDER_TYPE_SERVICEMANAGER)
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS gbinder_hwservicemanager_parent_class
 | 
			
		||||
#define GBINDER_TYPE_HWSERVICEMANAGER (gbinder_hwservicemanager_get_type())
 | 
			
		||||
#define GBINDER_HWSERVICEMANAGER(obj) \
 | 
			
		||||
    G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_HWSERVICEMANAGER, \
 | 
			
		||||
    GBinderHwServiceManager)
 | 
			
		||||
 | 
			
		||||
enum gbinder_hwservicemanager_calls {
 | 
			
		||||
    GET_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
 | 
			
		||||
    ADD_TRANSACTION,
 | 
			
		||||
@@ -59,9 +76,76 @@ enum gbinder_hwservicemanager_calls {
 | 
			
		||||
    REGISTER_PASSTHROUGH_CLIENT_TRANSACTION
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum gbinder_hwservicemanager_notifications {
 | 
			
		||||
    ON_REGISTRATION_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* As a special case, ServiceManager's handle is zero */
 | 
			
		||||
#define HWSERVICEMANAGER_HANDLE (0)
 | 
			
		||||
#define HWSERVICEMANAGER_IFACE  "android.hidl.manager@1.0::IServiceManager"
 | 
			
		||||
#define HWSERVICEMANAGER_NOTIFICATION_IFACE \
 | 
			
		||||
    "android.hidl.manager@1.0::IServiceNotification"
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_hwservicemanager_handle_registration(
 | 
			
		||||
    GBinderHwServiceManager* self,
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
{
 | 
			
		||||
    char* fqname = gbinder_reader_read_hidl_string(reader);
 | 
			
		||||
    char* name = gbinder_reader_read_hidl_string(reader);
 | 
			
		||||
    gboolean preexisting;
 | 
			
		||||
 | 
			
		||||
    /* (string fqName, string name, bool preexisting) */
 | 
			
		||||
    if (fqname && name && gbinder_reader_read_bool(reader, &preexisting) &&
 | 
			
		||||
        gbinder_reader_at_end(reader)) {
 | 
			
		||||
        char* full_name = g_strconcat(fqname, "/", name, NULL);
 | 
			
		||||
 | 
			
		||||
        GDEBUG("%s %s", full_name, preexisting ? "true" : "false");
 | 
			
		||||
        gbinder_servicemanager_service_registered(&self->manager, full_name);
 | 
			
		||||
        g_free(full_name);
 | 
			
		||||
    } else {
 | 
			
		||||
        GWARN("Failed to parse IServiceNotification::onRegistration payload");
 | 
			
		||||
    }
 | 
			
		||||
    g_free(fqname);
 | 
			
		||||
    g_free(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
gbinder_hwservicemanager_notification(
 | 
			
		||||
    GBinderLocalObject* obj,
 | 
			
		||||
    GBinderRemoteRequest* req,
 | 
			
		||||
    guint code,
 | 
			
		||||
    guint flags,
 | 
			
		||||
    int* status,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(user_data);
 | 
			
		||||
    const char* iface = gbinder_remote_request_interface(req);
 | 
			
		||||
 | 
			
		||||
    if (!g_strcmp0(iface, HWSERVICEMANAGER_NOTIFICATION_IFACE)) {
 | 
			
		||||
        GBinderReader reader;
 | 
			
		||||
 | 
			
		||||
        gbinder_remote_request_init_reader(req, &reader);
 | 
			
		||||
        switch (code) {
 | 
			
		||||
        case ON_REGISTRATION_TRANSACTION:
 | 
			
		||||
            GDEBUG(HWSERVICEMANAGER_NOTIFICATION_IFACE " %u onRegistration",
 | 
			
		||||
                code);
 | 
			
		||||
            gbinder_hwservicemanager_handle_registration(self, &reader);
 | 
			
		||||
            *status = GBINDER_STATUS_OK;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            GDEBUG(HWSERVICEMANAGER_NOTIFICATION_IFACE " %u", code);
 | 
			
		||||
            *status = GBINDER_STATUS_FAILED;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        GDEBUG("%s %u", iface, code);
 | 
			
		||||
        *status = GBINDER_STATUS_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_hwservicemanager_new(
 | 
			
		||||
@@ -74,7 +158,7 @@ gbinder_hwservicemanager_new(
 | 
			
		||||
static
 | 
			
		||||
char**
 | 
			
		||||
gbinder_hwservicemanager_list(
 | 
			
		||||
    GBinderHwServiceManager* self)
 | 
			
		||||
    GBinderServiceManager* self)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
			
		||||
    GBinderRemoteReply* reply = gbinder_client_transact_sync_reply
 | 
			
		||||
@@ -110,6 +194,7 @@ gbinder_hwservicemanager_get_service(
 | 
			
		||||
    /* e.g. "android.hardware.radio@1.1::IRadio/slot1" */
 | 
			
		||||
    const char* sep = strchr(fqinstance, '/');
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
 | 
			
		||||
    if (sep) {
 | 
			
		||||
        GBinderRemoteReply* reply;
 | 
			
		||||
        GBinderLocalRequest* req = gbinder_client_new_request(self->client);
 | 
			
		||||
@@ -169,11 +254,123 @@ gbinder_hwservicemanager_add_service(
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_hwservicemanager_watch_free(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderHwServiceManagerWatch* watch = data;
 | 
			
		||||
 | 
			
		||||
    g_free(watch->name);
 | 
			
		||||
    gbinder_local_object_drop(watch->callback);
 | 
			
		||||
    g_free(watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBINDER_SERVICEMANAGER_NAME_CHECK
 | 
			
		||||
gbinder_hwservicemanager_check_name(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name)
 | 
			
		||||
{
 | 
			
		||||
    if (name) {
 | 
			
		||||
        const gsize len = strlen(name);
 | 
			
		||||
        static const char allowed_chars[] = "./0123456789:@"
 | 
			
		||||
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 | 
			
		||||
            "abcdefghijklmnopqrstuvwxyz";
 | 
			
		||||
 | 
			
		||||
        if (len && strspn(name, allowed_chars) == len) {
 | 
			
		||||
            return strchr(name, '/') ?
 | 
			
		||||
                GBINDER_SERVICEMANAGER_NAME_NORMALIZE :
 | 
			
		||||
                GBINDER_SERVICEMANAGER_NAME_OK;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return GBINDER_SERVICEMANAGER_NAME_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
char*
 | 
			
		||||
gbinder_hwservicemanager_normalize_name(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name)
 | 
			
		||||
{
 | 
			
		||||
    /* Slash must be there, see gbinder_hwservicemanager_check_name() above */
 | 
			
		||||
    return g_strndup(name, strchr(name, '/') - name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_hwservicemanager_watch(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
    const char* name)
 | 
			
		||||
{
 | 
			
		||||
    GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(manager);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_client_new_request(manager->client);
 | 
			
		||||
    GBinderRemoteReply* reply;
 | 
			
		||||
    GBinderHwServiceManagerWatch* watch =
 | 
			
		||||
        g_new0(GBinderHwServiceManagerWatch, 1);
 | 
			
		||||
    gboolean success = FALSE;
 | 
			
		||||
    int status;
 | 
			
		||||
 | 
			
		||||
    watch->name = g_strdup(name);
 | 
			
		||||
    watch->callback = gbinder_servicemanager_new_local_object(manager,
 | 
			
		||||
        HWSERVICEMANAGER_NOTIFICATION_IFACE,
 | 
			
		||||
        gbinder_hwservicemanager_notification, self);
 | 
			
		||||
    g_hash_table_replace(self->watch_table, watch->name, watch);
 | 
			
		||||
 | 
			
		||||
    /* registerForNotifications(string fqName, string name,
 | 
			
		||||
     * IServiceNotification callback) generates (bool success); */
 | 
			
		||||
    gbinder_local_request_append_hidl_string(req, name);
 | 
			
		||||
    gbinder_local_request_append_hidl_string(req, "");
 | 
			
		||||
    gbinder_local_request_append_local_object(req, watch->callback);
 | 
			
		||||
    reply = gbinder_client_transact_sync_reply(manager->client,
 | 
			
		||||
        REGISTER_FOR_NOTIFICATIONS_TRANSACTION, req, &status);
 | 
			
		||||
 | 
			
		||||
    if (status == GBINDER_STATUS_OK && reply) {
 | 
			
		||||
        GBinderReader reader;
 | 
			
		||||
 | 
			
		||||
        gbinder_remote_reply_init_reader(reply, &reader);
 | 
			
		||||
        if (gbinder_reader_read_int32(&reader, &status) &&
 | 
			
		||||
            status == GBINDER_STATUS_OK) {
 | 
			
		||||
            gbinder_reader_read_bool(&reader, &success);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_remote_reply_unref(reply);
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    if (!success) {
 | 
			
		||||
        /* unwatch() won't be called if we return FALSE */
 | 
			
		||||
        g_hash_table_remove(self->watch_table, watch->name);
 | 
			
		||||
    }
 | 
			
		||||
    return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_hwservicemanager_unwatch(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
    const char* name)
 | 
			
		||||
{
 | 
			
		||||
    g_hash_table_remove(GBINDER_HWSERVICEMANAGER(manager)->watch_table, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_hwservicemanager_init(
 | 
			
		||||
    GBinderHwServiceManager* self)
 | 
			
		||||
{
 | 
			
		||||
    self->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 | 
			
		||||
        NULL, gbinder_hwservicemanager_watch_free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_hwservicemanager_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(object);
 | 
			
		||||
 | 
			
		||||
    g_hash_table_destroy(self->watch_table);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -184,10 +381,16 @@ gbinder_hwservicemanager_class_init(
 | 
			
		||||
    klass->handle = HWSERVICEMANAGER_HANDLE;
 | 
			
		||||
    klass->iface = HWSERVICEMANAGER_IFACE;
 | 
			
		||||
    klass->default_device = GBINDER_DEFAULT_HWBINDER;
 | 
			
		||||
    klass->rpc_protocol = &gbinder_rpc_protocol_hwbinder;
 | 
			
		||||
 | 
			
		||||
    klass->list = gbinder_hwservicemanager_list;
 | 
			
		||||
    klass->get_service = gbinder_hwservicemanager_get_service;
 | 
			
		||||
    klass->add_service = gbinder_hwservicemanager_add_service;
 | 
			
		||||
    klass->check_name = gbinder_hwservicemanager_check_name;
 | 
			
		||||
    klass->normalize_name = gbinder_hwservicemanager_normalize_name;
 | 
			
		||||
    klass->watch = gbinder_hwservicemanager_watch;
 | 
			
		||||
    klass->unwatch = gbinder_hwservicemanager_unwatch;
 | 
			
		||||
    G_OBJECT_CLASS(klass)->finalize = gbinder_hwservicemanager_finalize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -90,6 +90,21 @@ GBINDER_IO_FN(write_read)(
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Returns size of the object's extra data */
 | 
			
		||||
static
 | 
			
		||||
gsize
 | 
			
		||||
GBINDER_IO_FN(object_data_size)(
 | 
			
		||||
    const void* obj)
 | 
			
		||||
{
 | 
			
		||||
    const struct binder_buffer_object* buf = obj;
 | 
			
		||||
 | 
			
		||||
    if (buf && buf->hdr.type == BINDER_TYPE_PTR) {
 | 
			
		||||
        return buf->length;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Writes pointer to the buffer */
 | 
			
		||||
static
 | 
			
		||||
guint
 | 
			
		||||
@@ -113,7 +128,7 @@ GBINDER_IO_FN(encode_local_object)(
 | 
			
		||||
    struct flat_binder_object* dest = out;
 | 
			
		||||
 | 
			
		||||
    memset(dest, 0, sizeof(*dest));
 | 
			
		||||
    dest->hdr.type = BINDER_TYPE_BINDER;
 | 
			
		||||
    dest->hdr.type = obj ? BINDER_TYPE_BINDER : BINDER_TYPE_WEAK_HANDLE;
 | 
			
		||||
    dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
 | 
			
		||||
    dest->binder = (uintptr_t)obj;
 | 
			
		||||
    return sizeof(*dest);
 | 
			
		||||
@@ -445,6 +460,8 @@ const GBinderIo GBINDER_IO_PREFIX = {
 | 
			
		||||
        .failed_reply = BR_FAILED_REPLY
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    .object_data_size = GBINDER_IO_FN(object_data_size),
 | 
			
		||||
 | 
			
		||||
    /* Encoders */
 | 
			
		||||
    .encode_pointer = GBINDER_IO_FN(encode_pointer),
 | 
			
		||||
    .encode_local_object = GBINDER_IO_FN(encode_local_object),
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -118,6 +118,9 @@ struct gbinder_io {
 | 
			
		||||
        guint failed_reply;
 | 
			
		||||
    } br;
 | 
			
		||||
 | 
			
		||||
    /* Size of the object's extra data */
 | 
			
		||||
    gsize (*object_data_size)(const void* obj);
 | 
			
		||||
 | 
			
		||||
    /* Writes pointer to the buffer. The destination buffer must have
 | 
			
		||||
     * at least GBINDER_IO_MAX_POINTER_SIZE bytes available. The
 | 
			
		||||
     * actual size is returned. */
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -88,6 +88,7 @@ static pthread_mutex_t gbinder_ipc_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
#define GBINDER_IPC_MAX_TX_THREADS (15)
 | 
			
		||||
#define GBINDER_IPC_MAX_LOOPERS (15)
 | 
			
		||||
#define GBINDER_IPC_LOOPER_START_TIMEOUT_SEC (2)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * When looper receives the transaction:
 | 
			
		||||
@@ -134,6 +135,9 @@ struct gbinder_ipc_looper {
 | 
			
		||||
    GBinderDriver* driver;
 | 
			
		||||
    GBinderIpc* ipc; /* Not a reference! */
 | 
			
		||||
    GThread* thread;
 | 
			
		||||
    GMutex mutex;
 | 
			
		||||
    GCond start_cond;
 | 
			
		||||
    gboolean started;
 | 
			
		||||
    int pipefd[2];
 | 
			
		||||
    int txfd[2];
 | 
			
		||||
};
 | 
			
		||||
@@ -344,6 +348,8 @@ gbinder_ipc_looper_free(
 | 
			
		||||
        close(looper->txfd[1]);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_driver_unref(looper->driver);
 | 
			
		||||
    g_cond_clear(&looper->start_cond);
 | 
			
		||||
    g_mutex_clear(&looper->mutex);
 | 
			
		||||
    g_slice_free(GBinderIpcLooper, looper);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -381,6 +387,11 @@ gbinder_ipc_looper_thread(
 | 
			
		||||
        int result;
 | 
			
		||||
 | 
			
		||||
        GDEBUG("Looper %s running", gbinder_driver_dev(driver));
 | 
			
		||||
        g_mutex_lock(&looper->mutex);
 | 
			
		||||
        looper->started = TRUE;
 | 
			
		||||
        g_cond_broadcast(&looper->start_cond);
 | 
			
		||||
        g_mutex_unlock(&looper->mutex);
 | 
			
		||||
 | 
			
		||||
        memset(&pipefd, 0, sizeof(pipefd));
 | 
			
		||||
        pipefd.fd = looper->pipefd[0]; /* read end of the pipe */
 | 
			
		||||
        pipefd.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
 | 
			
		||||
@@ -436,6 +447,11 @@ gbinder_ipc_looper_thread(
 | 
			
		||||
        } else {
 | 
			
		||||
            GDEBUG("Looper %s is abandoned", gbinder_driver_dev(driver));
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        g_mutex_lock(&looper->mutex);
 | 
			
		||||
        looper->started = TRUE;
 | 
			
		||||
        g_cond_broadcast(&looper->start_cond);
 | 
			
		||||
        g_mutex_unlock(&looper->mutex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gbinder_ipc_looper_unref(looper);
 | 
			
		||||
@@ -460,6 +476,8 @@ gbinder_ipc_looper_new(
 | 
			
		||||
        memcpy(looper->pipefd, fd, sizeof(fd));
 | 
			
		||||
        looper->txfd[0] = looper->txfd[1] = -1;
 | 
			
		||||
        g_atomic_int_set(&looper->refcount, 1);
 | 
			
		||||
        g_cond_init(&looper->start_cond);
 | 
			
		||||
        g_mutex_init(&looper->mutex);
 | 
			
		||||
        looper->handler.f = &handler_functions;
 | 
			
		||||
        looper->ipc = ipc;
 | 
			
		||||
        looper->driver = gbinder_driver_ref(ipc->driver);
 | 
			
		||||
@@ -488,6 +506,7 @@ gbinder_ipc_looper_check(
 | 
			
		||||
        GBinderIpcPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
        if (!priv->looper) {
 | 
			
		||||
            GBinderIpcLooper* looper;
 | 
			
		||||
            /* Lock */
 | 
			
		||||
            g_mutex_lock(&priv->looper_mutex);
 | 
			
		||||
            if (!priv->looper) {
 | 
			
		||||
@@ -496,6 +515,23 @@ gbinder_ipc_looper_check(
 | 
			
		||||
            }
 | 
			
		||||
            g_mutex_unlock(&priv->looper_mutex);
 | 
			
		||||
            /* Unlock */
 | 
			
		||||
 | 
			
		||||
            /* We are not ready to accept incoming transactions until
 | 
			
		||||
             * looper has started. We may need to wait a bit. */
 | 
			
		||||
            looper = priv->looper;
 | 
			
		||||
            if (!looper->started) {
 | 
			
		||||
                /* Lock */
 | 
			
		||||
                g_mutex_lock(&looper->mutex);
 | 
			
		||||
                if (!looper->started) {
 | 
			
		||||
                    g_cond_wait_until(&looper->start_cond, &looper->mutex,
 | 
			
		||||
                        g_get_monotonic_time() +
 | 
			
		||||
                        GBINDER_IPC_LOOPER_START_TIMEOUT_SEC *
 | 
			
		||||
                        G_TIME_SPAN_SECOND);
 | 
			
		||||
                    GASSERT(looper->started);
 | 
			
		||||
                }
 | 
			
		||||
                g_mutex_unlock(&looper->mutex);
 | 
			
		||||
                /* Unlock */
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -981,7 +1017,8 @@ gbinder_ipc_tx_proc(
 | 
			
		||||
 | 
			
		||||
GBinderIpc*
 | 
			
		||||
gbinder_ipc_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const GBinderRpcProtocol* protocol)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* self = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -994,7 +1031,7 @@ gbinder_ipc_new(
 | 
			
		||||
    if (self) {
 | 
			
		||||
        gbinder_ipc_ref(self);
 | 
			
		||||
    } else {
 | 
			
		||||
        GBinderDriver* driver = gbinder_driver_new(dev);
 | 
			
		||||
        GBinderDriver* driver = gbinder_driver_new(dev, protocol);
 | 
			
		||||
 | 
			
		||||
        if (driver) {
 | 
			
		||||
            GBinderIpcPriv* priv;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -70,7 +70,8 @@ void
 | 
			
		||||
 | 
			
		||||
GBinderIpc*
 | 
			
		||||
gbinder_ipc_new(
 | 
			
		||||
    const char* dev);
 | 
			
		||||
   const char* dev,
 | 
			
		||||
   const GBinderRpcProtocol* protocol);
 | 
			
		||||
 | 
			
		||||
GBinderIpc*
 | 
			
		||||
gbinder_ipc_ref(
 | 
			
		||||
 
 | 
			
		||||
@@ -271,6 +271,7 @@ gbinder_local_object_handle_release_proc(
 | 
			
		||||
    self->strong_refs--;
 | 
			
		||||
    g_signal_emit(self, gbinder_local_object_signals
 | 
			
		||||
        [SIGNAL_STRONG_REFS_CHANGED], 0);
 | 
			
		||||
    gbinder_local_object_unref(self);
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -440,6 +441,7 @@ void
 | 
			
		||||
gbinder_local_object_handle_acquire(
 | 
			
		||||
    GBinderLocalObject* self)
 | 
			
		||||
{
 | 
			
		||||
    gbinder_local_object_ref(self);
 | 
			
		||||
    gbinder_local_object_handle_later(self,
 | 
			
		||||
        gbinder_local_object_handle_acquire_proc);
 | 
			
		||||
}
 | 
			
		||||
@@ -487,6 +489,7 @@ gbinder_local_object_finalize(
 | 
			
		||||
    GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
 | 
			
		||||
    GBinderLocalObjectPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    GASSERT(!self->strong_refs);
 | 
			
		||||
    gbinder_ipc_unref(self->ipc);
 | 
			
		||||
    g_free(priv->iface);
 | 
			
		||||
    G_OBJECT_CLASS(gbinder_local_object_parent_class)->finalize(local);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
#include "gbinder_local_reply_p.h"
 | 
			
		||||
#include "gbinder_output_data.h"
 | 
			
		||||
#include "gbinder_writer_p.h"
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_intarray.h>
 | 
			
		||||
@@ -92,6 +93,20 @@ gbinder_local_reply_new(
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
gbinder_local_reply_new_from_data(
 | 
			
		||||
    GBinderBuffer* buffer,
 | 
			
		||||
    void** objects)
 | 
			
		||||
{
 | 
			
		||||
    const GBinderIo* io = gbinder_buffer_io(buffer);
 | 
			
		||||
    GBinderLocalReply* self = gbinder_local_reply_new(io);
 | 
			
		||||
 | 
			
		||||
    if (self) {
 | 
			
		||||
        gbinder_writer_data_set_contents(&self->data, buffer, objects);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_reply_free(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -45,6 +45,11 @@ GBinderOutputData*
 | 
			
		||||
gbinder_local_reply_data(
 | 
			
		||||
    GBinderLocalReply* reply);
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
gbinder_local_reply_new_from_data(
 | 
			
		||||
    GBinderBuffer* buffer,
 | 
			
		||||
    void** objects);
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_LOCAL_REPLY_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -33,6 +33,8 @@
 | 
			
		||||
#include "gbinder_local_request_p.h"
 | 
			
		||||
#include "gbinder_output_data.h"
 | 
			
		||||
#include "gbinder_writer_p.h"
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_intarray.h>
 | 
			
		||||
@@ -42,6 +44,7 @@ struct gbinder_local_request {
 | 
			
		||||
    gint refcount;
 | 
			
		||||
    GBinderWriterData data;
 | 
			
		||||
    GBinderOutputData out;
 | 
			
		||||
    GBinderBufferMemory* memory;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GBINDER_INLINE_FUNC
 | 
			
		||||
@@ -101,6 +104,20 @@ gbinder_local_request_new(
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_local_request_new_from_data(
 | 
			
		||||
    GBinderBuffer* buffer,
 | 
			
		||||
    void** objects)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* self = gbinder_local_request_new
 | 
			
		||||
        (gbinder_buffer_io(buffer), NULL);
 | 
			
		||||
 | 
			
		||||
    if (self) {
 | 
			
		||||
        gbinder_writer_data_set_contents(&self->data, buffer, objects);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_request_free(
 | 
			
		||||
@@ -111,6 +128,7 @@ gbinder_local_request_free(
 | 
			
		||||
    g_byte_array_free(data->bytes, TRUE);
 | 
			
		||||
    gutil_int_array_free(data->offsets, TRUE);
 | 
			
		||||
    gbinder_cleanup_free(data->cleanup);
 | 
			
		||||
    gbinder_buffer_memory_unref(self->memory);
 | 
			
		||||
    g_slice_free(GBinderLocalRequest, self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -46,6 +46,11 @@ GBinderOutputData*
 | 
			
		||||
gbinder_local_request_data(
 | 
			
		||||
    GBinderLocalRequest* req);
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_local_request_new_from_data(
 | 
			
		||||
    GBinderBuffer* buffer,
 | 
			
		||||
    void** objects);
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -305,6 +305,77 @@ gbinder_reader_skip_buffer(
 | 
			
		||||
    return gbinder_reader_read_buffer_impl(reader, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Helper for gbinder_reader_read_hidl_struct() macro */
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_struct1(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize size) /* since 1.0.9 */
 | 
			
		||||
{
 | 
			
		||||
    const void* result = NULL;
 | 
			
		||||
    GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
 | 
			
		||||
 | 
			
		||||
    /* Check the size */
 | 
			
		||||
    if (buf && buf->size == size) {
 | 
			
		||||
        result = buf->data;
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Doesn't copy the data */
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_vec(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* count,
 | 
			
		||||
    gsize* elemsize)
 | 
			
		||||
{
 | 
			
		||||
    GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
 | 
			
		||||
    gsize out_count = 0, out_elemsize = 0;
 | 
			
		||||
    const void* out = NULL;
 | 
			
		||||
 | 
			
		||||
    if (buf && buf->size == sizeof(HidlVec)) {
 | 
			
		||||
        const HidlVec* vec = buf->data;
 | 
			
		||||
        const void* next = vec->data.ptr;
 | 
			
		||||
 | 
			
		||||
        if (next) {
 | 
			
		||||
            GBinderBuffer* vbuf = gbinder_reader_read_buffer(reader);
 | 
			
		||||
 | 
			
		||||
            if (vbuf && vbuf->data == next && ((!vec->count && !vbuf->size) ||
 | 
			
		||||
                (vec->count && vbuf->size && !(vbuf->size % vec->count)))) {
 | 
			
		||||
                out_elemsize = vec->count ? (vbuf->size / vec->count) : 0;
 | 
			
		||||
                out_count = vec->count;
 | 
			
		||||
                out = vbuf->data;
 | 
			
		||||
            }
 | 
			
		||||
            gbinder_buffer_free(vbuf);
 | 
			
		||||
        } else if (!vec->count) {
 | 
			
		||||
            /* Any non-NULL pointer just to indicate success */
 | 
			
		||||
            out = vec;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
    if (elemsize) {
 | 
			
		||||
        *elemsize = out_elemsize;
 | 
			
		||||
    }
 | 
			
		||||
    if (count) {
 | 
			
		||||
        *count = out_count;
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Helper for gbinder_reader_read_hidl_struct_vec() macro */
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_vec1(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* count,
 | 
			
		||||
    guint expected_elem_size) /* since 1.0.9 */
 | 
			
		||||
{
 | 
			
		||||
    gsize actual;
 | 
			
		||||
    const void* data = gbinder_reader_read_hidl_vec(reader, count, &actual);
 | 
			
		||||
 | 
			
		||||
    /* Actual size will be zero for an empty array */
 | 
			
		||||
    return (data && (actual == expected_elem_size || !actual)) ? data : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char*
 | 
			
		||||
gbinder_reader_read_hidl_string(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
@@ -484,6 +555,32 @@ gbinder_reader_skip_string16(
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_byte_array(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize* len) /* since 1.0.12 */
 | 
			
		||||
{
 | 
			
		||||
    GBinderReaderPriv* p = gbinder_reader_cast(reader);
 | 
			
		||||
    const void* data = NULL;
 | 
			
		||||
    const gint32* ptr;
 | 
			
		||||
    *len = 0;
 | 
			
		||||
 | 
			
		||||
    if (gbinder_reader_can_read(p, sizeof(*ptr))) {
 | 
			
		||||
        ptr = (void*)p->ptr;
 | 
			
		||||
        if (*ptr <= 0) {
 | 
			
		||||
            p->ptr += sizeof(*ptr);
 | 
			
		||||
            /* Any non-NULL pointer just to indicate success */
 | 
			
		||||
            data = p->start;
 | 
			
		||||
        } else if (gbinder_reader_can_read(p, sizeof(*ptr) + *ptr)) {
 | 
			
		||||
            *len = (gsize)*ptr;
 | 
			
		||||
            p->ptr += sizeof(*ptr);
 | 
			
		||||
            data = p->ptr;
 | 
			
		||||
            p->ptr += *len;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gsize
 | 
			
		||||
gbinder_reader_bytes_read(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_remote_reply_p.h"
 | 
			
		||||
#include "gbinder_local_reply_p.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
#include "gbinder_object_registry.h"
 | 
			
		||||
#include "gbinder_buffer.h"
 | 
			
		||||
@@ -117,6 +118,18 @@ gbinder_remote_reply_is_empty(
 | 
			
		||||
    return !self || !self->data.buffer || !self->data.buffer->size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
gbinder_remote_reply_copy_to_local(
 | 
			
		||||
    GBinderRemoteReply* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        GBinderReaderData* d = &self->data;
 | 
			
		||||
 | 
			
		||||
        return gbinder_local_reply_new_from_data(d->buffer, d->objects);
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
inline
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
#include "gbinder_remote_request_p.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
#include "gbinder_rpc_protocol.h"
 | 
			
		||||
#include "gbinder_local_request_p.h"
 | 
			
		||||
#include "gbinder_object_registry.h"
 | 
			
		||||
#include "gbinder_buffer.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
@@ -68,6 +69,18 @@ gbinder_remote_request_new(
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_remote_request_copy_to_local(
 | 
			
		||||
    GBinderRemoteRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        GBinderReaderData* d = &self->data;
 | 
			
		||||
 | 
			
		||||
        return gbinder_local_request_new_from_data(d->buffer, d->objects);
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_request_free(
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -109,22 +109,22 @@ gbinder_rpc_protocol_hwbinder_read_rpc_header(
 | 
			
		||||
 * Interface
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
const GBinderRpcProtocol gbinder_rpc_protocol_binder = {
 | 
			
		||||
    .read_rpc_header = gbinder_rpc_protocol_binder_read_rpc_header,
 | 
			
		||||
    .write_rpc_header = gbinder_rpc_protocol_binder_write_rpc_header
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const GBinderRpcProtocol gbinder_rpc_protocol_hwbinder = {
 | 
			
		||||
    .read_rpc_header = gbinder_rpc_protocol_hwbinder_read_rpc_header,
 | 
			
		||||
    .write_rpc_header = gbinder_rpc_protocol_hwbinder_write_rpc_header
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const GBinderRpcProtocol*
 | 
			
		||||
gbinder_rpc_protocol_for_device(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    static const GBinderRpcProtocol protocol_binder = {
 | 
			
		||||
        .read_rpc_header = gbinder_rpc_protocol_binder_read_rpc_header,
 | 
			
		||||
        .write_rpc_header = gbinder_rpc_protocol_binder_write_rpc_header
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const GBinderRpcProtocol protocol_hwbinder = {
 | 
			
		||||
        .read_rpc_header = gbinder_rpc_protocol_hwbinder_read_rpc_header,
 | 
			
		||||
        .write_rpc_header = gbinder_rpc_protocol_hwbinder_write_rpc_header
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return (dev && !strcmp(dev, GBINDER_DEFAULT_HWBINDER)) ?
 | 
			
		||||
        &protocol_hwbinder : &protocol_binder;
 | 
			
		||||
        &gbinder_rpc_protocol_hwbinder : &gbinder_rpc_protocol_binder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,10 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *      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
 | 
			
		||||
@@ -45,6 +46,10 @@ struct gbinder_rpc_protocol {
 | 
			
		||||
    void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const GBinderRpcProtocol gbinder_rpc_protocol_binder;
 | 
			
		||||
extern const GBinderRpcProtocol gbinder_rpc_protocol_hwbinder;
 | 
			
		||||
 | 
			
		||||
/* Returns one of the above based on the device name */
 | 
			
		||||
const GBinderRpcProtocol*
 | 
			
		||||
gbinder_rpc_protocol_for_device(
 | 
			
		||||
    const char* dev);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -44,6 +44,17 @@
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_servicemanager_watch {
 | 
			
		||||
    char* name;
 | 
			
		||||
    char* detail;
 | 
			
		||||
    GQuark quark;
 | 
			
		||||
    gboolean watched;
 | 
			
		||||
} GBinderServiceManagerWatch;
 | 
			
		||||
 | 
			
		||||
struct gbinder_servicemanager_priv {
 | 
			
		||||
    GHashTable* watch_table;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
 | 
			
		||||
    G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +71,16 @@ G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
 | 
			
		||||
#define GBINDER_IS_SERVICEMANAGER_TYPE(klass) \
 | 
			
		||||
    G_TYPE_CHECK_CLASS_TYPE(klass, GBINDER_TYPE_SERVICEMANAGER)
 | 
			
		||||
 | 
			
		||||
enum gbinder_servicemanager_signal {
 | 
			
		||||
    SIGNAL_REGISTRATION,
 | 
			
		||||
    SIGNAL_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char SIGNAL_REGISTRATION_NAME[] = "servicemanager-registration";
 | 
			
		||||
#define DETAIL_LEN 32
 | 
			
		||||
 | 
			
		||||
static guint gbinder_servicemanager_signals[SIGNAL_COUNT] = { 0 };
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Implementation
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -81,53 +102,29 @@ gbinder_servicemanager_class_ref(
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new_with_type(
 | 
			
		||||
    GType type,
 | 
			
		||||
    const char* dev)
 | 
			
		||||
static
 | 
			
		||||
GBinderServiceManagerWatch*
 | 
			
		||||
gbinder_servicemanager_watch_new(
 | 
			
		||||
    const char* name)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManager* self = NULL;
 | 
			
		||||
    GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
 | 
			
		||||
    GBinderServiceManagerWatch* watch = g_new0(GBinderServiceManagerWatch, 1);
 | 
			
		||||
 | 
			
		||||
    if (klass) {
 | 
			
		||||
        GBinderIpc* ipc;
 | 
			
		||||
    watch->name = g_strdup(name);
 | 
			
		||||
    watch->detail = g_compute_checksum_for_string(G_CHECKSUM_MD5, name, -1);
 | 
			
		||||
    watch->quark = g_quark_from_string(watch->detail);
 | 
			
		||||
    return watch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        if (!dev) dev = klass->default_device;
 | 
			
		||||
        ipc = gbinder_ipc_new(dev);
 | 
			
		||||
        if (ipc) {
 | 
			
		||||
            GBinderRemoteObject* object = gbinder_ipc_get_remote_object
 | 
			
		||||
                (ipc, klass->handle);
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_watch_free(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManagerWatch* watch = data;
 | 
			
		||||
 | 
			
		||||
            if (object) {
 | 
			
		||||
                /* Lock */
 | 
			
		||||
                g_mutex_lock(&klass->mutex);
 | 
			
		||||
                if (klass->table) {
 | 
			
		||||
                    self = g_hash_table_lookup(klass->table, dev);
 | 
			
		||||
                }
 | 
			
		||||
                if (self) {
 | 
			
		||||
                    gbinder_servicemanager_ref(self);
 | 
			
		||||
                } else {
 | 
			
		||||
                    char* key = g_strdup(dev); /* Owned by the hashtable */
 | 
			
		||||
 | 
			
		||||
                    GVERBOSE_("%s", dev);
 | 
			
		||||
                    self = g_object_new(type, NULL);
 | 
			
		||||
                    self->client = gbinder_client_new(object, klass->iface);
 | 
			
		||||
                    self->dev = gbinder_remote_object_dev(object);
 | 
			
		||||
                    if (!klass->table) {
 | 
			
		||||
                        klass->table = g_hash_table_new_full(g_str_hash,
 | 
			
		||||
                            g_str_equal, g_free, NULL);
 | 
			
		||||
                    }
 | 
			
		||||
                    g_hash_table_replace(klass->table, key, self);
 | 
			
		||||
                }
 | 
			
		||||
                g_mutex_unlock(&klass->mutex);
 | 
			
		||||
                /* Unlock */
 | 
			
		||||
                gbinder_remote_object_unref(object);
 | 
			
		||||
            }
 | 
			
		||||
            gbinder_ipc_unref(ipc);
 | 
			
		||||
        }
 | 
			
		||||
        g_type_class_unref(klass);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
    g_free(watch->name);
 | 
			
		||||
    g_free(watch->detail);
 | 
			
		||||
    g_free(watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_servicemanager_list_tx_data {
 | 
			
		||||
@@ -256,6 +253,89 @@ gbinder_servicemanager_add_service_tx_free(
 | 
			
		||||
    g_slice_free(GBinderServiceManagerAddServiceTxData, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal interface
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new_with_type(
 | 
			
		||||
    GType type,
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManager* self = NULL;
 | 
			
		||||
    GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
 | 
			
		||||
 | 
			
		||||
    if (klass) {
 | 
			
		||||
        GBinderIpc* ipc;
 | 
			
		||||
 | 
			
		||||
        if (!dev) dev = klass->default_device;
 | 
			
		||||
        ipc = gbinder_ipc_new(dev, klass->rpc_protocol);
 | 
			
		||||
        if (ipc) {
 | 
			
		||||
            GBinderRemoteObject* object = gbinder_ipc_get_remote_object
 | 
			
		||||
                (ipc, klass->handle);
 | 
			
		||||
 | 
			
		||||
            if (object) {
 | 
			
		||||
                /* Lock */
 | 
			
		||||
                g_mutex_lock(&klass->mutex);
 | 
			
		||||
                if (klass->table) {
 | 
			
		||||
                    self = g_hash_table_lookup(klass->table, dev);
 | 
			
		||||
                }
 | 
			
		||||
                if (self) {
 | 
			
		||||
                    gbinder_servicemanager_ref(self);
 | 
			
		||||
                } else {
 | 
			
		||||
                    char* key = g_strdup(dev); /* Owned by the hashtable */
 | 
			
		||||
 | 
			
		||||
                    GVERBOSE_("%s", dev);
 | 
			
		||||
                    self = g_object_new(type, NULL);
 | 
			
		||||
                    self->client = gbinder_client_new(object, klass->iface);
 | 
			
		||||
                    self->dev = gbinder_remote_object_dev(object);
 | 
			
		||||
                    if (!klass->table) {
 | 
			
		||||
                        klass->table = g_hash_table_new_full(g_str_hash,
 | 
			
		||||
                            g_str_equal, g_free, NULL);
 | 
			
		||||
                    }
 | 
			
		||||
                    g_hash_table_replace(klass->table, key, self);
 | 
			
		||||
                }
 | 
			
		||||
                g_mutex_unlock(&klass->mutex);
 | 
			
		||||
                /* Unlock */
 | 
			
		||||
                gbinder_remote_object_unref(object);
 | 
			
		||||
            }
 | 
			
		||||
            gbinder_ipc_unref(ipc);
 | 
			
		||||
        }
 | 
			
		||||
        g_type_class_unref(klass);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_service_registered(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManagerClass* klass = GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
			
		||||
    GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
    GBinderServiceManagerWatch* watch = NULL;
 | 
			
		||||
    const char* normalized_name;
 | 
			
		||||
    char* tmp_name = NULL;
 | 
			
		||||
 | 
			
		||||
    switch (klass->check_name(self, name)) {
 | 
			
		||||
    case GBINDER_SERVICEMANAGER_NAME_OK:
 | 
			
		||||
        normalized_name = name;
 | 
			
		||||
        break;
 | 
			
		||||
    case GBINDER_SERVICEMANAGER_NAME_NORMALIZE:
 | 
			
		||||
        normalized_name = tmp_name = klass->normalize_name(self, name);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        normalized_name = NULL;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    if (normalized_name) {
 | 
			
		||||
        watch = g_hash_table_lookup(priv->watch_table, normalized_name);
 | 
			
		||||
    }
 | 
			
		||||
    g_free(tmp_name);
 | 
			
		||||
    g_signal_emit(self, gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
 | 
			
		||||
        watch ? watch->quark : 0, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Interface
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -433,6 +513,88 @@ gbinder_servicemanager_cancel(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
gbinder_servicemanager_add_registration_handler(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderServiceManagerRegistrationFunc func,
 | 
			
		||||
    void* data) /* Since 1.0.13 */
 | 
			
		||||
{
 | 
			
		||||
    gulong id = 0;
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(self) && G_LIKELY(func)) {
 | 
			
		||||
        char* tmp_name = NULL;
 | 
			
		||||
        GBinderServiceManagerClass* klass =
 | 
			
		||||
            GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
			
		||||
 | 
			
		||||
        switch (klass->check_name(self, name)) {
 | 
			
		||||
        case GBINDER_SERVICEMANAGER_NAME_OK:
 | 
			
		||||
            break;
 | 
			
		||||
        case GBINDER_SERVICEMANAGER_NAME_NORMALIZE:
 | 
			
		||||
            name = tmp_name = klass->normalize_name(self, name);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            name = NULL;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (name) {
 | 
			
		||||
            GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
            GBinderServiceManagerWatch* watch = NULL;
 | 
			
		||||
 | 
			
		||||
            watch = g_hash_table_lookup(priv->watch_table, name);
 | 
			
		||||
            if (!watch) {
 | 
			
		||||
                watch = gbinder_servicemanager_watch_new(name);
 | 
			
		||||
                g_hash_table_insert(priv->watch_table, watch->name, watch);
 | 
			
		||||
            }
 | 
			
		||||
            if (!watch->watched) {
 | 
			
		||||
                watch->watched = klass->watch(self, name);
 | 
			
		||||
                if (watch->watched) {
 | 
			
		||||
                    GDEBUG("Watching %s", watch->name);
 | 
			
		||||
                } else {
 | 
			
		||||
                    GWARN("Failed to watch %s", watch->name);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            id = g_signal_connect_closure_by_id(self,
 | 
			
		||||
                gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
 | 
			
		||||
                watch->quark, g_cclosure_new(G_CALLBACK(func), data, NULL),
 | 
			
		||||
                FALSE);
 | 
			
		||||
        }
 | 
			
		||||
        g_free(tmp_name);
 | 
			
		||||
    }
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_remove_handler(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    gulong id) /* Since 1.0.13 */
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self) && G_LIKELY(id)) {
 | 
			
		||||
        GBinderServiceManagerClass* klass =
 | 
			
		||||
            GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
			
		||||
        GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
        GHashTableIter it;
 | 
			
		||||
        gpointer value;
 | 
			
		||||
 | 
			
		||||
        g_signal_handler_disconnect(self, id);
 | 
			
		||||
        g_hash_table_iter_init(&it, priv->watch_table);
 | 
			
		||||
        while (g_hash_table_iter_next(&it, NULL, &value)) {
 | 
			
		||||
            GBinderServiceManagerWatch* watch = value;
 | 
			
		||||
 | 
			
		||||
            if (watch->watched && !g_signal_has_handler_pending(self,
 | 
			
		||||
                gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
 | 
			
		||||
                watch->quark, TRUE)) {
 | 
			
		||||
                /* This must be the one we have just removed */
 | 
			
		||||
                GDEBUG("Unwatching %s", watch->name);
 | 
			
		||||
                watch->watched = FALSE;
 | 
			
		||||
                klass->unwatch(self, watch->name);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internals
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -442,6 +604,12 @@ void
 | 
			
		||||
gbinder_servicemanager_init(
 | 
			
		||||
    GBinderServiceManager* self)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManagerPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
 | 
			
		||||
        GBINDER_TYPE_SERVICEMANAGER, GBinderServiceManagerPriv);
 | 
			
		||||
 | 
			
		||||
    self->priv = priv;
 | 
			
		||||
    priv->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 | 
			
		||||
        NULL, gbinder_servicemanager_watch_free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -450,8 +618,7 @@ gbinder_servicemanager_dispose(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
 | 
			
		||||
    GBinderServiceManagerClass* klass =
 | 
			
		||||
        GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
			
		||||
    GBinderServiceManagerClass* klass = GBINDER_SERVICEMANAGER_GET_CLASS(self);
 | 
			
		||||
 | 
			
		||||
    GVERBOSE_("%s", self->dev);
 | 
			
		||||
    /* Lock */
 | 
			
		||||
@@ -493,9 +660,10 @@ gbinder_servicemanager_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
 | 
			
		||||
    GBinderServiceManagerPriv* priv = self->priv;
 | 
			
		||||
 | 
			
		||||
    gutil_idle_pool_drain(self->pool);
 | 
			
		||||
    gutil_idle_pool_unref(self->pool);
 | 
			
		||||
    g_hash_table_destroy(priv->watch_table);
 | 
			
		||||
    gutil_idle_pool_destroy(self->pool);
 | 
			
		||||
    gbinder_client_unref(self->client);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
@@ -508,8 +676,13 @@ gbinder_servicemanager_class_init(
 | 
			
		||||
    GObjectClass* object_class = G_OBJECT_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    g_mutex_init(&klass->mutex);
 | 
			
		||||
    g_type_class_add_private(klass, sizeof(GBinderServiceManagerPriv));
 | 
			
		||||
    object_class->dispose = gbinder_servicemanager_dispose;
 | 
			
		||||
    object_class->finalize = gbinder_servicemanager_finalize;
 | 
			
		||||
    gbinder_servicemanager_signals[SIGNAL_REGISTRATION] =
 | 
			
		||||
        g_signal_new(SIGNAL_REGISTRATION_NAME, G_OBJECT_CLASS_TYPE(klass),
 | 
			
		||||
            G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, 0, NULL, NULL, NULL,
 | 
			
		||||
            G_TYPE_NONE, 1, G_TYPE_STRING);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -39,13 +39,22 @@
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_servicemanager_priv GBinderServiceManagerPriv;
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_servicemanager {
 | 
			
		||||
    GObject parent;
 | 
			
		||||
    GBinderServiceManagerPriv* priv;
 | 
			
		||||
    const char* dev;
 | 
			
		||||
    GBinderClient* client;
 | 
			
		||||
    GUtilIdlePool* pool;
 | 
			
		||||
} GBinderServiceManager;
 | 
			
		||||
 | 
			
		||||
typedef enum gbinder_servicemanager_name_check {
 | 
			
		||||
    GBINDER_SERVICEMANAGER_NAME_OK,
 | 
			
		||||
    GBINDER_SERVICEMANAGER_NAME_NORMALIZE,
 | 
			
		||||
    GBINDER_SERVICEMANAGER_NAME_INVALID,
 | 
			
		||||
} GBINDER_SERVICEMANAGER_NAME_CHECK;
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_servicemanager_class {
 | 
			
		||||
    GObjectClass parent;
 | 
			
		||||
    GMutex mutex;
 | 
			
		||||
@@ -54,6 +63,7 @@ typedef struct gbinder_servicemanager_class {
 | 
			
		||||
    guint32 handle;
 | 
			
		||||
    const char* iface;
 | 
			
		||||
    const char* default_device;
 | 
			
		||||
    const GBinderRpcProtocol* rpc_protocol;
 | 
			
		||||
 | 
			
		||||
    /* Methods (synchronous) */
 | 
			
		||||
    char** (*list)(GBinderServiceManager* self);
 | 
			
		||||
@@ -62,6 +72,15 @@ typedef struct gbinder_servicemanager_class {
 | 
			
		||||
    int (*add_service)
 | 
			
		||||
        (GBinderServiceManager* self, const char* name,
 | 
			
		||||
            GBinderLocalObject* obj);
 | 
			
		||||
 | 
			
		||||
    /* Checking/normalizing watch names */
 | 
			
		||||
    GBINDER_SERVICEMANAGER_NAME_CHECK (*check_name)
 | 
			
		||||
        (GBinderServiceManager* self, const char* name);
 | 
			
		||||
    char* (*normalize_name)(GBinderServiceManager* self, const char* name);
 | 
			
		||||
 | 
			
		||||
    /* If watch() returns FALSE, unwatch() is not called */
 | 
			
		||||
    gboolean (*watch)(GBinderServiceManager* self, const char* name);
 | 
			
		||||
    void (*unwatch)(GBinderServiceManager* self, const char* name);
 | 
			
		||||
} GBinderServiceManagerClass;
 | 
			
		||||
 | 
			
		||||
GType gbinder_servicemanager_get_type(void);
 | 
			
		||||
@@ -72,6 +91,11 @@ gbinder_servicemanager_new_with_type(
 | 
			
		||||
    GType type,
 | 
			
		||||
    const char* dev);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_service_registered(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name);
 | 
			
		||||
 | 
			
		||||
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -35,6 +35,7 @@
 | 
			
		||||
 | 
			
		||||
#include <gbinder_types.h>
 | 
			
		||||
 | 
			
		||||
typedef struct gbinder_buffer_memory GBinderBufferMemory;
 | 
			
		||||
typedef struct gbinder_cleanup GBinderCleanup;
 | 
			
		||||
typedef struct gbinder_driver GBinderDriver;
 | 
			
		||||
typedef struct gbinder_handler GBinderHandler;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "gbinder_writer_p.h"
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
#include "gbinder_log.h"
 | 
			
		||||
 | 
			
		||||
@@ -51,6 +52,53 @@ GBINDER_INLINE_FUNC GBinderWriterPriv* gbinder_writer_cast(GBinderWriter* pub)
 | 
			
		||||
GBINDER_INLINE_FUNC GBinderWriterData* gbinder_writer_data(GBinderWriter* pub)
 | 
			
		||||
    { return G_LIKELY(pub) ? gbinder_writer_cast(pub)->data : NULL; }
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_memory_cleanup(
 | 
			
		||||
    gpointer memory)
 | 
			
		||||
{
 | 
			
		||||
    gbinder_buffer_memory_unref(memory);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_set_contents(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    GBinderBuffer* buffer,
 | 
			
		||||
    void** objects)
 | 
			
		||||
{
 | 
			
		||||
    gsize bufsize;
 | 
			
		||||
    const guint8* bufdata = gbinder_buffer_data(buffer, &bufsize);
 | 
			
		||||
    const GBinderIo* io = gbinder_buffer_io(buffer);
 | 
			
		||||
    GBinderBufferMemory* mem = gbinder_buffer_memory(buffer);
 | 
			
		||||
 | 
			
		||||
    GASSERT(data->io == io);
 | 
			
		||||
    g_byte_array_set_size(data->bytes, 0);
 | 
			
		||||
    gutil_int_array_set_count(data->offsets, 0);
 | 
			
		||||
    data->buffers_size = 0;
 | 
			
		||||
 | 
			
		||||
    g_byte_array_append(data->bytes, bufdata, bufsize);
 | 
			
		||||
    if (mem) {
 | 
			
		||||
        data->cleanup = gbinder_cleanup_add(data->cleanup,
 | 
			
		||||
            gbinder_writer_data_memory_cleanup,
 | 
			
		||||
            gbinder_buffer_memory_ref(mem));
 | 
			
		||||
    }
 | 
			
		||||
    if (objects && *objects) {
 | 
			
		||||
        if (!data->offsets) {
 | 
			
		||||
            data->offsets = gutil_int_array_new();
 | 
			
		||||
        }
 | 
			
		||||
        while (*objects) {
 | 
			
		||||
            const guint8* obj = *objects++;
 | 
			
		||||
            gsize offset = obj - bufdata;
 | 
			
		||||
            gsize objsize = io->object_data_size(obj);
 | 
			
		||||
 | 
			
		||||
            GASSERT(offset > 0 && offset < bufsize);
 | 
			
		||||
            gutil_int_array_append(data->offsets, (int)offset);
 | 
			
		||||
            /* Size of each buffer has to be 8-byte aligned */
 | 
			
		||||
            data->buffers_size += G_ALIGN8(objsize);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_record_offset(
 | 
			
		||||
@@ -71,16 +119,16 @@ gbinder_writer_data_write_buffer_object(
 | 
			
		||||
    gsize size,
 | 
			
		||||
    const GBinderParent* parent)
 | 
			
		||||
{
 | 
			
		||||
    GByteArray* dest = data->bytes;
 | 
			
		||||
    const guint offset = dest->len;
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    const guint offset = buf->len;
 | 
			
		||||
    guint n;
 | 
			
		||||
 | 
			
		||||
    /* Preallocate enough space */
 | 
			
		||||
    g_byte_array_set_size(dest, offset + GBINDER_MAX_BUFFER_OBJECT_SIZE);
 | 
			
		||||
    g_byte_array_set_size(buf, offset + GBINDER_MAX_BUFFER_OBJECT_SIZE);
 | 
			
		||||
    /* Write the object */
 | 
			
		||||
    n = data->io->encode_buffer_object(dest->data + offset, ptr, size, parent);
 | 
			
		||||
    n = data->io->encode_buffer_object(buf->data + offset, ptr, size, parent);
 | 
			
		||||
    /* Fix the data size */
 | 
			
		||||
    g_byte_array_set_size(dest, offset + n);
 | 
			
		||||
    g_byte_array_set_size(buf, offset + n);
 | 
			
		||||
    /* Record the offset */
 | 
			
		||||
    gbinder_writer_data_record_offset(data, offset);
 | 
			
		||||
    /* The driver seems to require each buffer to be 8-byte aligned */
 | 
			
		||||
@@ -117,7 +165,7 @@ gbinder_writer_data_append_bool(
 | 
			
		||||
 | 
			
		||||
    /* Boolean values are padded to 4-byte boundary */
 | 
			
		||||
    padded[0] = (value != FALSE);
 | 
			
		||||
    padded[1] = padded[2] = padded[3] = 0xff;
 | 
			
		||||
    padded[1] = padded[2] = padded[3] = 0;
 | 
			
		||||
    g_byte_array_append(data->bytes, padded, sizeof(padded));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -138,10 +186,11 @@ gbinder_writer_data_append_int32(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    guint32 value)
 | 
			
		||||
{
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    guint32* ptr;
 | 
			
		||||
 | 
			
		||||
    g_byte_array_set_size(data->bytes, data->bytes->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(data->bytes->data + (data->bytes->len - sizeof(*ptr)));
 | 
			
		||||
    g_byte_array_set_size(buf, buf->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(buf->data + (buf->len - sizeof(*ptr)));
 | 
			
		||||
    *ptr = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -162,10 +211,11 @@ gbinder_writer_data_append_int64(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    guint64 value)
 | 
			
		||||
{
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    guint64* ptr;
 | 
			
		||||
 | 
			
		||||
    g_byte_array_set_size(data->bytes, data->bytes->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(data->bytes->data + (data->bytes->len - sizeof(*ptr)));
 | 
			
		||||
    g_byte_array_set_size(buf, buf->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(buf->data + (buf->len - sizeof(*ptr)));
 | 
			
		||||
    *ptr = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -186,10 +236,11 @@ gbinder_writer_data_append_float(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    gfloat value)
 | 
			
		||||
{
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    gfloat* ptr;
 | 
			
		||||
 | 
			
		||||
    g_byte_array_set_size(data->bytes, data->bytes->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(data->bytes->data + (data->bytes->len - sizeof(*ptr)));
 | 
			
		||||
    g_byte_array_set_size(buf, buf->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(buf->data + (buf->len - sizeof(*ptr)));
 | 
			
		||||
    *ptr = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -210,10 +261,11 @@ gbinder_writer_data_append_double(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    gdouble value)
 | 
			
		||||
{
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    gdouble* ptr;
 | 
			
		||||
 | 
			
		||||
    g_byte_array_set_size(data->bytes, data->bytes->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(data->bytes->data + (data->bytes->len - sizeof(*ptr)));
 | 
			
		||||
    g_byte_array_set_size(buf, buf->len + sizeof(*ptr));
 | 
			
		||||
    ptr = (void*)(buf->data + (buf->len - sizeof(*ptr)));
 | 
			
		||||
    *ptr = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -253,15 +305,16 @@ gbinder_writer_data_append_string8_len(
 | 
			
		||||
    gsize len)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(str)) {
 | 
			
		||||
        const gsize old_size = data->bytes->len;
 | 
			
		||||
        GByteArray* buf = data->bytes;
 | 
			
		||||
        const gsize old_size = buf->len;
 | 
			
		||||
        gsize padded_len = G_ALIGN4(len + 1);
 | 
			
		||||
        guint32* dest;
 | 
			
		||||
 | 
			
		||||
        /* Preallocate space */
 | 
			
		||||
        g_byte_array_set_size(data->bytes, old_size + padded_len);
 | 
			
		||||
        g_byte_array_set_size(buf, old_size + padded_len);
 | 
			
		||||
 | 
			
		||||
        /* Zero the last word */
 | 
			
		||||
        dest = (guint32*)(data->bytes->data + old_size);
 | 
			
		||||
        dest = (guint32*)(buf->data + old_size);
 | 
			
		||||
        dest[padded_len/4 - 1] = 0;
 | 
			
		||||
 | 
			
		||||
        /* Copy the data */
 | 
			
		||||
@@ -304,7 +357,8 @@ gbinder_writer_data_append_string16_len(
 | 
			
		||||
    const char* utf8,
 | 
			
		||||
    gssize num_bytes)
 | 
			
		||||
{
 | 
			
		||||
    const gsize old_size = data->bytes->len;
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    const gsize old_size = buf->len;
 | 
			
		||||
 | 
			
		||||
    if (utf8) {
 | 
			
		||||
        const char* end = utf8;
 | 
			
		||||
@@ -322,8 +376,8 @@ gbinder_writer_data_append_string16_len(
 | 
			
		||||
        gunichar2* utf16_ptr;
 | 
			
		||||
 | 
			
		||||
        /* Preallocate space */
 | 
			
		||||
        g_byte_array_set_size(data->bytes, old_size + padded_len + 4);
 | 
			
		||||
        len_ptr = (guint32*)(data->bytes->data + old_size);
 | 
			
		||||
        g_byte_array_set_size(buf, old_size + padded_len + 4);
 | 
			
		||||
        len_ptr = (guint32*)(buf->data + old_size);
 | 
			
		||||
        utf16_ptr = (gunichar2*)(len_ptr + 1);
 | 
			
		||||
 | 
			
		||||
        /* TODO: this could be optimized for ASCII strings, i.e. if
 | 
			
		||||
@@ -350,13 +404,13 @@ gbinder_writer_data_append_string16_len(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Correct the packet size if necessaary */
 | 
			
		||||
        g_byte_array_set_size(data->bytes, old_size + padded_len + 4);
 | 
			
		||||
        g_byte_array_set_size(buf, old_size + padded_len + 4);
 | 
			
		||||
    } else if (utf8) {
 | 
			
		||||
        /* Empty string */
 | 
			
		||||
        guint16* ptr16;
 | 
			
		||||
 | 
			
		||||
        g_byte_array_set_size(data->bytes, old_size + 8);
 | 
			
		||||
        ptr16 = (guint16*)(data->bytes->data + old_size);
 | 
			
		||||
        g_byte_array_set_size(buf, old_size + 8);
 | 
			
		||||
        ptr16 = (guint16*)(buf->data + old_size);
 | 
			
		||||
        ptr16[0] = ptr16[1] = ptr16[2] = 0; ptr16[3] = 0xffff;
 | 
			
		||||
    } else {
 | 
			
		||||
        /* NULL string */
 | 
			
		||||
@@ -442,6 +496,54 @@ gbinder_writer_append_hidl_string(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_vec(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize)
 | 
			
		||||
{
 | 
			
		||||
    GBinderParent vec_parent;
 | 
			
		||||
    HidlVec* vec = g_new0(HidlVec, 1);
 | 
			
		||||
    const gsize total = count * elemsize;
 | 
			
		||||
    void* buf = g_memdup(base, total);
 | 
			
		||||
 | 
			
		||||
    /* Prepare parent descriptor for the string data */
 | 
			
		||||
    vec_parent.index = gbinder_writer_data_prepare(data);
 | 
			
		||||
    vec_parent.offset = HIDL_VEC_BUFFER_OFFSET;
 | 
			
		||||
 | 
			
		||||
    /* Fill in the vector descriptor */
 | 
			
		||||
    if (buf) {
 | 
			
		||||
        vec->data.ptr = buf;
 | 
			
		||||
        vec->count = count;
 | 
			
		||||
        data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, buf);
 | 
			
		||||
    }
 | 
			
		||||
    vec->owns_buffer = TRUE;
 | 
			
		||||
    data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, vec);
 | 
			
		||||
 | 
			
		||||
    /* Write the buffer object pointing to the vector descriptor */
 | 
			
		||||
    gbinder_writer_data_write_buffer_object(data, vec, sizeof(*vec), NULL);
 | 
			
		||||
 | 
			
		||||
    /* Not sure what's the right way to deal with NULL vectors... */
 | 
			
		||||
    if (buf) {
 | 
			
		||||
        gbinder_writer_data_write_buffer_object(data, buf, total, &vec_parent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_hidl_vec(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize)
 | 
			
		||||
{
 | 
			
		||||
    GBinderWriterData* data = gbinder_writer_data(self);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(data)) {
 | 
			
		||||
        gbinder_writer_data_append_hidl_vec(data, base, count, elemsize);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_string(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
@@ -575,16 +677,16 @@ gbinder_writer_data_append_local_object(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GByteArray* dest = data->bytes;
 | 
			
		||||
    const guint offset = dest->len;
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    const guint offset = buf->len;
 | 
			
		||||
    guint n;
 | 
			
		||||
 | 
			
		||||
    /* Preallocate enough space */
 | 
			
		||||
    g_byte_array_set_size(dest, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
 | 
			
		||||
    g_byte_array_set_size(buf, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
 | 
			
		||||
    /* Write the object */
 | 
			
		||||
    n = data->io->encode_local_object(dest->data + offset, obj);
 | 
			
		||||
    n = data->io->encode_local_object(buf->data + offset, obj);
 | 
			
		||||
    /* Fix the data size */
 | 
			
		||||
    g_byte_array_set_size(dest, offset + n);
 | 
			
		||||
    g_byte_array_set_size(buf, offset + n);
 | 
			
		||||
    /* Record the offset */
 | 
			
		||||
    gbinder_writer_data_record_offset(data, offset);
 | 
			
		||||
}
 | 
			
		||||
@@ -601,21 +703,51 @@ gbinder_writer_append_remote_object(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_byte_array(
 | 
			
		||||
    GBinderWriter* self,
 | 
			
		||||
    const void* byte_array,
 | 
			
		||||
    gint32 len) /* since 1.0.12 */
 | 
			
		||||
{
 | 
			
		||||
    GBinderWriterData* data = gbinder_writer_data(self);
 | 
			
		||||
 | 
			
		||||
    GASSERT(len >= 0);
 | 
			
		||||
    if (G_LIKELY(data)) {
 | 
			
		||||
        GByteArray* buf = data->bytes;
 | 
			
		||||
        void* ptr;
 | 
			
		||||
 | 
			
		||||
        if (!byte_array) {
 | 
			
		||||
            len = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        g_byte_array_set_size(buf, buf->len + sizeof(len) + len);
 | 
			
		||||
        ptr = buf->data + (buf->len - sizeof(len) - len);
 | 
			
		||||
 | 
			
		||||
        if (len > 0) {
 | 
			
		||||
            *((gint32*)ptr) = len;
 | 
			
		||||
            ptr += sizeof(len);
 | 
			
		||||
            memcpy(ptr, byte_array, len);
 | 
			
		||||
        } else {
 | 
			
		||||
            *((gint32*)ptr) = -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_remote_object(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    GBinderRemoteObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    GByteArray* dest = data->bytes;
 | 
			
		||||
    const guint offset = dest->len;
 | 
			
		||||
    GByteArray* buf = data->bytes;
 | 
			
		||||
    const guint offset = buf->len;
 | 
			
		||||
    guint n;
 | 
			
		||||
 | 
			
		||||
    /* Preallocate enough space */
 | 
			
		||||
    g_byte_array_set_size(dest, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
 | 
			
		||||
    g_byte_array_set_size(buf, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
 | 
			
		||||
    /* Write the object */
 | 
			
		||||
    n = data->io->encode_remote_object(dest->data + offset, obj);
 | 
			
		||||
    n = data->io->encode_remote_object(buf->data + offset, obj);
 | 
			
		||||
    /* Fix the data size */
 | 
			
		||||
    g_byte_array_set_size(dest, offset + n);
 | 
			
		||||
    g_byte_array_set_size(buf, offset + n);
 | 
			
		||||
    /* Record the offset */
 | 
			
		||||
    gbinder_writer_data_record_offset(data, offset);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -50,6 +50,12 @@ gbinder_writer_init(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    GBinderWriterData* data);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_set_contents(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    GBinderBuffer* buffer,
 | 
			
		||||
    void** objects);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_bool(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
@@ -104,6 +110,13 @@ gbinder_writer_data_append_buffer_object(
 | 
			
		||||
    gsize size,
 | 
			
		||||
    const GBinderParent* parent);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_vec(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
    const void* base,
 | 
			
		||||
    guint count,
 | 
			
		||||
    guint elemsize);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_data_append_hidl_string(
 | 
			
		||||
    GBinderWriterData* data,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -54,10 +54,15 @@ typedef struct app_options {
 | 
			
		||||
 | 
			
		||||
typedef struct app {
 | 
			
		||||
    const AppOptions* opt;
 | 
			
		||||
    char* fqname;
 | 
			
		||||
    GMainLoop* loop;
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    GBinderLocalObject* local;
 | 
			
		||||
    GBinderRemoteObject* remote;
 | 
			
		||||
    gulong wait_id;
 | 
			
		||||
    gulong death_id;
 | 
			
		||||
    GBinderClient* client;
 | 
			
		||||
    GThread* thread;
 | 
			
		||||
    int ret;
 | 
			
		||||
} App;
 | 
			
		||||
 | 
			
		||||
@@ -171,46 +176,80 @@ app_input_thread(
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
app_connect_remote(
 | 
			
		||||
    App* app)
 | 
			
		||||
{
 | 
			
		||||
    app->remote = gbinder_servicemanager_get_service_sync(app->sm,
 | 
			
		||||
        app->fqname, NULL); /* autoreleased pointer */
 | 
			
		||||
 | 
			
		||||
    if (app->remote) {
 | 
			
		||||
        const AppOptions* opt = app->opt;
 | 
			
		||||
 | 
			
		||||
        GINFO("Connected to %s", app->fqname);
 | 
			
		||||
        gbinder_remote_object_ref(app->remote);
 | 
			
		||||
        app->client = gbinder_client_new(app->remote, opt->iface);
 | 
			
		||||
        app->death_id = gbinder_remote_object_add_death_handler(app->remote,
 | 
			
		||||
            app_remote_died, app);
 | 
			
		||||
        app->thread = g_thread_new("input", app_input_thread, app);
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
app_registration_handler(
 | 
			
		||||
    GBinderServiceManager* sm,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    App* app = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("\"%s\" appeared", name);
 | 
			
		||||
    if (!strcmp(name, app->fqname) && app_connect_remote(app)) {
 | 
			
		||||
        gbinder_servicemanager_remove_handler(app->sm, app->wait_id);
 | 
			
		||||
        app->wait_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
app_run(
 | 
			
		||||
   App* app)
 | 
			
		||||
{
 | 
			
		||||
    const AppOptions* opt = app->opt;
 | 
			
		||||
    char* fqname = opt->fqname ? g_strdup(opt->fqname) :
 | 
			
		||||
    guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, app);
 | 
			
		||||
    guint sigint = g_unix_signal_add(SIGINT, app_signal, app);
 | 
			
		||||
 | 
			
		||||
    app->fqname = opt->fqname ? g_strdup(opt->fqname) :
 | 
			
		||||
        strchr(opt->name, '/') ? g_strdup(opt->name) :
 | 
			
		||||
        g_strconcat(opt->iface, "/", opt->name, NULL);
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    GBinderRemoteObject* remote = gbinder_remote_object_ref
 | 
			
		||||
        (gbinder_servicemanager_get_service_sync(app->sm, fqname, &status));
 | 
			
		||||
    if (remote) {
 | 
			
		||||
        guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, app);
 | 
			
		||||
        guint sigint = g_unix_signal_add(SIGINT, app_signal, app);
 | 
			
		||||
        gulong death_id = gbinder_remote_object_add_death_handler
 | 
			
		||||
            (remote, app_remote_died, app);
 | 
			
		||||
        GThread* thread = g_thread_new("input", app_input_thread, app);
 | 
			
		||||
 | 
			
		||||
        GINFO("Connected to %s\n", fqname);
 | 
			
		||||
 | 
			
		||||
        app->client = gbinder_client_new(remote, opt->iface);
 | 
			
		||||
        app->ret = RET_OK;
 | 
			
		||||
        app->loop = g_main_loop_new(NULL, TRUE);
 | 
			
		||||
        g_main_loop_run(app->loop);
 | 
			
		||||
 | 
			
		||||
        g_source_remove(sigtrm);
 | 
			
		||||
        g_source_remove(sigint);
 | 
			
		||||
        g_main_loop_unref(app->loop);
 | 
			
		||||
 | 
			
		||||
        gbinder_remote_object_remove_handler(remote, death_id);
 | 
			
		||||
        gbinder_remote_object_unref(remote);
 | 
			
		||||
 | 
			
		||||
        /* Not the cleanest exit, just dropping the thread... */
 | 
			
		||||
        g_thread_unref(thread);
 | 
			
		||||
        app->loop = NULL;
 | 
			
		||||
    } else {
 | 
			
		||||
        GERR("No such service: %s (%d)", fqname, status);
 | 
			
		||||
    if (!app_connect_remote(app)) {
 | 
			
		||||
        GINFO("Waiting for %s", app->fqname);
 | 
			
		||||
        app->wait_id = gbinder_servicemanager_add_registration_handler(app->sm,
 | 
			
		||||
            app->fqname, app_registration_handler, app);
 | 
			
		||||
    }
 | 
			
		||||
    g_free(fqname);
 | 
			
		||||
 | 
			
		||||
    app->loop = g_main_loop_new(NULL, TRUE);
 | 
			
		||||
    app->ret = RET_OK;
 | 
			
		||||
    g_main_loop_run(app->loop);
 | 
			
		||||
 | 
			
		||||
    g_source_remove(sigtrm);
 | 
			
		||||
    g_source_remove(sigint);
 | 
			
		||||
    g_main_loop_unref(app->loop);
 | 
			
		||||
 | 
			
		||||
    if (app->thread) {
 | 
			
		||||
        /* Not the cleanest of exits, just dropping the thread... */
 | 
			
		||||
        g_thread_unref(app->thread);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_remote_object_remove_handler(app->remote, app->death_id);
 | 
			
		||||
    gbinder_remote_object_unref(app->remote);
 | 
			
		||||
    gbinder_local_object_drop(app->local);
 | 
			
		||||
    gbinder_client_unref(app->client);
 | 
			
		||||
    g_free(app->fqname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
@@ -311,8 +350,6 @@ int main(int argc, char* argv[])
 | 
			
		||||
            app.local = gbinder_servicemanager_new_local_object(app.sm,
 | 
			
		||||
                NULL, NULL, NULL);
 | 
			
		||||
            app_run(&app);
 | 
			
		||||
            gbinder_local_object_unref(app.local);
 | 
			
		||||
            gbinder_client_unref(app.client);
 | 
			
		||||
            gbinder_servicemanager_unref(app.sm);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -103,9 +103,13 @@ ifneq ($(strip $(DEPS)),)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE) $(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(RELEASE_EXE) $(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
$(COVERAGE_EXE) $(COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR)
 | 
			
		||||
$(DEBUG_LIB): | debug_lib
 | 
			
		||||
$(RELEASE_LIB): | release_lib
 | 
			
		||||
$(COVERAGE_LIB): | coverage_lib
 | 
			
		||||
 | 
			
		||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
$(COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Rules
 | 
			
		||||
@@ -166,13 +170,13 @@ $(RELEASE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c
 | 
			
		||||
$(COVERAGE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_PLUGIN_LIB) $(DEBUG_OBJS)
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_LIB) $(DEBUG_OBJS)
 | 
			
		||||
	$(LD) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) $(DEBUG_LIBS) -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_PLUGIN_LIB) $(RELEASE_OBJS)
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_LIB) $(RELEASE_OBJS)
 | 
			
		||||
	$(LD) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) $(RELEASE_LIBS) -o $@
 | 
			
		||||
 | 
			
		||||
$(COVERAGE_EXE): $(COVERAGE_PLUGIN_LIB) $(COVERAGE_OBJS)
 | 
			
		||||
$(COVERAGE_EXE): $(COVERAG_LIB) $(COVERAGE_OBJS)
 | 
			
		||||
	$(LD) $(COVERAGE_LDFLAGS) $(COVERAGE_OBJS) $(COVERAGE_LIBS) -o $@
 | 
			
		||||
 | 
			
		||||
debug_lib:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -32,7 +32,9 @@
 | 
			
		||||
 | 
			
		||||
#include "gbinder_system.h"
 | 
			
		||||
 | 
			
		||||
#define GLOG_MODULE_NAME test_binder_log
 | 
			
		||||
#include <gutil_log.h>
 | 
			
		||||
GLOG_MODULE_DEFINE2("test_binder", gutil_log_default);
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -61,6 +63,7 @@ typedef struct test_binder_node {
 | 
			
		||||
    char* path;
 | 
			
		||||
    int refcount;
 | 
			
		||||
    const TestBinderIo* io;
 | 
			
		||||
    GHashTable* destroy_map;
 | 
			
		||||
} TestBinderNode;
 | 
			
		||||
 | 
			
		||||
typedef struct test_binder {
 | 
			
		||||
@@ -123,6 +126,25 @@ typedef struct binder_pre_cookie_64 {
 | 
			
		||||
#define BR_DEAD_BINDER_64       _IOR('r', 15, guint64)
 | 
			
		||||
#define BR_FAILED_REPLY          _IO('r', 17)
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_io_free_buffer(
 | 
			
		||||
    TestBinder* binder,
 | 
			
		||||
    void* ptr)
 | 
			
		||||
{
 | 
			
		||||
    if (ptr) {
 | 
			
		||||
        TestBinderNode* node = binder->node;
 | 
			
		||||
        GDestroyNotify destroy = g_hash_table_lookup(node->destroy_map, ptr);
 | 
			
		||||
 | 
			
		||||
        if (destroy) {
 | 
			
		||||
            g_hash_table_remove(node->destroy_map, ptr);
 | 
			
		||||
            destroy(ptr);
 | 
			
		||||
        } else {
 | 
			
		||||
            g_free(ptr);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
int
 | 
			
		||||
test_io_handle_write_read_64(
 | 
			
		||||
@@ -151,7 +173,8 @@ test_io_handle_write_read_64(
 | 
			
		||||
                /* Is there anything special about transactions and replies? */
 | 
			
		||||
                break;
 | 
			
		||||
            case BC_FREE_BUFFER_64:
 | 
			
		||||
                g_free((void*)(gsize)(*(guint64*)write_ptr));
 | 
			
		||||
                test_io_free_buffer(binder,
 | 
			
		||||
                    GSIZE_TO_POINTER(*(guint64*)write_ptr));
 | 
			
		||||
                break;
 | 
			
		||||
            case BC_INCREFS:
 | 
			
		||||
            case BC_ACQUIRE:
 | 
			
		||||
@@ -219,6 +242,7 @@ test_binder_node_unref(
 | 
			
		||||
    node->refcount--;
 | 
			
		||||
    if (!node->refcount) {
 | 
			
		||||
        g_hash_table_remove(test_node_map, node->path);
 | 
			
		||||
        g_hash_table_destroy(node->destroy_map);
 | 
			
		||||
        g_free(node->path);
 | 
			
		||||
        g_free(node);
 | 
			
		||||
    }
 | 
			
		||||
@@ -228,24 +252,57 @@ test_binder_node_unref(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
TestBinder*
 | 
			
		||||
test_binder_from_fd(
 | 
			
		||||
    int fd)
 | 
			
		||||
{
 | 
			
		||||
    TestBinder* binder = NULL;
 | 
			
		||||
    GASSERT(test_fd_map);
 | 
			
		||||
    if (test_fd_map) {
 | 
			
		||||
        binder = g_hash_table_lookup(test_fd_map, GINT_TO_POINTER(fd));
 | 
			
		||||
        GASSERT(binder);
 | 
			
		||||
    }
 | 
			
		||||
    return binder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_io_destroy_none(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    GDEBUG("Not freeing %p", data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_binder_set_destroy(
 | 
			
		||||
    int fd,
 | 
			
		||||
    gpointer ptr,
 | 
			
		||||
    GDestroyNotify destroy)
 | 
			
		||||
{
 | 
			
		||||
    TestBinder* binder = test_binder_from_fd(fd);
 | 
			
		||||
 | 
			
		||||
    if (binder) {
 | 
			
		||||
        TestBinderNode* node = binder->node;
 | 
			
		||||
 | 
			
		||||
        g_hash_table_replace(node->destroy_map, ptr,
 | 
			
		||||
            destroy ? destroy : test_io_destroy_none);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_binder_push_data(
 | 
			
		||||
    int fd,
 | 
			
		||||
    const void* data)
 | 
			
		||||
{
 | 
			
		||||
    GASSERT(test_fd_map);
 | 
			
		||||
    if (test_fd_map) {
 | 
			
		||||
        gpointer key = GINT_TO_POINTER(fd);
 | 
			
		||||
        TestBinder* binder = g_hash_table_lookup(test_fd_map, key);
 | 
			
		||||
    TestBinder* binder = test_binder_from_fd(fd);
 | 
			
		||||
 | 
			
		||||
        GASSERT(binder);
 | 
			
		||||
        if (binder) {
 | 
			
		||||
            const guint32* cmd = data;
 | 
			
		||||
            const int len = sizeof(*cmd) + _IOC_SIZE(*cmd);
 | 
			
		||||
    if (binder) {
 | 
			
		||||
        const guint32* cmd = data;
 | 
			
		||||
        const int len = sizeof(*cmd) + _IOC_SIZE(*cmd);
 | 
			
		||||
 | 
			
		||||
            return write(binder->private_fd, data, len) == len;
 | 
			
		||||
        }
 | 
			
		||||
        return write(binder->private_fd, data, len) == len;
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
@@ -440,6 +497,7 @@ gbinder_system_open(
 | 
			
		||||
            node->path = g_strdup(path);
 | 
			
		||||
            node->refcount = 1;
 | 
			
		||||
            node->io = &test_io_64;
 | 
			
		||||
            node->destroy_map = g_hash_table_new(g_direct_hash, g_direct_equal);
 | 
			
		||||
            if (!test_node_map) {
 | 
			
		||||
                test_node_map = g_hash_table_new(g_str_hash, g_str_equal);
 | 
			
		||||
            }
 | 
			
		||||
@@ -466,24 +524,19 @@ int
 | 
			
		||||
gbinder_system_close(
 | 
			
		||||
    int fd)
 | 
			
		||||
{
 | 
			
		||||
    GASSERT(test_fd_map);
 | 
			
		||||
    if (test_fd_map) {
 | 
			
		||||
        gpointer key = GINT_TO_POINTER(fd);
 | 
			
		||||
        TestBinder* binder = g_hash_table_lookup(test_fd_map, key);
 | 
			
		||||
    TestBinder* binder = test_binder_from_fd(fd);
 | 
			
		||||
 | 
			
		||||
        GASSERT(binder);
 | 
			
		||||
        if (binder) {
 | 
			
		||||
            g_hash_table_remove(test_fd_map, key);
 | 
			
		||||
            if (!g_hash_table_size(test_fd_map)) {
 | 
			
		||||
                g_hash_table_unref(test_fd_map);
 | 
			
		||||
                test_fd_map = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            test_binder_node_unref(binder->node);
 | 
			
		||||
            close(binder->public_fd);
 | 
			
		||||
            close(binder->private_fd);
 | 
			
		||||
            g_free(binder);
 | 
			
		||||
            return 0;
 | 
			
		||||
    if (binder) {
 | 
			
		||||
        g_hash_table_remove(test_fd_map, GINT_TO_POINTER(fd));
 | 
			
		||||
        if (!g_hash_table_size(test_fd_map)) {
 | 
			
		||||
            g_hash_table_unref(test_fd_map);
 | 
			
		||||
            test_fd_map = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        test_binder_node_unref(binder->node);
 | 
			
		||||
        close(binder->public_fd);
 | 
			
		||||
        close(binder->private_fd);
 | 
			
		||||
        g_free(binder);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    errno = EBADF;
 | 
			
		||||
    return -1;
 | 
			
		||||
@@ -495,27 +548,21 @@ gbinder_system_ioctl(
 | 
			
		||||
    int request,
 | 
			
		||||
    void* data)
 | 
			
		||||
{
 | 
			
		||||
    GASSERT(test_fd_map);
 | 
			
		||||
    if (test_fd_map) {
 | 
			
		||||
        gpointer key = GINT_TO_POINTER(fd);
 | 
			
		||||
        TestBinder* binder = g_hash_table_lookup(test_fd_map, key);
 | 
			
		||||
    TestBinder* binder = test_binder_from_fd(fd);
 | 
			
		||||
    if (binder) {
 | 
			
		||||
        const TestBinderIo* io = binder->node->io;
 | 
			
		||||
 | 
			
		||||
        GASSERT(binder);
 | 
			
		||||
        if (binder) {
 | 
			
		||||
            const TestBinderIo* io = binder->node->io;
 | 
			
		||||
 | 
			
		||||
            switch (request) {
 | 
			
		||||
            case BINDER_VERSION:
 | 
			
		||||
                return test_binder_ioctl_version(binder, data);
 | 
			
		||||
            case BINDER_SET_MAX_THREADS:
 | 
			
		||||
                return 0;
 | 
			
		||||
            default:
 | 
			
		||||
                if (request == io->write_read_request) {
 | 
			
		||||
                    return io->handle_write_read(binder, data);
 | 
			
		||||
                } else {
 | 
			
		||||
                    errno = EINVAL;
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
        switch (request) {
 | 
			
		||||
        case BINDER_VERSION:
 | 
			
		||||
            return test_binder_ioctl_version(binder, data);
 | 
			
		||||
        case BINDER_SET_MAX_THREADS:
 | 
			
		||||
            return 0;
 | 
			
		||||
        default:
 | 
			
		||||
            if (request == io->write_read_request) {
 | 
			
		||||
                return io->handle_write_read(binder, data);
 | 
			
		||||
            } else {
 | 
			
		||||
                errno = EINVAL;
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -95,6 +95,12 @@ test_binder_br_reply_status(
 | 
			
		||||
    int fd,
 | 
			
		||||
    gint32 status);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_binder_set_destroy(
 | 
			
		||||
    int fd,
 | 
			
		||||
    gpointer ptr,
 | 
			
		||||
    GDestroyNotify destroy);
 | 
			
		||||
 | 
			
		||||
#endif /* TEST_BINDER_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -46,9 +46,10 @@ void
 | 
			
		||||
test_null(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new(NULL, NULL, 0);
 | 
			
		||||
    GBinderBuffer* buf2;
 | 
			
		||||
    gsize size = 1;
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
 | 
			
		||||
@@ -66,6 +67,10 @@ test_null(
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(NULL);
 | 
			
		||||
    g_assert(!gbinder_buffer_driver(NULL));
 | 
			
		||||
    g_assert(!gbinder_buffer_io(NULL));
 | 
			
		||||
    g_assert(!gbinder_buffer_data(NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_buffer_data(NULL, &size));
 | 
			
		||||
    g_assert(!size);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -80,12 +85,20 @@ test_parent(
 | 
			
		||||
{
 | 
			
		||||
    static const guint8 data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
 | 
			
		||||
    void* ptr = g_memdup(data, sizeof(data));
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    gsize size = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderBuffer* parent = gbinder_buffer_new(driver, ptr, sizeof(data));
 | 
			
		||||
    GBinderBuffer* buf = gbinder_buffer_new_with_parent
 | 
			
		||||
        (parent, ptr, sizeof(data));
 | 
			
		||||
 | 
			
		||||
    g_assert(gbinder_buffer_driver(buf) == driver);
 | 
			
		||||
    g_assert(gbinder_buffer_io(buf));
 | 
			
		||||
    g_assert(gbinder_buffer_io(buf) == gbinder_driver_io(driver));
 | 
			
		||||
    g_assert(gbinder_buffer_memory(buf));
 | 
			
		||||
    g_assert(gbinder_buffer_data(buf, NULL) == ptr);
 | 
			
		||||
    g_assert(gbinder_buffer_data(buf, &size) == ptr);
 | 
			
		||||
    g_assert(size == sizeof(data));
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
    gbinder_buffer_free(parent);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -54,7 +54,7 @@ test_client_new(
 | 
			
		||||
    guint handle,
 | 
			
		||||
    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, handle);
 | 
			
		||||
    GBinderClient* client = gbinder_client_new(obj, iface);
 | 
			
		||||
@@ -95,7 +95,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);
 | 
			
		||||
    GBinderClient* client = gbinder_client_new(obj, "foo");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -56,8 +56,8 @@ test_basic(
 | 
			
		||||
    GBinderDriver* driver;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_driver_new(""));
 | 
			
		||||
    driver = gbinder_driver_new(dev);
 | 
			
		||||
    g_assert(!gbinder_driver_new("", NULL));
 | 
			
		||||
    driver = gbinder_driver_new(dev, NULL);
 | 
			
		||||
    g_assert(driver);
 | 
			
		||||
    g_assert(!g_strcmp0(dev, gbinder_driver_dev(driver)));
 | 
			
		||||
    g_assert(gbinder_driver_ref(driver) == driver);
 | 
			
		||||
@@ -86,7 +86,7 @@ void
 | 
			
		||||
test_noop(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const int fd = gbinder_driver_fd(driver);
 | 
			
		||||
 | 
			
		||||
    g_assert(driver);
 | 
			
		||||
@@ -116,7 +116,7 @@ test_local_request(
 | 
			
		||||
        0x00, 0x00, 0x00, 0x00
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_driver_local_request_new(driver, iface);
 | 
			
		||||
    GBinderOutputData* data = gbinder_local_request_data(req);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -91,8 +91,8 @@ 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);
 | 
			
		||||
 | 
			
		||||
    g_assert(ipc);
 | 
			
		||||
    g_assert(ipc2);
 | 
			
		||||
@@ -101,14 +101,14 @@ test_basic(
 | 
			
		||||
    gbinder_ipc_unref(ipc2);
 | 
			
		||||
 | 
			
		||||
    /* 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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
@@ -120,7 +120,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);
 | 
			
		||||
@@ -141,7 +141,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);
 | 
			
		||||
@@ -196,7 +196,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);
 | 
			
		||||
@@ -253,7 +253,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);
 | 
			
		||||
@@ -310,7 +310,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);
 | 
			
		||||
@@ -356,7 +356,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);
 | 
			
		||||
@@ -404,7 +404,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);
 | 
			
		||||
@@ -445,7 +445,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);
 | 
			
		||||
@@ -475,7 +475,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);
 | 
			
		||||
@@ -522,7 +522,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);
 | 
			
		||||
@@ -566,7 +566,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,
 | 
			
		||||
@@ -629,7 +629,7 @@ void
 | 
			
		||||
test_transact_incoming(
 | 
			
		||||
    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);
 | 
			
		||||
@@ -690,7 +690,7 @@ void
 | 
			
		||||
test_transact_status_reply(
 | 
			
		||||
    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);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -149,7 +149,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);
 | 
			
		||||
    GBinderLocalObject* foo;
 | 
			
		||||
    GBinderLocalObject* bar;
 | 
			
		||||
@@ -201,7 +201,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 =
 | 
			
		||||
@@ -256,7 +256,7 @@ test_descriptor_chain(
 | 
			
		||||
    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 =
 | 
			
		||||
@@ -323,7 +323,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_ipc_new_local_object(ipc, custom_iface,
 | 
			
		||||
@@ -428,7 +428,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_ipc_new_local_object(ipc, custom_iface,
 | 
			
		||||
@@ -468,7 +468,7 @@ void
 | 
			
		||||
test_increfs(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_ipc_new_local_object
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -510,7 +510,7 @@ void
 | 
			
		||||
test_decrefs(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_ipc_new_local_object
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -552,7 +552,7 @@ void
 | 
			
		||||
test_acquire(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_ipc_new_local_object
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
@@ -594,7 +594,7 @@ void
 | 
			
		||||
test_release(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderLocalObject* obj = gbinder_ipc_new_local_object
 | 
			
		||||
        (ipc, NULL, NULL, NULL);
 | 
			
		||||
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -31,10 +31,13 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "test_binder.h"
 | 
			
		||||
 | 
			
		||||
#include "gbinder_local_object.h"
 | 
			
		||||
#include "gbinder_local_reply_p.h"
 | 
			
		||||
#include "gbinder_output_data.h"
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_writer.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
#include "gbinder_ipc.h"
 | 
			
		||||
@@ -56,6 +59,17 @@ test_int_inc(
 | 
			
		||||
    (*((int*)data))++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderBuffer*
 | 
			
		||||
test_buffer_from_bytes(
 | 
			
		||||
    GBinderDriver* driver,
 | 
			
		||||
    const GByteArray* bytes)
 | 
			
		||||
{
 | 
			
		||||
    /* Prevent double free */
 | 
			
		||||
    test_binder_set_destroy(gbinder_driver_fd(driver), bytes->data, NULL);
 | 
			
		||||
    return gbinder_buffer_new(driver, bytes->data, bytes->len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -74,6 +88,7 @@ test_null(
 | 
			
		||||
    gbinder_local_reply_init_writer(NULL, NULL);
 | 
			
		||||
    gbinder_local_reply_init_writer(NULL, &writer);
 | 
			
		||||
    g_assert(!gbinder_local_reply_data(NULL));
 | 
			
		||||
    g_assert(!gbinder_local_reply_new_from_data(NULL, NULL));
 | 
			
		||||
 | 
			
		||||
    gbinder_local_reply_cleanup(NULL, NULL, &count);
 | 
			
		||||
    gbinder_local_reply_cleanup(NULL, test_int_inc, &count);
 | 
			
		||||
@@ -122,8 +137,8 @@ void
 | 
			
		||||
test_bool(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    static const guint8 output_true[] = { 0x01, 0xff, 0xff, 0xff };
 | 
			
		||||
    static const guint8 output_false[] = { 0x00, 0xff, 0xff, 0xff };
 | 
			
		||||
    static const guint8 output_true[] = { 0x01, 0x00, 0x00, 0x00 };
 | 
			
		||||
    static const guint8 output_false[] = { 0x00, 0x00, 0x00, 0x00 };
 | 
			
		||||
    GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
 | 
			
		||||
@@ -384,7 +399,7 @@ test_local_object(
 | 
			
		||||
    GBinderLocalReply* reply;
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GUtilIntArray* offsets;
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(NULL);
 | 
			
		||||
    GBinderIpc* ipc = gbinder_ipc_new(NULL, NULL);
 | 
			
		||||
    GBinderLocalObject* obj =
 | 
			
		||||
        gbinder_ipc_new_local_object(ipc, "foo", NULL, NULL);
 | 
			
		||||
 | 
			
		||||
@@ -438,6 +453,47 @@ test_remote_object(
 | 
			
		||||
    gbinder_local_reply_unref(reply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * remote_reply
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_remote_reply(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    /* The size of the string gets aligned at 4-byte boundary */
 | 
			
		||||
    static const char input[] = "test";
 | 
			
		||||
    static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(driver);
 | 
			
		||||
    GBinderLocalReply* req = gbinder_local_reply_new(io);
 | 
			
		||||
    GBinderLocalReply* req2;
 | 
			
		||||
    GBinderOutputData* data2;
 | 
			
		||||
    const GByteArray* bytes;
 | 
			
		||||
    const GByteArray* bytes2;
 | 
			
		||||
    GBinderBuffer* buffer;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_reply_append_string8(req, input);
 | 
			
		||||
    bytes = gbinder_local_reply_data(req)->bytes;
 | 
			
		||||
 | 
			
		||||
    /* Copy flat structures (no binder objects) */
 | 
			
		||||
    buffer = test_buffer_from_bytes(driver, bytes);
 | 
			
		||||
    req2 = gbinder_local_reply_new_from_data(buffer, NULL);
 | 
			
		||||
    gbinder_buffer_free(buffer);
 | 
			
		||||
 | 
			
		||||
    data2 = gbinder_local_reply_data(req2);
 | 
			
		||||
    bytes2 = data2->bytes;
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data2));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data2));
 | 
			
		||||
    g_assert(bytes2->len == sizeof(output));
 | 
			
		||||
    g_assert(!memcmp(bytes2->data, output, bytes2->len));
 | 
			
		||||
 | 
			
		||||
    gbinder_local_reply_unref(req2);
 | 
			
		||||
    gbinder_local_reply_unref(req);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -460,6 +516,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "hidl_string_vec", test_hidl_string_vec);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "local_object", test_local_object);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "remote_object", test_remote_object);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "remote_reply", test_remote_reply);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -31,9 +31,12 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "test_binder.h"
 | 
			
		||||
 | 
			
		||||
#include "gbinder_local_request_p.h"
 | 
			
		||||
#include "gbinder_output_data.h"
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_writer.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
 | 
			
		||||
@@ -54,6 +57,17 @@ test_int_inc(
 | 
			
		||||
    (*((int*)data))++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderBuffer*
 | 
			
		||||
test_buffer_from_bytes(
 | 
			
		||||
    GBinderDriver* driver,
 | 
			
		||||
    const GByteArray* bytes)
 | 
			
		||||
{
 | 
			
		||||
    /* Prevent double free */
 | 
			
		||||
    test_binder_set_destroy(gbinder_driver_fd(driver), bytes->data, NULL);
 | 
			
		||||
    return gbinder_buffer_new(driver, bytes->data, bytes->len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -68,6 +82,7 @@ test_null(
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_local_request_new(NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_local_request_ref(NULL));
 | 
			
		||||
    g_assert(!gbinder_local_request_new_from_data(NULL, NULL));
 | 
			
		||||
    gbinder_local_request_unref(NULL);
 | 
			
		||||
    gbinder_local_request_init_writer(NULL, NULL);
 | 
			
		||||
    gbinder_local_request_init_writer(NULL, &writer);
 | 
			
		||||
@@ -152,8 +167,8 @@ void
 | 
			
		||||
test_bool(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    static const guint8 output_true[] = { 0x01, 0xff, 0xff, 0xff };
 | 
			
		||||
    static const guint8 output_false[] = { 0x00, 0xff, 0xff, 0xff };
 | 
			
		||||
    static const guint8 output_true[] = { 0x01, 0x00, 0x00, 0x00 };
 | 
			
		||||
    static const guint8 output_false[] = { 0x00, 0x00, 0x00, 0x00 };
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
 | 
			
		||||
@@ -436,6 +451,125 @@ test_remote_object(
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * remote_request
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_remote_request(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    /* The size of the string gets aligned at 4-byte boundary */
 | 
			
		||||
    static const char input[] = "test";
 | 
			
		||||
    static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
    GBinderLocalRequest* req2;
 | 
			
		||||
    GBinderOutputData* data2;
 | 
			
		||||
    const GByteArray* bytes;
 | 
			
		||||
    const GByteArray* bytes2;
 | 
			
		||||
    GBinderBuffer* buffer;
 | 
			
		||||
    void* no_obj = NULL;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_string8(req, input);
 | 
			
		||||
    bytes = gbinder_local_request_data(req)->bytes;
 | 
			
		||||
 | 
			
		||||
    /* Copy flat structures (no binder objects) */
 | 
			
		||||
    buffer = test_buffer_from_bytes(driver, bytes);
 | 
			
		||||
    req2 = gbinder_local_request_new_from_data(buffer, NULL);
 | 
			
		||||
    gbinder_buffer_free(buffer);
 | 
			
		||||
 | 
			
		||||
    data2 = gbinder_local_request_data(req2);
 | 
			
		||||
    bytes2 = data2->bytes;
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data2));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data2));
 | 
			
		||||
    g_assert(bytes2->len == sizeof(output));
 | 
			
		||||
    g_assert(!memcmp(bytes2->data, output, bytes2->len));
 | 
			
		||||
    gbinder_local_request_unref(req2);
 | 
			
		||||
 | 
			
		||||
    /* Same thing but with non-NULL (albeit empty) array of objects */
 | 
			
		||||
    buffer = test_buffer_from_bytes(driver, bytes);
 | 
			
		||||
    req2 = gbinder_local_request_new_from_data(buffer, &no_obj);
 | 
			
		||||
    gbinder_buffer_free(buffer);
 | 
			
		||||
 | 
			
		||||
    data2 = gbinder_local_request_data(req2);
 | 
			
		||||
    bytes2 = data2->bytes;
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data2));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data2));
 | 
			
		||||
    g_assert(bytes2->len == sizeof(output));
 | 
			
		||||
    g_assert(!memcmp(bytes2->data, output, bytes2->len));
 | 
			
		||||
    gbinder_local_request_unref(req2);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * remote_request_obj
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_remote_request_obj_validate_data(
 | 
			
		||||
    GBinderOutputData* data)
 | 
			
		||||
{
 | 
			
		||||
    const GByteArray* bytes = data->bytes;
 | 
			
		||||
    GUtilIntArray* offsets = gbinder_output_data_offsets(data);
 | 
			
		||||
 | 
			
		||||
    offsets = gbinder_output_data_offsets(data);
 | 
			
		||||
    g_assert(offsets);
 | 
			
		||||
    g_assert(offsets->count == 3);
 | 
			
		||||
    g_assert(offsets->data[0] == 4);
 | 
			
		||||
    g_assert(offsets->data[1] == 4 + BUFFER_OBJECT_SIZE_64);
 | 
			
		||||
    g_assert(offsets->data[2] == 4 + 2*BUFFER_OBJECT_SIZE_64);
 | 
			
		||||
    g_assert(bytes->len == 4 + 2*BUFFER_OBJECT_SIZE_64 + BINDER_OBJECT_SIZE_64);
 | 
			
		||||
    /* HidlString + the contents (2 bytes) aligned at 8-byte boundary */
 | 
			
		||||
    g_assert(gbinder_output_data_buffers_size(data) == (sizeof(HidlString)+8));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_remote_request_obj(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    const GBinderIo* io = gbinder_driver_io(driver);
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
 | 
			
		||||
    GBinderLocalRequest* req2;
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GUtilIntArray* offsets;
 | 
			
		||||
    GBinderBuffer* buffer;
 | 
			
		||||
    const GByteArray* bytes;
 | 
			
		||||
    void** objects;
 | 
			
		||||
    guint i;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_append_int32(req, 1);
 | 
			
		||||
    gbinder_local_request_append_hidl_string(req, "2");
 | 
			
		||||
    gbinder_local_request_append_local_object(req, NULL);
 | 
			
		||||
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    test_remote_request_obj_validate_data(data);
 | 
			
		||||
    bytes = data->bytes;
 | 
			
		||||
    offsets = gbinder_output_data_offsets(data);
 | 
			
		||||
    objects = g_new0(void*, offsets->count + 1);
 | 
			
		||||
    for (i = 0; i < offsets->count; i++) {
 | 
			
		||||
        objects[i] = bytes->data + offsets->data[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buffer = test_buffer_from_bytes(driver, data->bytes);
 | 
			
		||||
    req2 = gbinder_local_request_new_from_data(buffer, objects);
 | 
			
		||||
    gbinder_buffer_free(buffer);
 | 
			
		||||
    g_free(objects);
 | 
			
		||||
 | 
			
		||||
    test_remote_request_obj_validate_data(gbinder_local_request_data(req2));
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
    gbinder_local_request_unref(req2);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -459,6 +593,8 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "hidl_string_vec", test_hidl_string_vec);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "local_object", test_local_object);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "remote_object", test_remote_object);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "remote_request", test_remote_request);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "remote_request_obj", test_remote_request_obj);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -74,20 +74,20 @@ static const TestHeaderData test_header_tests[] = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * default
 | 
			
		||||
 * device
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_default(
 | 
			
		||||
test_device(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const GBinderRpcProtocol* p1 = gbinder_rpc_protocol_for_device(NULL);
 | 
			
		||||
    const GBinderRpcProtocol* p2 = gbinder_rpc_protocol_for_device
 | 
			
		||||
        (GBINDER_DEFAULT_BINDER);
 | 
			
		||||
 | 
			
		||||
    g_assert(p1);
 | 
			
		||||
    g_assert(p1 == p2);
 | 
			
		||||
    g_assert(gbinder_rpc_protocol_for_device(NULL) ==
 | 
			
		||||
        &gbinder_rpc_protocol_binder);
 | 
			
		||||
    g_assert(gbinder_rpc_protocol_for_device(GBINDER_DEFAULT_BINDER) ==
 | 
			
		||||
        &gbinder_rpc_protocol_binder);
 | 
			
		||||
    g_assert(gbinder_rpc_protocol_for_device(GBINDER_DEFAULT_HWBINDER) ==
 | 
			
		||||
        &gbinder_rpc_protocol_hwbinder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
@@ -140,7 +140,7 @@ test_read_header(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHeaderData* test = test_data;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(test->dev);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(test->dev, NULL);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
 | 
			
		||||
        gbinder_rpc_protocol_for_device(test->dev), 0, 0);
 | 
			
		||||
 | 
			
		||||
@@ -162,7 +162,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    guint i;
 | 
			
		||||
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "default", test_default);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "device", test_device);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "no_header", test_no_header);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_header_tests); i++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -37,13 +37,17 @@
 | 
			
		||||
#include "gbinder_ipc.h"
 | 
			
		||||
#include "gbinder_reader_p.h"
 | 
			
		||||
#include "gbinder_remote_object_p.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
typedef struct binder_buffer_object_64 {
 | 
			
		||||
    guint32 type;
 | 
			
		||||
    guint32 flags;
 | 
			
		||||
    guint64 buffer;
 | 
			
		||||
    union {
 | 
			
		||||
        const void* ptr;
 | 
			
		||||
        guint64 value;
 | 
			
		||||
    } buffer;
 | 
			
		||||
    guint64 length;
 | 
			
		||||
    guint64 parent;
 | 
			
		||||
    guint64 parent_offset;
 | 
			
		||||
@@ -51,6 +55,9 @@ typedef struct binder_buffer_object_64 {
 | 
			
		||||
 | 
			
		||||
#define BINDER_TYPE_HANDLE GBINDER_FOURCC('s','h','*',0x85)
 | 
			
		||||
#define BINDER_TYPE_PTR GBINDER_FOURCC('p','t','*',0x85)
 | 
			
		||||
#define BINDER_BUFFER_FLAG_HAS_PARENT 0x01
 | 
			
		||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
 | 
			
		||||
G_STATIC_ASSERT(sizeof(BinderObject64) == BUFFER_OBJECT_SIZE_64);
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * empty
 | 
			
		||||
@@ -62,6 +69,8 @@ test_empty(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    gsize count = 1, elemsize = 1;
 | 
			
		||||
    gsize len;
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, NULL, 0, 0);
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
@@ -78,12 +87,20 @@ 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_hidl_struct1(&reader, 1));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec(&reader, NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec(&reader, &count, &elemsize));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec1(&reader, NULL, 1));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_vec1(&reader, &count, 1));
 | 
			
		||||
    g_assert(!count);
 | 
			
		||||
    g_assert(!elemsize);
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_string(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_hidl_string_vec(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_skip_buffer(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_string8(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_string16(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_skip_string16(&reader));
 | 
			
		||||
    g_assert(!gbinder_reader_read_byte_array(&reader, &len));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
@@ -97,7 +114,7 @@ test_byte(
 | 
			
		||||
{
 | 
			
		||||
    const guint8 in = 42;
 | 
			
		||||
    guint8 out = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
@@ -131,7 +148,7 @@ test_bool(
 | 
			
		||||
    const guint8 in_true[4] = { 0x01, 0xff, 0xff, 0xff };
 | 
			
		||||
    const guint8 in_false[4] = { 0x00, 0xff, 0xff, 0xff };
 | 
			
		||||
    gboolean out = FALSE;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
@@ -180,7 +197,7 @@ test_int32(
 | 
			
		||||
    const guint32 in = 42;
 | 
			
		||||
    guint32 out1 = 0;
 | 
			
		||||
    gint32 out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
@@ -219,7 +236,7 @@ test_int64(
 | 
			
		||||
    const guint64 in = 42;
 | 
			
		||||
    guint64 out1 = 0;
 | 
			
		||||
    gint64 out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
@@ -258,7 +275,7 @@ test_float(
 | 
			
		||||
    const gfloat in = 42;
 | 
			
		||||
    gfloat out1 = 0;
 | 
			
		||||
    gfloat out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
@@ -297,7 +314,7 @@ test_double(
 | 
			
		||||
    const gdouble in = 42;
 | 
			
		||||
    gdouble out1 = 0;
 | 
			
		||||
    gdouble out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
@@ -361,7 +378,7 @@ test_string8(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestStringData* test = test_data;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
    const char* str;
 | 
			
		||||
@@ -425,7 +442,7 @@ void
 | 
			
		||||
test_string16_null(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
    char dummy;
 | 
			
		||||
@@ -464,7 +481,7 @@ test_string16(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestStringData* test = test_data;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
    const gboolean valid = (test->out != NULL);
 | 
			
		||||
@@ -503,6 +520,308 @@ test_string16(
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_struct
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
typedef struct test_hidl_struct {
 | 
			
		||||
    const char* name;
 | 
			
		||||
    const void* in;
 | 
			
		||||
    guint in_size;
 | 
			
		||||
    guint struct_size;
 | 
			
		||||
    const void* data;
 | 
			
		||||
} TestHidlStruct;
 | 
			
		||||
 | 
			
		||||
typedef struct test_hidl_struct_type {
 | 
			
		||||
    guint32 x;
 | 
			
		||||
} TestHidlStructType;
 | 
			
		||||
 | 
			
		||||
static const TestHidlStructType test_hidl_struct_data = { 0 };
 | 
			
		||||
static const BinderObject64 test_hidl_struct_ok_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_struct_data },
 | 
			
		||||
        sizeof(test_hidl_struct_data), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_struct_big_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_struct_data },
 | 
			
		||||
        2 * sizeof(test_hidl_struct_data), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const TestHidlStruct test_hidl_struct_tests[] = {
 | 
			
		||||
    { "ok", TEST_ARRAY_AND_SIZE(test_hidl_struct_ok_buf),
 | 
			
		||||
      sizeof(TestHidlStructType), &test_hidl_struct_data },
 | 
			
		||||
    { "badsize",  TEST_ARRAY_AND_SIZE(test_hidl_struct_big_buf),
 | 
			
		||||
      sizeof(TestHidlStructType), NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_hidl_struct(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlStruct* test = test_data;
 | 
			
		||||
    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);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
 | 
			
		||||
    g_assert(ipc);
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
    data.buffer = buf;
 | 
			
		||||
    data.reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    data.objects = g_new0(void*, 2);
 | 
			
		||||
    data.objects[0] = buf->data;
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, test->in_size);
 | 
			
		||||
    g_assert(gbinder_reader_read_hidl_struct1(&reader, test->struct_size) ==
 | 
			
		||||
        test->data);
 | 
			
		||||
 | 
			
		||||
    g_free(data.objects);
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_vec
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_hidl_vec {
 | 
			
		||||
    const char* name;
 | 
			
		||||
    const void* in;
 | 
			
		||||
    guint in_size;
 | 
			
		||||
    const guint* offset;
 | 
			
		||||
    guint offset_count;
 | 
			
		||||
    const void* data;
 | 
			
		||||
    guint count;
 | 
			
		||||
    guint elemsize;
 | 
			
		||||
} TestHidlVec;
 | 
			
		||||
 | 
			
		||||
static const guint test_hidl_vec_2offsets [] = { 0, BUFFER_OBJECT_SIZE_64 };
 | 
			
		||||
static const guint8 test_hidl_vec_2bytes_data [] = { 0x01, 0x02 };
 | 
			
		||||
static const HidlVec test_hidl_vec_2bytes = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_2bytes_data,
 | 
			
		||||
    sizeof(test_hidl_vec_2bytes_data),
 | 
			
		||||
    TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_2bytes_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_2bytes },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_2bytes_data },
 | 
			
		||||
        sizeof(test_hidl_vec_2bytes_data), 0,
 | 
			
		||||
        HIDL_VEC_BUFFER_OFFSET
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const HidlVec test_hidl_vec_empty = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_2bytes_data, 0, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_empty_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_empty },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_2bytes_data },
 | 
			
		||||
        0, 0, HIDL_VEC_BUFFER_OFFSET
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const guint test_hidl_vec_1offset [] = {0};
 | 
			
		||||
static const HidlVec test_hidl_vec_null = {{0}, 0, TRUE};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_null_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_null },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Buffer smaller than HidlVec */
 | 
			
		||||
static const BinderObject64 test_hidl_vec_short_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_empty },
 | 
			
		||||
        sizeof(HidlVec) - 1, 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* NULL buffer with size 1 */
 | 
			
		||||
static const guint test_hidl_vec_badnull_offsets [] = {0};
 | 
			
		||||
static const HidlVec test_hidl_vec_badnull = {{0}, 1, TRUE};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badnull_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badnull },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Buffer size not divisible by count */
 | 
			
		||||
static const guint8 test_hidl_vec_badsize_data [] = { 0x01, 0x02, 0x03 };
 | 
			
		||||
static const HidlVec test_hidl_vec_badsize = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badsize_data, 2, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badsize_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badsize },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data },
 | 
			
		||||
        sizeof(test_hidl_vec_badsize_data), 0,
 | 
			
		||||
        HIDL_VEC_BUFFER_OFFSET
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Bad buffer address */
 | 
			
		||||
static const guint8 test_hidl_vec_badbuf_data [] = { 0x01, 0x02, 0x03 };
 | 
			
		||||
static const HidlVec test_hidl_vec_badbuf = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badbuf_data,
 | 
			
		||||
    sizeof(test_hidl_vec_badbuf_data), TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badbuf_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badbuf },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data },
 | 
			
		||||
        sizeof(test_hidl_vec_badsize_data), 0,
 | 
			
		||||
        HIDL_VEC_BUFFER_OFFSET
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Non-zero count and zero size */
 | 
			
		||||
static const HidlVec test_hidl_vec_badcount1 = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badsize_data, 1, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badcount1_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badcount1 },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data }, 0, 0,
 | 
			
		||||
        HIDL_VEC_BUFFER_OFFSET
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Zero count0 and non-zero size */
 | 
			
		||||
static const HidlVec test_hidl_vec_badcount2 = {
 | 
			
		||||
    .data.ptr = test_hidl_vec_badsize_data, 0, TRUE
 | 
			
		||||
};
 | 
			
		||||
static const BinderObject64 test_hidl_vec_badcount2_buf [] = {
 | 
			
		||||
    {
 | 
			
		||||
        BINDER_TYPE_PTR, 0,
 | 
			
		||||
        { &test_hidl_vec_badcount2 },
 | 
			
		||||
        sizeof(HidlVec), 0, 0
 | 
			
		||||
    },{
 | 
			
		||||
        BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
 | 
			
		||||
        { test_hidl_vec_badsize_data },
 | 
			
		||||
        sizeof(test_hidl_vec_badsize_data), 0,
 | 
			
		||||
        HIDL_VEC_BUFFER_OFFSET
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const TestHidlVec test_hidl_vec_tests[] = {
 | 
			
		||||
    { "2bytes", TEST_ARRAY_AND_SIZE(test_hidl_vec_2bytes_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2bytes_data), 1 },
 | 
			
		||||
    { "empty", TEST_ARRAY_AND_SIZE(test_hidl_vec_empty_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets),
 | 
			
		||||
      test_hidl_vec_2bytes_data, 0, 0 },
 | 
			
		||||
    { "null", TEST_ARRAY_AND_SIZE(test_hidl_vec_null_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset),
 | 
			
		||||
      &test_hidl_vec_null, 0, 0 },
 | 
			
		||||
    { "missingbuf", test_hidl_vec_2bytes_buf,
 | 
			
		||||
      sizeof(test_hidl_vec_2bytes_buf[0]),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
 | 
			
		||||
    { "shortbuf", TEST_ARRAY_AND_SIZE(test_hidl_vec_short_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
 | 
			
		||||
    { "badnull", TEST_ARRAY_AND_SIZE(test_hidl_vec_badnull_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
 | 
			
		||||
    { "badsize", TEST_ARRAY_AND_SIZE(test_hidl_vec_badsize_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
 | 
			
		||||
    { "badbuf", TEST_ARRAY_AND_SIZE(test_hidl_vec_badbuf_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
 | 
			
		||||
    { "badcount1", TEST_ARRAY_AND_SIZE(test_hidl_vec_badcount1_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
 | 
			
		||||
    { "badcount2", TEST_ARRAY_AND_SIZE(test_hidl_vec_badcount2_buf),
 | 
			
		||||
      TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_hidl_vec(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlVec* test = test_data;
 | 
			
		||||
    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);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    gsize n = 0, elem = 0;
 | 
			
		||||
 | 
			
		||||
    g_assert(ipc);
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
    data.buffer = buf;
 | 
			
		||||
    data.reg = gbinder_ipc_object_registry(ipc);
 | 
			
		||||
    if (test->offset) {
 | 
			
		||||
        guint i;
 | 
			
		||||
 | 
			
		||||
        data.objects = g_new(void*, test->offset_count + 1);
 | 
			
		||||
        for (i = 0; i < test->offset_count; i++) {
 | 
			
		||||
            data.objects[i] = (guint8*)buf->data + test->offset[i];
 | 
			
		||||
        }
 | 
			
		||||
        data.objects[i] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, test->in_size);
 | 
			
		||||
    g_assert(gbinder_reader_read_hidl_vec(&reader, &n, &elem) == test->data);
 | 
			
		||||
    g_assert(n == test->count);
 | 
			
		||||
    g_assert(elem == test->elemsize);
 | 
			
		||||
 | 
			
		||||
    if (test->data) {
 | 
			
		||||
        n = 42;
 | 
			
		||||
        gbinder_reader_init(&reader, &data, 0, test->in_size);
 | 
			
		||||
        g_assert(gbinder_reader_read_hidl_vec1(&reader, &n, test->elemsize) ==
 | 
			
		||||
            test->data);
 | 
			
		||||
        g_assert(n == test->count);
 | 
			
		||||
 | 
			
		||||
        /* Test invalid expected size */
 | 
			
		||||
        gbinder_reader_init(&reader, &data, 0, test->in_size);
 | 
			
		||||
        if (test->count) {
 | 
			
		||||
            g_assert(!gbinder_reader_read_hidl_vec1(&reader, NULL,
 | 
			
		||||
                test->elemsize + 1));
 | 
			
		||||
        } else {
 | 
			
		||||
            /* If total size is zero, we can't really check the element size */
 | 
			
		||||
            g_assert(gbinder_reader_read_hidl_vec1(&reader, NULL,
 | 
			
		||||
                test->elemsize + 1) == test->data);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        gbinder_reader_init(&reader, &data, 0, test->in_size);
 | 
			
		||||
        g_assert(!gbinder_reader_read_hidl_vec1(&reader, &n, test->elemsize));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_free(data.objects);
 | 
			
		||||
    gbinder_buffer_free(buf);
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_string_err
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -517,7 +836,7 @@ typedef struct test_hidl_string_err {
 | 
			
		||||
 | 
			
		||||
static const guint8 test_hidl_string_err_short [] = { 0x00 };
 | 
			
		||||
static const guint8 test_hidl_string_err_empty [] = {
 | 
			
		||||
    TEST_INT32_BYTES(GBINDER_FOURCC('p', 't', '*', 0x85)),
 | 
			
		||||
    TEST_INT32_BYTES(BINDER_TYPE_PTR),
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
@@ -547,7 +866,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);
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
@@ -589,7 +908,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));
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
@@ -647,7 +966,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));
 | 
			
		||||
    GBinderRemoteObject* obj = NULL;
 | 
			
		||||
@@ -681,7 +1000,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;
 | 
			
		||||
@@ -693,7 +1012,7 @@ test_vec(
 | 
			
		||||
    memset(&vec, 0, sizeof(vec));
 | 
			
		||||
    memset(&obj, 0, sizeof(obj));
 | 
			
		||||
    obj.type = BINDER_TYPE_PTR;
 | 
			
		||||
    obj.buffer = (gsize)&vec;
 | 
			
		||||
    obj.buffer.ptr = &vec;
 | 
			
		||||
 | 
			
		||||
    /* This one will fail because the buffer is one byte short */
 | 
			
		||||
    obj.length = sizeof(vec) - 1;
 | 
			
		||||
@@ -723,6 +1042,93 @@ test_vec(
 | 
			
		||||
    gbinder_ipc_unref(ipc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * byte_array
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_byte_array(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char in_data[] = "1234abcd";
 | 
			
		||||
    gint32 in_len = sizeof(in_data) - 1;
 | 
			
		||||
    const void* out_data = NULL;
 | 
			
		||||
    gsize out_len = 0;
 | 
			
		||||
    void* tmp;
 | 
			
		||||
    gsize tmp_len = sizeof(in_len) + in_len;
 | 
			
		||||
    gint32 null_len = -1;
 | 
			
		||||
 | 
			
		||||
    GBinderDriver* driver;
 | 
			
		||||
    GBinderReader reader;
 | 
			
		||||
    GBinderReaderData data;
 | 
			
		||||
 | 
			
		||||
    /* test for failed read (wrong len part of byte array) */
 | 
			
		||||
    g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
 | 
			
		||||
    tmp = g_malloc0(1);
 | 
			
		||||
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, tmp, 1);
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, 1);
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_reader_read_byte_array(&reader, &out_len));
 | 
			
		||||
    g_assert(!gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert(out_len == 0);
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
 | 
			
		||||
    /* test for failed read (wrong data part of byte array) */
 | 
			
		||||
    g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
 | 
			
		||||
    tmp = g_malloc0(in_len - 1);
 | 
			
		||||
    memcpy(tmp, &in_len, sizeof(in_len));
 | 
			
		||||
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, tmp, in_len - 1);
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, in_len - 1);
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_reader_read_byte_array(&reader, &out_len));
 | 
			
		||||
    g_assert(!gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert(out_len == 0);
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
 | 
			
		||||
    /* test for empty (len 0) byte array */
 | 
			
		||||
    g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
 | 
			
		||||
    tmp = g_malloc0(sizeof(null_len));
 | 
			
		||||
    memcpy(tmp, &null_len, sizeof(null_len));
 | 
			
		||||
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, tmp, sizeof(null_len));
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, sizeof(null_len));
 | 
			
		||||
 | 
			
		||||
    g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert(out_len == 0);
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
 | 
			
		||||
    /* test for data */
 | 
			
		||||
    g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
 | 
			
		||||
    tmp = g_malloc0(tmp_len);
 | 
			
		||||
    memcpy(tmp, &in_len, sizeof(in_len));
 | 
			
		||||
    memcpy(tmp + sizeof(in_len), in_data, in_len);
 | 
			
		||||
 | 
			
		||||
    memset(&data, 0, sizeof(data));
 | 
			
		||||
    data.buffer = gbinder_buffer_new(driver, tmp, tmp_len);
 | 
			
		||||
    gbinder_reader_init(&reader, &data, 0, tmp_len);
 | 
			
		||||
 | 
			
		||||
    g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert((gsize)in_len == out_len);
 | 
			
		||||
    g_assert(memcmp(in_data, out_data, in_len) == 0);
 | 
			
		||||
 | 
			
		||||
    gbinder_buffer_free(data.buffer);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -759,6 +1165,24 @@ int main(int argc, char* argv[])
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_struct_tests); i++) {
 | 
			
		||||
        const TestHidlStruct* test = test_hidl_struct_tests + i;
 | 
			
		||||
        char* path = g_strconcat(TEST_PREFIX "/hidl_struct/", test->name,
 | 
			
		||||
            NULL);
 | 
			
		||||
 | 
			
		||||
        g_test_add_data_func(path, test, test_hidl_struct);
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_vec_tests); i++) {
 | 
			
		||||
        const TestHidlVec* test = test_hidl_vec_tests + i;
 | 
			
		||||
        char* path = g_strconcat(TEST_PREFIX "/hidl_vec/", test->name,
 | 
			
		||||
            NULL);
 | 
			
		||||
 | 
			
		||||
        g_test_add_data_func(path, test, test_hidl_vec);
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_string_err_tests); i++) {
 | 
			
		||||
        const TestHidlStringErr* test = test_hidl_string_err_tests + i;
 | 
			
		||||
        char* path = g_strconcat(TEST_PREFIX "/hidl_string/err-", test->name,
 | 
			
		||||
@@ -772,6 +1196,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "/object/object/invalid", test_object_invalid);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "/object/object/no_reg", test_object_no_reg);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "/vec", test_vec);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "/byte_array", test_byte_array);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -67,7 +67,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);
 | 
			
		||||
    GBinderRemoteObject* obj2 = gbinder_object_registry_get_remote(reg, 2);
 | 
			
		||||
@@ -108,7 +108,7 @@ test_dead(
 | 
			
		||||
{
 | 
			
		||||
    const guint handle = 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);
 | 
			
		||||
    GBinderRemoteObject* obj = gbinder_ipc_get_remote_object(ipc, handle);
 | 
			
		||||
    gulong id = gbinder_remote_object_add_death_handler
 | 
			
		||||
        (obj, test_dead_done, loop);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -35,10 +35,17 @@
 | 
			
		||||
#include "gbinder_buffer_p.h"
 | 
			
		||||
#include "gbinder_driver.h"
 | 
			
		||||
#include "gbinder_reader.h"
 | 
			
		||||
#include "gbinder_local_reply_p.h"
 | 
			
		||||
#include "gbinder_remote_reply_p.h"
 | 
			
		||||
#include "gbinder_output_data.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_intarray.h>
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
#define BINDER_TYPE_BINDER GBINDER_FOURCC('s', 'b', '*', 0x85)
 | 
			
		||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -56,6 +63,7 @@ test_null(
 | 
			
		||||
    gbinder_remote_reply_init_reader(NULL, &reader);
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert(gbinder_remote_reply_is_empty(NULL));
 | 
			
		||||
    g_assert(!gbinder_remote_reply_copy_to_local(NULL));
 | 
			
		||||
    g_assert(!gbinder_remote_reply_read_int32(NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_remote_reply_read_uint32(NULL, NULL));
 | 
			
		||||
    g_assert(!gbinder_remote_reply_read_int64(NULL, NULL));
 | 
			
		||||
@@ -74,7 +82,7 @@ void
 | 
			
		||||
test_empty(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_remote_reply_set_data
 | 
			
		||||
@@ -120,7 +128,7 @@ test_int32(
 | 
			
		||||
    };
 | 
			
		||||
    guint32 out1 = 0;
 | 
			
		||||
    gint32 out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
 | 
			
		||||
@@ -151,7 +159,7 @@ test_int64(
 | 
			
		||||
    };
 | 
			
		||||
    guint64 out1 = 0;
 | 
			
		||||
    gint64 out2 = 0;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
 | 
			
		||||
@@ -180,7 +188,7 @@ test_string8(
 | 
			
		||||
    static const guint8 reply_data [] = {
 | 
			
		||||
        'b', 'a', 'r', 0x00
 | 
			
		||||
    };
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
 | 
			
		||||
 | 
			
		||||
    gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
 | 
			
		||||
@@ -208,7 +216,7 @@ test_string16(
 | 
			
		||||
        TEST_INT16_BYTES('b'), TEST_INT16_BYTES('a'),
 | 
			
		||||
        TEST_INT16_BYTES('r'), 0x00, 0x00
 | 
			
		||||
    };
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
 | 
			
		||||
    GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
 | 
			
		||||
    char* str;
 | 
			
		||||
 | 
			
		||||
@@ -225,6 +233,55 @@ test_string16(
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * to_local
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_to_local(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    static const guint8 reply_data [] = {
 | 
			
		||||
        /* 32-bit integer */
 | 
			
		||||
        TEST_INT32_BYTES(42),
 | 
			
		||||
        /* 64-bit NULL flat_binder_object */
 | 
			
		||||
        TEST_INT32_BYTES(BINDER_TYPE_BINDER),   /* hdr.type */
 | 
			
		||||
        TEST_INT32_BYTES(0x17f),                /* flags */
 | 
			
		||||
        TEST_INT64_BYTES(0),                    /* handle */
 | 
			
		||||
        TEST_INT64_BYTES(0)                     /* cookie */
 | 
			
		||||
    };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev, NULL);
 | 
			
		||||
    GBinderRemoteReply* req = gbinder_remote_reply_new(NULL);
 | 
			
		||||
    GBinderLocalReply* req2;
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    const GByteArray* bytes;
 | 
			
		||||
    GUtilIntArray* offsets;
 | 
			
		||||
    guint8* req_data = g_memdup(reply_data, sizeof(reply_data));
 | 
			
		||||
    void** objects = g_new0(void*, 2);
 | 
			
		||||
 | 
			
		||||
    /* Skip the 32-bit integer */
 | 
			
		||||
    objects[0] = req_data + 4;
 | 
			
		||||
    gbinder_remote_reply_set_data(req, gbinder_buffer_new(driver, req_data,
 | 
			
		||||
        sizeof(reply_data)), objects);
 | 
			
		||||
 | 
			
		||||
    /* Convert to GBinderLocalReply */
 | 
			
		||||
    req2 = gbinder_remote_reply_copy_to_local(req);
 | 
			
		||||
    data = gbinder_local_reply_data(req2);
 | 
			
		||||
    offsets = gbinder_output_data_offsets(data);
 | 
			
		||||
    bytes = data->bytes;
 | 
			
		||||
    g_assert(offsets);
 | 
			
		||||
    g_assert(offsets->count == 1);
 | 
			
		||||
    g_assert(offsets->data[0] == 4);
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert(bytes->len == sizeof(reply_data));
 | 
			
		||||
 | 
			
		||||
    gbinder_remote_reply_unref(req);
 | 
			
		||||
    gbinder_local_reply_unref(req2);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -241,6 +298,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "int64", test_int64);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "string8", test_string8);
 | 
			
		||||
    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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -37,6 +37,11 @@
 | 
			
		||||
#include "gbinder_reader.h"
 | 
			
		||||
#include "gbinder_remote_request_p.h"
 | 
			
		||||
#include "gbinder_rpc_protocol.h"
 | 
			
		||||
#include "gbinder_local_request_p.h"
 | 
			
		||||
#include "gbinder_output_data.h"
 | 
			
		||||
#include "gbinder_io.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_intarray.h>
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
@@ -50,6 +55,9 @@ static TestOpt test_opt;
 | 
			
		||||
    TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'), \
 | 
			
		||||
    TEST_INT16_BYTES('o'), 0x00, 0x00
 | 
			
		||||
 | 
			
		||||
#define BINDER_TYPE_BINDER GBINDER_FOURCC('s', 'b', '*', 0x85)
 | 
			
		||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -67,6 +75,7 @@ test_null(
 | 
			
		||||
    gbinder_remote_request_init_reader(NULL, &reader);
 | 
			
		||||
    g_assert(gbinder_reader_at_end(&reader));
 | 
			
		||||
    g_assert(!gbinder_remote_request_interface(NULL));
 | 
			
		||||
    g_assert(!gbinder_remote_request_copy_to_local(NULL));
 | 
			
		||||
    g_assert(gbinder_remote_request_sender_pid(NULL) == (pid_t)(-1));
 | 
			
		||||
    g_assert(gbinder_remote_request_sender_euid(NULL) == (uid_t)(-1));
 | 
			
		||||
    g_assert(!gbinder_remote_request_read_int32(NULL, NULL));
 | 
			
		||||
@@ -116,7 +125,7 @@ test_int32(
 | 
			
		||||
    guint32 out1 = 0;
 | 
			
		||||
    gint32 out2 = 0;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev, NULL);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
 | 
			
		||||
        gbinder_rpc_protocol_for_device(dev), 0, 0);
 | 
			
		||||
 | 
			
		||||
@@ -150,7 +159,7 @@ test_int64(
 | 
			
		||||
    guint64 out1 = 0;
 | 
			
		||||
    gint64 out2 = 0;
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev, NULL);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
 | 
			
		||||
        gbinder_rpc_protocol_for_device(dev), 0, 0);
 | 
			
		||||
 | 
			
		||||
@@ -182,7 +191,7 @@ test_string8(
 | 
			
		||||
        'b', 'a', 'r', 0x00
 | 
			
		||||
    };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev, NULL);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
 | 
			
		||||
        gbinder_rpc_protocol_for_device(dev), 0, 0);
 | 
			
		||||
 | 
			
		||||
@@ -213,7 +222,7 @@ test_string16(
 | 
			
		||||
        TEST_INT16_BYTES('r'), 0x00, 0x00
 | 
			
		||||
    };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev);
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev, NULL);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
 | 
			
		||||
        gbinder_rpc_protocol_for_device(dev), 0, 0);
 | 
			
		||||
    char* str;
 | 
			
		||||
@@ -231,6 +240,59 @@ test_string16(
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * to_local
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_to_local(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    static const guint8 request_data [] = {
 | 
			
		||||
        TEST_RPC_HEADER,
 | 
			
		||||
        /* 32-bit integer */
 | 
			
		||||
        TEST_INT32_BYTES(42),
 | 
			
		||||
        /* 64-bit NULL flat_binder_object */
 | 
			
		||||
        TEST_INT32_BYTES(BINDER_TYPE_BINDER),   /* hdr.type */
 | 
			
		||||
        TEST_INT32_BYTES(0x17f),                /* flags */
 | 
			
		||||
        TEST_INT64_BYTES(0),                    /* handle */
 | 
			
		||||
        TEST_INT64_BYTES(0)                     /* cookie */
 | 
			
		||||
    };
 | 
			
		||||
    const char* dev = GBINDER_DEFAULT_BINDER;
 | 
			
		||||
    GBinderDriver* driver = gbinder_driver_new(dev, NULL);
 | 
			
		||||
    GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
 | 
			
		||||
        gbinder_rpc_protocol_for_device(dev), 0, 0);
 | 
			
		||||
    GBinderLocalRequest* req2;
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    const GByteArray* bytes;
 | 
			
		||||
    GUtilIntArray* offsets;
 | 
			
		||||
    guint8* req_data = g_memdup(request_data, sizeof(request_data));
 | 
			
		||||
    void** objects = g_new0(void*, 2);
 | 
			
		||||
 | 
			
		||||
    /* Skip the 32-bit integer */
 | 
			
		||||
    objects[0] = req_data + 4;
 | 
			
		||||
    gbinder_remote_request_set_data(req, gbinder_buffer_new(driver, req_data,
 | 
			
		||||
        sizeof(request_data)), objects);
 | 
			
		||||
 | 
			
		||||
    g_assert(!g_strcmp0(gbinder_remote_request_interface(req), TEST_RPC_IFACE));
 | 
			
		||||
 | 
			
		||||
    /* Convert to GBinderLocalRequest */
 | 
			
		||||
    req2 = gbinder_remote_request_copy_to_local(req);
 | 
			
		||||
    data = gbinder_local_request_data(req2);
 | 
			
		||||
    offsets = gbinder_output_data_offsets(data);
 | 
			
		||||
    bytes = data->bytes;
 | 
			
		||||
    g_assert(offsets);
 | 
			
		||||
    g_assert(offsets->count == 1);
 | 
			
		||||
    g_assert(offsets->data[0] == 4);
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert(bytes->len == sizeof(request_data));
 | 
			
		||||
 | 
			
		||||
    gbinder_remote_request_unref(req);
 | 
			
		||||
    gbinder_local_request_unref(req2);
 | 
			
		||||
    gbinder_driver_unref(driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -246,6 +308,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "int64", test_int64);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "string8", test_string8);
 | 
			
		||||
    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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018 Jolla Ltd.
 | 
			
		||||
 * Contact: Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,9 +13,9 @@
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the name of Jolla Ltd nor the names of its contributors may
 | 
			
		||||
 *      be used to endorse or promote products derived from this software
 | 
			
		||||
 *      without specific prior written permission.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *      this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
@@ -78,6 +78,7 @@ test_null(
 | 
			
		||||
    gbinder_writer_append_bool(&writer, FALSE);
 | 
			
		||||
    gbinder_writer_append_bytes(NULL, NULL, 0);
 | 
			
		||||
    gbinder_writer_append_bytes(&writer, NULL, 0);
 | 
			
		||||
    gbinder_writer_append_hidl_vec(NULL, NULL, 0, 0);
 | 
			
		||||
    gbinder_writer_append_hidl_string(NULL, NULL);
 | 
			
		||||
    gbinder_writer_append_hidl_string(&writer, NULL);
 | 
			
		||||
    gbinder_writer_append_hidl_string_vec(NULL, NULL, 0);
 | 
			
		||||
@@ -90,6 +91,8 @@ test_null(
 | 
			
		||||
    gbinder_writer_append_local_object(&writer, NULL);
 | 
			
		||||
    gbinder_writer_append_remote_object(NULL, NULL);
 | 
			
		||||
    gbinder_writer_append_remote_object(&writer, NULL);
 | 
			
		||||
    gbinder_writer_append_byte_array(NULL, NULL, 0);
 | 
			
		||||
    gbinder_writer_append_byte_array(&writer, NULL, 0);
 | 
			
		||||
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(NULL));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(NULL));
 | 
			
		||||
@@ -201,9 +204,9 @@ test_bool(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    const char encoded[] = {
 | 
			
		||||
        0x00, 0xff, 0xff, 0xff,
 | 
			
		||||
        0x01, 0xff, 0xff, 0xff,
 | 
			
		||||
        0x01, 0xff, 0xff, 0xff
 | 
			
		||||
        0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
        0x01, 0x00, 0x00, 0x00,
 | 
			
		||||
        0x01, 0x00, 0x00, 0x00
 | 
			
		||||
    };
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
@@ -339,6 +342,67 @@ test_string16(
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_vec
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_hidl_vec_data {
 | 
			
		||||
    const char* name;
 | 
			
		||||
    const GBinderIo* io;
 | 
			
		||||
    const void* data;
 | 
			
		||||
    const gsize count;
 | 
			
		||||
    const gsize elemsize;
 | 
			
		||||
    const guint* offsets;
 | 
			
		||||
    guint offsets_count;
 | 
			
		||||
    guint buffers_size;
 | 
			
		||||
} TestHidlVecData;
 | 
			
		||||
 | 
			
		||||
static guint test_hidl_vec_offsets_0[] =
 | 
			
		||||
    { 0 };
 | 
			
		||||
static guint test_hidl_vec_offsets_32[] =
 | 
			
		||||
    { 0, BUFFER_OBJECT_SIZE_32 };
 | 
			
		||||
static guint test_hidl_vec_offsets_64[] =
 | 
			
		||||
    { 0, BUFFER_OBJECT_SIZE_64 };
 | 
			
		||||
 | 
			
		||||
static const TestHidlVecData test_hidl_vec_tests[] = {
 | 
			
		||||
    { "32/null", &gbinder_io_32, NULL, 0, 0,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_0), sizeof(HidlVec) },
 | 
			
		||||
    { "32/2x1", &gbinder_io_32, "xy", 2, 1,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_32),
 | 
			
		||||
      sizeof(HidlVec) + 8 /* vec data aligned at 8 bytes boundary */ },
 | 
			
		||||
    { "64/null", &gbinder_io_64, NULL, 0, 0,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_0), sizeof(HidlVec) },
 | 
			
		||||
    { "64/2x2", &gbinder_io_64, "xxyy", 2, 2,
 | 
			
		||||
      TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_64),
 | 
			
		||||
      sizeof(HidlVec) + 8 /* vec data aligned at 8 bytes boundary */ }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_hidl_vec(
 | 
			
		||||
    gconstpointer test_data)
 | 
			
		||||
{
 | 
			
		||||
    const TestHidlVecData* test = test_data;
 | 
			
		||||
    GBinderLocalRequest* req = gbinder_local_request_new(test->io, NULL);
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
    GUtilIntArray* offsets;
 | 
			
		||||
    guint i;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_hidl_vec(&writer, test->data,
 | 
			
		||||
        test->count, test->elemsize);
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    offsets = gbinder_output_data_offsets(data);
 | 
			
		||||
    g_assert(offsets);
 | 
			
		||||
    g_assert(offsets->count == test->offsets_count);
 | 
			
		||||
    for (i = 0; i < offsets->count; i++) {
 | 
			
		||||
        g_assert(offsets->data[i] == test->offsets[i]);
 | 
			
		||||
    }
 | 
			
		||||
    g_assert(gbinder_output_data_buffers_size(data) == test->buffers_size);
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * hidl_string
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -621,6 +685,58 @@ test_remote_object(
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * byte_array
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_byte_array(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req;
 | 
			
		||||
    GBinderOutputData* data;
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
    const char in_data[] = "abcd1234";
 | 
			
		||||
    gint32 in_len = sizeof(in_data) - 1;
 | 
			
		||||
    gint32 null_len = -1;
 | 
			
		||||
 | 
			
		||||
    /* test for NULL byte array with non-zero len */
 | 
			
		||||
    req = gbinder_local_request_new(&gbinder_io_64, NULL);
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_byte_array(&writer, NULL, 42);
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert(data->bytes->len == sizeof(gint32));
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data, &null_len, data->bytes->len));
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    /* test for valid array with zero len */
 | 
			
		||||
    req = gbinder_local_request_new(&gbinder_io_64, NULL);
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_byte_array(&writer, in_data, 0);
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert(data->bytes->len == sizeof(gint32));
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data, &null_len, data->bytes->len));
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    /* test for valid array with correct len */
 | 
			
		||||
    req = gbinder_local_request_new(&gbinder_io_64, NULL);
 | 
			
		||||
    gbinder_local_request_init_writer(req, &writer);
 | 
			
		||||
    gbinder_writer_append_byte_array(&writer, in_data, in_len);
 | 
			
		||||
    data = gbinder_local_request_data(req);
 | 
			
		||||
    g_assert(!gbinder_output_data_offsets(data));
 | 
			
		||||
    g_assert(!gbinder_output_data_buffers_size(data));
 | 
			
		||||
    g_assert(data->bytes->len == sizeof(in_len) + in_len);
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data, &in_len, sizeof(in_len)));
 | 
			
		||||
    g_assert(!memcmp(data->bytes->data + sizeof(in_len), in_data, in_len));
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
@@ -649,6 +765,14 @@ int main(int argc, char* argv[])
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_vec_tests); i++) {
 | 
			
		||||
        const TestHidlVecData* test = test_hidl_vec_tests + i;
 | 
			
		||||
        char* path = g_strconcat(TEST_PREFIX "hidl_vec/", test->name, NULL);
 | 
			
		||||
 | 
			
		||||
        g_test_add_data_func(path, test, test_hidl_vec);
 | 
			
		||||
        g_free(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "hidl_string/2strings", test_hidl_string2);
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test_hidl_string_tests); i++) {
 | 
			
		||||
        const TestHidlStringData* test = test_hidl_string_tests + i;
 | 
			
		||||
@@ -671,6 +795,7 @@ int main(int argc, char* argv[])
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "parent", test_parent);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "local_object", test_local_object);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "remote_object", test_remote_object);
 | 
			
		||||
    g_test_add_func(TEST_PREFIX "byte_array", test_byte_array);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user