Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9903e7398 | ||
|
|
39b69f27ee | ||
|
|
31a1d19b4e | ||
|
|
f4a923c3dc | ||
|
|
171ff7d1e4 | ||
|
|
5cfbf22b81 | ||
|
|
5a35ed5ea1 | ||
|
|
1978359f15 | ||
|
|
fef6543f1a | ||
|
|
b1a9200803 | ||
|
|
fada30868a | ||
|
|
8414e9485f | ||
|
|
f6d8d485bc | ||
|
|
6ea0d6c631 | ||
|
|
31c6c05c1e | ||
|
|
d855d695db | ||
|
|
922cc82029 | ||
|
|
80498378f2 | ||
|
|
51856865df | ||
|
|
d26dcca37e | ||
|
|
5ac02fcb2e | ||
|
|
110cd65779 | ||
|
|
67e665b619 | ||
|
|
d1c431c370 | ||
|
|
2167a82c73 | ||
|
|
d113d3bf4a | ||
|
|
b2206adae5 | ||
|
|
8075cce1b1 | ||
|
|
29e4c79f75 | ||
|
|
3b299d3345 | ||
|
|
7421fff380 | ||
|
|
694aad637b | ||
|
|
c8c7222e06 | ||
|
|
9c6e31ef41 | ||
|
|
6a8d5c0c6e | ||
|
|
96ca10396b | ||
|
|
61cef824e8 | ||
|
|
972517d32d | ||
|
|
217a03642a | ||
|
|
f14783b8cf | ||
|
|
4f75c6e37b | ||
|
|
4eb3b66a0e | ||
|
|
6b74d5faed | ||
|
|
10d72ec42c | ||
|
|
9eae4ef819 | ||
|
|
b3657e396f | ||
|
|
a69885d05f | ||
|
|
306d08112b | ||
|
|
b489becf51 | ||
|
|
8a27829af3 | ||
|
|
d67b73502e | ||
|
|
4ecf3ae24d | ||
|
|
d0542e759d | ||
|
|
ffa44ac5b3 |
2
AUTHORS
2
AUTHORS
@@ -1,2 +1,4 @@
|
||||
Slava Monich <slava.monich@jolla.com>
|
||||
Matti Lehtimäki <matti.lehtimaki@gmail.com>
|
||||
Franz-Josef Haider <franz.haider@jolla.com>
|
||||
Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
|
||||
3
Makefile
3
Makefile
@@ -24,7 +24,7 @@ all: debug release pkgconfig
|
||||
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 0
|
||||
VERSION_RELEASE = 6
|
||||
VERSION_RELEASE = 17
|
||||
|
||||
# Version for pkg-config
|
||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
@@ -62,6 +62,7 @@ SRC = \
|
||||
gbinder_remote_reply.c \
|
||||
gbinder_remote_request.c \
|
||||
gbinder_rpc_protocol.c \
|
||||
gbinder_servicepoll.c \
|
||||
gbinder_writer.c
|
||||
|
||||
SRC += \
|
||||
|
||||
6
README
6
README
@@ -1 +1,7 @@
|
||||
GLib-style interface to binder (Android IPC mechanism)
|
||||
|
||||
Provides:
|
||||
|
||||
1. Integration with GLib event loop
|
||||
2. Detection of 32 vs 64 bit kernel at runtime
|
||||
3. Asynchronous transactions that don't block the event thread
|
||||
|
||||
77
debian/changelog
vendored
77
debian/changelog
vendored
@@ -1,3 +1,80 @@
|
||||
libgbinder (1.0.17) unstable; urgency=low
|
||||
|
||||
* Added gbinder_writer_append_string16_utf16()
|
||||
* Added gbinder_reader_read_nullable_string16_utf16()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Fri, 07 Dec 2018 02:54:07 +0200
|
||||
|
||||
libgbinder (1.0.16) unstable; urgency=low
|
||||
|
||||
* Added GBinderHidlVec and GBinderHidlString types
|
||||
* Added gbinder_reader_copy()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 06 Dec 2018 19:03:32 +0200
|
||||
|
||||
libgbinder (1.0.15) unstable; urgency=low
|
||||
|
||||
* Implemented service polling for old servicemanager
|
||||
* Added new tests and improved coverage for existing ones
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 05 Dec 2018 12:11:34 +0200
|
||||
|
||||
libgbinder (1.0.14) unstable; urgency=low
|
||||
|
||||
* Changed bool padding from 0xff to 0x00
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 27 Nov 2018 17:20:18 +0200
|
||||
|
||||
libgbinder (1.0.13) unstable; urgency=low
|
||||
|
||||
* Support for service registration notifications
|
||||
* Make sure looper is started before gbinder_ipc_looper_new() returns
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sat, 17 Nov 2018 01:52:28 +0200
|
||||
|
||||
libgbinder (1.0.12) unstable; urgency=low
|
||||
|
||||
* Add byte array reader and writer
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 31 Oct 2018 17:04:38 +0300
|
||||
|
||||
libgbinder (1.0.11) unstable; urgency=low
|
||||
|
||||
* Use BINDER_TYPE_WEAK_HANDLE for NULL objects
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 24 Oct 2018 18:57:28 +0300
|
||||
|
||||
libgbinder (1.0.10) unstable; urgency=low
|
||||
|
||||
* Fixed dependencies for unit tests
|
||||
* Plugged memory leak in unit_reader
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Wed, 10 Oct 2018 14:44:44 +0300
|
||||
|
||||
libgbinder (1.0.9) unstable; urgency=low
|
||||
|
||||
* Respect strong refs to GBinderLocalObject
|
||||
* Added gbinder_reader_read_hidl_struct macro
|
||||
* Added gbinder_reader_read_hidl_type_vec macro
|
||||
* Added gbinder_reader_read_hidl_byte_vec macro
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Mon, 08 Oct 2018 11:41:33 +0300
|
||||
|
||||
libgbinder (1.0.8) unstable; urgency=low
|
||||
|
||||
* Added gbinder_writer_append_hidl_vec()
|
||||
* Added Added gbinder_reader_read_hidl_vec()
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Tue, 25 Sep 2018 01:08:54 +0300
|
||||
|
||||
libgbinder (1.0.7) unstable; urgency=low
|
||||
|
||||
* Added gbinder_remote_request_copy_to_local()
|
||||
* Added gbinder_remote_reply_copy_to_local()
|
||||
* Make sure RPC protocol matches servicemanager type
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Sun, 23 Sep 2018 22:47:16 +0300
|
||||
|
||||
libgbinder (1.0.6) unstable; urgency=low
|
||||
|
||||
* Fixed GBinderServiceManager lifecycle management
|
||||
|
||||
4
debian/control
vendored
4
debian/control
vendored
@@ -2,13 +2,13 @@ Source: libgbinder
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Maintainer: Slava Monich <slava.monich@jolla.com>
|
||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.29)
|
||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.34)
|
||||
Standards-Version: 3.8.4
|
||||
|
||||
Package: libgbinder
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Depends: libglibutil (>= 1.0.29), ${shlibs:Depends}, ${misc:Depends}
|
||||
Depends: libglibutil (>= 1.0.34), ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Binder client library
|
||||
|
||||
Package: libgbinder-dev
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -53,7 +53,7 @@ struct gbinder_reader {
|
||||
|
||||
gboolean
|
||||
gbinder_reader_at_end(
|
||||
GBinderReader* reader);
|
||||
const GBinderReader* reader);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_byte(
|
||||
@@ -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)
|
||||
@@ -140,17 +165,33 @@ gbinder_reader_read_nullable_string16(
|
||||
GBinderReader* reader,
|
||||
char** out);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_string16_utf16(
|
||||
GBinderReader* reader,
|
||||
gunichar2** out,
|
||||
gsize* len); /* since 1.0.17 */
|
||||
|
||||
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);
|
||||
const GBinderReader* reader);
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_remaining(
|
||||
GBinderReader* reader);
|
||||
const GBinderReader* reader);
|
||||
|
||||
void
|
||||
gbinder_reader_copy(
|
||||
GBinderReader* dest,
|
||||
const GBinderReader* src); /* Since 1.0.16 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -50,6 +50,11 @@ gbinder_remote_reply_init_reader(
|
||||
GBinderRemoteReply* reply,
|
||||
GBinderReader* reader);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_remote_reply_copy_to_local(
|
||||
GBinderRemoteReply* reply) /* since 1.0.6 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Convenience function to decode replies with just one data item */
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -62,6 +62,11 @@ uid_t
|
||||
gbinder_remote_request_sender_euid(
|
||||
GBinderRemoteRequest* req); /* since 1.0.2 */
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_remote_request_copy_to_local(
|
||||
GBinderRemoteRequest* req) /* since 1.0.6 */
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Convenience function to decode requests with just one data item */
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -61,6 +61,13 @@ void
|
||||
int status,
|
||||
void* user_data);
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderServiceManagerRegistrationFunc)(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
void* user_data);
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new(
|
||||
const char* dev);
|
||||
@@ -130,6 +137,18 @@ gbinder_servicemanager_cancel(
|
||||
GBinderServiceManager* sm,
|
||||
gulong id);
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_registration_handler(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
GBinderServiceManagerRegistrationFunc func,
|
||||
void* user_data); /* Since 1.0.13 */
|
||||
|
||||
void
|
||||
gbinder_servicemanager_remove_handler(
|
||||
GBinderServiceManager* sm,
|
||||
gulong id); /* Since 1.0.13 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_H */
|
||||
|
||||
@@ -72,6 +72,30 @@ typedef struct gbinder_servicemanager GBinderServiceManager;
|
||||
typedef struct gbinder_writer GBinderWriter;
|
||||
typedef struct gbinder_parent GBinderParent;
|
||||
|
||||
/* Basic HIDL types */
|
||||
|
||||
typedef struct gbinder_hidl_vec {
|
||||
union {
|
||||
guint64 value;
|
||||
const void* ptr;
|
||||
} data;
|
||||
guint32 count;
|
||||
guint32 owns_buffer;
|
||||
} GBinderHidlVec;
|
||||
|
||||
#define GBINDER_HIDL_VEC_BUFFER_OFFSET (0)
|
||||
|
||||
typedef struct gbinder_hidl_string {
|
||||
union {
|
||||
guint64 value;
|
||||
const char* str;
|
||||
} data;
|
||||
guint32 len;
|
||||
guint32 owns_buffer;
|
||||
} GBinderHidlString;
|
||||
|
||||
#define GBINDER_HIDL_STRING_BUFFER_OFFSET (0)
|
||||
|
||||
/*
|
||||
* Each RPC call is identified by the interface name returned
|
||||
* by gbinder_remote_request_interface() the transaction code.
|
||||
|
||||
@@ -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
|
||||
@@ -86,6 +86,12 @@ gbinder_writer_append_string16_len(
|
||||
const char* utf8,
|
||||
gssize num_bytes);
|
||||
|
||||
void
|
||||
gbinder_writer_append_string16_utf16(
|
||||
GBinderWriter* writer,
|
||||
const gunichar2* utf16,
|
||||
gssize length); /* Since 1.0.17 */
|
||||
|
||||
void
|
||||
gbinder_writer_append_string8(
|
||||
GBinderWriter* writer,
|
||||
@@ -121,6 +127,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 +155,12 @@ gbinder_writer_append_remote_object(
|
||||
GBinderWriter* writer,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
void
|
||||
gbinder_writer_append_byte_array(
|
||||
GBinderWriter* self,
|
||||
const void* byte_array,
|
||||
gint32 len); /* since 1.0.12 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_WRITER_H */
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
Name: libgbinder
|
||||
Version: 1.0.6
|
||||
Version: 1.0.17
|
||||
Release: 0
|
||||
Summary: Binder client library
|
||||
Group: Development/Libraries
|
||||
License: BSD
|
||||
URL: https://github.com/mer-hybris/libgbinder
|
||||
Source: %{name}-%{version}.tar.bz2
|
||||
Requires: libglibutil >= 1.0.29
|
||||
Requires: libglibutil >= 1.0.34
|
||||
BuildRequires: pkgconfig(glib-2.0)
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.29
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.34
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -36,12 +36,12 @@
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
typedef struct gbinder_buffer_memory {
|
||||
struct gbinder_buffer_memory {
|
||||
gint refcount;
|
||||
void* buffer;
|
||||
gsize size;
|
||||
GBinderDriver* driver;
|
||||
} GBinderBufferMemory;
|
||||
};
|
||||
|
||||
typedef struct gbinder_buffer_priv {
|
||||
GBinderBuffer pub;
|
||||
@@ -81,7 +81,6 @@ gbinder_buffer_memory_free(
|
||||
g_slice_free(GBinderBufferMemory, self);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderBufferMemory*
|
||||
gbinder_buffer_memory_ref(
|
||||
GBinderBufferMemory* self)
|
||||
@@ -93,7 +92,6 @@ gbinder_buffer_memory_ref(
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_buffer_memory_unref(
|
||||
GBinderBufferMemory* self)
|
||||
@@ -155,10 +153,30 @@ gbinder_buffer_new_with_parent(
|
||||
gsize size)
|
||||
{
|
||||
return gbinder_buffer_alloc(parent ?
|
||||
gbinder_buffer_memory_ref(gbinder_buffer_cast(parent)->memory) : NULL,
|
||||
gbinder_buffer_memory_ref(gbinder_buffer_memory(parent)) : NULL,
|
||||
data, size);
|
||||
}
|
||||
|
||||
gconstpointer
|
||||
gbinder_buffer_data(
|
||||
GBinderBuffer* self,
|
||||
gsize* size)
|
||||
{
|
||||
GBinderBufferMemory* memory = gbinder_buffer_memory(self);
|
||||
|
||||
if (G_LIKELY(memory)) {
|
||||
if (size) {
|
||||
*size = memory->size;
|
||||
}
|
||||
return memory->buffer;
|
||||
} else {
|
||||
if (size) {
|
||||
*size = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_buffer_driver(
|
||||
GBinderBuffer* self)
|
||||
@@ -173,6 +191,22 @@ gbinder_buffer_driver(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const GBinderIo*
|
||||
gbinder_buffer_io(
|
||||
GBinderBuffer* buf)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_buffer_driver(buf);
|
||||
|
||||
return driver ? gbinder_driver_io(driver) : NULL;
|
||||
}
|
||||
|
||||
GBinderBufferMemory*
|
||||
gbinder_buffer_memory(
|
||||
GBinderBuffer* self)
|
||||
{
|
||||
return G_LIKELY(self) ? gbinder_buffer_cast(self)->memory : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -53,8 +53,26 @@ GBinderDriver*
|
||||
gbinder_buffer_driver(
|
||||
GBinderBuffer* buf);
|
||||
|
||||
#define gbinder_buffer_io(buf) \
|
||||
gbinder_driver_io(gbinder_buffer_driver(buf))
|
||||
GBinderBufferMemory*
|
||||
gbinder_buffer_memory(
|
||||
GBinderBuffer* buf);
|
||||
|
||||
gconstpointer
|
||||
gbinder_buffer_data(
|
||||
GBinderBuffer* buf,
|
||||
gsize* size);
|
||||
|
||||
const GBinderIo*
|
||||
gbinder_buffer_io(
|
||||
GBinderBuffer* buf);
|
||||
|
||||
GBinderBufferMemory*
|
||||
gbinder_buffer_memory_ref(
|
||||
GBinderBufferMemory* mem);
|
||||
|
||||
void
|
||||
gbinder_buffer_memory_unref(
|
||||
GBinderBufferMemory* mem);
|
||||
|
||||
#endif /* GBINDER_BUFFER_PRIVATE_H */
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -31,6 +31,8 @@
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_servicepoll.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
@@ -42,13 +44,31 @@
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef GBinderServiceManager GBinderDefaultServiceManager;
|
||||
typedef struct gbinder_defaultservicemanager_watch {
|
||||
GBinderServicePoll* poll;
|
||||
char* name;
|
||||
gulong handler_id;
|
||||
guint notify_id;
|
||||
} GBinderDefaultServiceManagerWatch;
|
||||
|
||||
typedef GBinderServiceManagerClass GBinderDefaultServiceManagerClass;
|
||||
typedef struct gbinder_defaultservicemanager {
|
||||
GBinderServiceManager manager;
|
||||
GBinderServicePoll* poll;
|
||||
GHashTable* watch_table;
|
||||
} GBinderDefaultServiceManager;
|
||||
|
||||
G_DEFINE_TYPE(GBinderDefaultServiceManager,
|
||||
gbinder_defaultservicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define PARENT_CLASS gbinder_defaultservicemanager_parent_class
|
||||
#define GBINDER_TYPE_DEFAULTSERVICEMANAGER \
|
||||
gbinder_defaultservicemanager_get_type()
|
||||
#define GBINDER_DEFAULTSERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_DEFAULTSERVICEMANAGER, \
|
||||
GBinderDefaultServiceManager)
|
||||
|
||||
enum gbinder_defaultservicemanager_calls {
|
||||
GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
CHECK_SERVICE_TRANSACTION,
|
||||
@@ -65,7 +85,76 @@ gbinder_defaultservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_defaultservicemanager_get_type(), dev);
|
||||
(GBINDER_TYPE_DEFAULTSERVICEMANAGER, dev);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_watch_proc(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name_added,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch = user_data;
|
||||
|
||||
if (!g_strcmp0(name_added, watch->name)) {
|
||||
GBinderServiceManager* manager =
|
||||
gbinder_servicepoll_manager(watch->poll);
|
||||
|
||||
if (watch->notify_id) {
|
||||
g_source_remove(watch->notify_id);
|
||||
watch->notify_id = 0;
|
||||
}
|
||||
gbinder_servicemanager_service_registered(manager, name_added);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_defaultservicemanager_watch_notify(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch = user_data;
|
||||
GBinderServiceManager* manager = gbinder_servicepoll_manager(watch->poll);
|
||||
char* name = g_strdup(watch->name);
|
||||
|
||||
GASSERT(watch->notify_id);
|
||||
watch->notify_id = 0;
|
||||
gbinder_servicemanager_service_registered(manager, name);
|
||||
g_free(name);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_watch_free(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch = user_data;
|
||||
|
||||
if (watch->notify_id) {
|
||||
g_source_remove(watch->notify_id);
|
||||
}
|
||||
gbinder_servicepoll_remove_handler(watch->poll, watch->handler_id);
|
||||
gbinder_servicepoll_unref(watch->poll);
|
||||
g_free(watch->name);
|
||||
g_slice_free(GBinderDefaultServiceManagerWatch, watch);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderDefaultServiceManagerWatch*
|
||||
gbinder_defaultservicemanager_watch_new(
|
||||
GBinderDefaultServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderDefaultServiceManagerWatch* watch =
|
||||
g_slice_new0(GBinderDefaultServiceManagerWatch);
|
||||
|
||||
watch->name = g_strdup(name);
|
||||
watch->poll = gbinder_servicepoll_new(&manager->manager, &manager->poll);
|
||||
watch->handler_id = gbinder_servicepoll_add_handler(watch->poll,
|
||||
gbinder_defaultservicemanager_watch_proc, watch);
|
||||
return watch;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -150,11 +239,61 @@ gbinder_defaultservicemanager_add_service(
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
gbinder_defaultservicemanager_check_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
return GBINDER_SERVICEMANAGER_NAME_OK;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_defaultservicemanager_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderDefaultServiceManager* self = GBINDER_DEFAULTSERVICEMANAGER(manager);
|
||||
GBinderDefaultServiceManagerWatch* watch =
|
||||
gbinder_defaultservicemanager_watch_new(self, name);
|
||||
|
||||
g_hash_table_replace(self->watch_table, watch->name, watch);
|
||||
if (gbinder_servicepoll_is_known_name(watch->poll, name)) {
|
||||
watch->notify_id =
|
||||
g_idle_add(gbinder_defaultservicemanager_watch_notify, watch);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_unwatch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
g_hash_table_remove(GBINDER_DEFAULTSERVICEMANAGER(manager)->watch_table,
|
||||
name);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_init(
|
||||
GBinderDefaultServiceManager* self)
|
||||
{
|
||||
self->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
NULL, gbinder_defaultservicemanager_watch_free);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderDefaultServiceManager* self = GBINDER_DEFAULTSERVICEMANAGER(object);
|
||||
|
||||
g_hash_table_destroy(self->watch_table);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -165,10 +304,16 @@ 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;
|
||||
/* normalize_name is not needed */
|
||||
klass->watch = gbinder_defaultservicemanager_watch;
|
||||
klass->unwatch = gbinder_defaultservicemanager_unwatch;
|
||||
G_OBJECT_CLASS(klass)->finalize = gbinder_defaultservicemanager_finalize;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -672,7 +672,8 @@ gbinder_driver_txstatus(
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_driver_new(
|
||||
const char* dev)
|
||||
const char* dev,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
const int fd = gbinder_system_open(dev, O_RDWR | O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
@@ -711,8 +712,10 @@ gbinder_driver_new(
|
||||
GERR("%s failed to set max threads (%u): %s", dev,
|
||||
max_threads, strerror(errno));
|
||||
}
|
||||
/* Choose the protocol based on the device name */
|
||||
self->protocol = gbinder_rpc_protocol_for_device(dev);
|
||||
/* Choose the protocol based on the device name
|
||||
* if none is explicitely specified */
|
||||
self->protocol = protocol ? protocol :
|
||||
gbinder_rpc_protocol_for_device(dev);
|
||||
return self;
|
||||
} else {
|
||||
GERR("%s failed to mmap: %s", dev, strerror(errno));
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -39,7 +39,8 @@ struct pollfd;
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_driver_new(
|
||||
const char* dev);
|
||||
const char* dev,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_driver_ref(
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -31,23 +31,40 @@
|
||||
*/
|
||||
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
#include <gbinder_local_object.h>
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
#include <gbinder_remote_request.h>
|
||||
#include <gbinder_reader.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef GBinderServiceManager GBinderHwServiceManager;
|
||||
typedef struct gbinder_hwservicemanager_watch {
|
||||
char* name;
|
||||
GBinderLocalObject* callback;
|
||||
} GBinderHwServiceManagerWatch;
|
||||
|
||||
typedef GBinderServiceManagerClass GBinderHwServiceManagerClass;
|
||||
typedef struct gbinder_hwservicemanager {
|
||||
GBinderServiceManager manager;
|
||||
GHashTable* watch_table;
|
||||
} GBinderHwServiceManager;
|
||||
|
||||
G_DEFINE_TYPE(GBinderHwServiceManager,
|
||||
gbinder_hwservicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define PARENT_CLASS gbinder_hwservicemanager_parent_class
|
||||
#define GBINDER_TYPE_HWSERVICEMANAGER (gbinder_hwservicemanager_get_type())
|
||||
#define GBINDER_HWSERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_HWSERVICEMANAGER, \
|
||||
GBinderHwServiceManager)
|
||||
|
||||
enum gbinder_hwservicemanager_calls {
|
||||
GET_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
ADD_TRANSACTION,
|
||||
@@ -59,9 +76,76 @@ enum gbinder_hwservicemanager_calls {
|
||||
REGISTER_PASSTHROUGH_CLIENT_TRANSACTION
|
||||
};
|
||||
|
||||
enum gbinder_hwservicemanager_notifications {
|
||||
ON_REGISTRATION_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION
|
||||
};
|
||||
|
||||
/* As a special case, ServiceManager's handle is zero */
|
||||
#define HWSERVICEMANAGER_HANDLE (0)
|
||||
#define HWSERVICEMANAGER_IFACE "android.hidl.manager@1.0::IServiceManager"
|
||||
#define HWSERVICEMANAGER_NOTIFICATION_IFACE \
|
||||
"android.hidl.manager@1.0::IServiceNotification"
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_handle_registration(
|
||||
GBinderHwServiceManager* self,
|
||||
GBinderReader* reader)
|
||||
{
|
||||
char* fqname = gbinder_reader_read_hidl_string(reader);
|
||||
char* name = gbinder_reader_read_hidl_string(reader);
|
||||
gboolean preexisting;
|
||||
|
||||
/* (string fqName, string name, bool preexisting) */
|
||||
if (fqname && name && gbinder_reader_read_bool(reader, &preexisting) &&
|
||||
gbinder_reader_at_end(reader)) {
|
||||
char* full_name = g_strconcat(fqname, "/", name, NULL);
|
||||
|
||||
GDEBUG("%s %s", full_name, preexisting ? "true" : "false");
|
||||
gbinder_servicemanager_service_registered(&self->manager, full_name);
|
||||
g_free(full_name);
|
||||
} else {
|
||||
GWARN("Failed to parse IServiceNotification::onRegistration payload");
|
||||
}
|
||||
g_free(fqname);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_hwservicemanager_notification(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(user_data);
|
||||
const char* iface = gbinder_remote_request_interface(req);
|
||||
|
||||
if (!g_strcmp0(iface, HWSERVICEMANAGER_NOTIFICATION_IFACE)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
switch (code) {
|
||||
case ON_REGISTRATION_TRANSACTION:
|
||||
GDEBUG(HWSERVICEMANAGER_NOTIFICATION_IFACE " %u onRegistration",
|
||||
code);
|
||||
gbinder_hwservicemanager_handle_registration(self, &reader);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
break;
|
||||
default:
|
||||
GDEBUG(HWSERVICEMANAGER_NOTIFICATION_IFACE " %u", code);
|
||||
*status = GBINDER_STATUS_FAILED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GDEBUG("%s %u", iface, code);
|
||||
*status = GBINDER_STATUS_FAILED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
@@ -74,7 +158,7 @@ gbinder_hwservicemanager_new(
|
||||
static
|
||||
char**
|
||||
gbinder_hwservicemanager_list(
|
||||
GBinderHwServiceManager* self)
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
GBinderRemoteReply* reply = gbinder_client_transact_sync_reply
|
||||
@@ -110,6 +194,7 @@ gbinder_hwservicemanager_get_service(
|
||||
/* e.g. "android.hardware.radio@1.1::IRadio/slot1" */
|
||||
const char* sep = strchr(fqinstance, '/');
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
|
||||
if (sep) {
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
@@ -169,11 +254,123 @@ gbinder_hwservicemanager_add_service(
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_watch_free(
|
||||
gpointer data)
|
||||
{
|
||||
GBinderHwServiceManagerWatch* watch = data;
|
||||
|
||||
g_free(watch->name);
|
||||
gbinder_local_object_drop(watch->callback);
|
||||
g_free(watch);
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
gbinder_hwservicemanager_check_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
if (name) {
|
||||
const gsize len = strlen(name);
|
||||
static const char allowed_chars[] = "./0123456789:@"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
if (len && strspn(name, allowed_chars) == len) {
|
||||
return strchr(name, '/') ?
|
||||
GBINDER_SERVICEMANAGER_NAME_NORMALIZE :
|
||||
GBINDER_SERVICEMANAGER_NAME_OK;
|
||||
}
|
||||
}
|
||||
return GBINDER_SERVICEMANAGER_NAME_INVALID;
|
||||
}
|
||||
|
||||
static
|
||||
char*
|
||||
gbinder_hwservicemanager_normalize_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
/* Slash must be there, see gbinder_hwservicemanager_check_name() above */
|
||||
return g_strndup(name, strchr(name, '/') - name);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_hwservicemanager_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(manager);
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(manager->client);
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderHwServiceManagerWatch* watch =
|
||||
g_new0(GBinderHwServiceManagerWatch, 1);
|
||||
gboolean success = FALSE;
|
||||
int status;
|
||||
|
||||
watch->name = g_strdup(name);
|
||||
watch->callback = gbinder_servicemanager_new_local_object(manager,
|
||||
HWSERVICEMANAGER_NOTIFICATION_IFACE,
|
||||
gbinder_hwservicemanager_notification, self);
|
||||
g_hash_table_replace(self->watch_table, watch->name, watch);
|
||||
|
||||
/* registerForNotifications(string fqName, string name,
|
||||
* IServiceNotification callback) generates (bool success); */
|
||||
gbinder_local_request_append_hidl_string(req, name);
|
||||
gbinder_local_request_append_hidl_string(req, "");
|
||||
gbinder_local_request_append_local_object(req, watch->callback);
|
||||
reply = gbinder_client_transact_sync_reply(manager->client,
|
||||
REGISTER_FOR_NOTIFICATIONS_TRANSACTION, req, &status);
|
||||
|
||||
if (status == GBINDER_STATUS_OK && reply) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
if (gbinder_reader_read_int32(&reader, &status) &&
|
||||
status == GBINDER_STATUS_OK) {
|
||||
gbinder_reader_read_bool(&reader, &success);
|
||||
}
|
||||
}
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
if (!success) {
|
||||
/* unwatch() won't be called if we return FALSE */
|
||||
g_hash_table_remove(self->watch_table, watch->name);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_unwatch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
g_hash_table_remove(GBINDER_HWSERVICEMANAGER(manager)->watch_table, name);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_init(
|
||||
GBinderHwServiceManager* self)
|
||||
{
|
||||
self->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
NULL, gbinder_hwservicemanager_watch_free);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderHwServiceManager* self = GBINDER_HWSERVICEMANAGER(object);
|
||||
|
||||
g_hash_table_destroy(self->watch_table);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -184,10 +381,16 @@ gbinder_hwservicemanager_class_init(
|
||||
klass->handle = HWSERVICEMANAGER_HANDLE;
|
||||
klass->iface = HWSERVICEMANAGER_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_HWBINDER;
|
||||
klass->rpc_protocol = &gbinder_rpc_protocol_hwbinder;
|
||||
|
||||
klass->list = gbinder_hwservicemanager_list;
|
||||
klass->get_service = gbinder_hwservicemanager_get_service;
|
||||
klass->add_service = gbinder_hwservicemanager_add_service;
|
||||
klass->check_name = gbinder_hwservicemanager_check_name;
|
||||
klass->normalize_name = gbinder_hwservicemanager_normalize_name;
|
||||
klass->watch = gbinder_hwservicemanager_watch;
|
||||
klass->unwatch = gbinder_hwservicemanager_unwatch;
|
||||
G_OBJECT_CLASS(klass)->finalize = gbinder_hwservicemanager_finalize;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -90,6 +90,21 @@ GBINDER_IO_FN(write_read)(
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns size of the object's extra data */
|
||||
static
|
||||
gsize
|
||||
GBINDER_IO_FN(object_data_size)(
|
||||
const void* obj)
|
||||
{
|
||||
const struct binder_buffer_object* buf = obj;
|
||||
|
||||
if (buf && buf->hdr.type == BINDER_TYPE_PTR) {
|
||||
return buf->length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes pointer to the buffer */
|
||||
static
|
||||
guint
|
||||
@@ -113,7 +128,7 @@ GBINDER_IO_FN(encode_local_object)(
|
||||
struct flat_binder_object* dest = out;
|
||||
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
dest->hdr.type = BINDER_TYPE_BINDER;
|
||||
dest->hdr.type = obj ? BINDER_TYPE_BINDER : BINDER_TYPE_WEAK_HANDLE;
|
||||
dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->binder = (uintptr_t)obj;
|
||||
return sizeof(*dest);
|
||||
@@ -445,6 +460,8 @@ const GBinderIo GBINDER_IO_PREFIX = {
|
||||
.failed_reply = BR_FAILED_REPLY
|
||||
},
|
||||
|
||||
.object_data_size = GBINDER_IO_FN(object_data_size),
|
||||
|
||||
/* Encoders */
|
||||
.encode_pointer = GBINDER_IO_FN(encode_pointer),
|
||||
.encode_local_object = GBINDER_IO_FN(encode_local_object),
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -118,6 +118,9 @@ struct gbinder_io {
|
||||
guint failed_reply;
|
||||
} br;
|
||||
|
||||
/* Size of the object's extra data */
|
||||
gsize (*object_data_size)(const void* obj);
|
||||
|
||||
/* Writes pointer to the buffer. The destination buffer must have
|
||||
* at least GBINDER_IO_MAX_POINTER_SIZE bytes available. The
|
||||
* actual size is returned. */
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -88,6 +88,7 @@ static pthread_mutex_t gbinder_ipc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#define GBINDER_IPC_MAX_TX_THREADS (15)
|
||||
#define GBINDER_IPC_MAX_LOOPERS (15)
|
||||
#define GBINDER_IPC_LOOPER_START_TIMEOUT_SEC (2)
|
||||
|
||||
/*
|
||||
* When looper receives the transaction:
|
||||
@@ -134,6 +135,9 @@ struct gbinder_ipc_looper {
|
||||
GBinderDriver* driver;
|
||||
GBinderIpc* ipc; /* Not a reference! */
|
||||
GThread* thread;
|
||||
GMutex mutex;
|
||||
GCond start_cond;
|
||||
gboolean started;
|
||||
int pipefd[2];
|
||||
int txfd[2];
|
||||
};
|
||||
@@ -344,6 +348,8 @@ gbinder_ipc_looper_free(
|
||||
close(looper->txfd[1]);
|
||||
}
|
||||
gbinder_driver_unref(looper->driver);
|
||||
g_cond_clear(&looper->start_cond);
|
||||
g_mutex_clear(&looper->mutex);
|
||||
g_slice_free(GBinderIpcLooper, looper);
|
||||
}
|
||||
|
||||
@@ -381,6 +387,11 @@ gbinder_ipc_looper_thread(
|
||||
int result;
|
||||
|
||||
GDEBUG("Looper %s running", gbinder_driver_dev(driver));
|
||||
g_mutex_lock(&looper->mutex);
|
||||
looper->started = TRUE;
|
||||
g_cond_broadcast(&looper->start_cond);
|
||||
g_mutex_unlock(&looper->mutex);
|
||||
|
||||
memset(&pipefd, 0, sizeof(pipefd));
|
||||
pipefd.fd = looper->pipefd[0]; /* read end of the pipe */
|
||||
pipefd.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
|
||||
@@ -436,6 +447,11 @@ gbinder_ipc_looper_thread(
|
||||
} else {
|
||||
GDEBUG("Looper %s is abandoned", gbinder_driver_dev(driver));
|
||||
}
|
||||
} else {
|
||||
g_mutex_lock(&looper->mutex);
|
||||
looper->started = TRUE;
|
||||
g_cond_broadcast(&looper->start_cond);
|
||||
g_mutex_unlock(&looper->mutex);
|
||||
}
|
||||
|
||||
gbinder_ipc_looper_unref(looper);
|
||||
@@ -460,6 +476,8 @@ gbinder_ipc_looper_new(
|
||||
memcpy(looper->pipefd, fd, sizeof(fd));
|
||||
looper->txfd[0] = looper->txfd[1] = -1;
|
||||
g_atomic_int_set(&looper->refcount, 1);
|
||||
g_cond_init(&looper->start_cond);
|
||||
g_mutex_init(&looper->mutex);
|
||||
looper->handler.f = &handler_functions;
|
||||
looper->ipc = ipc;
|
||||
looper->driver = gbinder_driver_ref(ipc->driver);
|
||||
@@ -488,6 +506,7 @@ gbinder_ipc_looper_check(
|
||||
GBinderIpcPriv* priv = self->priv;
|
||||
|
||||
if (!priv->looper) {
|
||||
GBinderIpcLooper* looper;
|
||||
/* Lock */
|
||||
g_mutex_lock(&priv->looper_mutex);
|
||||
if (!priv->looper) {
|
||||
@@ -496,6 +515,23 @@ gbinder_ipc_looper_check(
|
||||
}
|
||||
g_mutex_unlock(&priv->looper_mutex);
|
||||
/* Unlock */
|
||||
|
||||
/* We are not ready to accept incoming transactions until
|
||||
* looper has started. We may need to wait a bit. */
|
||||
looper = priv->looper;
|
||||
if (!looper->started) {
|
||||
/* Lock */
|
||||
g_mutex_lock(&looper->mutex);
|
||||
if (!looper->started) {
|
||||
g_cond_wait_until(&looper->start_cond, &looper->mutex,
|
||||
g_get_monotonic_time() +
|
||||
GBINDER_IPC_LOOPER_START_TIMEOUT_SEC *
|
||||
G_TIME_SPAN_SECOND);
|
||||
GASSERT(looper->started);
|
||||
}
|
||||
g_mutex_unlock(&looper->mutex);
|
||||
/* Unlock */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -981,7 +1017,8 @@ gbinder_ipc_tx_proc(
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_new(
|
||||
const char* dev)
|
||||
const char* dev,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
GBinderIpc* self = NULL;
|
||||
|
||||
@@ -994,7 +1031,7 @@ gbinder_ipc_new(
|
||||
if (self) {
|
||||
gbinder_ipc_ref(self);
|
||||
} else {
|
||||
GBinderDriver* driver = gbinder_driver_new(dev);
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, protocol);
|
||||
|
||||
if (driver) {
|
||||
GBinderIpcPriv* priv;
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -70,7 +70,8 @@ void
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_new(
|
||||
const char* dev);
|
||||
const char* dev,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_ref(
|
||||
|
||||
@@ -271,6 +271,7 @@ gbinder_local_object_handle_release_proc(
|
||||
self->strong_refs--;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_STRONG_REFS_CHANGED], 0);
|
||||
gbinder_local_object_unref(self);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
@@ -440,6 +441,7 @@ void
|
||||
gbinder_local_object_handle_acquire(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_ref(self);
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_acquire_proc);
|
||||
}
|
||||
@@ -487,6 +489,7 @@ gbinder_local_object_finalize(
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
GASSERT(!self->strong_refs);
|
||||
gbinder_ipc_unref(self->ipc);
|
||||
g_free(priv->iface);
|
||||
G_OBJECT_CLASS(gbinder_local_object_parent_class)->finalize(local);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_writer_p.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
@@ -92,6 +93,20 @@ gbinder_local_reply_new(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new_from_data(
|
||||
GBinderBuffer* buffer,
|
||||
void** objects)
|
||||
{
|
||||
const GBinderIo* io = gbinder_buffer_io(buffer);
|
||||
GBinderLocalReply* self = gbinder_local_reply_new(io);
|
||||
|
||||
if (self) {
|
||||
gbinder_writer_data_set_contents(&self->data, buffer, objects);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_reply_free(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -45,6 +45,11 @@ GBinderOutputData*
|
||||
gbinder_local_reply_data(
|
||||
GBinderLocalReply* reply);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new_from_data(
|
||||
GBinderBuffer* buffer,
|
||||
void** objects);
|
||||
|
||||
#endif /* GBINDER_LOCAL_REPLY_PRIVATE_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_writer_p.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_io.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
@@ -42,6 +44,7 @@ struct gbinder_local_request {
|
||||
gint refcount;
|
||||
GBinderWriterData data;
|
||||
GBinderOutputData out;
|
||||
GBinderBufferMemory* memory;
|
||||
};
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
@@ -101,6 +104,20 @@ gbinder_local_request_new(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new_from_data(
|
||||
GBinderBuffer* buffer,
|
||||
void** objects)
|
||||
{
|
||||
GBinderLocalRequest* self = gbinder_local_request_new
|
||||
(gbinder_buffer_io(buffer), NULL);
|
||||
|
||||
if (self) {
|
||||
gbinder_writer_data_set_contents(&self->data, buffer, objects);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_request_free(
|
||||
@@ -111,6 +128,7 @@ gbinder_local_request_free(
|
||||
g_byte_array_free(data->bytes, TRUE);
|
||||
gutil_int_array_free(data->offsets, TRUE);
|
||||
gbinder_cleanup_free(data->cleanup);
|
||||
gbinder_buffer_memory_unref(self->memory);
|
||||
g_slice_free(GBinderLocalRequest, self);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -46,6 +46,11 @@ GBinderOutputData*
|
||||
gbinder_local_request_data(
|
||||
GBinderLocalRequest* req);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new_from_data(
|
||||
GBinderBuffer* buffer,
|
||||
void** objects);
|
||||
|
||||
#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -50,6 +50,8 @@ G_STATIC_ASSERT(sizeof(GBinderReader) >= sizeof(GBinderReaderPriv));
|
||||
|
||||
static inline GBinderReaderPriv* gbinder_reader_cast(GBinderReader* reader)
|
||||
{ return (GBinderReaderPriv*)reader; }
|
||||
static inline const GBinderReaderPriv* gbinder_reader_cast_c
|
||||
(const GBinderReader* reader) { return (GBinderReaderPriv*)reader; }
|
||||
|
||||
void
|
||||
gbinder_reader_init(
|
||||
@@ -81,9 +83,9 @@ gbinder_reader_init(
|
||||
|
||||
gboolean
|
||||
gbinder_reader_at_end(
|
||||
GBinderReader* reader)
|
||||
const GBinderReader* reader)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
|
||||
|
||||
return p->ptr >= p->end;
|
||||
}
|
||||
@@ -305,6 +307,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(GBinderHidlVec)) {
|
||||
const GBinderHidlVec* 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)
|
||||
@@ -312,8 +385,8 @@ gbinder_reader_read_hidl_string(
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
char* str = NULL;
|
||||
|
||||
if (buf && buf->size == sizeof(HidlString)) {
|
||||
const HidlString* s = buf->data;
|
||||
if (buf && buf->size == sizeof(GBinderHidlString)) {
|
||||
const GBinderHidlString* s = buf->data;
|
||||
GBinderBuffer* sbuf = gbinder_reader_read_buffer(reader);
|
||||
|
||||
if (sbuf && sbuf->size == s->len + 1 &&
|
||||
@@ -334,8 +407,8 @@ gbinder_reader_read_hidl_string_vec(
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
|
||||
/* First buffer contains hidl_vector */
|
||||
if (buf && buf->size == sizeof(HidlVec)) {
|
||||
HidlVec* vec = buf->data;
|
||||
if (buf && buf->size == sizeof(GBinderHidlVec)) {
|
||||
GBinderHidlVec* vec = buf->data;
|
||||
const guint n = vec->count;
|
||||
const void* next = vec->data.ptr;
|
||||
|
||||
@@ -348,8 +421,9 @@ gbinder_reader_read_hidl_string_vec(
|
||||
} else {
|
||||
/* The second buffer (if any) contains n hidl_string's */
|
||||
buf = gbinder_reader_read_buffer(reader);
|
||||
if (buf && buf->data == next && buf->size == sizeof(HidlString)*n) {
|
||||
const HidlString* strings = buf->data;
|
||||
if (buf && buf->data == next &&
|
||||
buf->size == (sizeof(GBinderHidlString) * n)) {
|
||||
const GBinderHidlString* strings = buf->data;
|
||||
GBinderBuffer* sbuf;
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
guint i;
|
||||
@@ -357,7 +431,7 @@ gbinder_reader_read_hidl_string_vec(
|
||||
/* Now we expect n buffers containing the actual data */
|
||||
for (i=0; i<n &&
|
||||
(sbuf = gbinder_reader_read_buffer(reader)); i++) {
|
||||
const HidlString* s = strings + i;
|
||||
const GBinderHidlString* s = strings + i;
|
||||
if (sbuf->size == s->len + 1 &&
|
||||
sbuf->data == s->data.str &&
|
||||
s->data.str[s->len] == 0) {
|
||||
@@ -418,6 +492,24 @@ gboolean
|
||||
gbinder_reader_read_nullable_string16(
|
||||
GBinderReader* reader,
|
||||
char** out)
|
||||
{
|
||||
gunichar2* str;
|
||||
gsize len;
|
||||
|
||||
if (gbinder_reader_read_nullable_string16_utf16(reader, &str, &len)) {
|
||||
if (out) {
|
||||
*out = str ? g_utf16_to_utf8(str, len, NULL, NULL, NULL) : NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_string16_utf16(
|
||||
GBinderReader* reader,
|
||||
gunichar2** out,
|
||||
gsize* out_len) /* since 1.0.17 */
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
@@ -431,15 +523,21 @@ gbinder_reader_read_nullable_string16(
|
||||
if (out) {
|
||||
*out = NULL;
|
||||
}
|
||||
if (out_len) {
|
||||
*out_len = 0;
|
||||
}
|
||||
return TRUE;
|
||||
} else if (len >= 0) {
|
||||
const guint32 padded_len = G_ALIGN4((len+1)*2);
|
||||
const gunichar2* utf16 = (const gunichar2*)(p->ptr + 4);
|
||||
const guint32 padded_len = G_ALIGN4((len + 1)*2);
|
||||
gunichar2* utf16 = (gunichar2*)(p->ptr + 4);
|
||||
|
||||
if ((p->ptr + padded_len + 4) <= p->end) {
|
||||
p->ptr += padded_len + 4;
|
||||
if (out) {
|
||||
*out = g_utf16_to_utf8(utf16, len, NULL, NULL, NULL);
|
||||
*out = utf16;
|
||||
}
|
||||
if (out_len) {
|
||||
*out_len = len;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -484,24 +582,59 @@ gbinder_reader_skip_string16(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_read(
|
||||
GBinderReader* reader)
|
||||
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(
|
||||
const GBinderReader* reader)
|
||||
{
|
||||
const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
|
||||
|
||||
return p->ptr - p->start;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_remaining(
|
||||
GBinderReader* reader)
|
||||
const GBinderReader* reader)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
const GBinderReaderPriv* p = gbinder_reader_cast_c(reader);
|
||||
|
||||
return p->end - p->ptr;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_reader_copy(
|
||||
GBinderReader* dest,
|
||||
const GBinderReader* src)
|
||||
{
|
||||
/* It's actually quite simple :) */
|
||||
memcpy(dest, src, sizeof(*dest));
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "gbinder_remote_reply_p.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_buffer.h"
|
||||
@@ -117,6 +118,18 @@ gbinder_remote_reply_is_empty(
|
||||
return !self || !self->data.buffer || !self->data.buffer->size;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_remote_reply_copy_to_local(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* d = &self->data;
|
||||
|
||||
return gbinder_local_reply_new_from_data(d->buffer, d->objects);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
void
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "gbinder_remote_request_p.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_buffer.h"
|
||||
#include "gbinder_log.h"
|
||||
@@ -68,6 +69,18 @@ gbinder_remote_request_new(
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_remote_request_copy_to_local(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* d = &self->data;
|
||||
|
||||
return gbinder_local_request_new_from_data(d->buffer, d->objects);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_request_free(
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -109,22 +109,22 @@ gbinder_rpc_protocol_hwbinder_read_rpc_header(
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
const GBinderRpcProtocol gbinder_rpc_protocol_binder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_binder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_binder_write_rpc_header
|
||||
};
|
||||
|
||||
const GBinderRpcProtocol gbinder_rpc_protocol_hwbinder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_hwbinder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_hwbinder_write_rpc_header
|
||||
};
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_for_device(
|
||||
const char* dev)
|
||||
{
|
||||
static const GBinderRpcProtocol protocol_binder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_binder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_binder_write_rpc_header
|
||||
};
|
||||
|
||||
static const GBinderRpcProtocol protocol_hwbinder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_hwbinder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_hwbinder_write_rpc_header
|
||||
};
|
||||
|
||||
return (dev && !strcmp(dev, GBINDER_DEFAULT_HWBINDER)) ?
|
||||
&protocol_hwbinder : &protocol_binder;
|
||||
&gbinder_rpc_protocol_hwbinder : &gbinder_rpc_protocol_binder;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,10 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -45,6 +46,10 @@ struct gbinder_rpc_protocol {
|
||||
void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
|
||||
};
|
||||
|
||||
extern const GBinderRpcProtocol gbinder_rpc_protocol_binder;
|
||||
extern const GBinderRpcProtocol gbinder_rpc_protocol_hwbinder;
|
||||
|
||||
/* Returns one of the above based on the device name */
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_for_device(
|
||||
const char* dev);
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -44,6 +44,17 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct gbinder_servicemanager_watch {
|
||||
char* name;
|
||||
char* detail;
|
||||
GQuark quark;
|
||||
gboolean watched;
|
||||
} GBinderServiceManagerWatch;
|
||||
|
||||
struct gbinder_servicemanager_priv {
|
||||
GHashTable* watch_table;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
@@ -60,6 +71,16 @@ G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
|
||||
#define GBINDER_IS_SERVICEMANAGER_TYPE(klass) \
|
||||
G_TYPE_CHECK_CLASS_TYPE(klass, GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
enum gbinder_servicemanager_signal {
|
||||
SIGNAL_REGISTRATION,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
static const char SIGNAL_REGISTRATION_NAME[] = "servicemanager-registration";
|
||||
#define DETAIL_LEN 32
|
||||
|
||||
static guint gbinder_servicemanager_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
@@ -81,53 +102,29 @@ gbinder_servicemanager_class_ref(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev)
|
||||
static
|
||||
GBinderServiceManagerWatch*
|
||||
gbinder_servicemanager_watch_new(
|
||||
const char* name)
|
||||
{
|
||||
GBinderServiceManager* self = NULL;
|
||||
GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
|
||||
GBinderServiceManagerWatch* watch = g_new0(GBinderServiceManagerWatch, 1);
|
||||
|
||||
if (klass) {
|
||||
GBinderIpc* ipc;
|
||||
watch->name = g_strdup(name);
|
||||
watch->detail = g_compute_checksum_for_string(G_CHECKSUM_MD5, name, -1);
|
||||
watch->quark = g_quark_from_string(watch->detail);
|
||||
return watch;
|
||||
}
|
||||
|
||||
if (!dev) dev = klass->default_device;
|
||||
ipc = gbinder_ipc_new(dev);
|
||||
if (ipc) {
|
||||
GBinderRemoteObject* object = gbinder_ipc_get_remote_object
|
||||
(ipc, klass->handle);
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_watch_free(
|
||||
gpointer data)
|
||||
{
|
||||
GBinderServiceManagerWatch* watch = data;
|
||||
|
||||
if (object) {
|
||||
/* Lock */
|
||||
g_mutex_lock(&klass->mutex);
|
||||
if (klass->table) {
|
||||
self = g_hash_table_lookup(klass->table, dev);
|
||||
}
|
||||
if (self) {
|
||||
gbinder_servicemanager_ref(self);
|
||||
} else {
|
||||
char* key = g_strdup(dev); /* Owned by the hashtable */
|
||||
|
||||
GVERBOSE_("%s", dev);
|
||||
self = g_object_new(type, NULL);
|
||||
self->client = gbinder_client_new(object, klass->iface);
|
||||
self->dev = gbinder_remote_object_dev(object);
|
||||
if (!klass->table) {
|
||||
klass->table = g_hash_table_new_full(g_str_hash,
|
||||
g_str_equal, g_free, NULL);
|
||||
}
|
||||
g_hash_table_replace(klass->table, key, self);
|
||||
}
|
||||
g_mutex_unlock(&klass->mutex);
|
||||
/* Unlock */
|
||||
gbinder_remote_object_unref(object);
|
||||
}
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
g_type_class_unref(klass);
|
||||
}
|
||||
return self;
|
||||
g_free(watch->name);
|
||||
g_free(watch->detail);
|
||||
g_free(watch);
|
||||
}
|
||||
|
||||
typedef struct gbinder_servicemanager_list_tx_data {
|
||||
@@ -256,6 +253,89 @@ gbinder_servicemanager_add_service_tx_free(
|
||||
g_slice_free(GBinderServiceManagerAddServiceTxData, data);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internal interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev)
|
||||
{
|
||||
GBinderServiceManager* self = NULL;
|
||||
GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
|
||||
|
||||
if (klass) {
|
||||
GBinderIpc* ipc;
|
||||
|
||||
if (!dev) dev = klass->default_device;
|
||||
ipc = gbinder_ipc_new(dev, klass->rpc_protocol);
|
||||
if (ipc) {
|
||||
GBinderRemoteObject* object = gbinder_ipc_get_remote_object
|
||||
(ipc, klass->handle);
|
||||
|
||||
if (object) {
|
||||
/* Lock */
|
||||
g_mutex_lock(&klass->mutex);
|
||||
if (klass->table) {
|
||||
self = g_hash_table_lookup(klass->table, dev);
|
||||
}
|
||||
if (self) {
|
||||
gbinder_servicemanager_ref(self);
|
||||
} else {
|
||||
char* key = g_strdup(dev); /* Owned by the hashtable */
|
||||
|
||||
GVERBOSE_("%s", dev);
|
||||
self = g_object_new(type, NULL);
|
||||
self->client = gbinder_client_new(object, klass->iface);
|
||||
self->dev = gbinder_remote_object_dev(object);
|
||||
if (!klass->table) {
|
||||
klass->table = g_hash_table_new_full(g_str_hash,
|
||||
g_str_equal, g_free, NULL);
|
||||
}
|
||||
g_hash_table_replace(klass->table, key, self);
|
||||
}
|
||||
g_mutex_unlock(&klass->mutex);
|
||||
/* Unlock */
|
||||
gbinder_remote_object_unref(object);
|
||||
}
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
g_type_class_unref(klass);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_servicemanager_service_registered(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
GBinderServiceManagerClass* klass = GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
GBinderServiceManagerWatch* watch = NULL;
|
||||
const char* normalized_name;
|
||||
char* tmp_name = NULL;
|
||||
|
||||
switch (klass->check_name(self, name)) {
|
||||
case GBINDER_SERVICEMANAGER_NAME_OK:
|
||||
normalized_name = name;
|
||||
break;
|
||||
case GBINDER_SERVICEMANAGER_NAME_NORMALIZE:
|
||||
normalized_name = tmp_name = klass->normalize_name(self, name);
|
||||
break;
|
||||
default:
|
||||
normalized_name = NULL;
|
||||
break;
|
||||
}
|
||||
if (normalized_name) {
|
||||
watch = g_hash_table_lookup(priv->watch_table, normalized_name);
|
||||
}
|
||||
g_free(tmp_name);
|
||||
g_signal_emit(self, gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
|
||||
watch ? watch->quark : 0, name);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
@@ -433,6 +513,88 @@ gbinder_servicemanager_cancel(
|
||||
}
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_registration_handler(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderServiceManagerRegistrationFunc func,
|
||||
void* data) /* Since 1.0.13 */
|
||||
{
|
||||
gulong id = 0;
|
||||
|
||||
if (G_LIKELY(self) && G_LIKELY(func)) {
|
||||
char* tmp_name = NULL;
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
|
||||
switch (klass->check_name(self, name)) {
|
||||
case GBINDER_SERVICEMANAGER_NAME_OK:
|
||||
break;
|
||||
case GBINDER_SERVICEMANAGER_NAME_NORMALIZE:
|
||||
name = tmp_name = klass->normalize_name(self, name);
|
||||
break;
|
||||
default:
|
||||
name = NULL;
|
||||
break;
|
||||
}
|
||||
if (name) {
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
GBinderServiceManagerWatch* watch = NULL;
|
||||
|
||||
watch = g_hash_table_lookup(priv->watch_table, name);
|
||||
if (!watch) {
|
||||
watch = gbinder_servicemanager_watch_new(name);
|
||||
g_hash_table_insert(priv->watch_table, watch->name, watch);
|
||||
}
|
||||
if (!watch->watched) {
|
||||
watch->watched = klass->watch(self, name);
|
||||
if (watch->watched) {
|
||||
GDEBUG("Watching %s", watch->name);
|
||||
} else {
|
||||
GWARN("Failed to watch %s", watch->name);
|
||||
}
|
||||
}
|
||||
|
||||
id = g_signal_connect_closure_by_id(self,
|
||||
gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
|
||||
watch->quark, g_cclosure_new(G_CALLBACK(func), data, NULL),
|
||||
FALSE);
|
||||
}
|
||||
g_free(tmp_name);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_servicemanager_remove_handler(
|
||||
GBinderServiceManager* self,
|
||||
gulong id) /* Since 1.0.13 */
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
GHashTableIter it;
|
||||
gpointer value;
|
||||
|
||||
g_signal_handler_disconnect(self, id);
|
||||
g_hash_table_iter_init(&it, priv->watch_table);
|
||||
while (g_hash_table_iter_next(&it, NULL, &value)) {
|
||||
GBinderServiceManagerWatch* watch = value;
|
||||
|
||||
if (watch->watched && !g_signal_has_handler_pending(self,
|
||||
gbinder_servicemanager_signals[SIGNAL_REGISTRATION],
|
||||
watch->quark, TRUE)) {
|
||||
/* This must be the one we have just removed */
|
||||
GDEBUG("Unwatching %s", watch->name);
|
||||
watch->watched = FALSE;
|
||||
klass->unwatch(self, watch->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
@@ -442,6 +604,12 @@ void
|
||||
gbinder_servicemanager_init(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
GBinderServiceManagerPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
GBINDER_TYPE_SERVICEMANAGER, GBinderServiceManagerPriv);
|
||||
|
||||
self->priv = priv;
|
||||
priv->watch_table = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
NULL, gbinder_servicemanager_watch_free);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -450,8 +618,7 @@ gbinder_servicemanager_dispose(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
GBinderServiceManagerClass* klass = GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
|
||||
GVERBOSE_("%s", self->dev);
|
||||
/* Lock */
|
||||
@@ -493,9 +660,10 @@ gbinder_servicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
|
||||
GBinderServiceManagerPriv* priv = self->priv;
|
||||
|
||||
gutil_idle_pool_drain(self->pool);
|
||||
gutil_idle_pool_unref(self->pool);
|
||||
g_hash_table_destroy(priv->watch_table);
|
||||
gutil_idle_pool_destroy(self->pool);
|
||||
gbinder_client_unref(self->client);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
@@ -508,8 +676,13 @@ gbinder_servicemanager_class_init(
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_mutex_init(&klass->mutex);
|
||||
g_type_class_add_private(klass, sizeof(GBinderServiceManagerPriv));
|
||||
object_class->dispose = gbinder_servicemanager_dispose;
|
||||
object_class->finalize = gbinder_servicemanager_finalize;
|
||||
gbinder_servicemanager_signals[SIGNAL_REGISTRATION] =
|
||||
g_signal_new(SIGNAL_REGISTRATION_NAME, G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, 0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -39,13 +39,22 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
typedef struct gbinder_servicemanager_priv GBinderServiceManagerPriv;
|
||||
|
||||
typedef struct gbinder_servicemanager {
|
||||
GObject parent;
|
||||
GBinderServiceManagerPriv* priv;
|
||||
const char* dev;
|
||||
GBinderClient* client;
|
||||
GUtilIdlePool* pool;
|
||||
} GBinderServiceManager;
|
||||
|
||||
typedef enum gbinder_servicemanager_name_check {
|
||||
GBINDER_SERVICEMANAGER_NAME_OK,
|
||||
GBINDER_SERVICEMANAGER_NAME_NORMALIZE,
|
||||
GBINDER_SERVICEMANAGER_NAME_INVALID,
|
||||
} GBINDER_SERVICEMANAGER_NAME_CHECK;
|
||||
|
||||
typedef struct gbinder_servicemanager_class {
|
||||
GObjectClass parent;
|
||||
GMutex mutex;
|
||||
@@ -54,6 +63,7 @@ typedef struct gbinder_servicemanager_class {
|
||||
guint32 handle;
|
||||
const char* iface;
|
||||
const char* default_device;
|
||||
const GBinderRpcProtocol* rpc_protocol;
|
||||
|
||||
/* Methods (synchronous) */
|
||||
char** (*list)(GBinderServiceManager* self);
|
||||
@@ -62,6 +72,15 @@ typedef struct gbinder_servicemanager_class {
|
||||
int (*add_service)
|
||||
(GBinderServiceManager* self, const char* name,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
/* Checking/normalizing watch names */
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK (*check_name)
|
||||
(GBinderServiceManager* self, const char* name);
|
||||
char* (*normalize_name)(GBinderServiceManager* self, const char* name);
|
||||
|
||||
/* If watch() returns FALSE, unwatch() is not called */
|
||||
gboolean (*watch)(GBinderServiceManager* self, const char* name);
|
||||
void (*unwatch)(GBinderServiceManager* self, const char* name);
|
||||
} GBinderServiceManagerClass;
|
||||
|
||||
GType gbinder_servicemanager_get_type(void);
|
||||
@@ -72,6 +91,11 @@ gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev);
|
||||
|
||||
void
|
||||
gbinder_servicemanager_service_registered(
|
||||
GBinderServiceManager* self,
|
||||
const char* name);
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
|
||||
|
||||
/*
|
||||
|
||||
268
src/gbinder_servicepoll.c
Normal file
268
src/gbinder_servicepoll.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gbinder_servicepoll.h"
|
||||
#include "gbinder_servicemanager.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
/* This is configurable mostly so that unit testing doesn't take too long */
|
||||
guint gbinder_servicepoll_interval_ms = 2000;
|
||||
|
||||
typedef GObjectClass GBinderServicePollClass;
|
||||
struct gbinder_servicepoll {
|
||||
GObject object;
|
||||
GBinderServiceManager* manager;
|
||||
char** list;
|
||||
gulong list_id;
|
||||
guint timer_id;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GBinderServicePoll, gbinder_servicepoll, G_TYPE_OBJECT)
|
||||
#define GBINDER_TYPE_SERVICEPOLL (gbinder_servicepoll_get_type())
|
||||
#define GBINDER_SERVICEPOLL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_SERVICEPOLL, GBinderServicePoll))
|
||||
|
||||
enum gbinder_servicepoll_signal {
|
||||
SIGNAL_NAME_ADDED,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
static const char SIGNAL_NAME_ADDED_NAME[] = "servicepoll-name-added";
|
||||
|
||||
static guint gbinder_servicepoll_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
/* GBinderServiceManagerListFunc callback returns TRUE to keep the services
|
||||
* list, otherwise the caller will deallocate it. */
|
||||
gboolean
|
||||
gbinder_servicepoll_list(
|
||||
GBinderServiceManager* sm,
|
||||
char** services,
|
||||
void* user_data)
|
||||
{
|
||||
GBinderServicePoll* self = GBINDER_SERVICEPOLL(user_data);
|
||||
|
||||
gbinder_servicepoll_ref(self);
|
||||
self->list_id = 0;
|
||||
if (services) {
|
||||
const GStrV* ptr_new;
|
||||
|
||||
ptr_new = services = gutil_strv_sort(services, TRUE);
|
||||
if (self->list) {
|
||||
const GStrV* ptr_old = self->list;
|
||||
|
||||
while (*ptr_new && *ptr_old) {
|
||||
const int i = gutil_strv_find(ptr_old, *ptr_new);
|
||||
|
||||
if (i < 0) {
|
||||
/* New name */
|
||||
g_signal_emit(self, gbinder_servicepoll_signals
|
||||
[SIGNAL_NAME_ADDED], 0, *ptr_new);
|
||||
} else {
|
||||
int k;
|
||||
|
||||
/* If some names have disappeared, then i may be > 0 */
|
||||
for (k = 0; k < i; k ++) ptr_old++;
|
||||
ptr_old++;
|
||||
}
|
||||
ptr_new++;
|
||||
}
|
||||
}
|
||||
while (*ptr_new) {
|
||||
g_signal_emit(self, gbinder_servicepoll_signals
|
||||
[SIGNAL_NAME_ADDED], 0, *ptr_new);
|
||||
ptr_new++;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev(self->list);
|
||||
self->list = services;
|
||||
gbinder_servicepoll_unref(self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_servicepoll_timer(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServicePoll* self = GBINDER_SERVICEPOLL(user_data);
|
||||
|
||||
if (!self->list_id) {
|
||||
self->list_id = gbinder_servicemanager_list(self->manager,
|
||||
gbinder_servicepoll_list, self);
|
||||
}
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderServicePoll*
|
||||
gbinder_servicepoll_create(
|
||||
GBinderServiceManager* manager)
|
||||
{
|
||||
GBinderServicePoll* self = g_object_new(GBINDER_TYPE_SERVICEPOLL, NULL);
|
||||
|
||||
self->manager = gbinder_servicemanager_ref(manager);
|
||||
self->list_id = gbinder_servicemanager_list(manager,
|
||||
gbinder_servicepoll_list, self);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* API
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderServicePoll*
|
||||
gbinder_servicepoll_new(
|
||||
GBinderServiceManager* manager,
|
||||
GBinderServicePoll** weakptr)
|
||||
{
|
||||
if (weakptr) {
|
||||
if (*weakptr) {
|
||||
gbinder_servicepoll_ref(*weakptr);
|
||||
} else {
|
||||
*weakptr = gbinder_servicepoll_create(manager);
|
||||
g_object_add_weak_pointer(G_OBJECT(*weakptr), (gpointer*)weakptr);
|
||||
}
|
||||
return *weakptr;
|
||||
} else {
|
||||
return gbinder_servicepoll_create(manager);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderServicePoll*
|
||||
gbinder_servicepoll_ref(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(GBINDER_SERVICEPOLL(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_servicepoll_unref(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_SERVICEPOLL(self));
|
||||
}
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicepoll_manager(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
return G_LIKELY(self) ? self->manager : NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_servicepoll_is_known_name(
|
||||
GBinderServicePoll* self,
|
||||
const char* name)
|
||||
{
|
||||
return G_LIKELY(self) && gutil_strv_contains(self->list, name);
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicepoll_add_handler(
|
||||
GBinderServicePoll* self,
|
||||
GBinderServicePollFunc fn,
|
||||
void* user_data)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(fn)) ? g_signal_connect(self,
|
||||
SIGNAL_NAME_ADDED_NAME, G_CALLBACK(fn), user_data) : 0;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_servicepoll_remove_handler(
|
||||
GBinderServicePoll* self,
|
||||
gulong id)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
g_signal_handler_disconnect(self, id);
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicepoll_init(
|
||||
GBinderServicePoll* self)
|
||||
{
|
||||
self->timer_id = g_timeout_add(gbinder_servicepoll_interval_ms,
|
||||
gbinder_servicepoll_timer, self);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicepoll_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServicePoll* self = GBINDER_SERVICEPOLL(object);
|
||||
|
||||
g_source_remove(self->timer_id);
|
||||
gbinder_servicemanager_cancel(self->manager, self->list_id);
|
||||
gbinder_servicemanager_unref(self->manager);
|
||||
g_strfreev(self->list);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicepoll_class_init(
|
||||
GBinderServicePollClass* klass)
|
||||
{
|
||||
G_OBJECT_CLASS(klass)->finalize = gbinder_servicepoll_finalize;
|
||||
gbinder_servicepoll_signals[SIGNAL_NAME_ADDED] =
|
||||
g_signal_new(SIGNAL_NAME_ADDED_NAME, G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE,
|
||||
1, G_TYPE_STRING);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
88
src/gbinder_servicepoll.h
Normal file
88
src/gbinder_servicepoll.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GBINDER_SERVICEPOLL_H
|
||||
#define GBINDER_SERVICEPOLL_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
extern guint gbinder_servicepoll_interval_ms;
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderServicePollFunc)(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name_added,
|
||||
void* user_data);
|
||||
|
||||
GBinderServicePoll*
|
||||
gbinder_servicepoll_new(
|
||||
GBinderServiceManager* manager,
|
||||
GBinderServicePoll** weakptr);
|
||||
|
||||
GBinderServicePoll*
|
||||
gbinder_servicepoll_ref(
|
||||
GBinderServicePoll* poll);
|
||||
|
||||
void
|
||||
gbinder_servicepoll_unref(
|
||||
GBinderServicePoll* poll);
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicepoll_manager(
|
||||
GBinderServicePoll* poll);
|
||||
|
||||
gboolean
|
||||
gbinder_servicepoll_is_known_name(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name);
|
||||
|
||||
gulong
|
||||
gbinder_servicepoll_add_handler(
|
||||
GBinderServicePoll* poll,
|
||||
GBinderServicePollFunc func,
|
||||
void* user_data);
|
||||
|
||||
void
|
||||
gbinder_servicepoll_remove_handler(
|
||||
GBinderServicePoll* poll,
|
||||
gulong id);
|
||||
|
||||
#endif /* GBINDER_SERVICEPOLL_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -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;
|
||||
@@ -43,28 +44,7 @@ typedef struct gbinder_ipc GBinderIpc;
|
||||
typedef struct gbinder_object_registry GBinderObjectRegistry;
|
||||
typedef struct gbinder_output_data GBinderOutputData;
|
||||
typedef struct gbinder_rpc_protocol GBinderRpcProtocol;
|
||||
|
||||
typedef struct hidl_vec {
|
||||
union {
|
||||
guint64 value;
|
||||
const void* ptr;
|
||||
} data;
|
||||
guint32 count;
|
||||
guint32 owns_buffer;
|
||||
} HidlVec;
|
||||
|
||||
#define HIDL_VEC_BUFFER_OFFSET (0)
|
||||
|
||||
typedef struct hidl_string {
|
||||
union {
|
||||
guint64 value;
|
||||
const char* str;
|
||||
} data;
|
||||
guint32 len;
|
||||
guint32 owns_buffer;
|
||||
} HidlString;
|
||||
|
||||
#define HIDL_STRING_BUFFER_OFFSET (0)
|
||||
typedef struct gbinder_servicepoll GBinderServicePoll;
|
||||
|
||||
#define GBINDER_INLINE_FUNC static inline
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -298,14 +351,36 @@ gbinder_writer_data_append_string16(
|
||||
gbinder_writer_data_append_string16_len(data, utf8, utf8? strlen(utf8) : 0);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_append_string16_null(
|
||||
GBinderWriterData* data)
|
||||
{
|
||||
/* NULL string */
|
||||
gbinder_writer_data_append_int32(data, -1);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_append_string16_empty(
|
||||
GBinderWriterData* data)
|
||||
{
|
||||
GByteArray* buf = data->bytes;
|
||||
const gsize old_size = buf->len;
|
||||
guint16* ptr16;
|
||||
|
||||
/* Empty string */
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string16_len(
|
||||
GBinderWriterData* data,
|
||||
const char* utf8,
|
||||
gssize num_bytes)
|
||||
{
|
||||
const gsize old_size = data->bytes->len;
|
||||
|
||||
if (utf8) {
|
||||
const char* end = utf8;
|
||||
|
||||
@@ -316,14 +391,16 @@ gbinder_writer_data_append_string16_len(
|
||||
}
|
||||
|
||||
if (num_bytes > 0) {
|
||||
GByteArray* buf = data->bytes;
|
||||
const gsize old_size = buf->len;
|
||||
glong len = g_utf8_strlen(utf8, num_bytes);
|
||||
gsize padded_len = G_ALIGN4((len+1)*2);
|
||||
guint32* len_ptr;
|
||||
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,17 +427,72 @@ 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);
|
||||
ptr16[0] = ptr16[1] = ptr16[2] = 0; ptr16[3] = 0xffff;
|
||||
gbinder_writer_data_append_string16_empty(data);
|
||||
} else {
|
||||
/* NULL string */
|
||||
gbinder_writer_data_append_int32(data, -1);
|
||||
gbinder_writer_data_append_string16_null(data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_append_string16_utf16(
|
||||
GBinderWriterData* data,
|
||||
const gunichar2* utf16,
|
||||
gssize length)
|
||||
{
|
||||
if (length < 0) {
|
||||
length = 0;
|
||||
if (utf16) {
|
||||
const guint16* ptr;
|
||||
|
||||
/* Assume NULL terminated string */
|
||||
for (ptr = utf16; *ptr; ptr++);
|
||||
length = ptr - utf16;
|
||||
}
|
||||
}
|
||||
if (length > 0) {
|
||||
GByteArray* buf = data->bytes;
|
||||
const gsize old_size = buf->len;
|
||||
const gsize padded_size = G_ALIGN4((length + 1) * 2);
|
||||
guint32* len_ptr;
|
||||
gunichar2* utf16_ptr;
|
||||
|
||||
/* Preallocate space */
|
||||
g_byte_array_set_size(buf, old_size + padded_size + 4);
|
||||
len_ptr = (guint32*)(buf->data + old_size);
|
||||
utf16_ptr = (gunichar2*)(len_ptr + 1);
|
||||
|
||||
/* Actual length */
|
||||
*len_ptr = length;
|
||||
|
||||
/* Characters */
|
||||
memcpy(utf16_ptr, utf16, 2 * length);
|
||||
|
||||
/* Zero padding */
|
||||
memset(utf16_ptr + length, 0, padded_size - 2 * length);
|
||||
} else if (utf16) {
|
||||
/* Empty string */
|
||||
gbinder_writer_data_append_string16_empty(data);
|
||||
} else {
|
||||
/* NULL string */
|
||||
gbinder_writer_data_append_string16_null(data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_string16_utf16(
|
||||
GBinderWriter* self,
|
||||
const gunichar2* utf16,
|
||||
gssize length) /* Since 1.0.17 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_string16_utf16(data, utf16, length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,18 +574,66 @@ gbinder_writer_append_hidl_string(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_vec(
|
||||
GBinderWriterData* data,
|
||||
const void* base,
|
||||
guint count,
|
||||
guint elemsize)
|
||||
{
|
||||
GBinderParent vec_parent;
|
||||
GBinderHidlVec* vec = g_new0(GBinderHidlVec, 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 = GBINDER_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,
|
||||
const char* str)
|
||||
{
|
||||
GBinderParent str_parent;
|
||||
HidlString* hidl_string = g_new0(HidlString, 1);
|
||||
GBinderHidlString* hidl_string = g_new0(GBinderHidlString, 1);
|
||||
const gsize len = str ? strlen(str) : 0;
|
||||
|
||||
/* Prepare parent descriptor for the string data */
|
||||
str_parent.index = gbinder_writer_data_prepare(data);
|
||||
str_parent.offset = HIDL_STRING_BUFFER_OFFSET;
|
||||
str_parent.offset = GBINDER_HIDL_STRING_BUFFER_OFFSET;
|
||||
|
||||
/* Fill in the string descriptor and store it */
|
||||
hidl_string->data.str = str;
|
||||
@@ -495,8 +675,8 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
gssize count)
|
||||
{
|
||||
GBinderParent vec_parent;
|
||||
HidlVec* vec = g_new0(HidlVec, 1);
|
||||
HidlString* strings = NULL;
|
||||
GBinderHidlVec* vec = g_new0(GBinderHidlVec, 1);
|
||||
GBinderHidlString* strings = NULL;
|
||||
int i;
|
||||
|
||||
if (count < 0) {
|
||||
@@ -506,11 +686,11 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
|
||||
/* Prepare parent descriptor for the vector data */
|
||||
vec_parent.index = gbinder_writer_data_prepare(data);
|
||||
vec_parent.offset = HIDL_VEC_BUFFER_OFFSET;
|
||||
vec_parent.offset = GBINDER_HIDL_VEC_BUFFER_OFFSET;
|
||||
|
||||
/* Fill in the vector descriptor */
|
||||
if (count > 0) {
|
||||
strings = g_new0(HidlString, count);
|
||||
strings = g_new0(GBinderHidlString, count);
|
||||
vec->data.ptr = strings;
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, strings);
|
||||
}
|
||||
@@ -521,7 +701,7 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
/* Fill in string descriptors */
|
||||
for (i = 0; i < count; i++) {
|
||||
const char* str = strv[i];
|
||||
HidlString* hidl_str = strings + i;
|
||||
GBinderHidlString* hidl_str = strings + i;
|
||||
|
||||
if ((hidl_str->data.str = str) != NULL) {
|
||||
hidl_str->len = strlen(str);
|
||||
@@ -536,7 +716,7 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
|
||||
/* Prepare parent descriptor for the string data */
|
||||
str_parent.index = data->offsets->count;
|
||||
str_parent.offset = HIDL_STRING_BUFFER_OFFSET;
|
||||
str_parent.offset = GBINDER_HIDL_STRING_BUFFER_OFFSET;
|
||||
|
||||
/* Write the vector data (it's parent for the string data) */
|
||||
gbinder_writer_data_write_buffer_object(data, strings,
|
||||
@@ -544,7 +724,7 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
|
||||
/* Write the string data */
|
||||
for (i = 0; i < count; i++) {
|
||||
HidlString* hidl_str = strings + i;
|
||||
GBinderHidlString* hidl_str = strings + i;
|
||||
|
||||
if (hidl_str->data.str) {
|
||||
gbinder_writer_data_write_buffer_object(data,
|
||||
@@ -553,7 +733,7 @@ gbinder_writer_data_append_hidl_string_vec(
|
||||
(guint)hidl_str->len, (guint)str_parent.index,
|
||||
(guint)data->buffers_size);
|
||||
}
|
||||
str_parent.offset += sizeof(HidlString);
|
||||
str_parent.offset += sizeof(GBinderHidlString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -575,16 +755,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 +781,51 @@ gbinder_writer_append_remote_object(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_byte_array(
|
||||
GBinderWriter* self,
|
||||
const void* byte_array,
|
||||
gint32 len) /* since 1.0.12 */
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
GASSERT(len >= 0);
|
||||
if (G_LIKELY(data)) {
|
||||
GByteArray* buf = data->bytes;
|
||||
void* ptr;
|
||||
|
||||
if (!byte_array) {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
g_byte_array_set_size(buf, buf->len + sizeof(len) + len);
|
||||
ptr = buf->data + (buf->len - sizeof(len) - len);
|
||||
|
||||
if (len > 0) {
|
||||
*((gint32*)ptr) = len;
|
||||
ptr += sizeof(len);
|
||||
memcpy(ptr, byte_array, len);
|
||||
} else {
|
||||
*((gint32*)ptr) = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_remote_object(
|
||||
GBinderWriterData* data,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
GByteArray* dest = data->bytes;
|
||||
const guint offset = dest->len;
|
||||
GByteArray* buf = data->bytes;
|
||||
const guint offset = buf->len;
|
||||
guint n;
|
||||
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(dest, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
g_byte_array_set_size(buf, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
/* Write the object */
|
||||
n = data->io->encode_remote_object(dest->data + offset, obj);
|
||||
n = data->io->encode_remote_object(buf->data + offset, obj);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(dest, offset + n);
|
||||
g_byte_array_set_size(buf, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -50,6 +50,12 @@ gbinder_writer_init(
|
||||
GBinderWriter* writer,
|
||||
GBinderWriterData* data);
|
||||
|
||||
void
|
||||
gbinder_writer_data_set_contents(
|
||||
GBinderWriterData* data,
|
||||
GBinderBuffer* buffer,
|
||||
void** objects);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_bool(
|
||||
GBinderWriterData* data,
|
||||
@@ -104,6 +110,13 @@ gbinder_writer_data_append_buffer_object(
|
||||
gsize size,
|
||||
const GBinderParent* parent);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_vec(
|
||||
GBinderWriterData* data,
|
||||
const void* base,
|
||||
guint count,
|
||||
guint elemsize);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_string(
|
||||
GBinderWriterData* data,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -54,10 +54,15 @@ typedef struct app_options {
|
||||
|
||||
typedef struct app {
|
||||
const AppOptions* opt;
|
||||
char* fqname;
|
||||
GMainLoop* loop;
|
||||
GBinderServiceManager* sm;
|
||||
GBinderLocalObject* local;
|
||||
GBinderRemoteObject* remote;
|
||||
gulong wait_id;
|
||||
gulong death_id;
|
||||
GBinderClient* client;
|
||||
GThread* thread;
|
||||
int ret;
|
||||
} App;
|
||||
|
||||
@@ -171,46 +176,80 @@ app_input_thread(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_connect_remote(
|
||||
App* app)
|
||||
{
|
||||
app->remote = gbinder_servicemanager_get_service_sync(app->sm,
|
||||
app->fqname, NULL); /* autoreleased pointer */
|
||||
|
||||
if (app->remote) {
|
||||
const AppOptions* opt = app->opt;
|
||||
|
||||
GINFO("Connected to %s", app->fqname);
|
||||
gbinder_remote_object_ref(app->remote);
|
||||
app->client = gbinder_client_new(app->remote, opt->iface);
|
||||
app->death_id = gbinder_remote_object_add_death_handler(app->remote,
|
||||
app_remote_died, app);
|
||||
app->thread = g_thread_new("input", app_input_thread, app);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_registration_handler(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
void* user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
GDEBUG("\"%s\" appeared", name);
|
||||
if (!strcmp(name, app->fqname) && app_connect_remote(app)) {
|
||||
gbinder_servicemanager_remove_handler(app->sm, app->wait_id);
|
||||
app->wait_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_run(
|
||||
App* app)
|
||||
{
|
||||
const AppOptions* opt = app->opt;
|
||||
char* fqname = opt->fqname ? g_strdup(opt->fqname) :
|
||||
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->fqname = opt->fqname ? g_strdup(opt->fqname) :
|
||||
strchr(opt->name, '/') ? g_strdup(opt->name) :
|
||||
g_strconcat(opt->iface, "/", opt->name, NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
app->client = gbinder_client_new(remote, opt->iface);
|
||||
app->ret = RET_OK;
|
||||
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);
|
||||
|
||||
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->thread) {
|
||||
/* Not the cleanest of exits, just dropping the thread... */
|
||||
g_thread_unref(app->thread);
|
||||
}
|
||||
g_free(fqname);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ all:
|
||||
@$(MAKE) -C unit_remote_object $*
|
||||
@$(MAKE) -C unit_remote_reply $*
|
||||
@$(MAKE) -C unit_remote_request $*
|
||||
@$(MAKE) -C unit_servicemanager $*
|
||||
@$(MAKE) -C unit_servicepoll $*
|
||||
@$(MAKE) -C unit_writer $*
|
||||
|
||||
clean: unitclean
|
||||
|
||||
@@ -103,9 +103,13 @@ ifneq ($(strip $(DEPS)),)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_EXE) $(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_EXE) $(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
$(COVERAGE_EXE) $(COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR)
|
||||
$(DEBUG_LIB): | debug_lib
|
||||
$(RELEASE_LIB): | release_lib
|
||||
$(COVERAGE_LIB): | coverage_lib
|
||||
|
||||
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
$(COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
@@ -166,13 +170,13 @@ $(RELEASE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c
|
||||
$(COVERAGE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c
|
||||
$(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_PLUGIN_LIB) $(DEBUG_OBJS)
|
||||
$(DEBUG_EXE): $(DEBUG_LIB) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) $(DEBUG_LIBS) -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_PLUGIN_LIB) $(RELEASE_OBJS)
|
||||
$(RELEASE_EXE): $(RELEASE_LIB) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) $(RELEASE_LIBS) -o $@
|
||||
|
||||
$(COVERAGE_EXE): $(COVERAGE_PLUGIN_LIB) $(COVERAGE_OBJS)
|
||||
$(COVERAGE_EXE): $(COVERAG_LIB) $(COVERAGE_OBJS)
|
||||
$(LD) $(COVERAGE_LDFLAGS) $(COVERAGE_OBJS) $(COVERAGE_LIBS) -o $@
|
||||
|
||||
debug_lib:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -32,7 +32,9 @@
|
||||
|
||||
#include "gbinder_system.h"
|
||||
|
||||
#define GLOG_MODULE_NAME test_binder_log
|
||||
#include <gutil_log.h>
|
||||
GLOG_MODULE_DEFINE2("test_binder", gutil_log_default);
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -61,6 +63,7 @@ typedef struct test_binder_node {
|
||||
char* path;
|
||||
int refcount;
|
||||
const TestBinderIo* io;
|
||||
GHashTable* destroy_map;
|
||||
} TestBinderNode;
|
||||
|
||||
typedef struct test_binder {
|
||||
@@ -123,6 +126,25 @@ typedef struct binder_pre_cookie_64 {
|
||||
#define BR_DEAD_BINDER_64 _IOR('r', 15, guint64)
|
||||
#define BR_FAILED_REPLY _IO('r', 17)
|
||||
|
||||
static
|
||||
void
|
||||
test_io_free_buffer(
|
||||
TestBinder* binder,
|
||||
void* ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
TestBinderNode* node = binder->node;
|
||||
GDestroyNotify destroy = g_hash_table_lookup(node->destroy_map, ptr);
|
||||
|
||||
if (destroy) {
|
||||
g_hash_table_remove(node->destroy_map, ptr);
|
||||
destroy(ptr);
|
||||
} else {
|
||||
g_free(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
test_io_handle_write_read_64(
|
||||
@@ -151,7 +173,8 @@ test_io_handle_write_read_64(
|
||||
/* Is there anything special about transactions and replies? */
|
||||
break;
|
||||
case BC_FREE_BUFFER_64:
|
||||
g_free((void*)(gsize)(*(guint64*)write_ptr));
|
||||
test_io_free_buffer(binder,
|
||||
GSIZE_TO_POINTER(*(guint64*)write_ptr));
|
||||
break;
|
||||
case BC_INCREFS:
|
||||
case BC_ACQUIRE:
|
||||
@@ -219,6 +242,7 @@ test_binder_node_unref(
|
||||
node->refcount--;
|
||||
if (!node->refcount) {
|
||||
g_hash_table_remove(test_node_map, node->path);
|
||||
g_hash_table_destroy(node->destroy_map);
|
||||
g_free(node->path);
|
||||
g_free(node);
|
||||
}
|
||||
@@ -228,25 +252,58 @@ 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);
|
||||
|
||||
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,14 +524,10 @@ 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);
|
||||
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;
|
||||
@@ -484,7 +538,6 @@ gbinder_system_close(
|
||||
g_free(binder);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
@@ -495,12 +548,7 @@ 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);
|
||||
|
||||
GASSERT(binder);
|
||||
TestBinder* binder = test_binder_from_fd(fd);
|
||||
if (binder) {
|
||||
const TestBinderIo* io = binder->node->io;
|
||||
|
||||
@@ -518,7 +566,6 @@ gbinder_system_ioctl(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -95,6 +95,12 @@ test_binder_br_reply_status(
|
||||
int fd,
|
||||
gint32 status);
|
||||
|
||||
void
|
||||
test_binder_set_destroy(
|
||||
int fd,
|
||||
gpointer ptr,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
#endif /* TEST_BINDER_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -16,6 +16,8 @@ unit_reader \
|
||||
unit_remote_object \
|
||||
unit_remote_reply \
|
||||
unit_remote_request \
|
||||
unit_servicemanager \
|
||||
unit_servicepoll \
|
||||
unit_writer"
|
||||
|
||||
function err() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -46,9 +46,10 @@ void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(NULL, NULL, 0);
|
||||
GBinderBuffer* buf2;
|
||||
gsize size = 1;
|
||||
|
||||
gbinder_buffer_free(buf);
|
||||
|
||||
@@ -66,6 +67,10 @@ test_null(
|
||||
|
||||
gbinder_buffer_free(NULL);
|
||||
g_assert(!gbinder_buffer_driver(NULL));
|
||||
g_assert(!gbinder_buffer_io(NULL));
|
||||
g_assert(!gbinder_buffer_data(NULL, NULL));
|
||||
g_assert(!gbinder_buffer_data(NULL, &size));
|
||||
g_assert(!size);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
@@ -80,12 +85,20 @@ test_parent(
|
||||
{
|
||||
static const guint8 data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
|
||||
void* ptr = g_memdup(data, sizeof(data));
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
gsize size = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderBuffer* parent = gbinder_buffer_new(driver, ptr, sizeof(data));
|
||||
GBinderBuffer* buf = gbinder_buffer_new_with_parent
|
||||
(parent, ptr, sizeof(data));
|
||||
|
||||
g_assert(gbinder_buffer_driver(buf) == driver);
|
||||
g_assert(gbinder_buffer_io(buf));
|
||||
g_assert(gbinder_buffer_io(buf) == gbinder_driver_io(driver));
|
||||
g_assert(gbinder_buffer_memory(buf));
|
||||
g_assert(gbinder_buffer_data(buf, NULL) == ptr);
|
||||
g_assert(gbinder_buffer_data(buf, &size) == ptr);
|
||||
g_assert(size == sizeof(data));
|
||||
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_buffer_free(parent);
|
||||
gbinder_driver_unref(driver);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -54,7 +54,7 @@ test_client_new(
|
||||
guint handle,
|
||||
const char* iface)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, handle);
|
||||
GBinderClient* client = gbinder_client_new(obj, iface);
|
||||
@@ -95,7 +95,7 @@ void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, 0);
|
||||
GBinderClient* client = gbinder_client_new(obj, "foo");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -56,8 +56,8 @@ test_basic(
|
||||
GBinderDriver* driver;
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
|
||||
g_assert(!gbinder_driver_new(""));
|
||||
driver = gbinder_driver_new(dev);
|
||||
g_assert(!gbinder_driver_new("", NULL));
|
||||
driver = gbinder_driver_new(dev, NULL);
|
||||
g_assert(driver);
|
||||
g_assert(!g_strcmp0(dev, gbinder_driver_dev(driver)));
|
||||
g_assert(gbinder_driver_ref(driver) == driver);
|
||||
@@ -86,7 +86,7 @@ void
|
||||
test_noop(
|
||||
void)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const int fd = gbinder_driver_fd(driver);
|
||||
|
||||
g_assert(driver);
|
||||
@@ -116,7 +116,7 @@ test_local_request(
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderLocalRequest* req = gbinder_driver_local_request_new(driver, iface);
|
||||
GBinderOutputData* data = gbinder_local_request_data(req);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -91,8 +91,8 @@ void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
|
||||
|
||||
g_assert(ipc);
|
||||
g_assert(ipc2);
|
||||
@@ -101,14 +101,14 @@ test_basic(
|
||||
gbinder_ipc_unref(ipc2);
|
||||
|
||||
/* Second gbinder_ipc_new returns the same (default) object */
|
||||
g_assert(gbinder_ipc_new(NULL) == ipc);
|
||||
g_assert(gbinder_ipc_new("") == ipc);
|
||||
g_assert(gbinder_ipc_new(NULL, NULL) == ipc);
|
||||
g_assert(gbinder_ipc_new("", NULL) == ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* Invalid path */
|
||||
g_assert(!gbinder_ipc_new("invalid path"));
|
||||
g_assert(!gbinder_ipc_new("invalid path", NULL));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -120,7 +120,7 @@ void
|
||||
test_sync_oneway(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
@@ -141,7 +141,7 @@ void
|
||||
test_sync_reply_ok_status(
|
||||
int* status)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
@@ -196,7 +196,7 @@ void
|
||||
test_sync_reply_error(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
@@ -253,7 +253,7 @@ void
|
||||
test_transact_ok(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
@@ -310,7 +310,7 @@ void
|
||||
test_transact_dead(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
@@ -356,7 +356,7 @@ void
|
||||
test_transact_failed(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
@@ -404,7 +404,7 @@ void
|
||||
test_transact_status(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
@@ -445,7 +445,7 @@ void
|
||||
test_transact_custom(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, NULL,
|
||||
test_transact_custom_done, NULL, loop);
|
||||
@@ -475,7 +475,7 @@ void
|
||||
test_transact_custom2(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, NULL, NULL,
|
||||
test_transact_custom_destroy, loop);
|
||||
@@ -522,7 +522,7 @@ void
|
||||
test_transact_cancel(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel_exec,
|
||||
test_transact_cancel_done, test_transact_cancel_destroy, loop);
|
||||
@@ -566,7 +566,7 @@ void
|
||||
test_transact_cancel2(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
/* Reusing test_transact_cancel_done and test_transact_cancel_destroy */
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel2_exec,
|
||||
@@ -629,7 +629,7 @@ void
|
||||
test_transact_incoming(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
@@ -690,7 +690,7 @@ void
|
||||
test_transact_status_reply(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -149,7 +149,7 @@ void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderLocalObject* foo;
|
||||
GBinderLocalObject* bar;
|
||||
@@ -186,6 +186,48 @@ test_basic(
|
||||
gbinder_local_object_unref(bar);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* ping
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_ping(
|
||||
void)
|
||||
{
|
||||
static const guint8 req_data [] = { TEST_BASE_INTERFACE_HEADER_BYTES };
|
||||
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, 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, NULL, NULL, NULL);
|
||||
GBinderLocalReply* reply;
|
||||
|
||||
gbinder_remote_request_set_data(req, gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(req_data, sizeof(req_data)), sizeof(req_data)), NULL);
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), base_interface));
|
||||
g_assert(gbinder_local_object_can_handle_transaction(obj, base_interface,
|
||||
HIDL_PING_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_LOOPER);
|
||||
|
||||
/* If can_handle_transaction() returns TRANSACTION_LOOPER then it must be
|
||||
* handled by handle_looper_transaction() */
|
||||
g_assert(!gbinder_local_object_handle_transaction(obj, req,
|
||||
HIDL_PING_TRANSACTION, 0, &status));
|
||||
g_assert(status == (-EBADMSG));
|
||||
reply = gbinder_local_object_handle_looper_transaction(obj, req,
|
||||
HIDL_PING_TRANSACTION, 0, &status);
|
||||
g_assert(reply);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* get_descriptor
|
||||
*==========================================================================*/
|
||||
@@ -195,13 +237,11 @@ void
|
||||
test_get_descriptor(
|
||||
void)
|
||||
{
|
||||
static const guint8 req_data [] = {
|
||||
TEST_BASE_INTERFACE_HEADER_BYTES
|
||||
};
|
||||
static const guint8 req_data [] = { TEST_BASE_INTERFACE_HEADER_BYTES };
|
||||
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 +296,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 +363,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 +468,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 +508,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 +550,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 +592,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 +634,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);
|
||||
@@ -627,6 +667,7 @@ int main(int argc, char* argv[])
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "basic", test_basic);
|
||||
g_test_add_func(TEST_PREFIX "ping", test_ping);
|
||||
g_test_add_func(TEST_PREFIX "get_descriptor", test_get_descriptor);
|
||||
g_test_add_func(TEST_PREFIX "descriptor_chain", test_descriptor_chain);
|
||||
g_test_add_func(TEST_PREFIX "custom_iface", test_custom_iface);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -344,7 +359,7 @@ test_hidl_string(
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(HidlString));
|
||||
g_assert(gbinder_output_data_buffers_size(data)==sizeof(GBinderHidlString));
|
||||
g_assert(data->bytes->len == BUFFER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
@@ -367,7 +382,7 @@ test_hidl_string_vec(
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(HidlVec));
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(GBinderHidlVec));
|
||||
g_assert(data->bytes->len == BUFFER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
@@ -384,7 +399,7 @@ test_local_object(
|
||||
GBinderLocalReply* reply;
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(NULL);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(NULL, NULL);
|
||||
GBinderLocalObject* obj =
|
||||
gbinder_ipc_new_local_object(ipc, "foo", NULL, NULL);
|
||||
|
||||
@@ -438,6 +453,47 @@ test_remote_object(
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* remote_reply
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_remote_reply(
|
||||
void)
|
||||
{
|
||||
/* The size of the string gets aligned at 4-byte boundary */
|
||||
static const char input[] = "test";
|
||||
static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalReply* req = gbinder_local_reply_new(io);
|
||||
GBinderLocalReply* req2;
|
||||
GBinderOutputData* data2;
|
||||
const GByteArray* bytes;
|
||||
const GByteArray* bytes2;
|
||||
GBinderBuffer* buffer;
|
||||
|
||||
gbinder_local_reply_append_string8(req, input);
|
||||
bytes = gbinder_local_reply_data(req)->bytes;
|
||||
|
||||
/* Copy flat structures (no binder objects) */
|
||||
buffer = test_buffer_from_bytes(driver, bytes);
|
||||
req2 = gbinder_local_reply_new_from_data(buffer, NULL);
|
||||
gbinder_buffer_free(buffer);
|
||||
|
||||
data2 = gbinder_local_reply_data(req2);
|
||||
bytes2 = data2->bytes;
|
||||
g_assert(!gbinder_output_data_offsets(data2));
|
||||
g_assert(!gbinder_output_data_buffers_size(data2));
|
||||
g_assert(bytes2->len == sizeof(output));
|
||||
g_assert(!memcmp(bytes2->data, output, bytes2->len));
|
||||
|
||||
gbinder_local_reply_unref(req2);
|
||||
gbinder_local_reply_unref(req);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
@@ -460,6 +516,7 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_PREFIX "hidl_string_vec", test_hidl_string_vec);
|
||||
g_test_add_func(TEST_PREFIX "local_object", test_local_object);
|
||||
g_test_add_func(TEST_PREFIX "remote_object", test_remote_object);
|
||||
g_test_add_func(TEST_PREFIX "remote_reply", test_remote_reply);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -31,9 +31,12 @@
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#include "test_binder.h"
|
||||
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_writer.h"
|
||||
#include "gbinder_io.h"
|
||||
|
||||
@@ -54,6 +57,17 @@ test_int_inc(
|
||||
(*((int*)data))++;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderBuffer*
|
||||
test_buffer_from_bytes(
|
||||
GBinderDriver* driver,
|
||||
const GByteArray* bytes)
|
||||
{
|
||||
/* Prevent double free */
|
||||
test_binder_set_destroy(gbinder_driver_fd(driver), bytes->data, NULL);
|
||||
return gbinder_buffer_new(driver, bytes->data, bytes->len);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
@@ -68,6 +82,7 @@ test_null(
|
||||
|
||||
g_assert(!gbinder_local_request_new(NULL, NULL));
|
||||
g_assert(!gbinder_local_request_ref(NULL));
|
||||
g_assert(!gbinder_local_request_new_from_data(NULL, NULL));
|
||||
gbinder_local_request_unref(NULL);
|
||||
gbinder_local_request_init_writer(NULL, NULL);
|
||||
gbinder_local_request_init_writer(NULL, &writer);
|
||||
@@ -152,8 +167,8 @@ void
|
||||
test_bool(
|
||||
void)
|
||||
{
|
||||
static const guint8 output_true[] = { 0x01, 0xff, 0xff, 0xff };
|
||||
static const guint8 output_false[] = { 0x00, 0xff, 0xff, 0xff };
|
||||
static const guint8 output_true[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
static const guint8 output_false[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderOutputData* data;
|
||||
|
||||
@@ -360,7 +375,7 @@ test_hidl_string(
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(HidlString));
|
||||
g_assert(gbinder_output_data_buffers_size(data)==sizeof(GBinderHidlString));
|
||||
g_assert(data->bytes->len == BUFFER_OBJECT_SIZE_32);
|
||||
gbinder_local_request_unref(req);
|
||||
}
|
||||
@@ -383,7 +398,7 @@ test_hidl_string_vec(
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(HidlVec));
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(GBinderHidlVec));
|
||||
g_assert(data->bytes->len == BUFFER_OBJECT_SIZE_32);
|
||||
gbinder_local_request_unref(req);
|
||||
}
|
||||
@@ -436,6 +451,126 @@ 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);
|
||||
/* GBinderHidlString + the contents (2 bytes) aligned at 8-byte boundary */
|
||||
g_assert(gbinder_output_data_buffers_size(data) ==
|
||||
(sizeof(GBinderHidlString) + 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 +594,8 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_PREFIX "hidl_string_vec", test_hidl_string_vec);
|
||||
g_test_add_func(TEST_PREFIX "local_object", test_local_object);
|
||||
g_test_add_func(TEST_PREFIX "remote_object", test_remote_object);
|
||||
g_test_add_func(TEST_PREFIX "remote_request", test_remote_request);
|
||||
g_test_add_func(TEST_PREFIX "remote_request_obj", test_remote_request_obj);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -74,20 +74,20 @@ static const TestHeaderData test_header_tests[] = {
|
||||
};
|
||||
|
||||
/*==========================================================================*
|
||||
* default
|
||||
* device
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_default(
|
||||
test_device(
|
||||
void)
|
||||
{
|
||||
const GBinderRpcProtocol* p1 = gbinder_rpc_protocol_for_device(NULL);
|
||||
const GBinderRpcProtocol* p2 = gbinder_rpc_protocol_for_device
|
||||
(GBINDER_DEFAULT_BINDER);
|
||||
|
||||
g_assert(p1);
|
||||
g_assert(p1 == p2);
|
||||
g_assert(gbinder_rpc_protocol_for_device(NULL) ==
|
||||
&gbinder_rpc_protocol_binder);
|
||||
g_assert(gbinder_rpc_protocol_for_device(GBINDER_DEFAULT_BINDER) ==
|
||||
&gbinder_rpc_protocol_binder);
|
||||
g_assert(gbinder_rpc_protocol_for_device(GBINDER_DEFAULT_HWBINDER) ==
|
||||
&gbinder_rpc_protocol_hwbinder);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -140,7 +140,7 @@ test_read_header(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestHeaderData* test = test_data;
|
||||
GBinderDriver* driver = gbinder_driver_new(test->dev);
|
||||
GBinderDriver* driver = gbinder_driver_new(test->dev, NULL);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(test->dev), 0, 0);
|
||||
|
||||
@@ -162,7 +162,7 @@ int main(int argc, char* argv[])
|
||||
guint i;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "default", test_default);
|
||||
g_test_add_func(TEST_PREFIX "device", test_device);
|
||||
g_test_add_func(TEST_PREFIX "no_header", test_no_header);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(test_header_tests); i++) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -37,13 +37,17 @@
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_io.h"
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
typedef struct binder_buffer_object_64 {
|
||||
guint32 type;
|
||||
guint32 flags;
|
||||
guint64 buffer;
|
||||
union {
|
||||
const void* ptr;
|
||||
guint64 value;
|
||||
} buffer;
|
||||
guint64 length;
|
||||
guint64 parent;
|
||||
guint64 parent_offset;
|
||||
@@ -51,6 +55,9 @@ typedef struct binder_buffer_object_64 {
|
||||
|
||||
#define BINDER_TYPE_HANDLE GBINDER_FOURCC('s','h','*',0x85)
|
||||
#define BINDER_TYPE_PTR GBINDER_FOURCC('p','t','*',0x85)
|
||||
#define BINDER_BUFFER_FLAG_HAS_PARENT 0x01
|
||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
|
||||
G_STATIC_ASSERT(sizeof(BinderObject64) == BUFFER_OBJECT_SIZE_64);
|
||||
|
||||
/*==========================================================================*
|
||||
* empty
|
||||
@@ -62,6 +69,8 @@ test_empty(
|
||||
void)
|
||||
{
|
||||
GBinderReader reader;
|
||||
gsize count = 1, elemsize = 1;
|
||||
gsize len;
|
||||
|
||||
gbinder_reader_init(&reader, NULL, 0, 0);
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
@@ -78,12 +87,20 @@ test_empty(
|
||||
g_assert(!gbinder_reader_read_object(&reader));
|
||||
g_assert(!gbinder_reader_read_nullable_object(&reader, NULL));
|
||||
g_assert(!gbinder_reader_read_buffer(&reader));
|
||||
g_assert(!gbinder_reader_read_hidl_struct1(&reader, 1));
|
||||
g_assert(!gbinder_reader_read_hidl_vec(&reader, NULL, NULL));
|
||||
g_assert(!gbinder_reader_read_hidl_vec(&reader, &count, &elemsize));
|
||||
g_assert(!gbinder_reader_read_hidl_vec1(&reader, NULL, 1));
|
||||
g_assert(!gbinder_reader_read_hidl_vec1(&reader, &count, 1));
|
||||
g_assert(!count);
|
||||
g_assert(!elemsize);
|
||||
g_assert(!gbinder_reader_read_hidl_string(&reader));
|
||||
g_assert(!gbinder_reader_read_hidl_string_vec(&reader));
|
||||
g_assert(!gbinder_reader_skip_buffer(&reader));
|
||||
g_assert(!gbinder_reader_read_string8(&reader));
|
||||
g_assert(!gbinder_reader_read_string16(&reader));
|
||||
g_assert(!gbinder_reader_skip_string16(&reader));
|
||||
g_assert(!gbinder_reader_read_byte_array(&reader, &len));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
@@ -97,7 +114,7 @@ test_byte(
|
||||
{
|
||||
const guint8 in = 42;
|
||||
guint8 out = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
@@ -131,7 +148,7 @@ test_bool(
|
||||
const guint8 in_true[4] = { 0x01, 0xff, 0xff, 0xff };
|
||||
const guint8 in_false[4] = { 0x00, 0xff, 0xff, 0xff };
|
||||
gboolean out = FALSE;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
@@ -180,7 +197,7 @@ test_int32(
|
||||
const guint32 in = 42;
|
||||
guint32 out1 = 0;
|
||||
gint32 out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
@@ -219,7 +236,7 @@ test_int64(
|
||||
const guint64 in = 42;
|
||||
guint64 out1 = 0;
|
||||
gint64 out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
@@ -258,7 +275,7 @@ test_float(
|
||||
const gfloat in = 42;
|
||||
gfloat out1 = 0;
|
||||
gfloat out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
@@ -297,7 +314,7 @@ test_double(
|
||||
const gdouble in = 42;
|
||||
gdouble out1 = 0;
|
||||
gdouble out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
|
||||
@@ -361,7 +378,7 @@ test_string8(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestStringData* test = test_data;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderReader reader;
|
||||
GBinderReaderData data;
|
||||
const char* str;
|
||||
@@ -425,9 +442,11 @@ 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;
|
||||
gunichar2* out2 = NULL;
|
||||
gsize len = 0;
|
||||
char dummy;
|
||||
char* out = &dummy;
|
||||
|
||||
@@ -437,6 +456,16 @@ test_string16_null(
|
||||
g_memdup(TEST_ARRAY_AND_SIZE(test_string16_in_null)),
|
||||
sizeof(test_string16_in_null));
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
|
||||
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, NULL, NULL));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
|
||||
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, &out2, &len));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert(!out2);
|
||||
g_assert(!len);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
|
||||
g_assert(gbinder_reader_read_nullable_string16(&reader, NULL));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
@@ -464,10 +493,12 @@ 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);
|
||||
gunichar2* out2 = NULL;
|
||||
gsize len = 0;
|
||||
char* str = NULL;
|
||||
|
||||
g_assert(driver);
|
||||
@@ -475,6 +506,22 @@ test_string16(
|
||||
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
|
||||
test->in_size);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, test->in_size);
|
||||
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, NULL,
|
||||
NULL) == valid);
|
||||
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
|
||||
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, test->in_size);
|
||||
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, &out2,
|
||||
&len) == valid);
|
||||
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
|
||||
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
|
||||
if (valid) {
|
||||
g_assert(out2);
|
||||
g_assert((gsize)len == strlen(test->out));
|
||||
}
|
||||
|
||||
gbinder_reader_init(&reader, &data, 0, test->in_size);
|
||||
g_assert(gbinder_reader_read_nullable_string16(&reader, NULL) == valid);
|
||||
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
|
||||
@@ -503,6 +550,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 GBinderHidlVec 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(GBinderHidlVec), 0, 0
|
||||
},{
|
||||
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
|
||||
{ test_hidl_vec_2bytes_data },
|
||||
sizeof(test_hidl_vec_2bytes_data), 0,
|
||||
GBINDER_HIDL_VEC_BUFFER_OFFSET
|
||||
}
|
||||
};
|
||||
|
||||
static const GBinderHidlVec 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(GBinderHidlVec), 0, 0
|
||||
},{
|
||||
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
|
||||
{ test_hidl_vec_2bytes_data },
|
||||
0, 0, GBINDER_HIDL_VEC_BUFFER_OFFSET
|
||||
}
|
||||
};
|
||||
|
||||
static const guint test_hidl_vec_1offset [] = {0};
|
||||
static const GBinderHidlVec test_hidl_vec_null = {{0}, 0, TRUE};
|
||||
static const BinderObject64 test_hidl_vec_null_buf [] = {
|
||||
{
|
||||
BINDER_TYPE_PTR, 0,
|
||||
{ &test_hidl_vec_null },
|
||||
sizeof(GBinderHidlVec), 0, 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Buffer smaller than GBinderHidlVec */
|
||||
static const BinderObject64 test_hidl_vec_short_buf [] = {
|
||||
{
|
||||
BINDER_TYPE_PTR, 0,
|
||||
{ &test_hidl_vec_empty },
|
||||
sizeof(GBinderHidlVec) - 1, 0, 0
|
||||
}
|
||||
};
|
||||
|
||||
/* NULL buffer with size 1 */
|
||||
static const guint test_hidl_vec_badnull_offsets [] = {0};
|
||||
static const GBinderHidlVec test_hidl_vec_badnull = {{0}, 1, TRUE};
|
||||
static const BinderObject64 test_hidl_vec_badnull_buf [] = {
|
||||
{
|
||||
BINDER_TYPE_PTR, 0,
|
||||
{ &test_hidl_vec_badnull },
|
||||
sizeof(GBinderHidlVec), 0, 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Buffer size not divisible by count */
|
||||
static const guint8 test_hidl_vec_badsize_data [] = { 0x01, 0x02, 0x03 };
|
||||
static const GBinderHidlVec 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(GBinderHidlVec), 0, 0
|
||||
},{
|
||||
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
|
||||
{ test_hidl_vec_badsize_data },
|
||||
sizeof(test_hidl_vec_badsize_data), 0,
|
||||
GBINDER_HIDL_VEC_BUFFER_OFFSET
|
||||
}
|
||||
};
|
||||
|
||||
/* Bad buffer address */
|
||||
static const guint8 test_hidl_vec_badbuf_data [] = { 0x01, 0x02, 0x03 };
|
||||
static const GBinderHidlVec 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(GBinderHidlVec), 0, 0
|
||||
},{
|
||||
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
|
||||
{ test_hidl_vec_badsize_data },
|
||||
sizeof(test_hidl_vec_badsize_data), 0,
|
||||
GBINDER_HIDL_VEC_BUFFER_OFFSET
|
||||
}
|
||||
};
|
||||
|
||||
/* Non-zero count and zero size */
|
||||
static const GBinderHidlVec 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(GBinderHidlVec), 0, 0
|
||||
},{
|
||||
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
|
||||
{ test_hidl_vec_badsize_data }, 0, 0,
|
||||
GBINDER_HIDL_VEC_BUFFER_OFFSET
|
||||
}
|
||||
};
|
||||
|
||||
/* Zero count0 and non-zero size */
|
||||
static const GBinderHidlVec 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(GBinderHidlVec), 0, 0
|
||||
},{
|
||||
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
|
||||
{ test_hidl_vec_badsize_data },
|
||||
sizeof(test_hidl_vec_badsize_data), 0,
|
||||
GBINDER_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
|
||||
*==========================================================================*/
|
||||
@@ -516,8 +865,16 @@ typedef struct test_hidl_string_err {
|
||||
} TestHidlStringErr;
|
||||
|
||||
static const guint8 test_hidl_string_err_short [] = { 0x00 };
|
||||
static const guint8 test_hidl_string_err_bad_obj [] = {
|
||||
TEST_INT32_BYTES(BINDER_TYPE_HANDLE),
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 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,
|
||||
@@ -530,6 +887,7 @@ static const guint test_hidl_string_err_one_offset [] = { 0 };
|
||||
|
||||
static const TestHidlStringErr test_hidl_string_err_tests [] = {
|
||||
{ "no-data", TEST_ARRAY_AND_SIZE(test_hidl_string_err_short), NULL },
|
||||
{ "no-object", TEST_ARRAY_AND_SIZE(test_hidl_string_err_bad_obj), NULL },
|
||||
{ "no-offset", TEST_ARRAY_AND_SIZE(test_hidl_string_err_empty), NULL },
|
||||
{ "empty-offset", TEST_ARRAY_AND_SIZE(test_hidl_string_err_empty),
|
||||
test_hidl_string_err_one_offset, 0 },
|
||||
@@ -547,7 +905,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 +947,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 +1005,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,11 +1039,11 @@ 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;
|
||||
HidlVec vec;
|
||||
GBinderHidlVec vec;
|
||||
char** out;
|
||||
|
||||
g_assert(ipc);
|
||||
@@ -693,7 +1051,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,55 +1081,225 @@ 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);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* copy
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_copy(
|
||||
void)
|
||||
{
|
||||
const char in_data1[] = "12345678";
|
||||
const char in_data2[] = "abcdefgh";
|
||||
gint32 in_len1 = sizeof(in_data1) - 1;
|
||||
gint32 in_len2 = sizeof(in_data2) - 1;
|
||||
const void* out_data = NULL;
|
||||
gsize out_len = 0;
|
||||
void* tmp;
|
||||
guint8* ptr;
|
||||
gsize tmp_len = 2 * sizeof(guint32) + in_len1 + in_len2;
|
||||
|
||||
GBinderDriver* driver;
|
||||
GBinderReader reader;
|
||||
GBinderReader reader2;
|
||||
GBinderReaderData data;
|
||||
|
||||
/* test for data */
|
||||
g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
|
||||
ptr = tmp = g_malloc0(tmp_len);
|
||||
memcpy(ptr, &in_len1, sizeof(in_len1));
|
||||
ptr += sizeof(in_len1);
|
||||
memcpy(ptr, in_data1, in_len1);
|
||||
ptr += in_len1;
|
||||
memcpy(ptr, &in_len2, sizeof(in_len2));
|
||||
ptr += sizeof(in_len2);
|
||||
memcpy(ptr, in_data2, in_len2);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.buffer = gbinder_buffer_new(driver, tmp, tmp_len);
|
||||
gbinder_reader_init(&reader, &data, 0, tmp_len);
|
||||
|
||||
/* Read the first array */
|
||||
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
|
||||
g_assert((gsize)in_len1 == out_len);
|
||||
g_assert(memcmp(in_data1, out_data, in_len1) == 0);
|
||||
|
||||
/* Copy the reader */
|
||||
gbinder_reader_copy(&reader2, &reader);
|
||||
|
||||
/* Read both and compare the output */
|
||||
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert((gsize)in_len2 == out_len);
|
||||
g_assert(memcmp(in_data2, out_data, in_len2) == 0);
|
||||
|
||||
g_assert((out_data = gbinder_reader_read_byte_array(&reader2, &out_len)));
|
||||
g_assert(gbinder_reader_at_end(&reader2));
|
||||
g_assert((gsize)in_len2 == out_len);
|
||||
g_assert(memcmp(in_data2, out_data, in_len2) == 0);
|
||||
|
||||
gbinder_buffer_free(data.buffer);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/reader/"
|
||||
#define TEST_(t) TEST_PREFIX t
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "empty", test_empty);
|
||||
g_test_add_func(TEST_PREFIX "byte", test_byte);
|
||||
g_test_add_func(TEST_PREFIX "bool", test_bool);
|
||||
g_test_add_func(TEST_PREFIX "int32", test_int32);
|
||||
g_test_add_func(TEST_PREFIX "int64", test_int64);
|
||||
g_test_add_func(TEST_PREFIX "float", test_float);
|
||||
g_test_add_func(TEST_PREFIX "double", test_double);
|
||||
g_test_add_func(TEST_("empty"), test_empty);
|
||||
g_test_add_func(TEST_("byte"), test_byte);
|
||||
g_test_add_func(TEST_("bool"), test_bool);
|
||||
g_test_add_func(TEST_("int32"), test_int32);
|
||||
g_test_add_func(TEST_("int64"), test_int64);
|
||||
g_test_add_func(TEST_("float"), test_float);
|
||||
g_test_add_func(TEST_("double"), test_double);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(test_string8_tests); i++) {
|
||||
const TestStringData* test = test_string8_tests + i;
|
||||
char* path = g_strconcat(TEST_PREFIX "/string8/", test->name, NULL);
|
||||
char* path = g_strconcat(TEST_("string8/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_string8);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
g_test_add_func(TEST_PREFIX "/string16/null", test_string16_null);
|
||||
g_test_add_func(TEST_("string16/null"), test_string16_null);
|
||||
for (i = 0; i < G_N_ELEMENTS(test_string16_tests); i++) {
|
||||
const TestStringData* test = test_string16_tests + i;
|
||||
char* path = g_strconcat(TEST_PREFIX "/string16/", test->name, NULL);
|
||||
char* path = g_strconcat(TEST_("string16/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_string16);
|
||||
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_("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_("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,
|
||||
char* path = g_strconcat(TEST_("hidl_string/err-"), test->name,
|
||||
NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_hidl_string_err);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
g_test_add_func(TEST_PREFIX "/object/object", test_object);
|
||||
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_("object/valid"), test_object);
|
||||
g_test_add_func(TEST_("object/invalid"), test_object_invalid);
|
||||
g_test_add_func(TEST_("object/no_reg"), test_object_no_reg);
|
||||
g_test_add_func(TEST_("vec"), test_vec);
|
||||
g_test_add_func(TEST_("byte_array"), test_byte_array);
|
||||
g_test_add_func(TEST_("copy"), test_copy);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -67,7 +67,7 @@ void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj1 = gbinder_object_registry_get_remote(reg, 1);
|
||||
GBinderRemoteObject* obj2 = gbinder_object_registry_get_remote(reg, 2);
|
||||
@@ -108,7 +108,7 @@ test_dead(
|
||||
{
|
||||
const guint handle = 1;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderRemoteObject* obj = gbinder_ipc_get_remote_object(ipc, handle);
|
||||
gulong id = gbinder_remote_object_add_death_handler
|
||||
(obj, test_dead_done, loop);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -35,10 +35,17 @@
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_remote_reply_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define BINDER_TYPE_BINDER GBINDER_FOURCC('s', 'b', '*', 0x85)
|
||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
@@ -56,6 +63,7 @@ test_null(
|
||||
gbinder_remote_reply_init_reader(NULL, &reader);
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert(gbinder_remote_reply_is_empty(NULL));
|
||||
g_assert(!gbinder_remote_reply_copy_to_local(NULL));
|
||||
g_assert(!gbinder_remote_reply_read_int32(NULL, NULL));
|
||||
g_assert(!gbinder_remote_reply_read_uint32(NULL, NULL));
|
||||
g_assert(!gbinder_remote_reply_read_int64(NULL, NULL));
|
||||
@@ -74,7 +82,7 @@ void
|
||||
test_empty(
|
||||
void)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
|
||||
|
||||
gbinder_remote_reply_set_data
|
||||
@@ -120,7 +128,7 @@ test_int32(
|
||||
};
|
||||
guint32 out1 = 0;
|
||||
gint32 out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
|
||||
|
||||
gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
|
||||
@@ -151,7 +159,7 @@ test_int64(
|
||||
};
|
||||
guint64 out1 = 0;
|
||||
gint64 out2 = 0;
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
|
||||
|
||||
gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
|
||||
@@ -180,7 +188,7 @@ test_string8(
|
||||
static const guint8 reply_data [] = {
|
||||
'b', 'a', 'r', 0x00
|
||||
};
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
|
||||
|
||||
gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
|
||||
@@ -208,7 +216,7 @@ test_string16(
|
||||
TEST_INT16_BYTES('b'), TEST_INT16_BYTES('a'),
|
||||
TEST_INT16_BYTES('r'), 0x00, 0x00
|
||||
};
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
|
||||
char* str;
|
||||
|
||||
@@ -225,6 +233,55 @@ test_string16(
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* to_local
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_to_local(
|
||||
void)
|
||||
{
|
||||
static const guint8 reply_data [] = {
|
||||
/* 32-bit integer */
|
||||
TEST_INT32_BYTES(42),
|
||||
/* 64-bit NULL flat_binder_object */
|
||||
TEST_INT32_BYTES(BINDER_TYPE_BINDER), /* hdr.type */
|
||||
TEST_INT32_BYTES(0x17f), /* flags */
|
||||
TEST_INT64_BYTES(0), /* handle */
|
||||
TEST_INT64_BYTES(0) /* cookie */
|
||||
};
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, NULL);
|
||||
GBinderRemoteReply* req = gbinder_remote_reply_new(NULL);
|
||||
GBinderLocalReply* req2;
|
||||
GBinderOutputData* data;
|
||||
const GByteArray* bytes;
|
||||
GUtilIntArray* offsets;
|
||||
guint8* req_data = g_memdup(reply_data, sizeof(reply_data));
|
||||
void** objects = g_new0(void*, 2);
|
||||
|
||||
/* Skip the 32-bit integer */
|
||||
objects[0] = req_data + 4;
|
||||
gbinder_remote_reply_set_data(req, gbinder_buffer_new(driver, req_data,
|
||||
sizeof(reply_data)), objects);
|
||||
|
||||
/* Convert to GBinderLocalReply */
|
||||
req2 = gbinder_remote_reply_copy_to_local(req);
|
||||
data = gbinder_local_reply_data(req2);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
bytes = data->bytes;
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 4);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(bytes->len == sizeof(reply_data));
|
||||
|
||||
gbinder_remote_reply_unref(req);
|
||||
gbinder_local_reply_unref(req2);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
@@ -241,6 +298,7 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_PREFIX "int64", test_int64);
|
||||
g_test_add_func(TEST_PREFIX "string8", test_string8);
|
||||
g_test_add_func(TEST_PREFIX "string16", test_string16);
|
||||
g_test_add_func(TEST_PREFIX "to_local", test_to_local);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
@@ -13,9 +13,9 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Jolla Ltd nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@@ -37,6 +37,11 @@
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_remote_request_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_io.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
@@ -50,6 +55,9 @@ static TestOpt test_opt;
|
||||
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'), \
|
||||
TEST_INT16_BYTES('o'), 0x00, 0x00
|
||||
|
||||
#define BINDER_TYPE_BINDER GBINDER_FOURCC('s', 'b', '*', 0x85)
|
||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
@@ -67,6 +75,7 @@ test_null(
|
||||
gbinder_remote_request_init_reader(NULL, &reader);
|
||||
g_assert(gbinder_reader_at_end(&reader));
|
||||
g_assert(!gbinder_remote_request_interface(NULL));
|
||||
g_assert(!gbinder_remote_request_copy_to_local(NULL));
|
||||
g_assert(gbinder_remote_request_sender_pid(NULL) == (pid_t)(-1));
|
||||
g_assert(gbinder_remote_request_sender_euid(NULL) == (uid_t)(-1));
|
||||
g_assert(!gbinder_remote_request_read_int32(NULL, NULL));
|
||||
@@ -116,7 +125,7 @@ test_int32(
|
||||
guint32 out1 = 0;
|
||||
gint32 out2 = 0;
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderDriver* driver = gbinder_driver_new(dev);
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, NULL);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(dev), 0, 0);
|
||||
|
||||
@@ -150,7 +159,7 @@ test_int64(
|
||||
guint64 out1 = 0;
|
||||
gint64 out2 = 0;
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderDriver* driver = gbinder_driver_new(dev);
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, NULL);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(dev), 0, 0);
|
||||
|
||||
@@ -182,7 +191,7 @@ test_string8(
|
||||
'b', 'a', 'r', 0x00
|
||||
};
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderDriver* driver = gbinder_driver_new(dev);
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, NULL);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(dev), 0, 0);
|
||||
|
||||
@@ -213,7 +222,7 @@ test_string16(
|
||||
TEST_INT16_BYTES('r'), 0x00, 0x00
|
||||
};
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderDriver* driver = gbinder_driver_new(dev);
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, NULL);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(dev), 0, 0);
|
||||
char* str;
|
||||
@@ -231,6 +240,59 @@ test_string16(
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* to_local
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_to_local(
|
||||
void)
|
||||
{
|
||||
static const guint8 request_data [] = {
|
||||
TEST_RPC_HEADER,
|
||||
/* 32-bit integer */
|
||||
TEST_INT32_BYTES(42),
|
||||
/* 64-bit NULL flat_binder_object */
|
||||
TEST_INT32_BYTES(BINDER_TYPE_BINDER), /* hdr.type */
|
||||
TEST_INT32_BYTES(0x17f), /* flags */
|
||||
TEST_INT64_BYTES(0), /* handle */
|
||||
TEST_INT64_BYTES(0) /* cookie */
|
||||
};
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
GBinderDriver* driver = gbinder_driver_new(dev, NULL);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
|
||||
gbinder_rpc_protocol_for_device(dev), 0, 0);
|
||||
GBinderLocalRequest* req2;
|
||||
GBinderOutputData* data;
|
||||
const GByteArray* bytes;
|
||||
GUtilIntArray* offsets;
|
||||
guint8* req_data = g_memdup(request_data, sizeof(request_data));
|
||||
void** objects = g_new0(void*, 2);
|
||||
|
||||
/* Skip the 32-bit integer */
|
||||
objects[0] = req_data + 4;
|
||||
gbinder_remote_request_set_data(req, gbinder_buffer_new(driver, req_data,
|
||||
sizeof(request_data)), objects);
|
||||
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), TEST_RPC_IFACE));
|
||||
|
||||
/* Convert to GBinderLocalRequest */
|
||||
req2 = gbinder_remote_request_copy_to_local(req);
|
||||
data = gbinder_local_request_data(req2);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
bytes = data->bytes;
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 4);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(bytes->len == sizeof(request_data));
|
||||
|
||||
gbinder_remote_request_unref(req);
|
||||
gbinder_local_request_unref(req2);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
@@ -246,6 +308,7 @@ int main(int argc, char* argv[])
|
||||
g_test_add_func(TEST_PREFIX "int64", test_int64);
|
||||
g_test_add_func(TEST_PREFIX "string8", test_string8);
|
||||
g_test_add_func(TEST_PREFIX "string16", test_string16);
|
||||
g_test_add_func(TEST_PREFIX "to_local", test_to_local);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
5
unit/unit_servicemanager/Makefile
Normal file
5
unit/unit_servicemanager/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_servicemanager
|
||||
|
||||
include ../common/Makefile
|
||||
684
unit/unit_servicemanager/unit_servicemanager.c
Normal file
684
unit/unit_servicemanager/unit_servicemanager.c
Normal file
@@ -0,0 +1,684 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
static
|
||||
void
|
||||
test_get_service_func(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderRemoteObject* obj,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
g_assert(FALSE);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_add_service_func(
|
||||
GBinderServiceManager* sm,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
g_assert(FALSE);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_registration_func_inc(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
void* user_data)
|
||||
{
|
||||
int* count = user_data;
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
test_transact_func(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* TestServiceManager
|
||||
*==========================================================================*/
|
||||
|
||||
typedef GBinderServiceManagerClass TestServiceManagerClass;
|
||||
typedef struct test_servicemanager {
|
||||
GBinderServiceManager manager;
|
||||
GBinderRemoteObject* remote;
|
||||
char** services;
|
||||
gboolean reject_name;
|
||||
} TestServiceManager;
|
||||
|
||||
#define TEST_SERVICEMANAGER(obj) \
|
||||
G_CAST(obj, TestServiceManager, manager.parent)
|
||||
#define TEST_SERVICEMANAGER2(obj, type) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), (type), TestServiceManager)
|
||||
|
||||
static
|
||||
char**
|
||||
test_servicemanager_list(
|
||||
GBinderServiceManager* sm)
|
||||
{
|
||||
TestServiceManager* self = TEST_SERVICEMANAGER(sm);
|
||||
|
||||
return g_strdupv(self->services);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderRemoteObject*
|
||||
test_servicemanager_get_service(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
int* status)
|
||||
{
|
||||
TestServiceManager* self = TEST_SERVICEMANAGER(sm);
|
||||
|
||||
if (gutil_strv_contains(self->services, name)) {
|
||||
if (!self->remote) {
|
||||
self->remote = gbinder_ipc_get_remote_object
|
||||
(gbinder_client_ipc(sm->client), 1);
|
||||
}
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return gbinder_remote_object_ref(self->remote);
|
||||
} else {
|
||||
*status = (-ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
test_servicemanager_add_service(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
TestServiceManager* self = TEST_SERVICEMANAGER(sm);
|
||||
|
||||
if (!gutil_strv_contains(self->services, name)) {
|
||||
self->services = gutil_strv_add(self->services, name);
|
||||
}
|
||||
return GBINDER_STATUS_OK;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* TestHwServiceManager
|
||||
*==========================================================================*/
|
||||
|
||||
typedef TestServiceManagerClass TestHwServiceManagerClass;
|
||||
typedef TestServiceManager TestHwServiceManager;
|
||||
|
||||
G_DEFINE_TYPE(TestHwServiceManager, test_hwservicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define TEST_HWSERVICEMANAGER_HANDLE (0)
|
||||
#define TEST_HWSERVICEMANAGER_IFACE "android.hidl.manager@1.0::IServiceManager"
|
||||
#define TEST_TYPE_HWSERVICEMANAGER (test_hwservicemanager_get_type())
|
||||
#define TEST_IS_HWSERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_TYPE(obj, TEST_TYPE_HWSERVICEMANAGER)
|
||||
#define TEST_HWSERVICEMANAGER(obj) \
|
||||
TEST_SERVICEMANAGER2(obj, TEST_TYPE_HWSERVICEMANAGER)
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
test_hwservicemanager_check_name(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name)
|
||||
{
|
||||
TestHwServiceManager* self = TEST_HWSERVICEMANAGER(sm);
|
||||
|
||||
return (!name || self->reject_name) ?
|
||||
GBINDER_SERVICEMANAGER_NAME_INVALID :
|
||||
GBINDER_SERVICEMANAGER_NAME_NORMALIZE;
|
||||
}
|
||||
|
||||
static
|
||||
char*
|
||||
test_hwservicemanager_normalize_name(
|
||||
GBinderServiceManager* self,
|
||||
const char* name)
|
||||
{
|
||||
return g_strdup(name);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_hwservicemanager_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_hwservicemanager_unwatch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_hwservicemanager_init(
|
||||
TestHwServiceManager* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_hwservicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
TestHwServiceManager* self = TEST_HWSERVICEMANAGER(object);
|
||||
|
||||
gbinder_remote_object_unref(self->remote);
|
||||
g_strfreev(self->services);
|
||||
G_OBJECT_CLASS(test_hwservicemanager_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_hwservicemanager_class_init(
|
||||
TestHwServiceManagerClass* klass)
|
||||
{
|
||||
klass->handle = TEST_HWSERVICEMANAGER_HANDLE;
|
||||
klass->iface = TEST_HWSERVICEMANAGER_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_HWBINDER;
|
||||
klass->rpc_protocol = &gbinder_rpc_protocol_hwbinder;
|
||||
klass->list = test_servicemanager_list;
|
||||
klass->get_service = test_servicemanager_get_service;
|
||||
klass->add_service = test_servicemanager_add_service;
|
||||
klass->check_name = test_hwservicemanager_check_name;
|
||||
klass->normalize_name = test_hwservicemanager_normalize_name;
|
||||
klass->watch = test_hwservicemanager_watch;
|
||||
klass->unwatch = test_hwservicemanager_unwatch;
|
||||
G_OBJECT_CLASS(klass)->finalize = test_hwservicemanager_finalize;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type(TEST_TYPE_HWSERVICEMANAGER,
|
||||
dev);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* TestDefServiceManager
|
||||
*==========================================================================*/
|
||||
|
||||
typedef TestServiceManagerClass TestDefServiceManagerClass;
|
||||
typedef TestServiceManager TestDefServiceManager;
|
||||
|
||||
G_DEFINE_TYPE(TestDefServiceManager, test_defservicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define TEST_DEFSERVICEMANAGER_HANDLE (0)
|
||||
#define TEST_DEFSERVICEMANAGER_IFACE "android.os.IServiceManager"
|
||||
#define TEST_TYPE_DEFSERVICEMANAGER (test_defservicemanager_get_type())
|
||||
#define TEST_IS_DEFSERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_TYPE(obj, TEST_TYPE_DEFSERVICEMANAGER)
|
||||
#define TEST_DEFSERVICEMANAGER(obj) \
|
||||
TEST_SERVICEMANAGER2(obj, TEST_TYPE_DEFSERVICEMANAGER)
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
test_defservicemanager_check_name(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name)
|
||||
{
|
||||
TestDefServiceManager* self = TEST_DEFSERVICEMANAGER(sm);
|
||||
|
||||
return (!name || self->reject_name) ?
|
||||
GBINDER_SERVICEMANAGER_NAME_INVALID :
|
||||
GBINDER_SERVICEMANAGER_NAME_OK;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_defservicemanager_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_defservicemanager_init(
|
||||
TestDefServiceManager* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_defservicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
TestDefServiceManager* self = TEST_DEFSERVICEMANAGER(object);
|
||||
|
||||
gbinder_remote_object_unref(self->remote);
|
||||
g_strfreev(self->services);
|
||||
G_OBJECT_CLASS(test_defservicemanager_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_defservicemanager_class_init(
|
||||
TestDefServiceManagerClass* klass)
|
||||
{
|
||||
klass->handle = TEST_DEFSERVICEMANAGER_HANDLE;
|
||||
klass->iface = TEST_DEFSERVICEMANAGER_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_BINDER;
|
||||
klass->rpc_protocol = &gbinder_rpc_protocol_binder;
|
||||
klass->list = test_servicemanager_list;
|
||||
klass->get_service = test_servicemanager_get_service;
|
||||
klass->add_service = test_servicemanager_add_service;
|
||||
klass->check_name = test_defservicemanager_check_name;
|
||||
klass->watch = test_defservicemanager_watch;
|
||||
G_OBJECT_CLASS(klass)->finalize = test_defservicemanager_finalize;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_defaultservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type(TEST_TYPE_DEFSERVICEMANAGER,
|
||||
dev);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
g_assert(!gbinder_servicemanager_new_with_type(0, NULL));
|
||||
g_assert(!gbinder_servicemanager_new_local_object(NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_ref(NULL));
|
||||
g_assert(!gbinder_servicemanager_list(NULL, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_list_sync(NULL));
|
||||
g_assert(!gbinder_servicemanager_get_service(NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_get_service_sync(NULL, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_add_service(NULL, NULL, NULL, NULL, NULL));
|
||||
g_assert(gbinder_servicemanager_add_service_sync(NULL, NULL, NULL) ==
|
||||
(-EINVAL));
|
||||
g_assert(!gbinder_servicemanager_add_registration_handler(NULL, NULL,
|
||||
NULL, NULL));
|
||||
gbinder_servicemanager_remove_handler(NULL, 0);
|
||||
gbinder_servicemanager_cancel(NULL, 0);
|
||||
gbinder_servicemanager_unref(NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* invalid
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_invalid(
|
||||
void)
|
||||
{
|
||||
int status = 0;
|
||||
GBinderServiceManager* sm =
|
||||
gbinder_servicemanager_new(GBINDER_DEFAULT_HWBINDER);
|
||||
|
||||
g_assert(!gbinder_servicemanager_new_with_type(GBINDER_TYPE_LOCAL_OBJECT,
|
||||
NULL));
|
||||
g_assert(TEST_IS_HWSERVICEMANAGER(sm));
|
||||
g_assert(!gbinder_servicemanager_list(sm, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_get_service(sm, "foo", NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_get_service(sm, NULL,
|
||||
test_get_service_func, NULL));
|
||||
g_assert(!gbinder_servicemanager_get_service_sync(sm, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_get_service_sync(sm, NULL, &status));
|
||||
g_assert(status == (-EINVAL));
|
||||
g_assert(!gbinder_servicemanager_add_service(sm, "foo", NULL, NULL, NULL));
|
||||
g_assert(!gbinder_servicemanager_add_service(sm, NULL, NULL,
|
||||
test_add_service_func, NULL));
|
||||
g_assert(gbinder_servicemanager_add_service_sync(sm, NULL, NULL) ==
|
||||
(-EINVAL));
|
||||
g_assert(gbinder_servicemanager_add_service_sync(sm, "foo", NULL) ==
|
||||
(-EINVAL));
|
||||
g_assert(!gbinder_servicemanager_add_registration_handler(sm, NULL, NULL,
|
||||
NULL));
|
||||
|
||||
gbinder_servicemanager_cancel(sm, 0);
|
||||
gbinder_servicemanager_remove_handler(sm, 0);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* basic
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderServiceManager* sm =
|
||||
gbinder_servicemanager_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderLocalObject* obj;
|
||||
|
||||
g_assert(sm);
|
||||
obj = gbinder_servicemanager_new_local_object(sm, "foo.bar",
|
||||
test_transact_func, NULL);
|
||||
g_assert(obj);
|
||||
gbinder_local_object_unref(obj);
|
||||
|
||||
g_assert(gbinder_servicemanager_ref(sm) == sm);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* reuse
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_reuse(
|
||||
void)
|
||||
{
|
||||
GBinderServiceManager* m1 =
|
||||
gbinder_servicemanager_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderServiceManager* m2 =
|
||||
gbinder_servicemanager_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderServiceManager* vnd1 =
|
||||
gbinder_servicemanager_new("/dev/vpnbinder");
|
||||
GBinderServiceManager* vnd2 =
|
||||
gbinder_servicemanager_new("/dev/vpnbinder");
|
||||
GBinderServiceManager* hw1 =
|
||||
gbinder_servicemanager_new(GBINDER_DEFAULT_HWBINDER);
|
||||
GBinderServiceManager* hw2 =
|
||||
gbinder_servicemanager_new(GBINDER_DEFAULT_HWBINDER);
|
||||
|
||||
g_assert(m1);
|
||||
g_assert(m1 == m2);
|
||||
|
||||
g_assert(vnd1);
|
||||
g_assert(vnd1 == vnd2);
|
||||
g_assert(vnd1 != m1);
|
||||
|
||||
g_assert(hw1);
|
||||
g_assert(hw1 == hw2);
|
||||
g_assert(hw1 != m1);
|
||||
g_assert(hw1 != vnd1);
|
||||
|
||||
gbinder_servicemanager_unref(m1);
|
||||
gbinder_servicemanager_unref(m2);
|
||||
gbinder_servicemanager_unref(vnd1);
|
||||
gbinder_servicemanager_unref(vnd2);
|
||||
gbinder_servicemanager_unref(hw1);
|
||||
gbinder_servicemanager_unref(hw2);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* notify
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_notify_type(
|
||||
GType t)
|
||||
{
|
||||
GBinderServiceManager* sm = gbinder_servicemanager_new_with_type(t, NULL);
|
||||
TestHwServiceManager* test = TEST_SERVICEMANAGER2(sm, t);
|
||||
const char* name = "foo";
|
||||
int count = 0;
|
||||
gulong id1 = gbinder_servicemanager_add_registration_handler(sm, name,
|
||||
test_registration_func_inc, &count);
|
||||
gulong id2 = gbinder_servicemanager_add_registration_handler(sm, name,
|
||||
test_registration_func_inc, &count);
|
||||
|
||||
g_assert(id1 && id2);
|
||||
test->services = gutil_strv_add(test->services, name);
|
||||
gbinder_servicemanager_service_registered(sm, name);
|
||||
g_assert(count == 2);
|
||||
count = 0;
|
||||
|
||||
/* Nothing is going to happen if the name get rejected by the class */
|
||||
test->reject_name = TRUE;
|
||||
g_assert(!gbinder_servicemanager_add_registration_handler(sm, name,
|
||||
test_registration_func_inc, &count));
|
||||
gbinder_servicemanager_service_registered(sm, name);
|
||||
g_assert(!count);
|
||||
|
||||
gbinder_servicemanager_remove_handler(sm, id1);
|
||||
gbinder_servicemanager_remove_handler(sm, id2);
|
||||
gbinder_servicemanager_unref(sm);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_notify(
|
||||
void)
|
||||
{
|
||||
test_notify_type(TEST_TYPE_HWSERVICEMANAGER);
|
||||
test_notify_type(TEST_TYPE_DEFSERVICEMANAGER);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* list
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_list_func(
|
||||
GBinderServiceManager* sm,
|
||||
char** services,
|
||||
void* user_data)
|
||||
{
|
||||
TestHwServiceManager* test = TEST_SERVICEMANAGER(sm);
|
||||
|
||||
g_assert(gutil_strv_equal(test->services, services));
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_list(
|
||||
void)
|
||||
{
|
||||
GBinderServiceManager* sm = gbinder_servicemanager_new(NULL);
|
||||
TestHwServiceManager* test = TEST_SERVICEMANAGER(sm);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
char** list;
|
||||
gulong id;
|
||||
|
||||
test->services = gutil_strv_add(test->services, "foo");
|
||||
list = gbinder_servicemanager_list_sync(sm);
|
||||
g_assert(gutil_strv_equal(test->services, list));
|
||||
g_strfreev(list);
|
||||
|
||||
id = gbinder_servicemanager_list(sm, test_list_func, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_servicemanager_unref(sm);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* get
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_get_func(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderRemoteObject* obj,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
g_assert(obj);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_get(
|
||||
void)
|
||||
{
|
||||
GBinderServiceManager* sm = gbinder_servicemanager_new(NULL);
|
||||
TestHwServiceManager* test = TEST_SERVICEMANAGER(sm);
|
||||
int status = -1;
|
||||
GBinderLocalObject* obj =
|
||||
gbinder_servicemanager_new_local_object(sm, "foo.bar",
|
||||
test_transact_func, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
/* Add a service */
|
||||
g_assert(obj);
|
||||
g_assert(gbinder_servicemanager_add_service_sync(sm, "foo", obj) ==
|
||||
GBINDER_STATUS_OK);
|
||||
gbinder_local_object_unref(obj);
|
||||
g_assert(gutil_strv_contains(test->services, "foo"));
|
||||
|
||||
/* And get it back */
|
||||
g_assert(gbinder_servicemanager_get_service_sync(sm, "foo", &status));
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
|
||||
/* Wrong name */
|
||||
g_assert(!gbinder_servicemanager_get_service_sync(sm, "bar", &status));
|
||||
g_assert(status == (-ENOENT));
|
||||
|
||||
/* Get it asynchronously */
|
||||
id = gbinder_servicemanager_get_service(sm, "foo", test_get_func, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_servicemanager_unref(sm);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* add
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_add_func(
|
||||
GBinderServiceManager* sm,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_add(
|
||||
void)
|
||||
{
|
||||
GBinderServiceManager* sm = gbinder_servicemanager_new(NULL);
|
||||
TestHwServiceManager* test = TEST_SERVICEMANAGER(sm);
|
||||
GBinderLocalObject* obj =
|
||||
gbinder_servicemanager_new_local_object(sm, "foo.bar",
|
||||
test_transact_func, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_servicemanager_add_service(sm, "foo", obj,
|
||||
test_add_func, loop);
|
||||
|
||||
g_assert(id);
|
||||
test_run(&test_opt, loop);
|
||||
g_assert(gutil_strv_contains(test->services, "foo"));
|
||||
|
||||
gbinder_servicemanager_unref(sm);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_(t) "/servicemanager/" t
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_("null"), test_null);
|
||||
g_test_add_func(TEST_("invalid"), test_invalid);
|
||||
g_test_add_func(TEST_("basic"), test_basic);
|
||||
g_test_add_func(TEST_("reuse"), test_reuse);
|
||||
g_test_add_func(TEST_("notify"), test_notify);
|
||||
g_test_add_func(TEST_("list"), test_list);
|
||||
g_test_add_func(TEST_("get"), test_get);
|
||||
g_test_add_func(TEST_("add"), test_add);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
5
unit/unit_servicepoll/Makefile
Normal file
5
unit/unit_servicepoll/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_servicepoll
|
||||
|
||||
include ../common/Makefile
|
||||
448
unit/unit_servicepoll/unit_servicepoll.c
Normal file
448
unit/unit_servicepoll/unit_servicepoll.c
Normal file
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
#include "gbinder_servicemanager_p.h"
|
||||
#include "gbinder_servicepoll.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
/*==========================================================================*
|
||||
* TestServiceManager
|
||||
*==========================================================================*/
|
||||
|
||||
typedef GBinderServiceManagerClass TestServiceManagerClass;
|
||||
typedef struct test_servicemanager {
|
||||
GBinderServiceManager manager;
|
||||
GMutex mutex;
|
||||
char** services;
|
||||
} TestServiceManager;
|
||||
|
||||
G_DEFINE_TYPE(TestServiceManager, test_servicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
#define TEST_SERVICEMANAGER_HANDLE (0)
|
||||
#define TEST_SERVICEMANAGER_IFACE "android.os.IServiceManager"
|
||||
#define TEST_TYPE_SERVICEMANAGER (test_servicemanager_get_type())
|
||||
#define TEST_SERVICEMANAGER(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
TEST_TYPE_SERVICEMANAGER, TestServiceManager)
|
||||
|
||||
static
|
||||
char**
|
||||
test_servicemanager_list(
|
||||
GBinderServiceManager* manager)
|
||||
{
|
||||
char** ret;
|
||||
TestServiceManager* self = TEST_SERVICEMANAGER(manager);
|
||||
|
||||
g_mutex_lock(&self->mutex);
|
||||
ret = g_strdupv(self->services);
|
||||
GDEBUG("%u", gutil_strv_length(ret));
|
||||
g_mutex_unlock(&self->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderRemoteObject*
|
||||
test_servicemanager_get_service(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name,
|
||||
int* status)
|
||||
{
|
||||
*status = (-ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
test_servicemanager_add_service(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
TestServiceManager* self = TEST_SERVICEMANAGER(manager);
|
||||
|
||||
g_mutex_lock(&self->mutex);
|
||||
if (!gutil_strv_contains(self->services, name)) {
|
||||
self->services = gutil_strv_add(self->services, name);
|
||||
}
|
||||
g_mutex_unlock(&self->mutex);
|
||||
return GBINDER_STATUS_OK;
|
||||
}
|
||||
|
||||
static
|
||||
GBINDER_SERVICEMANAGER_NAME_CHECK
|
||||
test_servicemanager_check_name(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
return name ?
|
||||
GBINDER_SERVICEMANAGER_NAME_INVALID :
|
||||
GBINDER_SERVICEMANAGER_NAME_OK;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_servicemanager_watch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_servicemanager_unwatch(
|
||||
GBinderServiceManager* manager,
|
||||
const char* name)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_servicemanager_init(
|
||||
TestServiceManager* self)
|
||||
{
|
||||
g_mutex_init(&self->mutex);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_servicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
TestServiceManager* self = TEST_SERVICEMANAGER(object);
|
||||
|
||||
g_mutex_clear(&self->mutex);
|
||||
g_strfreev(self->services);
|
||||
G_OBJECT_CLASS(test_servicemanager_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_servicemanager_class_init(
|
||||
TestServiceManagerClass* klass)
|
||||
{
|
||||
klass->handle = TEST_SERVICEMANAGER_HANDLE;
|
||||
klass->iface = TEST_SERVICEMANAGER_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_HWBINDER;
|
||||
klass->rpc_protocol = &gbinder_rpc_protocol_binder;
|
||||
klass->list = test_servicemanager_list;
|
||||
klass->get_service = test_servicemanager_get_service;
|
||||
klass->add_service = test_servicemanager_add_service;
|
||||
klass->check_name = test_servicemanager_check_name;
|
||||
klass->watch = test_servicemanager_watch;
|
||||
klass->unwatch = test_servicemanager_unwatch;
|
||||
G_OBJECT_CLASS(klass)->finalize = test_servicemanager_finalize;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_defaultservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type(TEST_TYPE_SERVICEMANAGER, dev);
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new(dev);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
g_assert(!gbinder_servicepoll_ref(NULL));
|
||||
g_assert(!gbinder_servicepoll_manager(NULL));
|
||||
g_assert(!gbinder_servicepoll_is_known_name(NULL, ""));
|
||||
g_assert(!gbinder_servicepoll_add_handler(NULL, NULL, NULL));
|
||||
gbinder_servicepoll_remove_handler(NULL, 0);
|
||||
gbinder_servicepoll_unref(NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* basic
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager = gbinder_servicemanager_new(NULL);
|
||||
GBinderServicePoll* poll = gbinder_servicepoll_new(manager, NULL);
|
||||
|
||||
g_assert(poll);
|
||||
g_assert(gbinder_servicepoll_manager(poll) == manager);
|
||||
g_assert(!gbinder_servicepoll_is_known_name(poll, "foo"));
|
||||
g_assert(!gbinder_servicepoll_add_handler(poll, NULL, NULL));
|
||||
gbinder_servicepoll_remove_handler(poll, 0); /* this does nothing */
|
||||
gbinder_servicepoll_unref(poll);
|
||||
|
||||
poll = gbinder_servicepoll_new(manager, &weakptr);
|
||||
g_assert(poll == weakptr);
|
||||
g_assert(poll == gbinder_servicepoll_new(manager, &weakptr));
|
||||
gbinder_servicepoll_unref(poll);
|
||||
gbinder_servicepoll_unref(poll);
|
||||
|
||||
gbinder_servicemanager_unref(manager);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* notify1
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_notify_proc(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name_added,
|
||||
void* user_data)
|
||||
{
|
||||
GDEBUG("\"%s\" added", name_added);
|
||||
if (!g_strcmp0(name_added, "foo")) {
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_notify1_foo(
|
||||
gpointer user_data)
|
||||
{
|
||||
TestServiceManager* test = user_data;
|
||||
|
||||
g_mutex_lock(&test->mutex);
|
||||
GDEBUG("adding \"foo\"");
|
||||
test->services = gutil_strv_add(test->services, "foo");
|
||||
g_mutex_unlock(&test->mutex);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_notify1_bar(
|
||||
gpointer user_data)
|
||||
{
|
||||
TestServiceManager* test = user_data;
|
||||
|
||||
g_mutex_lock(&test->mutex);
|
||||
GDEBUG("adding \"bar\"");
|
||||
test->services = gutil_strv_add(test->services, "bar");
|
||||
g_mutex_unlock(&test->mutex);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_notify1(
|
||||
void)
|
||||
{
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager = gbinder_servicemanager_new(NULL);
|
||||
TestServiceManager* test = TEST_SERVICEMANAGER(manager);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServicePoll* poll;
|
||||
gulong id;
|
||||
|
||||
gbinder_servicepoll_interval_ms = 100;
|
||||
poll = gbinder_servicepoll_new(manager, &weakptr);
|
||||
g_timeout_add(2 * gbinder_servicepoll_interval_ms,
|
||||
test_notify1_bar, test);
|
||||
g_timeout_add(4 * gbinder_servicepoll_interval_ms,
|
||||
test_notify1_foo, test);
|
||||
|
||||
id = gbinder_servicepoll_add_handler(poll, test_notify_proc, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(gbinder_servicepoll_is_known_name(poll, "foo"));
|
||||
g_assert(gbinder_servicepoll_is_known_name(poll, "bar"));
|
||||
gbinder_servicepoll_remove_handler(poll, id);
|
||||
gbinder_servicepoll_unref(poll);
|
||||
g_assert(!weakptr);
|
||||
gbinder_servicemanager_unref(manager);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* notify2
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_notify2_foo(
|
||||
gpointer user_data)
|
||||
{
|
||||
TestServiceManager* test = user_data;
|
||||
|
||||
g_mutex_lock(&test->mutex);
|
||||
GDEBUG("services = [\"bar\",\"foo\"]");
|
||||
g_strfreev(test->services);
|
||||
test->services = g_strsplit("bar,bar3,foo", ",", -1);
|
||||
g_mutex_unlock(&test->mutex);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_notify2_bar(
|
||||
gpointer user_data)
|
||||
{
|
||||
TestServiceManager* test = user_data;
|
||||
|
||||
g_mutex_lock(&test->mutex);
|
||||
GDEBUG("services = [\"bar1\",\"bar2\",\"bar3\"]");
|
||||
g_strfreev(test->services);
|
||||
test->services = g_strsplit("bar1,bar2,bar3", ",", -1);
|
||||
g_mutex_unlock(&test->mutex);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_notify2(
|
||||
void)
|
||||
{
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager = gbinder_servicemanager_new(NULL);
|
||||
TestServiceManager* test = TEST_SERVICEMANAGER(manager);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderServicePoll* poll;
|
||||
gulong id;
|
||||
|
||||
gbinder_servicepoll_interval_ms = 100;
|
||||
poll = gbinder_servicepoll_new(manager, &weakptr);
|
||||
g_timeout_add(2 * gbinder_servicepoll_interval_ms,
|
||||
test_notify2_bar, test);
|
||||
g_timeout_add(4 * gbinder_servicepoll_interval_ms,
|
||||
test_notify2_foo, test);
|
||||
|
||||
/* Reusing test_notify_proc */
|
||||
id = gbinder_servicepoll_add_handler(poll, test_notify_proc, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(gbinder_servicepoll_is_known_name(poll, "foo"));
|
||||
g_assert(gbinder_servicepoll_is_known_name(poll, "bar"));
|
||||
g_assert(gbinder_servicepoll_is_known_name(poll, "bar3"));
|
||||
g_assert(!gbinder_servicepoll_is_known_name(poll, "bar1"));
|
||||
g_assert(!gbinder_servicepoll_is_known_name(poll, "bar2"));
|
||||
gbinder_servicepoll_remove_handler(poll, id);
|
||||
gbinder_servicepoll_unref(poll);
|
||||
g_assert(!weakptr);
|
||||
gbinder_servicemanager_unref(manager);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* already_there
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_already_there_proc(
|
||||
GBinderServicePoll* poll,
|
||||
const char* name_added,
|
||||
void* user_data)
|
||||
{
|
||||
g_assert(!g_strcmp0(name_added, "foo"));
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_already_there(
|
||||
void)
|
||||
{
|
||||
GBinderServicePoll* weakptr = NULL;
|
||||
GBinderServiceManager* manager = gbinder_servicemanager_new(NULL);
|
||||
GBinderServicePoll* poll = gbinder_servicepoll_new(manager, &weakptr);
|
||||
TestServiceManager* test = TEST_SERVICEMANAGER(manager);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
test->services = gutil_strv_add(test->services, "foo");
|
||||
id = gbinder_servicepoll_add_handler(poll, test_already_there_proc, loop);
|
||||
|
||||
g_assert(id);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_servicepoll_remove_handler(poll, id);
|
||||
gbinder_servicepoll_unref(poll);
|
||||
g_assert(!weakptr);
|
||||
gbinder_servicemanager_unref(manager);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_(t) "/servicepoll/" t
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_("null"), test_null);
|
||||
g_test_add_func(TEST_("basic"), test_basic);
|
||||
g_test_add_func(TEST_("notify1"), test_notify1);
|
||||
g_test_add_func(TEST_("notify2"), test_notify2);
|
||||
g_test_add_func(TEST_("already_there"), test_already_there);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 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,10 +74,12 @@ test_null(
|
||||
gbinder_writer_append_string16(&writer, NULL);
|
||||
gbinder_writer_append_string16_len(NULL, NULL, 0);
|
||||
gbinder_writer_append_string16_len(&writer, NULL, 0);
|
||||
gbinder_writer_append_string16_utf16(NULL, NULL, 0);
|
||||
gbinder_writer_append_bool(NULL, FALSE);
|
||||
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 +92,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 +205,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 +343,136 @@ test_string16(
|
||||
gbinder_local_request_unref(req);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* utf16
|
||||
*==========================================================================*/
|
||||
|
||||
typedef struct test_utf16_data {
|
||||
const char* name;
|
||||
const gunichar2* in;
|
||||
gssize in_len;
|
||||
const guint8* out;
|
||||
gssize out_len;
|
||||
} TestUtf16Data;
|
||||
|
||||
static const guint8 utf16_tests_data_null[] = {
|
||||
TEST_INT32_BYTES(-1)
|
||||
};
|
||||
|
||||
static const guint8 utf16_tests_data_empty[] = {
|
||||
TEST_INT32_BYTES(0),
|
||||
0x00, 0x00, 0xff, 0xff
|
||||
};
|
||||
|
||||
static const guint8 utf16_tests_data_x[] = {
|
||||
TEST_INT32_BYTES(1),
|
||||
TEST_INT16_BYTES('x'), 0x00, 0x00
|
||||
};
|
||||
|
||||
static const guint8 utf16_tests_data_xy[] = {
|
||||
TEST_INT32_BYTES(2),
|
||||
TEST_INT16_BYTES('x'), TEST_INT16_BYTES('y'),
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const gunichar2 utf16_tests_input_empty[] = { 0 };
|
||||
static const gunichar2 utf16_tests_input_x[] = { 'x', 0 };
|
||||
static const gunichar2 utf16_tests_input_xy[] = { 'x', 'y', 0 };
|
||||
|
||||
static const TestUtf16Data test_utf16_tests[] = {
|
||||
{ "null", NULL, -1,
|
||||
TEST_ARRAY_AND_SIZE(utf16_tests_data_null) },
|
||||
{ "empty", utf16_tests_input_empty, -1,
|
||||
TEST_ARRAY_AND_SIZE(utf16_tests_data_empty) },
|
||||
{ "1", utf16_tests_input_x, -1,
|
||||
TEST_ARRAY_AND_SIZE(utf16_tests_data_x) },
|
||||
{ "2", utf16_tests_input_xy, 1,
|
||||
TEST_ARRAY_AND_SIZE(utf16_tests_data_x) },
|
||||
{ "3", utf16_tests_input_xy, -1,
|
||||
TEST_ARRAY_AND_SIZE(utf16_tests_data_xy) }
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
test_utf16(
|
||||
gconstpointer test_data)
|
||||
{
|
||||
const TestUtf16Data* test = test_data;
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
gbinder_local_request_init_writer(req, &writer);
|
||||
gbinder_writer_append_string16_utf16(&writer, test->in, test->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 == test->out_len);
|
||||
g_assert(!memcmp(data->bytes->data, test->out, test->out_len));
|
||||
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(GBinderHidlVec) },
|
||||
{ "32/2x1", &gbinder_io_32, "xy", 2, 1,
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_32),
|
||||
sizeof(GBinderHidlVec) + 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(GBinderHidlVec) },
|
||||
{ "64/2x2", &gbinder_io_64, "xxyy", 2, 2,
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_64),
|
||||
sizeof(GBinderHidlVec) + 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
|
||||
*==========================================================================*/
|
||||
@@ -361,15 +495,17 @@ static guint test_hidl_string_offsets_64[] =
|
||||
|
||||
static const TestHidlStringData test_hidl_string_tests[] = {
|
||||
{ "32/null", &gbinder_io_32, NULL,
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_offsets_0), sizeof(HidlString) },
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_offsets_0),
|
||||
sizeof(GBinderHidlString) },
|
||||
{ "32/xxx", &gbinder_io_32, "xxx",
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_offsets_32),
|
||||
sizeof(HidlString) + 8 /* string data aligned at 8 bytes boundary */ },
|
||||
sizeof(GBinderHidlString) + 8 /* string data aligned at 8 bytes */ },
|
||||
{ "64/null", &gbinder_io_64, NULL,
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_offsets_0), sizeof(HidlString) },
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_offsets_0),
|
||||
sizeof(GBinderHidlString) },
|
||||
{ "64/xxxxxxx", &gbinder_io_64, "xxxxxxx",
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_offsets_64),
|
||||
sizeof(HidlString) + 8 /* string data aligned at 8 bytes boundary */ }
|
||||
sizeof(GBinderHidlString) + 8 /* string data aligned at 8 bytes */ }
|
||||
};
|
||||
|
||||
static
|
||||
@@ -417,8 +553,9 @@ test_hidl_string2(
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(offsets->data[1] == BUFFER_OBJECT_SIZE_32);
|
||||
g_assert(offsets->data[2] == 2*BUFFER_OBJECT_SIZE_32);
|
||||
/* 2 HidlStrings + "foo" aligned at 8 bytes boundary */
|
||||
g_assert(gbinder_output_data_buffers_size(data) == 2*sizeof(HidlString)+8);
|
||||
/* 2 GBinderHidlStrings + "foo" aligned at 8 bytes boundary */
|
||||
g_assert(gbinder_output_data_buffers_size(data) ==
|
||||
(2 * sizeof(GBinderHidlString) + 8));
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
}
|
||||
@@ -449,18 +586,18 @@ static guint test_hidl_string_vec_offsets_1_64[] =
|
||||
static const TestHidlStringVecData test_hidl_string_vec_tests[] = {
|
||||
{ "32/null", &gbinder_io_32, NULL, -1,
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_vec_offsets_empty),
|
||||
sizeof(HidlVec) },
|
||||
sizeof(GBinderHidlVec) },
|
||||
{ "32/1", &gbinder_io_32,
|
||||
(const char**)TEST_ARRAY_AND_COUNT(test_hidl_string_vec_data_1),
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_vec_offsets_1_32),
|
||||
sizeof(HidlVec) + sizeof(HidlString) + 8 },
|
||||
sizeof(GBinderHidlVec) + sizeof(GBinderHidlString) + 8 },
|
||||
{ "64/null", &gbinder_io_64, NULL, -1,
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_vec_offsets_empty),
|
||||
sizeof(HidlVec) },
|
||||
sizeof(GBinderHidlVec) },
|
||||
{ "64/1", &gbinder_io_64,
|
||||
(const char**)TEST_ARRAY_AND_COUNT(test_hidl_string_vec_data_1),
|
||||
TEST_ARRAY_AND_COUNT(test_hidl_string_vec_offsets_1_64),
|
||||
sizeof(HidlVec) + sizeof(HidlString) + 8 },
|
||||
sizeof(GBinderHidlVec) + sizeof(GBinderHidlString) + 8 },
|
||||
};
|
||||
|
||||
static
|
||||
@@ -621,38 +758,107 @@ 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
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/writer/"
|
||||
#define TEST_(t) TEST_PREFIX t
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "int32", test_int32);
|
||||
g_test_add_func(TEST_PREFIX "int64", test_int64);
|
||||
g_test_add_func(TEST_PREFIX "float", test_float);
|
||||
g_test_add_func(TEST_PREFIX "double", test_double);
|
||||
g_test_add_func(TEST_PREFIX "bool", test_bool);
|
||||
g_test_add_func(TEST_PREFIX "bytes", test_bytes);
|
||||
g_test_add_func(TEST_PREFIX "string8", test_string8);
|
||||
g_test_add_func(TEST_("null"), test_null);
|
||||
g_test_add_func(TEST_("int32"), test_int32);
|
||||
g_test_add_func(TEST_("int64"), test_int64);
|
||||
g_test_add_func(TEST_("float"), test_float);
|
||||
g_test_add_func(TEST_("double"), test_double);
|
||||
g_test_add_func(TEST_("bool"), test_bool);
|
||||
g_test_add_func(TEST_("bytes"), test_bytes);
|
||||
g_test_add_func(TEST_("string8"), test_string8);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(test_string16_tests); i++) {
|
||||
const TestString16Data* test = test_string16_tests + i;
|
||||
char* path = g_strconcat(TEST_PREFIX "string16/", test->name, NULL);
|
||||
char* path = g_strconcat(TEST_("string16/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_string16);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
g_test_add_func(TEST_PREFIX "hidl_string/2strings", test_hidl_string2);
|
||||
for (i = 0; i < G_N_ELEMENTS(test_utf16_tests); i++) {
|
||||
const TestUtf16Data* test = test_utf16_tests + i;
|
||||
char* path = g_strconcat(TEST_("utf16/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_utf16);
|
||||
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_("hidl_vec/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_hidl_vec);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
g_test_add_func(TEST_("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;
|
||||
char* path = g_strconcat(TEST_PREFIX "hidl_string/", test->name, NULL);
|
||||
char* path = g_strconcat(TEST_("hidl_string/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_hidl_string);
|
||||
g_free(path);
|
||||
@@ -660,17 +866,17 @@ int main(int argc, char* argv[])
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(test_hidl_string_vec_tests); i++) {
|
||||
const TestHidlStringVecData* test = test_hidl_string_vec_tests + i;
|
||||
char* path = g_strconcat(TEST_PREFIX "hidl_string_vec/",
|
||||
test->name, NULL);
|
||||
char* path = g_strconcat(TEST_("hidl_string_vec/"), test->name, NULL);
|
||||
|
||||
g_test_add_data_func(path, test, test_hidl_string_vec);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
g_test_add_func(TEST_PREFIX "buffer", test_buffer);
|
||||
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_("buffer"), test_buffer);
|
||||
g_test_add_func(TEST_("parent"), test_parent);
|
||||
g_test_add_func(TEST_("local_object"), test_local_object);
|
||||
g_test_add_func(TEST_("remote_object"), test_remote_object);
|
||||
g_test_add_func(TEST_("byte_array"), test_byte_array);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user