Compare commits

...

42 Commits

Author SHA1 Message Date
Slava Monich
d855d695db Version 1.0.14 2018-11-27 17:21:33 +02:00
Slava Monich
922cc82029 Merge pull request #15 from monich/bool
Change bool padding from 0xff to 0x00
2018-11-27 17:15:57 +02:00
Slava Monich
80498378f2 [gbinder] Change bool padding from 0xff to 0x00. JB#42956
That should make it compatible with both java and hidl variants of
encoding (Android's libbinder vs libhwbinder)
2018-11-27 16:59:11 +02:00
Slava Monich
51856865df Version 1.0.13 2018-11-17 01:58:33 +02:00
Slava Monich
d26dcca37e [gbinder] Make sure looper is started
... before gbinder_ipc_looper_new() returns.
2018-11-17 01:49:50 +02:00
Slava Monich
5ac02fcb2e Merge pull request #14 from monich/registration
Support for service registration notifications
2018-11-17 01:47:28 +02:00
Slava Monich
110cd65779 [gbinder] Support for service registration notifications. JB#43815
android.hidl.manager@1.0::IServiceManager provides registration
notifications via android.hidl.manager@1.0::IServiceNotification
callback.

Sailfish OS services that talk to Android services via binder should
use this mechanism to wait for their Android counterpart at startup.
2018-11-17 01:41:02 +02:00
Slava Monich
67e665b619 Version 1.0.12 2018-10-31 17:07:45 +03:00
Slava Monich
d1c431c370 Acknowledge contributions 2018-10-31 17:03:44 +03:00
Slava Monich
2167a82c73 Housekeeping 2018-10-31 17:01:00 +03:00
Slava Monich
d113d3bf4a Merge pull request #12 from jusa/byte_array
Add byte array reader and writer.
2018-10-31 16:40:33 +03:00
Juho Hämäläinen
b2206adae5 [gbinder] Add byte array reader and writer. JB#43536
New functions gbinder_reader_read_byte_array() and
gbinder_writer_append_byte_array()
2018-10-30 07:28:19 +02:00
Slava Monich
8075cce1b1 Version 1.0.11 2018-10-24 18:59:30 +03:00
Slava Monich
29e4c79f75 Merge pull request #11 from krnlyng/jb43524
Make sure NULL objects are passed as BINDER_TYPE_WEAK_HANDLE
2018-10-24 18:53:58 +03:00
Franz-Josef Haider
3b299d3345 [local_object] Make sure NULL objects are passed as BINDER_TYPE_WEAK_HANDLE. Contributes to JB#43524
See also: https://android.googlesource.com/platform/frameworks/native/+/master/libs/binder/Parcel.cpp#264
2018-10-24 15:41:27 +00:00
Slava Monich
7421fff380 Updated README 2018-10-11 12:04:04 +03:00
Slava Monich
694aad637b Version 1.0.10 2018-10-10 14:46:40 +03:00
Slava Monich
c8c7222e06 [unit] Plugged memory leak in unit_reader. JB#42956 2018-10-10 14:44:25 +03:00
Slava Monich
9c6e31ef41 Merge pull request #10 from monich/deps
Fix dependencies for unit tests
2018-10-10 14:39:17 +03:00
Slava Monich
6a8d5c0c6e [unit] Fixed dependencies for unit tests. JB#42691 2018-10-10 14:38:38 +03:00
Slava Monich
96ca10396b Version 1.0.9 2018-10-08 11:43:53 +03:00
Slava Monich
61cef824e8 Merge pull request #9 from monich/read_hidl_struct
Add gbinder_reader_read_hidl_struct() and other macros
2018-10-08 11:20:13 +03:00
Slava Monich
972517d32d Merge pull request #8 from monich/strong_refs
Respect strong refs to GBinderLocalObject
2018-10-08 11:17:00 +03:00
Slava Monich
217a03642a [unit] Added test for new gbinder_reader_read_hidl_struct() 2018-10-08 11:13:00 +03:00
Slava Monich
f14783b8cf [gbinder] Add gbinder_reader_read_hidl_struct() macro. JB#42956
As well as two macros for reading arrays:

   gbinder_reader_read_hidl_type_vec() - vec<type>
   gbinder_reader_read_hidl_byte_vec() - vec<uint8_t>

These convenient for pulling structures and arrays from hwbinder
requests and responses.

Note that data are not being copied, all these macros return pointers
to the memory buffer passed to us by the kernel. Such pointers remain
valid as long the associated remote request/response is alive.
2018-10-06 18:07:39 +03:00
Slava Monich
4f75c6e37b [gbinder] Respect strong refs to GBinderLocalObject. JB#42956
This lets kernel to keep the object alive for a long time, after the
creator of the object drops its last reference.

That makes it even more important very important that creator drops
its last reference by calling gbinder_local_object_drop() rather than
gbinder_local_object_unref() to make sure that the handler function
doesn't get called anymore.
2018-10-06 11:39:02 +03:00
Slava Monich
4eb3b66a0e Version 1.0.8 2018-09-25 01:09:53 +03:00
Slava Monich
6b74d5faed Merge pull request #7 from monich/hidl_vec
Add gbinder_writer_append_hidl_vec() and gbinder_reader_read_hidl_vec()
2018-09-25 01:05:39 +03:00
Slava Monich
10d72ec42c [unit] Added test for gbinder_reader_read_hidl_vec() 2018-09-24 03:33:42 +03:00
Slava Monich
9eae4ef819 [gbinder] Added gbinder_reader_read_hidl_vec(). JB#42956
This provides a generic way to read any array of any primitive
types or structures. Note that it doesn't copy the data and
directly returns the pointer provided by the kernel.
2018-09-24 03:14:33 +03:00
Slava Monich
b3657e396f [unit] Added test for gbinder_writer_append_hidl_vec() 2018-09-24 00:48:56 +03:00
Slava Monich
a69885d05f [gbinder] Added gbinder_writer_append_hidl_vec(). JB#42956
This provides a generic way to write hidl-style array of any primitive
types or any structures as long as they don't contain pointers.
2018-09-24 00:47:14 +03:00
Slava Monich
306d08112b Version 1.0.7 2018-09-23 22:49:16 +03:00
Slava Monich
b489becf51 Merge pull request #5 from monich/forward
Add gbinder_remote_request_copy_to_local() and gbinder_remote_reply_copy_to_local()
2018-09-23 22:44:27 +03:00
Slava Monich
8a27829af3 [gbinder] Make sure RPC protocol matches servicemanager type
This makes it easier to use non-standard binder device name.
2018-09-22 12:15:20 +03:00
Slava Monich
d67b73502e [unit] Added test for gbinder_remote_reply_copy_to_local() 2018-09-22 12:15:20 +03:00
Slava Monich
4ecf3ae24d [gbinder] Added gbinder_remote_reply_copy_to_local(). JB#42956 2018-09-22 12:15:20 +03:00
Slava Monich
d0542e759d [unit] Added test for gbinder_remote_request_copy_to_local() 2018-09-22 12:15:20 +03:00
Slava Monich
ffa44ac5b3 [gbinder] Added gbinder_remote_request_copy_to_local(). JB#42956
This function could be useful for proxy services, as an easy way to
forward an incoming request. To complete the picture, we should also
have gbinder_remote_reply_copy_to_local() for forwarding replies.
2018-09-22 12:15:20 +03:00
Slava Monich
6509e5dac8 Version 1.0.6 2018-09-21 21:16:29 +03:00
Slava Monich
6b956c0d3c Merge pull request #6 from monich/ref_count
Fix GBinderServiceManager lifecycle management
2018-09-21 21:14:01 +03:00
Slava Monich
3b10a08bad [gbinder] Fixed GBinderServiceManager lifecycle management. Fixes JB#43018
Dispose callback is invoked with refcount 1
2018-09-21 20:27:40 +03:00
53 changed files with 2399 additions and 437 deletions

View File

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

View File

@@ -24,7 +24,7 @@ all: debug release pkgconfig
VERSION_MAJOR = 1
VERSION_MINOR = 0
VERSION_RELEASE = 5
VERSION_RELEASE = 14
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)

6
README
View File

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

62
debian/changelog vendored
View File

@@ -1,3 +1,65 @@
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
-- Slava Monich <slava.monich@jolla.com> Fri, 21 Sep 2018 21:15:28 +0300
libgbinder (1.0.5) unstable; urgency=low
* Added double and float support

4
debian/control vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,14 @@
Name: libgbinder
Version: 1.0.5
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 */
@@ -475,7 +642,7 @@ gbinder_servicemanager_dispose(
* gbinder_servicemanager_finalize() will not be called
* this time around.
*/
if (klass->table && object->ref_count == 0) {
if (klass->table && g_atomic_int_get(&object->ref_count) <= 1) {
g_hash_table_remove(klass->table, self->dev);
if (g_hash_table_size(klass->table) == 0) {
g_hash_table_unref(klass->table);
@@ -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);
}
/*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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++) {

View File

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

View File

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

View File

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

View File

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

View File

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