[-]
[+]
|
Changed |
_service:tar_git:libgbinder.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder.spec
^
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -2,5 +2,6 @@
<service name="tar_git">
<param name="url">https://github.com/mer-hybris/libgbinder.git</param>
<param name="branch">master</param>
+ <param name="revision">d6e131eb6e516da8c9f1a28c26ef7c40e0ae4644</param>
</service>
</services>
\ No newline at end of file
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/AUTHORS
^
|
@@ -2,3 +2,4 @@
Matti Lehtimäki <matti.lehtimaki@gmail.com>
Franz-Josef Haider <franz.haider@jolla.com>
Juho Hämäläinen <juho.hamalainen@jolla.com>
+Andrew Branson <andrew.branson@jolla.com>
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/Makefile
^
|
@@ -24,7 +24,7 @@
VERSION_MAJOR = 1
VERSION_MINOR = 0
-VERSION_RELEASE = 12
+VERSION_RELEASE = 21
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
@@ -62,6 +62,7 @@
gbinder_remote_reply.c \
gbinder_remote_request.c \
gbinder_rpc_protocol.c \
+ gbinder_servicepoll.c \
gbinder_writer.c
SRC += \
@@ -247,7 +248,7 @@
$(AR) rc $@ $?
ranlib $@
-$(PKGCONFIG): $(LIB_NAME).pc.in
+$(PKGCONFIG): $(LIB_NAME).pc.in Makefile
sed -e 's/\[version\]/'$(PCVERSION)/g $< > $@
#
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/debian/changelog
^
|
@@ -1,3 +1,63 @@
+libgbinder (1.0.21) unstable; urgency=low
+
+ * Added API to verwrite prefix length
+
+ -- Slava Monich <slava.monich@jolla.com> Tue, 18 Dec 2018 14:05:14 +0200
+
+libgbinder (1.0.20) unstable; urgency=low
+
+ * Added API to block incoming requests
+
+ -- Slava Monich <slava.monich@jolla.com> Mon, 17 Dec 2018 16:06:43 +0200
+
+libgbinder (1.0.19) unstable; urgency=low
+
+ * Added GBinderWriter memory allocation and cleanup API
+
+ -- Slava Monich <slava.monich@jolla.com> Fri, 14 Dec 2018 16:27:51 +0200
+
+libgbinder (1.0.18) unstable; urgency=low
+
+ * Implemented support for file descritors
+ * Allow GBinderClient without RPC header
+ * Added binder-dump test
+
+ -- Slava Monich <slava.monich@jolla.com> Mon, 10 Dec 2018 13:17:22 +0200
+
+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
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/debian/control
^
|
@@ -2,13 +2,13 @@
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
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/include/gbinder_reader.h
^
|
@@ -53,7 +53,7 @@
gboolean
gbinder_reader_at_end(
- GBinderReader* reader);
+ const GBinderReader* reader);
gboolean
gbinder_reader_read_byte(
@@ -95,6 +95,15 @@
GBinderReader* reader,
gdouble* value);
+int
+gbinder_reader_read_fd(
+ GBinderReader* reader); /* Since 1.0.18 */
+
+int
+gbinder_reader_read_dup_fd(
+ GBinderReader* reader) /* Since 1.0.18 */
+ G_GNUC_WARN_UNUSED_RESULT;
+
gboolean
gbinder_reader_read_nullable_object(
GBinderReader* reader,
@@ -166,6 +175,12 @@
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);
@@ -176,11 +191,16 @@
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
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/include/gbinder_remote_request.h
^
|
@@ -67,6 +67,16 @@
GBinderRemoteRequest* req) /* since 1.0.6 */
G_GNUC_WARN_UNUSED_RESULT;
+void
+gbinder_remote_request_block(
+ GBinderRemoteRequest* req); /* Since 1.0.20 */
+
+void
+gbinder_remote_request_complete(
+ GBinderRemoteRequest* req,
+ GBinderLocalReply* reply,
+ int status); /* Since 1.0.20 */
+
/* Convenience function to decode requests with just one data item */
gboolean
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/include/gbinder_servicemanager.h
^
|
@@ -13,9 +13,9 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Jolla Ltd nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -61,6 +61,13 @@
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 @@
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 */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/include/gbinder_types.h
^
|
@@ -72,6 +72,30 @@
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.
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/include/gbinder_writer.h
^
|
@@ -87,6 +87,12 @@
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,
const char* str);
@@ -108,6 +114,21 @@
const void* data,
gsize size);
+void
+gbinder_writer_append_fd(
+ GBinderWriter* writer,
+ int fd); /* Since 1.0.18 */
+
+gsize
+gbinder_writer_bytes_written(
+ GBinderWriter* writer); /* since 1.0.21 */
+
+void
+gbinder_writer_overwrite_int32(
+ GBinderWriter* writer,
+ gsize offset,
+ gint32 value); /* since 1.0.21 */
+
guint
gbinder_writer_append_buffer_object_with_parent(
GBinderWriter* writer,
@@ -151,10 +172,38 @@
void
gbinder_writer_append_byte_array(
- GBinderWriter* self,
+ GBinderWriter* writer,
const void* byte_array,
gint32 len); /* since 1.0.12 */
+void*
+gbinder_writer_malloc(
+ GBinderWriter* writer,
+ gsize size); /* since 1.0.19 */
+
+void*
+gbinder_writer_malloc0(
+ GBinderWriter* writer,
+ gsize size); /* since 1.0.19 */
+
+#define gbinder_writer_new(writer,type) \
+ ((type*) gbinder_writer_malloc(writer, sizeof(type)))
+
+#define gbinder_writer_new0(writer,type) \
+ ((type*) gbinder_writer_malloc0(writer, sizeof(type)))
+
+void*
+gbinder_writer_memdup(
+ GBinderWriter* writer,
+ const void* buf,
+ gsize size); /* since 1.0.19 */
+
+void
+gbinder_writer_add_cleanup(
+ GBinderWriter* writer,
+ GDestroyNotify destroy,
+ gpointer data); /* since 1.0.19 */
+
G_END_DECLS
#endif /* GBINDER_WRITER_H */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_buffer.c
^
|
@@ -36,54 +36,62 @@
#include <gutil_macros.h>
-struct gbinder_buffer_memory {
+struct gbinder_buffer_contents {
gint refcount;
void* buffer;
gsize size;
+ void** objects;
GBinderDriver* driver;
};
typedef struct gbinder_buffer_priv {
GBinderBuffer pub;
- GBinderBufferMemory* memory;
+ GBinderBufferContents* contents;
} GBinderBufferPriv;
static inline GBinderBufferPriv* gbinder_buffer_cast(GBinderBuffer* buf)
{ return G_CAST(buf, GBinderBufferPriv, pub); }
/*==========================================================================*
- * GBinderBufferMemory
+ * GBinderBufferContents
*==========================================================================*/
static
-GBinderBufferMemory*
-gbinder_buffer_memory_new(
+GBinderBufferContents*
+gbinder_buffer_contents_new(
GBinderDriver* driver,
void* buffer,
- gsize size)
+ gsize size,
+ void** objects)
{
- GBinderBufferMemory* self = g_slice_new0(GBinderBufferMemory);
+ GBinderBufferContents* self = g_slice_new0(GBinderBufferContents);
g_atomic_int_set(&self->refcount, 1);
self->buffer = buffer;
self->size = size;
+ self->objects = objects;
self->driver = gbinder_driver_ref(driver);
return self;
}
static
void
-gbinder_buffer_memory_free(
- GBinderBufferMemory* self)
+gbinder_buffer_contents_free(
+ GBinderBufferContents* self)
{
+ if (self->objects) {
+ gbinder_driver_close_fds(self->driver, self->objects,
+ ((guint8*)self->buffer) + self->size);
+ g_free(self->objects);
+ }
gbinder_driver_free_buffer(self->driver, self->buffer);
gbinder_driver_unref(self->driver);
- g_slice_free(GBinderBufferMemory, self);
+ g_slice_free(GBinderBufferContents, self);
}
-GBinderBufferMemory*
-gbinder_buffer_memory_ref(
- GBinderBufferMemory* self)
+GBinderBufferContents*
+gbinder_buffer_contents_ref(
+ GBinderBufferContents* self)
{
if (G_LIKELY(self)) {
GASSERT(self->refcount > 0);
@@ -93,13 +101,13 @@
}
void
-gbinder_buffer_memory_unref(
- GBinderBufferMemory* self)
+gbinder_buffer_contents_unref(
+ GBinderBufferContents* self)
{
if (G_LIKELY(self)) {
GASSERT(self->refcount > 0);
if (g_atomic_int_dec_and_test(&self->refcount)) {
- gbinder_buffer_memory_free(self);
+ gbinder_buffer_contents_free(self);
}
}
}
@@ -111,14 +119,14 @@
static
GBinderBuffer*
gbinder_buffer_alloc(
- GBinderBufferMemory* memory,
+ GBinderBufferContents* contents,
void* data,
gsize size)
{
GBinderBufferPriv* priv = g_slice_new0(GBinderBufferPriv);
GBinderBuffer* self = &priv->pub;
- priv->memory = memory;
+ priv->contents = contents;
self->data = data;
self->size = size;
return self;
@@ -131,7 +139,7 @@
if (G_LIKELY(self)) {
GBinderBufferPriv* priv = gbinder_buffer_cast(self);
- gbinder_buffer_memory_unref(priv->memory);
+ gbinder_buffer_contents_unref(priv->contents);
g_slice_free(GBinderBufferPriv, priv);
}
}
@@ -140,10 +148,12 @@
gbinder_buffer_new(
GBinderDriver* driver,
void* data,
- gsize size)
+ gsize size,
+ void** objects)
{
return gbinder_buffer_alloc((driver && data) ?
- gbinder_buffer_memory_new(driver, data, size) : NULL, data, size);
+ gbinder_buffer_contents_new(driver, data, size, objects) : NULL,
+ data, size);
}
GBinderBuffer*
@@ -153,7 +163,7 @@
gsize size)
{
return gbinder_buffer_alloc(parent ?
- gbinder_buffer_memory_ref(gbinder_buffer_memory(parent)) : NULL,
+ gbinder_buffer_contents_ref(gbinder_buffer_contents(parent)) : NULL,
data, size);
}
@@ -162,13 +172,13 @@
GBinderBuffer* self,
gsize* size)
{
- GBinderBufferMemory* memory = gbinder_buffer_memory(self);
+ GBinderBufferContents* contents = gbinder_buffer_contents(self);
- if (G_LIKELY(memory)) {
+ if (G_LIKELY(contents)) {
if (size) {
- *size = memory->size;
+ *size = contents->size;
}
- return memory->buffer;
+ return contents->buffer;
} else {
if (size) {
*size = 0;
@@ -184,8 +194,8 @@
if (G_LIKELY(self)) {
GBinderBufferPriv* priv = gbinder_buffer_cast(self);
- if (priv->memory) {
- return priv->memory->driver;
+ if (priv->contents) {
+ return priv->contents->driver;
}
}
return NULL;
@@ -200,11 +210,25 @@
return driver ? gbinder_driver_io(driver) : NULL;
}
-GBinderBufferMemory*
-gbinder_buffer_memory(
+void**
+gbinder_buffer_objects(
+ GBinderBuffer* self)
+{
+ if (G_LIKELY(self)) {
+ GBinderBufferPriv* priv = gbinder_buffer_cast(self);
+
+ if (priv->contents) {
+ return priv->contents->objects;
+ }
+ }
+ return NULL;
+}
+
+GBinderBufferContents*
+gbinder_buffer_contents(
GBinderBuffer* self)
{
- return G_LIKELY(self) ? gbinder_buffer_cast(self)->memory : NULL;
+ return G_LIKELY(self) ? gbinder_buffer_cast(self)->contents : NULL;
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_buffer_p.h
^
|
@@ -41,7 +41,8 @@
gbinder_buffer_new(
GBinderDriver* driver,
void* data,
- gsize size);
+ gsize size,
+ void** objects);
GBinderBuffer*
gbinder_buffer_new_with_parent(
@@ -53,8 +54,8 @@
gbinder_buffer_driver(
GBinderBuffer* buf);
-GBinderBufferMemory*
-gbinder_buffer_memory(
+GBinderBufferContents*
+gbinder_buffer_contents(
GBinderBuffer* buf);
gconstpointer
@@ -66,13 +67,17 @@
gbinder_buffer_io(
GBinderBuffer* buf);
-GBinderBufferMemory*
-gbinder_buffer_memory_ref(
- GBinderBufferMemory* mem);
+void**
+gbinder_buffer_objects(
+ GBinderBuffer* buffer);
+
+GBinderBufferContents*
+gbinder_buffer_contents_ref(
+ GBinderBufferContents* contents);
void
-gbinder_buffer_memory_unref(
- GBinderBufferMemory* mem);
+gbinder_buffer_contents_unref(
+ GBinderBufferContents* contents);
#endif /* GBINDER_BUFFER_PRIVATE_H */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_cleanup.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
@@ -49,22 +49,39 @@
#define ELEMENT_SIZE (sizeof(GBinderCleanupItem))
static
+void
+gbinder_cleanup_destroy_func(
+ gpointer data)
+{
+ GBinderCleanupItem* item = data;
+
+ item->destroy(item->pointer);
+}
+
+static
GBinderCleanup*
gbinder_cleanup_new()
{
- return (GBinderCleanup*)g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 0);
+ GArray* array = g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 0);
+
+ g_array_set_clear_func(array, gbinder_cleanup_destroy_func);
+ return (GBinderCleanup*)array;
}
void
-gbinder_cleanup_free(
+gbinder_cleanup_reset(
GBinderCleanup* self)
{
if (G_LIKELY(self)) {
- guint i;
+ g_array_set_size((GArray*)self, 0);
+ }
+}
- for (i = 0; i < self->count; i++) {
- self->items[i].destroy(self->items[i].pointer);
- }
+void
+gbinder_cleanup_free(
+ GBinderCleanup* self)
+{
+ if (G_LIKELY(self)) {
g_array_free((GArray*)self, TRUE);
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_cleanup.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
@@ -39,6 +39,10 @@
gbinder_cleanup_free(
GBinderCleanup* cleanup);
+void
+gbinder_cleanup_reset(
+ GBinderCleanup* cleanup);
+
GBinderCleanup*
gbinder_cleanup_add(
GBinderCleanup* cleanup,
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_client.c
^
|
@@ -75,7 +75,9 @@
gbinder_remote_object_unref(self->remote);
gbinder_local_request_unref(priv->basic_req);
g_free(priv->iface);
- g_bytes_unref(priv->rpc_header);
+ if (priv->rpc_header) {
+ g_bytes_unref(priv->rpc_header);
+ }
g_slice_free(GBinderClientPriv, priv);
}
@@ -117,13 +119,13 @@
GBinderRemoteObject* remote,
const char* iface)
{
- if (G_LIKELY(remote) && G_LIKELY(iface)) {
+ if (G_LIKELY(remote)) {
GBinderClientPriv* priv = g_slice_new0(GBinderClientPriv);
GBinderClient* self = &priv->pub;
- GBinderIpc* ipc = remote->ipc;
- GBinderOutputData* hdr;
+ GBinderDriver* driver = remote->ipc->driver;
g_atomic_int_set(&priv->refcount, 1);
+ self->remote = gbinder_remote_object_ref(remote);
/*
* Generate basic request (without additional parameters) and pull
@@ -131,12 +133,17 @@
* transactions which has no additional parameters. The header data
* are needed for building non-trivial requests.
*/
- priv->basic_req = gbinder_driver_local_request_new(ipc->driver, iface);
- hdr = gbinder_local_request_data(priv->basic_req);
- priv->rpc_header = g_bytes_new(hdr->bytes->data, hdr->bytes->len);
+ if (iface) {
+ GBinderOutputData* hdr;
- self->remote = gbinder_remote_object_ref(remote);
- self->iface = priv->iface = g_strdup(iface);
+ priv->basic_req = gbinder_driver_local_request_new(driver, iface);
+ hdr = gbinder_local_request_data(priv->basic_req);
+ priv->rpc_header = g_bytes_new(hdr->bytes->data, hdr->bytes->len);
+ self->iface = priv->iface = g_strdup(iface);
+ } else {
+ priv->basic_req = gbinder_local_request_new
+ (gbinder_driver_io(driver), NULL);
+ }
return self;
}
return NULL;
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_defaultservicemanager.c
^
|
@@ -32,6 +32,7 @@
#include "gbinder_servicemanager_p.h"
#include "gbinder_rpc_protocol.h"
+#include "gbinder_servicepoll.h"
#include "gbinder_log.h"
#include <gbinder_client.h>
@@ -43,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,
@@ -66,7 +85,76 @@
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
@@ -152,10 +240,60 @@
}
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
@@ -171,6 +309,11 @@
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;
}
/*
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_driver.c
^
|
@@ -439,11 +439,10 @@
/* Transfer data ownership to the request */
if (tx.data && tx.size) {
gbinder_driver_verbose_dump(' ', (uintptr_t)tx.data, tx.size);
- gbinder_remote_request_set_data(req,
- gbinder_buffer_new(self, tx.data, tx.size),
- tx.objects);
+ gbinder_remote_request_set_data(req, tx.code,
+ gbinder_buffer_new(self, tx.data, tx.size, tx.objects));
} else {
- g_free(tx.objects);
+ GASSERT(!tx.objects);
gbinder_driver_free_buffer(self, tx.data);
}
@@ -637,10 +636,9 @@
if (tx.data && tx.size) {
gbinder_driver_verbose_dump(' ', (uintptr_t)tx.data, tx.size);
gbinder_remote_reply_set_data(reply,
- gbinder_buffer_new(self, tx.data, tx.size),
- tx.objects);
+ gbinder_buffer_new(self, tx.data, tx.size, tx.objects));
} else {
- g_free(tx.objects);
+ GASSERT(!tx.objects);
gbinder_driver_free_buffer(self, tx.data);
}
@@ -864,6 +862,32 @@
}
void
+gbinder_driver_close_fds(
+ GBinderDriver* self,
+ void** objects,
+ const void* end)
+{
+ const GBinderIo* io = self->io;
+ void** ptr;
+
+ /* Caller checks objects for NULL */
+ for (ptr = objects; *ptr; ptr++) {
+ void* obj = *ptr;
+
+ GASSERT(obj < end);
+ if (obj < end) {
+ int fd;
+
+ if (io->decode_fd_object(obj, (guint8*)end - (guint8*)obj, &fd)) {
+ if (close(fd) < 0) {
+ GWARN("Error closing fd %d: %s", fd, strerror(errno));
+ }
+ }
+ }
+ }
+}
+
+void
gbinder_driver_free_buffer(
GBinderDriver* self,
void* buffer)
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_driver.h
^
|
@@ -98,6 +98,12 @@
guint32 handle);
void
+gbinder_driver_close_fds(
+ GBinderDriver* self,
+ void** objects,
+ const void* end);
+
+void
gbinder_driver_free_buffer(
GBinderDriver* driver,
void* buffer);
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_hwservicemanager.c
^
|
@@ -35,20 +35,36 @@
#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,
@@ -60,9 +76,76 @@
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(
@@ -75,7 +158,7 @@
static
char**
gbinder_hwservicemanager_list(
- GBinderHwServiceManager* self)
+ GBinderServiceManager* self)
{
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
GBinderRemoteReply* reply = gbinder_client_transact_sync_reply
@@ -111,6 +194,7 @@
/* 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);
@@ -172,9 +256,121 @@
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);
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_io.c
^
|
@@ -153,6 +153,21 @@
return sizeof(*dest);
}
+static
+guint
+GBINDER_IO_FN(encode_fd_object)(
+ void* out,
+ int fd)
+{
+ struct flat_binder_object* dest = out;
+
+ memset(dest, 0, sizeof(*dest));
+ dest->hdr.type = BINDER_TYPE_FD;
+ dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ dest->handle = fd;
+ return sizeof(*dest);
+}
+
/* Encodes binder_buffer_object */
static
guint
@@ -411,6 +426,28 @@
return 0;
}
+static
+guint
+GBINDER_IO_FN(decode_fd_object)(
+ const void* data,
+ gsize size,
+ int* fd)
+{
+ const struct flat_binder_object* obj = data;
+
+ if (size >= sizeof(*obj)) {
+ switch (obj->hdr.type) {
+ case BINDER_TYPE_FD:
+ if (fd) *fd = obj->handle;
+ return sizeof(*obj);
+ default:
+ break;
+ }
+ }
+ if (fd) *fd = -1;
+ return 0;
+}
+
const GBinderIo GBINDER_IO_PREFIX = {
.version = BINDER_CURRENT_PROTOCOL_VERSION,
.pointer_size = GBINDER_POINTER_SIZE,
@@ -466,6 +503,7 @@
.encode_pointer = GBINDER_IO_FN(encode_pointer),
.encode_local_object = GBINDER_IO_FN(encode_local_object),
.encode_remote_object = GBINDER_IO_FN(encode_remote_object),
+ .encode_fd_object = GBINDER_IO_FN(encode_fd_object),
.encode_buffer_object = GBINDER_IO_FN(encode_buffer_object),
.encode_death_notification = GBINDER_IO_FN(encode_death_notification),
.encode_transaction = GBINDER_IO_FN(encode_transaction),
@@ -478,6 +516,7 @@
.decode_binder_ptr_cookie = GBINDER_IO_FN(decode_binder_ptr_cookie),
.decode_binder_object = GBINDER_IO_FN(decode_binder_object),
.decode_buffer_object = GBINDER_IO_FN(decode_buffer_object),
+ .decode_fd_object = GBINDER_IO_FN(decode_fd_object),
/* ioctl wrappers */
.write_read = GBINDER_IO_FN(write_read)
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_io.h
^
|
@@ -131,6 +131,7 @@
#define GBINDER_MAX_BINDER_OBJECT_SIZE (24)
guint (*encode_local_object)(void* out, GBinderLocalObject* obj);
guint (*encode_remote_object)(void* out, GBinderRemoteObject* obj);
+ guint (*encode_fd_object)(void* out, int fd);
/* Encode binder_buffer_object */
#define GBINDER_MAX_BUFFER_OBJECT_SIZE (40)
@@ -167,6 +168,7 @@
GBinderObjectRegistry* reg, GBinderRemoteObject** obj);
guint (*decode_buffer_object)(GBinderBuffer* buf, gsize offset,
GBinderBuffer** out);
+ guint (*decode_fd_object)(const void* data, gsize size, int* fd);
/* ioctl wrappers */
int (*write_read)(int fd, GBinderIoBuf* write, GBinderIoBuf* read);
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_ipc.c
^
|
@@ -68,9 +68,9 @@
GMutex local_objects_mutex;
GHashTable* local_objects;
- /* We may need more loopers... But let's start with just one */
GMutex looper_mutex;
- GBinderIpcLooper* looper;
+ GBinderIpcLooper* primary_loopers;
+ GBinderIpcLooper* blocked_loopers;
};
typedef GObjectClass GBinderIpcClass;
@@ -88,6 +88,7 @@
#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:
@@ -99,7 +100,7 @@
* When the main thread receives GBinderIpcLooperTx:
*
* 1. Lets the object to process it and produce the response (GBinderOutput).
- * 2. Writes one byte to the sending end of the tx pipe.
+ * 2. Writes one byte (TX_DONE) to the sending end of the tx pipe.
* 3. Unreferences GBinderIpcLooperTx
*
* When tx pipe wakes up the looper:
@@ -110,11 +111,26 @@
* Note that GBinderIpcLooperTx can be deallocated on either looper or
* main thread, depending on whether looper gives up on the transaction
* before it gets processed.
+ *
+ * When transaction is blocked by gbinder_remote_request_block() call, it
+ * gets slightly more complicated. Then the main thread writes TX_BLOCKED
+ * to the pipe (rather than TX_DONE) and then looper thread spawn another
+ * looper and keeps waiting for TX_DONE.
*/
#define TX_DONE (0x2a)
+#define TX_BLOCKED (0x3b)
+
+typedef enum gbinder_ipc_looper_tx_state {
+ GBINDER_IPC_LOOPER_TX_SCHEDULED,
+ GBINDER_IPC_LOOPER_TX_PROCESSING,
+ GBINDER_IPC_LOOPER_TX_PROCESSED,
+ GBINDER_IPC_LOOPER_TX_BLOCKING,
+ GBINDER_IPC_LOOPER_TX_BLOCKED,
+ GBINDER_IPC_LOOPER_TX_COMPLETE
+} GBINDER_IPC_LOOPER_TX_STATE;
-typedef struct gbinder_ipc_looper_tx {
+struct gbinder_ipc_looper_tx {
/* Reference count */
gint refcount;
/* These are filled by the looper: */
@@ -124,16 +140,23 @@
GBinderLocalObject* obj;
GBinderRemoteRequest* req;
/* And these by the main thread processing the transaction: */
+ GBINDER_IPC_LOOPER_TX_STATE state;
GBinderLocalReply* reply;
int status;
-} GBinderIpcLooperTx;
+} /* GBinderIpcLooperTx */;
struct gbinder_ipc_looper {
gint refcount;
+ GBinderIpcLooper* next;
+ char* name;
GBinderHandler handler;
GBinderDriver* driver;
GBinderIpc* ipc; /* Not a reference! */
GThread* thread;
+ GMutex mutex;
+ GCond start_cond;
+ gint exit;
+ gint started;
int pipefd[2];
int txfd[2];
};
@@ -174,6 +197,11 @@
GBINDER_INLINE_FUNC const char* gbinder_ipc_name(GBinderIpc* self)
{ return gbinder_driver_dev(self->driver); }
+static
+GBinderIpcLooper*
+gbinder_ipc_looper_new(
+ GBinderIpc* ipc);
+
/*==========================================================================*
* GBinderIpcLooperTx
*==========================================================================*/
@@ -242,6 +270,91 @@
}
/*==========================================================================*
+ * State machine of transaction handling. All this is happening on the event
+ * thread and therefore doesn't need to be synchronized.
+ *
+ * SCHEDULED
+ * =========
+ * |
+ * PROCESSING
+ * ==========
+ * |
+ * --------------------- handler is called ---------------------------------
+ * |
+ * +---------------- request doesn't need to be blocked ----------+
+ * | |
+ * gbinder_remote_request_block() |
+ * | |
+ * BLOCKING -- gbinder_remote_request_complete() --> PROCESSED |
+ * ======== ========= |
+ * | | |
+ * --------------------- handler returns -----------------------------------
+ * | | |
+ * BLOCKED COMPLETE <-------+
+ * ======= ========
+ * ^
+ * ... |
+ * gbinder_remote_request_complete() is called later ----+
+ *==========================================================================*/
+
+void
+gbinder_remote_request_block(
+ GBinderRemoteRequest* req) /* Since 1.0.20 */
+{
+ if (G_LIKELY(req)) {
+ GBinderIpcLooperTx* tx = req->tx;
+
+ GASSERT(tx);
+ if (G_LIKELY(tx)) {
+ GASSERT(tx->state == GBINDER_IPC_LOOPER_TX_PROCESSING);
+ if (tx->state == GBINDER_IPC_LOOPER_TX_PROCESSING) {
+ tx->state = GBINDER_IPC_LOOPER_TX_BLOCKING;
+ }
+ }
+ }
+}
+
+void
+gbinder_remote_request_complete(
+ GBinderRemoteRequest* req,
+ GBinderLocalReply* reply,
+ int status) /* Since 1.0.20 */
+{
+ if (G_LIKELY(req)) {
+ GBinderIpcLooperTx* tx = req->tx;
+
+ GASSERT(tx);
+ if (G_LIKELY(tx)) {
+ const guint8 done = TX_DONE;
+
+ switch (tx->state) {
+ case GBINDER_IPC_LOOPER_TX_BLOCKING:
+ /* Called by the transaction handler */
+ tx->status = status;
+ tx->reply = gbinder_local_reply_ref(reply);
+ tx->state = GBINDER_IPC_LOOPER_TX_PROCESSED;
+ break;
+ case GBINDER_IPC_LOOPER_TX_BLOCKED:
+ /* Really asynchronous completion */
+ tx->status = status;
+ tx->reply = gbinder_local_reply_ref(reply);
+ tx->state = GBINDER_IPC_LOOPER_TX_COMPLETE;
+ /* Wake up the looper */
+ (void)write(tx->pipefd[1], &done, sizeof(done));
+ break;
+ default:
+ GWARN("Unexpected state %d in request completion", tx->state);
+ break;
+ }
+
+ /* Clear the transaction reference */
+ gbinder_ipc_looper_tx_unref(tx, FALSE);
+ req->tx = NULL;
+ }
+ }
+}
+
+/*==========================================================================*
* GBinderIpcLooper
*==========================================================================*/
@@ -251,11 +364,70 @@
gpointer data)
{
GBinderIpcLooperTx* tx = data;
- guint8 done = TX_DONE;
+ GBinderRemoteRequest* req = tx->req;
+ GBinderLocalReply* reply;
+ int status = GBINDER_STATUS_OK;
+ guint8 done;
+
+ /*
+ * Transaction reference for gbinder_remote_request_block()
+ * and gbinder_remote_request_complete().
+ */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_local_reply.c
^
|
@@ -95,14 +95,13 @@
GBinderLocalReply*
gbinder_local_reply_new_from_data(
- GBinderBuffer* buffer,
- void** objects)
+ GBinderBuffer* buffer)
{
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);
+ gbinder_writer_data_set_contents(&self->data, buffer);
}
return self;
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_local_reply_p.h
^
|
@@ -47,8 +47,7 @@
GBinderLocalReply*
gbinder_local_reply_new_from_data(
- GBinderBuffer* buffer,
- void** objects);
+ GBinderBuffer* buffer);
#endif /* GBINDER_LOCAL_REPLY_PRIVATE_H */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_local_request.c
^
|
@@ -44,7 +44,6 @@
gint refcount;
GBinderWriterData data;
GBinderOutputData out;
- GBinderBufferMemory* memory;
};
GBINDER_INLINE_FUNC
@@ -106,14 +105,13 @@
GBinderLocalRequest*
gbinder_local_request_new_from_data(
- GBinderBuffer* buffer,
- void** objects)
+ GBinderBuffer* buffer)
{
GBinderLocalRequest* self = gbinder_local_request_new
(gbinder_buffer_io(buffer), NULL);
if (self) {
- gbinder_writer_data_set_contents(&self->data, buffer, objects);
+ gbinder_writer_data_set_contents(&self->data, buffer);
}
return self;
}
@@ -128,7 +126,6 @@
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);
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_local_request_p.h
^
|
@@ -48,8 +48,7 @@
GBinderLocalRequest*
gbinder_local_request_new_from_data(
- GBinderBuffer* buffer,
- void** objects);
+ GBinderBuffer* buffer);
#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_reader.c
^
|
@@ -38,6 +38,9 @@
#include <gutil_macros.h>
+#include <errno.h>
+#include <fcntl.h>
+
typedef struct gbinder_reader_priv {
const guint8* start;
const guint8* end;
@@ -50,6 +53,8 @@
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 +86,9 @@
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;
}
@@ -229,16 +234,67 @@
}
}
+static
+inline
+gboolean
+gbinder_reader_can_read_object(
+ GBinderReaderPriv* p)
+{
+ const GBinderReaderData* data = p->data;
+
+ return data && data->reg &&
+ p->objects && p->objects[0] &&
+ p->ptr == p->objects[0];
+}
+
+int
+gbinder_reader_read_fd(
+ GBinderReader* reader) /* Since 1.0.18 */
+{
+ GBinderReaderPriv* p = gbinder_reader_cast(reader);
+
+ if (gbinder_reader_can_read_object(p)) {
+ int fd;
+ const guint eaten = p->data->reg->io->decode_fd_object(p->ptr,
+ gbinder_reader_bytes_remaining(reader), &fd);
+
+ if (eaten) {
+ GASSERT(fd >= 0);
+ p->ptr += eaten;
+ p->objects++;
+ return fd;
+ }
+ }
+ return -1;
+}
+
+int
+gbinder_reader_read_dup_fd(
+ GBinderReader* reader) /* Since 1.0.18 */
+{
+ const int fd = gbinder_reader_read_fd(reader);
+
+ if (fd >= 0) {
+ const int dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+
+ if (dupfd >= 0) {
+ return dupfd;
+ } else {
+ GWARN("Error dupping fd %d: %s", fd, strerror(errno));
+ }
+ }
+ return -1;
+}
+
gboolean
gbinder_reader_read_nullable_object(
GBinderReader* reader,
GBinderRemoteObject** out)
{
GBinderReaderPriv* p = gbinder_reader_cast(reader);
- const GBinderReaderData* data = p->data;
- if (data && data->reg && p->objects && p->objects[0] &&
- p->ptr == p->objects[0]) {
+ if (gbinder_reader_can_read_object(p)) {
+ const GBinderReaderData* data = p->data;
const guint eaten = data->reg->io->decode_binder_object(p->ptr,
gbinder_reader_bytes_remaining(reader), data->reg, out);
@@ -269,10 +325,9 @@
GBinderBuffer** out)
{
GBinderReaderPriv* p = gbinder_reader_cast(reader);
- const GBinderReaderData* data = p->data;
- if (data && data->reg && p->objects && p->objects[0] &&
- p->ptr == p->objects[0]) {
+ if (gbinder_reader_can_read_object(p)) {
+ const GBinderReaderData* data = p->data;
GBinderBuffer* buf = data->buffer;
const GBinderIo* io = data->reg->io;
const gsize offset = p->ptr - (guint8*)buf->data;
@@ -333,8 +388,8 @@
gsize out_count = 0, out_elemsize = 0;
const void* out = NULL;
- if (buf && buf->size == sizeof(HidlVec)) {
- const HidlVec* vec = buf->data;
+ if (buf && buf->size == sizeof(GBinderHidlVec)) {
+ const GBinderHidlVec* vec = buf->data;
const void* next = vec->data.ptr;
if (next) {
@@ -383,8 +438,8 @@
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 &&
@@ -405,8 +460,8 @@
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;
@@ -419,8 +474,9 @@
} 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;
@@ -428,7 +484,7 @@
/* 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) {
@@ -490,6 +546,24 @@
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);
if ((p->ptr + 4) <= p->end) {
@@ -502,15 +576,21 @@
if (out) {
*out = NULL;
}
+ if (out_len) {
+ *out_len = 0;
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_remote_reply.c
^
|
@@ -34,7 +34,7 @@
#include "gbinder_local_reply_p.h"
#include "gbinder_reader_p.h"
#include "gbinder_object_registry.h"
-#include "gbinder_buffer.h"
+#include "gbinder_buffer_p.h"
#include "gbinder_log.h"
#include <gutil_macros.h>
@@ -65,26 +65,22 @@
gbinder_object_registry_unref(data->reg);
gbinder_buffer_free(data->buffer);
- g_free(data->objects);
g_slice_free(GBinderRemoteReply, self);
}
void
gbinder_remote_reply_set_data(
GBinderRemoteReply* self,
- GBinderBuffer* buffer,
- void** objects)
+ GBinderBuffer* buffer)
{
if (G_LIKELY(self)) {
GBinderReaderData* data = &self->data;
- g_free(data->objects);
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
- data->objects = objects;
+ data->objects = gbinder_buffer_objects(buffer);
} else {
gbinder_buffer_free(buffer);
- g_free(objects);
}
}
@@ -125,7 +121,7 @@
if (G_LIKELY(self)) {
GBinderReaderData* d = &self->data;
- return gbinder_local_reply_new_from_data(d->buffer, d->objects);
+ return gbinder_local_reply_new_from_data(d->buffer);
}
return NULL;
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_remote_reply_p.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
@@ -44,8 +44,7 @@
void
gbinder_remote_reply_set_data(
GBinderRemoteReply* reply,
- GBinderBuffer* buffer,
- void** objects);
+ GBinderBuffer* buffer);
gboolean
gbinder_remote_reply_is_empty(
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_remote_request.c
^
|
@@ -35,12 +35,15 @@
#include "gbinder_rpc_protocol.h"
#include "gbinder_local_request_p.h"
#include "gbinder_object_registry.h"
-#include "gbinder_buffer.h"
+#include "gbinder_buffer_p.h"
#include "gbinder_log.h"
#include <gutil_macros.h>
-struct gbinder_remote_request {
+#include <errno.h>
+
+typedef struct gbinder_remote_request_priv {
+ GBinderRemoteRequest pub;
gint refcount;
pid_t pid;
uid_t euid;
@@ -49,7 +52,11 @@
char* iface2;
gsize header_size;
GBinderReaderData data;
-};
+} GBinderRemoteRequestPriv;
+
+GBINDER_INLINE_FUNC GBinderRemoteRequestPriv*
+gbinder_remote_request_cast(GBinderRemoteRequest* pub)
+ { return G_LIKELY(pub) ? G_CAST(pub,GBinderRemoteRequestPriv,pub) : NULL; }
GBinderRemoteRequest*
gbinder_remote_request_new(
@@ -58,7 +65,7 @@
pid_t pid,
uid_t euid)
{
- GBinderRemoteRequest* self = g_slice_new0(GBinderRemoteRequest);
+ GBinderRemoteRequestPriv* self = g_slice_new0(GBinderRemoteRequestPriv);
GBinderReaderData* data = &self->data;
g_atomic_int_set(&self->refcount, 1);
@@ -66,17 +73,19 @@
self->euid = euid;
self->protocol = protocol;
data->reg = gbinder_object_registry_ref(reg);
- return self;
+ return &self->pub;
}
GBinderLocalRequest*
gbinder_remote_request_copy_to_local(
- GBinderRemoteRequest* self)
+ GBinderRemoteRequest* req)
{
+ GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
+
if (G_LIKELY(self)) {
GBinderReaderData* d = &self->data;
- return gbinder_local_request_new_from_data(d->buffer, d->objects);
+ return gbinder_local_request_new_from_data(d->buffer);
}
return NULL;
}
@@ -84,22 +93,27 @@
static
void
gbinder_remote_request_free(
- GBinderRemoteRequest* self)
+ GBinderRemoteRequestPriv* self)
{
GBinderReaderData* data = &self->data;
+ GBinderRemoteRequest* req = &self->pub;
+ GASSERT(!req->tx);
+ if (req->tx) {
+ GWARN("Request is dropped without completing the transaction");
+ gbinder_remote_request_complete(req, NULL, -ECANCELED);
+ }
gbinder_object_registry_unref(data->reg);
gbinder_buffer_free(data->buffer);
- g_free(data->objects);
g_free(self->iface2);
- g_slice_free(GBinderRemoteRequest, self);
+ g_slice_free(GBinderRemoteRequestPriv, self);
}
static
inline
void
gbinder_remote_request_init_reader2(
- GBinderRemoteRequest* self,
+ GBinderRemoteRequestPriv* self,
GBinderReader* p)
{
/* The caller has already checked the request for NULL */
@@ -116,53 +130,64 @@
void
gbinder_remote_request_set_data(
- GBinderRemoteRequest* self,
- GBinderBuffer* buffer,
- void** objects)
+ GBinderRemoteRequest* req,
+ guint32 txcode,
+ GBinderBuffer* buffer)
{
+ GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
+
if (G_LIKELY(self)) {
GBinderReaderData* data = &self->data;
GBinderReader reader;
g_free(self->iface2);
- g_free(data->objects);
gbinder_buffer_free(data->buffer);
data->buffer = buffer;
- data->objects = objects;
+ data->objects = gbinder_buffer_objects(buffer);
/* Parse RPC header */
- self->header_size = 0;
gbinder_remote_request_init_reader2(self, &reader);
- self->iface = self->protocol->read_rpc_header(&reader, &self->iface2);
- self->header_size = gbinder_reader_bytes_read(&reader);
+ self->iface = self->protocol->read_rpc_header(&reader, txcode,
+ &self->iface2);
+ if (self->iface) {
+ self->header_size = gbinder_reader_bytes_read(&reader);
+ } else {
+ /* No RPC header */
+ self->header_size = 0;
+ }
} else {
gbinder_buffer_free(buffer);
- g_free(objects);
}
}
const char*
gbinder_remote_request_interface(
- GBinderRemoteRequest* self)
+ GBinderRemoteRequest* req)
{
+ GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
+
return G_LIKELY(self) ? self->iface : NULL;
}
GBinderRemoteRequest*
gbinder_remote_request_ref(
- GBinderRemoteRequest* self)
+ GBinderRemoteRequest* req)
{
+ GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
+
if (G_LIKELY(self)) {
GASSERT(self->refcount > 0);
g_atomic_int_inc(&self->refcount);
}
- return self;
+ return req;
}
void
gbinder_remote_request_unref(
- GBinderRemoteRequest* self)
+ GBinderRemoteRequest* req)
{
+ GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
+
if (G_LIKELY(self)) {
GASSERT(self->refcount > 0);
if (g_atomic_int_dec_and_test(&self->refcount)) {
@@ -173,9 +198,11 @@
void
gbinder_remote_request_init_reader(
- GBinderRemoteRequest* self,
+ GBinderRemoteRequest* req,
GBinderReader* reader)
{
+ GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
+
if (G_LIKELY(self)) {
gbinder_remote_request_init_reader2(self, reader);
} else {
@@ -185,15 +212,19 @@
pid_t
gbinder_remote_request_sender_pid(
- GBinderRemoteRequest* self)
+ GBinderRemoteRequest* req)
{
+ GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
+
return G_LIKELY(self) ? self->pid : (uid_t)(-1);
}
uid_t
gbinder_remote_request_sender_euid(
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_remote_request_p.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
@@ -37,6 +37,10 @@
#include "gbinder_types_p.h"
+struct gbinder_remote_request {
+ GBinderIpcLooperTx* tx;
+};
+
GBinderRemoteRequest*
gbinder_remote_request_new(
GBinderObjectRegistry* reg,
@@ -47,8 +51,8 @@
void
gbinder_remote_request_set_data(
GBinderRemoteRequest* request,
- GBinderBuffer* buffer,
- void** objects);
+ guint txcode,
+ GBinderBuffer* buffer);
#endif /* GBINDER_REMOTE_REQUEST_PRIVATE_H */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_rpc_protocol.c
^
|
@@ -69,9 +69,13 @@
const char*
gbinder_rpc_protocol_binder_read_rpc_header(
GBinderReader* reader,
+ guint32 txcode,
char** iface)
{
- if (gbinder_reader_read_int32(reader, NULL)) {
+ if (txcode > GBINDER_TRANSACTION(0,0,0)) {
+ /* Internal transaction e.g. GBINDER_DUMP_TRANSACTION etc. */
+ *iface = NULL;
+ } else if (gbinder_reader_read_int32(reader, NULL)) {
*iface = gbinder_reader_read_string16(reader);
} else {
*iface = NULL;
@@ -99,6 +103,7 @@
const char*
gbinder_rpc_protocol_hwbinder_read_rpc_header(
GBinderReader* reader,
+ guint32 txcode,
char** iface)
{
*iface = NULL;
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_rpc_protocol.h
^
|
@@ -42,7 +42,8 @@
*/
struct gbinder_rpc_protocol {
- const char* (*read_rpc_header)(GBinderReader* reader, char** iface);
+ const char* (*read_rpc_header)(GBinderReader* reader, guint32 txcode,
+ char** iface);
void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
};
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_servicemanager.c
^
|
@@ -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 @@
#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 @@
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);
-
- if (klass) {
- GBinderIpc* ipc;
+ GBinderServiceManagerWatch* watch = g_new0(GBinderServiceManagerWatch, 1);
- 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);
+ 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 (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 */
+static
+void
+gbinder_servicemanager_watch_free(
+ gpointer data)
+{
+ GBinderServiceManagerWatch* watch = data;
- 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 {
@@ -257,6 +254,89 @@
}
/*==========================================================================*
+ * 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 @@
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_servicemanager_p.h
^
|
@@ -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;
@@ -63,6 +72,15 @@
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);
@@ -73,6 +91,11 @@
GType type,
const char* dev);
+void
+gbinder_servicemanager_service_registered(
+ GBinderServiceManager* self,
+ const char* name);
+
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
/*
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_servicepoll.c
^
|
@@ -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)
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_servicepoll.h
^
|
@@ -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:
+ */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_types_p.h
^
|
@@ -35,7 +35,7 @@
#include <gbinder_types.h>
-typedef struct gbinder_buffer_memory GBinderBufferMemory;
+typedef struct gbinder_buffer_contents GBinderBufferContents;
typedef struct gbinder_cleanup GBinderCleanup;
typedef struct gbinder_driver GBinderDriver;
typedef struct gbinder_handler GBinderHandler;
@@ -44,28 +44,8 @@
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;
+typedef struct gbinder_ipc_looper_tx GBinderIpcLooperTx;
#define GBINDER_INLINE_FUNC static inline
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_writer.c
^
|
@@ -39,7 +39,10 @@
#include <gutil_macros.h>
#include <gutil_strv.h>
+#include <unistd.h>
#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
typedef struct gbinder_writer_priv {
GBinderWriterData* data;
@@ -54,47 +57,49 @@
static
void
-gbinder_writer_data_memory_cleanup(
- gpointer memory)
+gbinder_writer_data_buffer_cleanup(
+ gpointer data)
{
- gbinder_buffer_memory_unref(memory);
+ gbinder_buffer_contents_unref((GBinderBufferContents*)data);
}
void
gbinder_writer_data_set_contents(
GBinderWriterData* data,
- GBinderBuffer* buffer,
- void** objects)
+ GBinderBuffer* buffer)
{
gsize bufsize;
const guint8* bufdata = gbinder_buffer_data(buffer, &bufsize);
const GBinderIo* io = gbinder_buffer_io(buffer);
- GBinderBufferMemory* mem = gbinder_buffer_memory(buffer);
+ GBinderBufferContents* contents = gbinder_buffer_contents(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;
+ gbinder_cleanup_reset(data->cleanup);
g_byte_array_append(data->bytes, bufdata, bufsize);
- if (mem) {
+ if (contents) {
+ void** objects = gbinder_buffer_objects(buffer);
+
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);
+ gbinder_writer_data_buffer_cleanup,
+ gbinder_buffer_contents_ref(contents));
+ 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);
+ }
}
}
}
@@ -144,6 +149,14 @@
gbinder_writer_cast(self)->data = data;
}
+gsize
+gbinder_writer_bytes_written(
+ GBinderWriter* self) /* since 1.0.21 */
+{
+ GBinderWriterData* data = gbinder_writer_data(self);
+ return data->bytes->len;
+}
+
void
gbinder_writer_append_bool(
GBinderWriter* self,
@@ -165,7 +178,7 @@
/* 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));
}
@@ -195,6 +208,24 @@
}
void
+gbinder_writer_overwrite_int32(
+ GBinderWriter* self,
+ gsize offset,
+ gint32 value) /* since 1.0.21 */
+{
+ GBinderWriterData* data = gbinder_writer_data(self);
+ GByteArray* buf = data->bytes;
+ gint32* ptr;
+ if (buf->len >= offset + sizeof(*ptr)) {
+ ptr = (void*)(buf->data + offset);
+ *ptr = value;
+ } else {
+ GWARN("Can't overwrite at %d as buffer is only %d bytes long.",
+ offset, buf->len);
+ }
+}
+
+void
gbinder_writer_append_int64(
GBinderWriter* self,
guint64 value)
@@ -351,15 +382,36 @@
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)
{
- GByteArray* buf = data->bytes;
- const gsize old_size = buf->len;
-
if (utf8) {
const char* end = utf8;
@@ -370,6 +422,8 @@
}
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;
@@ -407,14 +461,69 @@
g_byte_array_set_size(buf, old_size + padded_len + 4);
} else if (utf8) {
/* Empty string */
- guint16* ptr16;
+ gbinder_writer_data_append_string16_empty(data);
+ } else {
+ /* NULL string */
+ gbinder_writer_data_append_string16_null(data);
+ }
+}
+
+static
+void
+gbinder_writer_data_append_string16_utf16(
+ GBinderWriterData* data,
+ const gunichar2* utf16,
+ gssize length)
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/src/gbinder_writer_p.h
^
|
@@ -53,8 +53,7 @@
void
gbinder_writer_data_set_contents(
GBinderWriterData* data,
- GBinderBuffer* buffer,
- void** objects);
+ GBinderBuffer* buffer);
void
gbinder_writer_data_append_bool(
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/test/Makefile
^
|
@@ -3,6 +3,7 @@
all:
%:
@$(MAKE) -C binder-client $*
+ @$(MAKE) -C binder-dump $*
@$(MAKE) -C binder-list $*
@$(MAKE) -C binder-service $*
@$(MAKE) -C rild-card-status $*
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/test/binder-client/binder-client.c
^
|
@@ -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 {
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;
@@ -172,45 +177,79 @@
}
static
+gboolean
+app_connect_remote(
+ App* app)
+{
+ app->remote = gbinder_servicemanager_get_service_sync(app->sm,
+ app->fqname, NULL); /* autoreleased pointer */
+
+ if (app->remote) {
+ const AppOptions* opt = app->opt;
+
+ GINFO("Connected to %s", app->fqname);
+ gbinder_remote_object_ref(app->remote);
+ app->client = gbinder_client_new(app->remote, opt->iface);
+ app->death_id = gbinder_remote_object_add_death_handler(app->remote,
+ app_remote_died, app);
+ app->thread = g_thread_new("input", app_input_thread, app);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static
+void
+app_registration_handler(
+ GBinderServiceManager* sm,
+ const char* name,
+ void* user_data)
+{
+ App* app = user_data;
+
+ GDEBUG("\"%s\" appeared", name);
+ if (!strcmp(name, app->fqname) && app_connect_remote(app)) {
+ gbinder_servicemanager_remove_handler(app->sm, app->wait_id);
+ app->wait_id = 0;
+ }
+}
+
+static
void
app_run(
App* app)
{
const AppOptions* opt = app->opt;
- char* fqname = opt->fqname ? g_strdup(opt->fqname) :
+ guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, app);
+ guint sigint = g_unix_signal_add(SIGINT, app_signal, app);
+
+ app->fqname = opt->fqname ? g_strdup(opt->fqname) :
strchr(opt->name, '/') ? g_strdup(opt->name) :
g_strconcat(opt->iface, "/", opt->name, NULL);
- int status = 0;
- GBinderRemoteObject* remote = gbinder_remote_object_ref
- (gbinder_servicemanager_get_service_sync(app->sm, fqname, &status));
- if (remote) {
- guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, app);
- guint sigint = g_unix_signal_add(SIGINT, app_signal, app);
- gulong death_id = gbinder_remote_object_add_death_handler
- (remote, app_remote_died, app);
- GThread* thread = g_thread_new("input", app_input_thread, app);
-
- GINFO("Connected to %s\n", fqname);
-
- app->client = gbinder_client_new(remote, opt->iface);
- app->ret = RET_OK;
- app->loop = g_main_loop_new(NULL, TRUE);
- g_main_loop_run(app->loop);
-
- g_source_remove(sigtrm);
- g_source_remove(sigint);
- g_main_loop_unref(app->loop);
-
- gbinder_remote_object_remove_handler(remote, death_id);
- gbinder_remote_object_unref(remote);
-
- /* Not the cleanest exit, just dropping the thread... */
- g_thread_unref(thread);
- app->loop = NULL;
- } else {
- GERR("No such service: %s (%d)", fqname, status);
+
+ if (!app_connect_remote(app)) {
+ GINFO("Waiting for %s", app->fqname);
+ app->wait_id = gbinder_servicemanager_add_registration_handler(app->sm,
+ app->fqname, app_registration_handler, app);
+ }
+
+ app->loop = g_main_loop_new(NULL, TRUE);
+ app->ret = RET_OK;
+ g_main_loop_run(app->loop);
+
+ g_source_remove(sigtrm);
+ g_source_remove(sigint);
+ g_main_loop_unref(app->loop);
+
+ if (app->thread) {
+ /* Not the cleanest of exits, just dropping the thread... */
+ g_thread_unref(app->thread);
}
- 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 @@
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);
}
}
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/test/binder-dump/Makefile
^
|
@@ -0,0 +1,140 @@
+# -*- Mode: makefile-gmake -*-
+
+.PHONY: all debug release clean cleaner
+.PHONY: libgbinder-release libgbinder-debug
+
+#
+# Required packages
+#
+
+PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
+
+#
+# Default target
+#
+
+all: debug release
+
+#
+# Executable
+#
+
+EXE = binder-dump
+
+#
+# Sources
+#
+
+SRC = $(EXE).c
+
+#
+# Directories
+#
+
+SRC_DIR = .
+BUILD_DIR = build
+LIB_DIR = ../..
+DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
+RELEASE_BUILD_DIR = $(BUILD_DIR)/release
+
+#
+# Tools and flags
+#
+
+CC = $(CROSS_COMPILE)gcc
+LD = $(CC)
+WARNINGS = -Wall
+INCLUDES = -I$(LIB_DIR)/include
+BASE_FLAGS = -fPIC
+CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
+ $(shell pkg-config --cflags $(PKGS))
+LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
+QUIET_MAKE = make --no-print-directory
+DEBUG_FLAGS = -g
+RELEASE_FLAGS =
+
+ifndef KEEP_SYMBOLS
+KEEP_SYMBOLS = 0
+endif
+
+ifneq ($(KEEP_SYMBOLS),0)
+RELEASE_FLAGS += -g
+SUBMAKE_OPTS += KEEP_SYMBOLS=1
+endif
+
+DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
+RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
+DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
+RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
+
+#
+# Files
+#
+
+DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
+RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
+DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
+RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
+DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
+RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
+DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
+RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
+
+#
+# Dependencies
+#
+
+DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(strip $(DEPS)),)
+-include $(DEPS)
+endif
+endif
+
+$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
+$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
+
+#
+# Rules
+#
+
+DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
+RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
+
+debug: libgbinder-debug $(DEBUG_EXE)
+
+release: libgbinder-release $(RELEASE_EXE)
+
+clean:
+ rm -f *~
+ rm -fr $(BUILD_DIR)
+
+cleaner: clean
+ @make -C $(LIB_DIR) clean
+
+$(DEBUG_BUILD_DIR):
+ mkdir -p $@
+
+$(RELEASE_BUILD_DIR):
+ mkdir -p $@
+
+$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
+ $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
+
+$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
+ $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
+
+$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
+ $(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
+
+$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
+ $(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
+ifeq ($(KEEP_SYMBOLS),0)
+ strip $@
+endif
+
+libgbinder-debug:
+ @make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
+
+libgbinder-release:
+ @make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/test/binder-dump/binder-dump.c
^
|
@@ -0,0 +1,237 @@
+/*
+ * 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.h>
+
+#include <gutil_log.h>
+
+#include <unistd.h>
+
+#define RET_OK (0)
+#define RET_NOTFOUND (1)
+#define RET_INVARG (2)
+#define RET_ERR (3)
+
+#define DEV_DEFAULT GBINDER_DEFAULT_BINDER
+
+#define GBINDER_TRANSACTION(c2,c3,c4) GBINDER_FOURCC('_',c2,c3,c4)
+#define GBINDER_DUMP_TRANSACTION GBINDER_TRANSACTION('D','M','P')
+
+typedef struct app_options {
+ char* dev;
+ const char* service;
+} AppOptions;
+
+typedef struct app {
+ const AppOptions* opt;
+ GMainLoop* loop;
+ GBinderServiceManager* sm;
+ int ret;
+} App;
+
+static const char pname[] = "binder-dump";
+
+static
+gboolean
+app_dump_service(
+ App* app,
+ const char* service)
+{
+ int status = 0;
+ GBinderRemoteObject* obj = gbinder_servicemanager_get_service_sync(app->sm,
+ service, &status);
+
+ if (obj) {
+ GBinderClient* client = gbinder_client_new(obj, NULL);
+ GBinderLocalRequest* req = gbinder_client_new_request(client);
+ GBinderRemoteReply* reply;
+ GBinderWriter writer;
+
+ gbinder_remote_object_ref(obj);
+ gbinder_local_request_init_writer(req, &writer);
+ gbinder_writer_append_fd(&writer, STDOUT_FILENO);
+ gbinder_writer_append_int32(&writer, 0);
+ reply = gbinder_client_transact_sync_reply(client,
+ GBINDER_DUMP_TRANSACTION, req, &status);
+ if (status < 0) {
+ GERR("Error %d", status);
+ }
+ gbinder_remote_object_unref(obj);
+ gbinder_remote_reply_unref(reply);
+ gbinder_local_request_unref(req);
+ gbinder_client_unref(client);
+ return TRUE;
+ } else {
+ GERR("No such service: %s (%d)", service, status);
+ return FALSE;
+ }
+}
+
+static
+void
+app_dump_services(
+ App* app,
+ char** strv)
+{
+ if (strv) {
+ while (*strv) {
+ const char* name = *strv++;
+
+ printf("========= %s\n", name);
+ app_dump_service(app, name);
+ }
+ }
+}
+
+static
+void
+app_run(
+ App* app)
+{
+ const AppOptions* opt = app->opt;
+
+ if (opt->service) {
+ app->ret = app_dump_service(app, opt->service) ? RET_OK : RET_NOTFOUND;
+ } else {
+ char** services = gbinder_servicemanager_list_sync(app->sm);
+
+ if (services) {
+ app_dump_services(app, services);
+ g_strfreev(services);
+ app->ret = RET_OK;
+ } else {
+ app->ret = RET_ERR;
+ }
+ }
+}
+
+static
+gboolean
+app_log_verbose(
+ const gchar* name,
+ const gchar* value,
+ gpointer data,
+ GError** error)
+{
+ gutil_log_default.level = GLOG_LEVEL_VERBOSE;
+ return TRUE;
+}
+
+static
+gboolean
+app_log_quiet(
+ const gchar* name,
+ const gchar* value,
+ gpointer data,
+ GError** error)
+{
+ gutil_log_default.level = GLOG_LEVEL_ERR;
+ return TRUE;
+}
+
+static
+gboolean
+app_init(
+ AppOptions* opt,
+ int argc,
+ char* argv[])
+{
+ gboolean ok = FALSE;
+ GOptionEntry entries[] = {
+ { "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ app_log_verbose, "Enable verbose output", NULL },
+ { "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+ app_log_quiet, "Be quiet", NULL },
+ { NULL }
+ };
+
+ GError* error = NULL;
+ GOptionContext* options = g_option_context_new("[SERVICE]");
+
+ memset(opt, 0, sizeof(*opt));
+
+ gutil_log_timestamp = FALSE;
+ gutil_log_set_type(GLOG_TYPE_STDERR, pname);
+ gutil_log_default.level = GLOG_LEVEL_DEFAULT;
+
+ g_option_context_add_main_entries(options, entries, NULL);
+ if (g_option_context_parse(options, &argc, &argv, &error)) {
+ char* help;
+
+ opt->dev = g_strdup(DEV_DEFAULT);
+ switch (argc) {
+ case 2:
+ opt->service = argv[1];
+ /* no break */
+ case 1:
+ ok = TRUE;
+ break;
+ default:
+ help = g_option_context_get_help(options, TRUE, NULL);
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/test/binder-list/binder-list.c
^
|
@@ -194,7 +194,7 @@
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
app_log_quiet, "Be quiet", NULL },
{ "async", 'a', 0, G_OPTION_ARG_NONE, &opt->async,
- "Parform operations asynchronously", NULL },
+ "Perform operations asynchronously", NULL },
{ "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
"Binder device [" DEV_DEFAULT "]", "DEVICE" },
{ NULL }
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/test/binder-service/binder-service.c
^
|
@@ -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
@@ -36,6 +36,9 @@
#include <glib-unix.h>
+#define BINDER_TRANSACTION(c2,c3,c4) GBINDER_FOURCC('_',c2,c3,c4)
+#define BINDER_DUMP_TRANSACTION BINDER_TRANSACTION('D','M','P')
+
#define RET_OK (0)
#define RET_NOTFOUND (1)
#define RET_INVARG (2)
@@ -49,6 +52,7 @@
char* dev;
char* iface;
const char* name;
+ gboolean async;
} AppOptions;
typedef struct app {
@@ -59,6 +63,11 @@
int ret;
} App;
+typedef struct response {
+ GBinderRemoteRequest* req;
+ GBinderLocalReply* reply;
+} Response;
+
static const char pname[] = "binder-service";
static
@@ -74,6 +83,29 @@
}
static
+gboolean
+app_async_resp(
+ gpointer user_data)
+{
+ Response* resp = user_data;
+
+ gbinder_remote_request_complete(resp->req, resp->reply, 0);
+ return G_SOURCE_REMOVE;
+}
+
+static
+void
+app_async_free(
+ gpointer user_data)
+{
+ Response* resp = user_data;
+
+ gbinder_local_reply_unref(resp->reply);
+ gbinder_remote_request_unref(resp->req);
+ g_free(resp);
+}
+
+static
GBinderLocalReply*
app_reply(
GBinderLocalObject* obj,
@@ -83,15 +115,52 @@
int* status,
void* user_data)
{
- char* str = gbinder_remote_request_read_string16(req);
- GBinderLocalReply* reply = gbinder_local_object_new_reply(obj);
+ App* app = user_data;
+ GBinderReader reader;
- GVERBOSE("\"%s\" %u", gbinder_remote_request_interface(req), code);
- GDEBUG("\"%s\"", str);
- gbinder_local_reply_append_string16(reply, str);
- g_free(str);
- *status = 0;
- return reply;
+ gbinder_remote_request_init_reader(req, &reader);
+ if (code == GBINDER_FIRST_CALL_TRANSACTION) {
+ const AppOptions* opt = app->opt;
+ const char* iface = gbinder_remote_request_interface(req);
+
+ if (!g_strcmp0(iface, opt->iface)) {
+ char* str = gbinder_reader_read_string16(&reader);
+ GBinderLocalReply* reply = gbinder_local_object_new_reply(obj);
+
+ GVERBOSE("\"%s\" %u", iface, code);
+ GDEBUG("\"%s\"", str);
+ *status = 0;
+ gbinder_local_reply_append_string16(reply, str);
+ g_free(str);
+ if (opt->async) {
+ Response* resp = g_new0(Response, 1);
+
+ resp->reply = reply;
+ resp->req = gbinder_remote_request_ref(req);
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, app_async_resp,
+ resp, app_async_free);
+ gbinder_remote_request_block(resp->req);
+ return NULL;
+ } else {
+ return reply;
+ }
+ } else {
+ GDEBUG("Unexpected interface \"%s\"", iface);
+ }
+ } else if (code == BINDER_DUMP_TRANSACTION) {
+ int fd = gbinder_reader_read_fd(&reader);
+ const char* dump = "Sorry, I've got nothing to dump...\n";
+ const gssize dump_len = strlen(dump);
+
+ GDEBUG("Dump request from %d", gbinder_remote_request_sender_pid(req));
+ if (write(fd, dump, dump_len) != dump_len) {
+ GERR("Failed to write dump: %s", strerror(errno));
+ }
+ *status = 0;
+ return NULL;
+ }
+ *status = -1;
+ return NULL;
}
static
@@ -175,6 +244,8 @@
"Binder device [" DEFAULT_DEVICE "]", "DEVICE" },
{ "interface", 'i', 0, G_OPTION_ARG_STRING, &opt->iface,
"Local interface [" DEFAULT_IFACE "]", "IFACE" },
+ { "async", 'a', 0, G_OPTION_ARG_NONE, &opt->async,
+ "Handle calls asynchronously", NULL },
{ NULL }
};
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/Makefile
^
|
@@ -3,6 +3,7 @@
all:
%:
@$(MAKE) -C unit_buffer $*
+ @$(MAKE) -C unit_cleanup $*
@$(MAKE) -C unit_client $*
@$(MAKE) -C unit_driver $*
@$(MAKE) -C unit_ipc $*
@@ -14,6 +15,8 @@
@$(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
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/coverage/run
^
|
@@ -5,6 +5,7 @@
TESTS="\
unit_buffer \
+unit_cleanup \
unit_client \
unit_driver \
unit_ipc \
@@ -16,6 +17,8 @@
unit_remote_object \
unit_remote_reply \
unit_remote_request \
+unit_servicemanager \
+unit_servicepoll \
unit_writer"
function err() {
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_buffer/unit_buffer.c
^
|
@@ -47,19 +47,21 @@
void)
{
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
- GBinderBuffer* buf = gbinder_buffer_new(NULL, NULL, 0);
+ GBinderBuffer* buf = gbinder_buffer_new(NULL, NULL, 0, NULL);
GBinderBuffer* buf2;
gsize size = 1;
gbinder_buffer_free(buf);
/* No need to reference the driver if there's no data */
- buf = gbinder_buffer_new(driver, NULL, 0);
+ buf = gbinder_buffer_new(driver, NULL, 0, NULL);
g_assert(!gbinder_buffer_driver(buf));
gbinder_buffer_free(buf);
buf = gbinder_buffer_new_with_parent(NULL, NULL, 0);
buf2 = gbinder_buffer_new_with_parent(buf, NULL, 0);
+ g_assert(!gbinder_buffer_objects(buf));
+ g_assert(!gbinder_buffer_objects(buf2));
g_assert(!gbinder_buffer_driver(buf));
g_assert(!gbinder_buffer_driver(buf2));
gbinder_buffer_free(buf);
@@ -67,6 +69,7 @@
gbinder_buffer_free(NULL);
g_assert(!gbinder_buffer_driver(NULL));
+ g_assert(!gbinder_buffer_objects(NULL));
g_assert(!gbinder_buffer_io(NULL));
g_assert(!gbinder_buffer_data(NULL, NULL));
g_assert(!gbinder_buffer_data(NULL, &size));
@@ -87,14 +90,14 @@
void* ptr = g_memdup(data, sizeof(data));
gsize size = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
- GBinderBuffer* parent = gbinder_buffer_new(driver, ptr, sizeof(data));
+ GBinderBuffer* parent = gbinder_buffer_new(driver, ptr, sizeof(data), NULL);
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_contents(buf));
g_assert(gbinder_buffer_data(buf, NULL) == ptr);
g_assert(gbinder_buffer_data(buf, &size) == ptr);
g_assert(size == sizeof(data));
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_cleanup/Makefile
^
|
@@ -0,0 +1,5 @@
+# -*- Mode: makefile-gmake -*-
+
+EXE = unit_cleanup
+
+include ../common/Makefile
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_cleanup/unit_cleanup.c
^
|
@@ -0,0 +1,126 @@
+/*
+ * 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_binder.h"
+
+#include "gbinder_cleanup.h"
+
+static TestOpt test_opt;
+
+static
+void
+test_cleanup_inc(
+ gpointer data)
+{
+ (*((int*)data))++;
+}
+
+/*==========================================================================*
+ * null
+ *==========================================================================*/
+
+static
+void
+test_null(
+ void)
+{
+ g_assert(!gbinder_cleanup_add(NULL, NULL, NULL));
+ gbinder_cleanup_free(NULL);
+ gbinder_cleanup_reset(NULL);
+}
+
+/*==========================================================================*
+ * basic
+ *==========================================================================*/
+
+static
+void
+test_basic(
+ void)
+{
+ int n1 = 0, n2 =0;
+ GBinderCleanup* cleanup = gbinder_cleanup_add(NULL, test_cleanup_inc, &n1);
+
+ g_assert(cleanup);
+ g_assert(gbinder_cleanup_add(cleanup, test_cleanup_inc, &n2) == cleanup);
+ gbinder_cleanup_free(cleanup);
+ g_assert(n1 == 1);
+ g_assert(n2 == 1);
+}
+
+/*==========================================================================*
+ * reset
+ *==========================================================================*/
+
+static
+void
+test_reset(
+ void)
+{
+ int n1 = 0, n2 =0;
+ GBinderCleanup* cleanup = gbinder_cleanup_add(NULL, test_cleanup_inc, &n1);
+
+ g_assert(cleanup);
+ g_assert(gbinder_cleanup_add(cleanup, test_cleanup_inc, &n2) == cleanup);
+ gbinder_cleanup_reset(cleanup);
+ g_assert(n1 == 1);
+ g_assert(n2 == 1);
+
+ gbinder_cleanup_free(cleanup);
+ g_assert(n1 == 1);
+ g_assert(n2 == 1);
+}
+
+/*==========================================================================*
+ * Common
+ *==========================================================================*/
+
+#define TEST_PREFIX "/cleanup/"
+#define TEST_(t) TEST_PREFIX 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_("reset"), test_reset);
+ test_init(&test_opt, argc, argv);
+ return g_test_run();
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_client/unit_client.c
^
|
@@ -100,7 +100,6 @@
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, 0);
GBinderClient* client = gbinder_client_new(obj, "foo");
- g_assert(!gbinder_client_new(obj, NULL));
g_assert(client);
g_assert(gbinder_client_ref(client) == client);
gbinder_client_unref(client);
@@ -112,6 +111,25 @@
}
/*==========================================================================*
+ * no_header
+ *==========================================================================*/
+
+static
+void
+test_no_header(
+ void)
+{
+ GBinderClient* client = test_client_new(0, NULL);
+ int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
+
+ test_binder_br_transaction_complete(fd);
+ g_assert(gbinder_client_transact_sync_oneway(client, 0, NULL) ==
+ GBINDER_STATUS_OK);
+
+ gbinder_client_unref(client);
+}
+
+/*==========================================================================*
* sync_oneway
*==========================================================================*/
@@ -326,17 +344,19 @@
*==========================================================================*/
#define TEST_PREFIX "/client/"
+#define TEST_(t) TEST_PREFIX t
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 "sync_oneway", test_sync_oneway);
- g_test_add_func(TEST_PREFIX "sync_reply", test_sync_reply);
- g_test_add_func(TEST_PREFIX "reply/ok1", test_reply_ok1);
- g_test_add_func(TEST_PREFIX "reply/ok2", test_reply_ok2);
- g_test_add_func(TEST_PREFIX "reply/ok3", test_reply_ok3);
+ g_test_add_func(TEST_("null"), test_null);
+ g_test_add_func(TEST_("basic"), test_basic);
+ g_test_add_func(TEST_("no_header"), test_no_header);
+ g_test_add_func(TEST_("sync_oneway"), test_sync_oneway);
+ g_test_add_func(TEST_("sync_reply"), test_sync_reply);
+ g_test_add_func(TEST_("reply/ok1"), test_reply_ok1);
+ g_test_add_func(TEST_("reply/ok2"), test_reply_ok2);
+ g_test_add_func(TEST_("reply/ok3"), test_reply_ok3);
test_init(&test_opt, argc, argv);
return g_test_run();
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_ipc/unit_ipc.c
^
|
@@ -52,6 +52,24 @@
static TestOpt test_opt;
+static
+gboolean
+test_unref_ipc(
+ gpointer ipc)
+{
+ gbinder_ipc_unref(ipc);
+ return G_SOURCE_REMOVE;
+}
+
+static
+void
+test_quit_when_destroyed(
+ gpointer loop,
+ GObject* obj)
+{
+ test_quit_later((GMainLoop*)loop);
+}
+
/*==========================================================================*
* null
*==========================================================================*/
@@ -607,26 +625,173 @@
}
static
+void
+test_transact_incoming(
+ void)
+{
+ 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);
+ const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
+ GMainLoop* loop = g_main_loop_new(NULL, FALSE);
+ GBinderLocalObject* obj = gbinder_ipc_new_local_object
+ (ipc, "test", test_transact_incoming_proc, loop);
+ GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
+ GBinderOutputData* data;
+ GBinderWriter writer;
+
+ gbinder_local_request_init_writer(req, &writer);
+ prot->write_rpc_header(&writer, "test");
+ gbinder_writer_append_string8(&writer, "message");
+ data = gbinder_local_request_data(req);
+
+ test_binder_br_transaction(fd, obj, 1, data->bytes);
+ test_run(&test_opt, loop);
+
+ /* Now we need to wait until GBinderIpc is destroyed */
+ GDEBUG("waiting for GBinderIpc to get destroyed");
+ g_object_weak_ref(G_OBJECT(ipc), test_quit_when_destroyed, loop);
+ gbinder_local_object_unref(obj);
+ gbinder_local_request_unref(req);
+ g_idle_add(test_unref_ipc, ipc);
+ test_run(&test_opt, loop);
+
+ g_main_loop_unref(loop);
+}
+
+/*==========================================================================*
+ * transact_status_reply
+ *==========================================================================*/
+
+static
+GBinderLocalReply*
+test_transact_status_reply_proc(
+ GBinderLocalObject* obj,
+ GBinderRemoteRequest* req,
+ guint code,
+ guint flags,
+ int* status,
+ void* user_data)
+{
+ GVERBOSE_("\"%s\" %u", gbinder_remote_request_interface(req), code);
+ g_assert(!flags);
+ g_assert(!g_strcmp0(gbinder_remote_request_interface(req), "test"));
+ g_assert(!g_strcmp0(gbinder_remote_request_read_string8(req), "message"));
+ g_assert(code == 1);
+ test_quit_later((GMainLoop*)user_data);
+
+ *status = EXPECTED_STATUS;
+ return NULL;
+}
+
+static
+void
+test_transact_status_reply(
+ void)
+{
+ 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);
+ const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
+ GMainLoop* loop = g_main_loop_new(NULL, FALSE);
+ GBinderLocalObject* obj = gbinder_ipc_new_local_object
+ (ipc, "test", test_transact_status_reply_proc, loop);
+ GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
+ GBinderOutputData* data;
+ GBinderWriter writer;
+
+ gbinder_local_request_init_writer(req, &writer);
+ prot->write_rpc_header(&writer, "test");
+ gbinder_writer_append_string8(&writer, "message");
+ data = gbinder_local_request_data(req);
+
+ test_binder_br_transaction(fd, obj, 1, data->bytes);
+ test_run(&test_opt, loop);
+
+ /* Now we need to wait until GBinderIpc is destroyed */
+ GDEBUG("waiting for GBinderIpc to get destroyed");
+ g_object_weak_ref(G_OBJECT(ipc), test_quit_when_destroyed, loop);
+ gbinder_local_object_unref(obj);
+ gbinder_local_request_unref(req);
+ g_idle_add(test_unref_ipc, ipc);
+ test_run(&test_opt, loop);
+
+ g_main_loop_unref(loop);
+}
+
+/*==========================================================================*
+ * transact_async
+ *==========================================================================*/
+
+typedef struct test_transact_async_req {
+ GBinderLocalObject* obj;
+ GBinderRemoteRequest* req;
+ GMainLoop* loop;
+} TestTransactAsyncReq;
+
+static
+void
+test_transact_async_done(
+ gpointer data)
+{
+ TestTransactAsyncReq* test = data;
+
+ gbinder_local_object_unref(test->obj);
+ gbinder_remote_request_unref(test->req);
+ test_quit_later(test->loop);
+ g_free(test);
+}
+
+static
gboolean
-test_transact_unref_ipc(
- gpointer ipc)
+test_transact_async_reply(
+ gpointer data)
{
- gbinder_ipc_unref(ipc);
+ TestTransactAsyncReq* test = data;
+ GBinderLocalReply* reply = gbinder_local_object_new_reply(test->obj);
+
+ gbinder_remote_request_complete(test->req, reply, 0);
+ gbinder_local_reply_unref(reply);
return G_SOURCE_REMOVE;
}
static
-void
-test_transact_done(
- gpointer loop,
- GObject* ipc)
+GBinderLocalReply*
+test_transact_async_proc(
+ GBinderLocalObject* obj,
+ GBinderRemoteRequest* req,
+ guint code,
+ guint flags,
+ int* status,
+ void* loop)
{
- test_quit_later((GMainLoop*)loop);
+ TestTransactAsyncReq* test = g_new(TestTransactAsyncReq, 1);
+
+ GVERBOSE_("\"%s\" %u", gbinder_remote_request_interface(req), code);
+ g_assert(!flags);
+ g_assert(gbinder_remote_request_sender_pid(req) == getpid());
+ g_assert(gbinder_remote_request_sender_euid(req) == geteuid());
+ g_assert(!g_strcmp0(gbinder_remote_request_interface(req), "test"));
+ g_assert(!g_strcmp0(gbinder_remote_request_read_string8(req), "message"));
+ g_assert(code == 1);
+
+ test->obj = gbinder_local_object_ref(obj);
+ test->req = gbinder_remote_request_ref(req);
+ test->loop = (GMainLoop*)loop;
+
+ gbinder_remote_request_block(req);
+ gbinder_remote_request_block(req); /* wrong state; has no effect */
+
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, test_transact_async_reply, test,
+ test_transact_async_done);
+ return NULL;
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_local_object/unit_local_object.c
^
|
@@ -73,7 +73,8 @@
GUtilIntArray* offsets = gbinder_output_data_offsets(out);
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
- g_memdup(out->bytes->data, out->bytes->len), out->bytes->len);
+ g_memdup(out->bytes->data, out->bytes->len),
+ out->bytes->len, NULL);
memset(data, 0, sizeof(*data));
data->buffer = buf;
@@ -187,6 +188,49 @@
}
/*==========================================================================*
+ * 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, HIDL_PING_TRANSACTION,
+ 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,9 +239,7 @@
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);
@@ -208,8 +250,9 @@
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);
+ gbinder_remote_request_set_data(req, HIDL_PING_TRANSACTION,
+ 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_GET_DESCRIPTOR_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_LOOPER);
@@ -263,8 +306,9 @@
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);
+ gbinder_remote_request_set_data(req, HIDL_PING_TRANSACTION,
+ 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_DESCRIPTOR_CHAIN_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_LOOPER);
@@ -334,8 +378,9 @@
char** strv;
char* str;
- gbinder_remote_request_set_data(req, gbinder_buffer_new(ipc->driver,
- g_memdup(req_data, sizeof(req_data)), sizeof(req_data)), NULL);
+ gbinder_remote_request_set_data(req, HIDL_PING_TRANSACTION,
+ gbinder_buffer_new(ipc->driver, g_memdup(req_data, sizeof(req_data)),
+ sizeof(req_data), NULL));
g_assert(gbinder_local_object_can_handle_transaction(obj, base_interface,
HIDL_DESCRIPTOR_CHAIN_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_LOOPER);
g_assert(gbinder_local_object_can_handle_transaction(obj, custom_iface,
@@ -434,8 +479,9 @@
GBinderLocalObject* obj = gbinder_ipc_new_local_object(ipc, custom_iface,
test_reply_status_handler, &count);
- gbinder_remote_request_set_data(req, gbinder_buffer_new(ipc->driver,
- g_memdup(req_data, sizeof(req_data)), sizeof(req_data)), NULL);
+ gbinder_remote_request_set_data(req, HIDL_PING_TRANSACTION,
+ gbinder_buffer_new(ipc->driver, g_memdup(req_data, sizeof(req_data)),
+ sizeof(req_data), NULL));
/* Execute the custom transaction */
g_assert(!gbinder_local_object_handle_transaction(obj, req,
@@ -627,6 +673,7 @@
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);
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_local_reply/unit_local_reply.c
^
|
@@ -67,7 +67,7 @@
{
/* Prevent double free */
test_binder_set_destroy(gbinder_driver_fd(driver), bytes->data, NULL);
- return gbinder_buffer_new(driver, bytes->data, bytes->len);
+ return gbinder_buffer_new(driver, bytes->data, bytes->len, NULL);
}
/*==========================================================================*
@@ -88,7 +88,7 @@
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));
+ g_assert(!gbinder_local_reply_new_from_data(NULL));
gbinder_local_reply_cleanup(NULL, NULL, &count);
gbinder_local_reply_cleanup(NULL, test_int_inc, &count);
@@ -137,8 +137,8 @@
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;
@@ -359,7 +359,7 @@
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);
}
@@ -382,7 +382,7 @@
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);
}
@@ -479,7 +479,7 @@
/* Copy flat structures (no binder objects) */
buffer = test_buffer_from_bytes(driver, bytes);
- req2 = gbinder_local_reply_new_from_data(buffer, NULL);
+ req2 = gbinder_local_reply_new_from_data(buffer);
gbinder_buffer_free(buffer);
data2 = gbinder_local_reply_data(req2);
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_local_request/unit_local_request.c
^
|
@@ -65,7 +65,19 @@
{
/* Prevent double free */
test_binder_set_destroy(gbinder_driver_fd(driver), bytes->data, NULL);
- return gbinder_buffer_new(driver, bytes->data, bytes->len);
+ return gbinder_buffer_new(driver, bytes->data, bytes->len, NULL);
+}
+
+static
+GBinderBuffer*
+test_buffer_from_bytes_and_objects(
+ GBinderDriver* driver,
+ const GByteArray* bytes,
+ void** objects)
+{
+ /* Prevent double free */
+ test_binder_set_destroy(gbinder_driver_fd(driver), bytes->data, NULL);
+ return gbinder_buffer_new(driver, bytes->data, bytes->len, objects);
}
/*==========================================================================*
@@ -82,7 +94,7 @@
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));
+ g_assert(!gbinder_local_request_new_from_data(NULL));
gbinder_local_request_unref(NULL);
gbinder_local_request_init_writer(NULL, NULL);
gbinder_local_request_init_writer(NULL, &writer);
@@ -167,8 +179,8 @@
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;
@@ -375,7 +387,7 @@
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);
}
@@ -398,7 +410,7 @@
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);
}
@@ -471,14 +483,14 @@
const GByteArray* bytes;
const GByteArray* bytes2;
GBinderBuffer* buffer;
- void* no_obj = NULL;
+ void** no_obj = g_new0(void*, 1);
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);
+ req2 = gbinder_local_request_new_from_data(buffer);
gbinder_buffer_free(buffer);
data2 = gbinder_local_request_data(req2);
@@ -490,8 +502,8 @@
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);
+ buffer = test_buffer_from_bytes_and_objects(driver, bytes, no_obj);
+ req2 = gbinder_local_request_new_from_data(buffer);
gbinder_buffer_free(buffer);
data2 = gbinder_local_request_data(req2);
@@ -525,8 +537,9 @@
g_assert(offsets->data[1] == 4 + BUFFER_OBJECT_SIZE_64);
g_assert(offsets->data[2] == 4 + 2*BUFFER_OBJECT_SIZE_64);
g_assert(bytes->len == 4 + 2*BUFFER_OBJECT_SIZE_64 + BINDER_OBJECT_SIZE_64);
- /* HidlString + the contents (2 bytes) aligned at 8-byte boundary */
- g_assert(gbinder_output_data_buffers_size(data) == (sizeof(HidlString)+8));
+ /* GBinderHidlString + the contents (2 bytes) aligned at 8-byte boundary */
+ g_assert(gbinder_output_data_buffers_size(data) ==
+ (sizeof(GBinderHidlString) + 8));
}
static
@@ -558,15 +571,15 @@
objects[i] = bytes->data + offsets->data[i];
}
- buffer = test_buffer_from_bytes(driver, data->bytes);
- req2 = gbinder_local_request_new_from_data(buffer, objects);
+ buffer = test_buffer_from_bytes_and_objects(driver, data->bytes, objects);
+ req2 = gbinder_local_request_new_from_data(buffer);
gbinder_buffer_free(buffer);
- g_free(objects);
test_remote_request_obj_validate_data(gbinder_local_request_data(req2));
- gbinder_local_request_unref(req);
+ /* req2 has to be freed first because req owns data */
gbinder_local_request_unref(req2);
+ gbinder_local_request_unref(req);
gbinder_driver_unref(driver);
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_protocol/unit_protocol.c
^
|
@@ -91,23 +91,45 @@
}
/*==========================================================================*
- * no_header
+ * no_header1
*==========================================================================*/
static
void
-test_no_header(
+test_no_header1(
void)
{
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
gbinder_rpc_protocol_for_device(GBINDER_DEFAULT_BINDER), 0, 0);
- gbinder_remote_request_set_data(req, NULL, NULL);
+ gbinder_remote_request_set_data(req, GBINDER_FIRST_CALL_TRANSACTION, NULL);
g_assert(!gbinder_remote_request_interface(req));
gbinder_remote_request_unref(req);
}
/*==========================================================================*
+ * no_header2
+ *==========================================================================*/
+
+static
+void
+test_no_header2(
+ void)
+{
+ const GBinderRpcProtocol* p = &gbinder_rpc_protocol_binder;
+ GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, p);
+ GBinderRemoteRequest* req = gbinder_remote_request_new(NULL, p, 0, 0);
+
+ gbinder_remote_request_set_data(req, GBINDER_DUMP_TRANSACTION,
+ gbinder_buffer_new(driver,
+ g_memdup(TEST_ARRAY_AND_SIZE(test_header_binder)),
+ sizeof(test_header_binder), NULL));
+ g_assert(!gbinder_remote_request_interface(req));
+ gbinder_remote_request_unref(req);
+ gbinder_driver_unref(driver);
+}
+
+/*==========================================================================*
* write_header
*==========================================================================*/
@@ -144,38 +166,39 @@
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
gbinder_rpc_protocol_for_device(test->dev), 0, 0);
- gbinder_remote_request_set_data(req, gbinder_buffer_new(driver,
- g_memdup(test->header, test->header_size), test->header_size), NULL);
+ gbinder_remote_request_set_data(req, GBINDER_FIRST_CALL_TRANSACTION,
+ gbinder_buffer_new(driver, g_memdup(test->header, test->header_size),
+ test->header_size, NULL));
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), test->iface));
gbinder_remote_request_unref(req);
gbinder_driver_unref(driver);
}
- /*==========================================================================*
+/*==========================================================================*
* Common
*==========================================================================*/
#define TEST_PREFIX "/protocol/"
+#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 "device", test_device);
- g_test_add_func(TEST_PREFIX "no_header", test_no_header);
+ g_test_add_func(TEST_("device"), test_device);
+ g_test_add_func(TEST_("no_header1"), test_no_header1);
+ g_test_add_func(TEST_("no_header2"), test_no_header2);
for (i = 0; i < G_N_ELEMENTS(test_header_tests); i++) {
const TestHeaderData* test = test_header_tests + i;
- char* path = g_strconcat(TEST_PREFIX, "/", test->name,
- "/read_header", NULL);
+ char* path;
+ path = g_strconcat(TEST_PREFIX, test->name, "/read_header", NULL);
g_test_add_data_func(path, test, test_read_header);
g_free(path);
- path = g_strconcat(TEST_PREFIX, "/", test->name,
- "/write_header", NULL);
-
+ path = g_strconcat(TEST_PREFIX, test->name, "/write_header", NULL);
g_test_add_data_func(path, test, test_write_header);
g_free(path);
}
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_reader/unit_reader.c
^
|
@@ -39,6 +39,9 @@
#include "gbinder_remote_object_p.h"
#include "gbinder_io.h"
+#include <unistd.h>
+#include <fcntl.h>
+
static TestOpt test_opt;
typedef struct binder_buffer_object_64 {
@@ -53,9 +56,12 @@
guint64 parent_offset;
} BinderObject64;
-#define BINDER_TYPE_HANDLE GBINDER_FOURCC('s','h','*',0x85)
-#define BINDER_TYPE_PTR GBINDER_FOURCC('p','t','*',0x85)
+#define BINDER_TYPE_(c1,c2,c3) GBINDER_FOURCC(c1,c2,c3,0x85)
+#define BINDER_TYPE_HANDLE BINDER_TYPE_('s','h','*')
+#define BINDER_TYPE_PTR BINDER_TYPE_('p','t','*')
+#define BINDER_TYPE_FD BINDER_TYPE_('f', 'd', '*')
#define BINDER_BUFFER_FLAG_HAS_PARENT 0x01
+#define BINDER_FLAG_ACCEPTS_FDS 0x100
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
G_STATIC_ASSERT(sizeof(BinderObject64) == BUFFER_OBJECT_SIZE_64);
@@ -121,7 +127,7 @@
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
- sizeof(in));
+ sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_byte(&reader, &out));
@@ -155,7 +161,7 @@
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver,
- g_memdup(&in_true, sizeof(in_true)), sizeof(in_true));
+ g_memdup(&in_true, sizeof(in_true)), sizeof(in_true), NULL);
/* true */
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
@@ -170,7 +176,7 @@
/* false */
gbinder_buffer_free(data.buffer);
data.buffer = gbinder_buffer_new(driver,
- g_memdup(&in_false, sizeof(in_false)), sizeof(in_false));
+ g_memdup(&in_false, sizeof(in_false)), sizeof(in_false), NULL);
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, NULL));
@@ -204,7 +210,7 @@
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
- sizeof(in));
+ sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_uint32(&reader, &out1));
@@ -243,7 +249,7 @@
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
- sizeof(in));
+ sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_uint64(&reader, &out1));
@@ -282,7 +288,7 @@
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
- sizeof(in));
+ sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_float(&reader, &out1));
@@ -321,7 +327,7 @@
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
- sizeof(in));
+ sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_double(&reader, &out1));
@@ -386,7 +392,7 @@
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
- test->in_size);
+ test->in_size, NULL);
gbinder_reader_init(&reader, &data, 0, test->in_size);
str = gbinder_reader_read_string8(&reader);
@@ -445,6 +451,8 @@
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
+ gunichar2* out2 = NULL;
+ gsize len = 0;
char dummy;
char* out = &dummy;
@@ -452,7 +460,17 @@
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(test_string16_in_null)),
- sizeof(test_string16_in_null));
+ sizeof(test_string16_in_null), 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));
@@ -485,12 +503,30 @@
GBinderReader reader;
GBinderReaderData data;
const gboolean valid = (test->out != NULL);
+ gunichar2* out2 = NULL;
+ gsize len = 0;
char* str = NULL;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
- test->in_size);
+ test->in_size, NULL);
+
+ 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);
@@ -566,7 +602,7 @@
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);
+ g_memdup(test->in, test->in_size), test->in_size, NULL);
GBinderReaderData data;
GBinderReader reader;
@@ -603,7 +639,7 @@
static const guint test_hidl_vec_2offsets [] = { 0, BUFFER_OBJECT_SIZE_64 };
static const guint8 test_hidl_vec_2bytes_data [] = { 0x01, 0x02 };
-static const HidlVec test_hidl_vec_2bytes = {
+static const GBinderHidlVec test_hidl_vec_2bytes = {
.data.ptr = test_hidl_vec_2bytes_data,
sizeof(test_hidl_vec_2bytes_data),
TRUE
@@ -612,81 +648,81 @@
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_2bytes },
- sizeof(HidlVec), 0, 0
+ sizeof(GBinderHidlVec), 0, 0
},{
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
{ test_hidl_vec_2bytes_data },
sizeof(test_hidl_vec_2bytes_data), 0,
- HIDL_VEC_BUFFER_OFFSET
+ GBINDER_HIDL_VEC_BUFFER_OFFSET
}
};
-static const HidlVec test_hidl_vec_empty = {
+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(HidlVec), 0, 0
+ sizeof(GBinderHidlVec), 0, 0
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_remote_reply/unit_remote_reply.c
^
|
@@ -59,7 +59,7 @@
g_assert(!gbinder_remote_reply_ref(NULL));
gbinder_remote_reply_unref(NULL);
- gbinder_remote_reply_set_data(NULL, NULL, NULL);
+ gbinder_remote_reply_set_data(NULL, NULL);
gbinder_remote_reply_init_reader(NULL, &reader);
g_assert(gbinder_reader_at_end(&reader));
g_assert(gbinder_remote_reply_is_empty(NULL));
@@ -85,8 +85,8 @@
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, NULL, 0), NULL);
+ gbinder_remote_reply_set_data(reply,
+ gbinder_buffer_new(driver, NULL, 0, NULL));
g_assert(gbinder_remote_reply_is_empty(reply));
gbinder_remote_reply_unref(reply);
@@ -132,8 +132,7 @@
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
- g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data)),
- NULL);
+ g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data), NULL));
g_assert(!gbinder_remote_reply_is_empty(reply));
g_assert(gbinder_remote_reply_read_uint32(reply, &out1));
@@ -163,8 +162,7 @@
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
- g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data)),
- NULL);
+ g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data), NULL));
g_assert(!gbinder_remote_reply_is_empty(reply));
g_assert(gbinder_remote_reply_read_uint64(reply, &out1));
@@ -192,8 +190,7 @@
GBinderRemoteReply* reply = gbinder_remote_reply_new(NULL);
gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
- g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data)),
- NULL);
+ g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data), NULL));
g_assert(!gbinder_remote_reply_is_empty(reply));
g_assert(!g_strcmp0(gbinder_remote_reply_read_string8(reply), "bar"));
@@ -221,8 +218,7 @@
char* str;
gbinder_remote_reply_set_data(reply, gbinder_buffer_new(driver,
- g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data)),
- NULL);
+ g_memdup(reply_data, sizeof(reply_data)), sizeof(reply_data), NULL));
g_assert(!gbinder_remote_reply_is_empty(reply));
str = gbinder_remote_reply_read_string16(reply);
@@ -264,7 +260,7 @@
/* 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);
+ sizeof(reply_data), objects));
/* Convert to GBinderLocalReply */
req2 = gbinder_remote_reply_copy_to_local(req);
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_remote_request/unit_remote_request.c
^
|
@@ -71,8 +71,10 @@
g_assert(!gbinder_remote_request_ref(NULL));
gbinder_remote_request_unref(NULL);
- gbinder_remote_request_set_data(NULL, NULL, NULL);
+ gbinder_remote_request_set_data(NULL, 0, NULL);
gbinder_remote_request_init_reader(NULL, &reader);
+ gbinder_remote_request_block(NULL);
+ gbinder_remote_request_complete(NULL, NULL, 0);
g_assert(gbinder_reader_at_end(&reader));
g_assert(!gbinder_remote_request_interface(NULL));
g_assert(!gbinder_remote_request_copy_to_local(NULL));
@@ -100,6 +102,10 @@
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
gbinder_rpc_protocol_for_device(NULL), 0, 0);
+ /* These two calls are wrong but won't cause problems: */
+ gbinder_remote_request_block(req);
+ gbinder_remote_request_complete(req, NULL, 0);
+
gbinder_remote_request_init_reader(req, &reader);
g_assert(gbinder_reader_at_end(&reader));
g_assert(!gbinder_remote_request_interface(req));
@@ -118,7 +124,7 @@
test_int32(
void)
{
- static const guint8 request_data [] = {
+ static const guint8 req_data [] = {
TEST_RPC_HEADER,
TEST_INT32_BYTES(42)
};
@@ -129,9 +135,9 @@
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
gbinder_rpc_protocol_for_device(dev), 0, 0);
- gbinder_remote_request_set_data(req, gbinder_buffer_new(driver,
- g_memdup(request_data, sizeof(request_data)), sizeof(request_data)),
- NULL);
+ gbinder_remote_request_set_data(req, GBINDER_FIRST_CALL_TRANSACTION,
+ gbinder_buffer_new(driver, g_memdup(req_data, sizeof(req_data)),
+ sizeof(req_data), NULL));
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), TEST_RPC_IFACE));
g_assert(gbinder_remote_request_read_uint32(req, &out1));
@@ -152,7 +158,7 @@
test_int64(
void)
{
- static const guint8 request_data [] = {
+ static const guint8 req_data [] = {
TEST_RPC_HEADER,
TEST_INT64_BYTES(42)
};
@@ -163,9 +169,9 @@
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
gbinder_rpc_protocol_for_device(dev), 0, 0);
- gbinder_remote_request_set_data(req, gbinder_buffer_new(driver,
- g_memdup(request_data, sizeof(request_data)), sizeof(request_data)),
- NULL);
+ gbinder_remote_request_set_data(req, GBINDER_FIRST_CALL_TRANSACTION,
+ gbinder_buffer_new(driver, g_memdup(req_data, sizeof(req_data)),
+ sizeof(req_data), NULL));
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), TEST_RPC_IFACE));
g_assert(gbinder_remote_request_read_uint64(req, &out1));
@@ -186,7 +192,7 @@
test_string8(
void)
{
- static const guint8 request_data [] = {
+ static const guint8 req_data [] = {
TEST_RPC_HEADER,
'b', 'a', 'r', 0x00
};
@@ -195,9 +201,9 @@
GBinderRemoteRequest* req = gbinder_remote_request_new(NULL,
gbinder_rpc_protocol_for_device(dev), 0, 0);
- gbinder_remote_request_set_data(req, gbinder_buffer_new(driver,
- g_memdup(request_data, sizeof(request_data)), sizeof(request_data)),
- NULL);
+ gbinder_remote_request_set_data(req, GBINDER_FIRST_CALL_TRANSACTION,
+ gbinder_buffer_new(driver, g_memdup(req_data, sizeof(req_data)),
+ sizeof(req_data), NULL));
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), TEST_RPC_IFACE));
g_assert(!g_strcmp0(gbinder_remote_request_read_string8(req), "bar"));
@@ -215,7 +221,7 @@
test_string16(
void)
{
- static const guint8 request_data [] = {
+ static const guint8 req_data [] = {
TEST_RPC_HEADER,
TEST_INT32_BYTES(3),
TEST_INT16_BYTES('b'), TEST_INT16_BYTES('a'),
@@ -227,9 +233,9 @@
gbinder_rpc_protocol_for_device(dev), 0, 0);
char* str;
- gbinder_remote_request_set_data(req, gbinder_buffer_new(driver,
- g_memdup(request_data, sizeof(request_data)), sizeof(request_data)),
- NULL);
+ gbinder_remote_request_set_data(req, GBINDER_FIRST_CALL_TRANSACTION,
+ gbinder_buffer_new(driver, g_memdup(req_data, sizeof(req_data)),
+ sizeof(req_data), NULL));
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), TEST_RPC_IFACE));
str = gbinder_remote_request_read_string16(req);
@@ -272,8 +278,8 @@
/* 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);
+ gbinder_remote_request_set_data(req, GBINDER_FIRST_CALL_TRANSACTION,
+ gbinder_buffer_new(driver, req_data, sizeof(request_data), objects));
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), TEST_RPC_IFACE));
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_servicemanager/Makefile
^
|
@@ -0,0 +1,5 @@
+# -*- Mode: makefile-gmake -*-
+
+EXE = unit_servicemanager
+
+include ../common/Makefile
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_servicemanager/unit_servicemanager.c
^
|
@@ -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
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_servicepoll/Makefile
^
|
@@ -0,0 +1,5 @@
+# -*- Mode: makefile-gmake -*-
+
+EXE = unit_servicepoll
+
+include ../common/Makefile
|
[-]
[+]
|
Added |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_servicepoll/unit_servicepoll.c
^
|
@@ -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));
|
[-]
[+]
|
Changed |
_service:tar_git:libgbinder-1.0.21.tar.bz2/unit/unit_writer/unit_writer.c
^
|
@@ -39,6 +39,8 @@
#include <gutil_intarray.h>
+#include <unistd.h>
+
static TestOpt test_opt;
#define BUFFER_OBJECT_SIZE_32 (24)
@@ -74,8 +76,10 @@
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_fd(NULL, 0);
gbinder_writer_append_bytes(NULL, NULL, 0);
gbinder_writer_append_bytes(&writer, NULL, 0);
gbinder_writer_append_hidl_vec(NULL, NULL, 0, 0);
@@ -93,9 +97,50 @@
gbinder_writer_append_remote_object(&writer, NULL);
gbinder_writer_append_byte_array(NULL, NULL, 0);
gbinder_writer_append_byte_array(&writer, NULL, 0);
+ gbinder_writer_add_cleanup(NULL, NULL, 0);
+ gbinder_writer_add_cleanup(NULL, g_free, 0);
g_assert(!gbinder_output_data_offsets(NULL));
g_assert(!gbinder_output_data_buffers_size(NULL));
+ g_assert(!gbinder_writer_malloc(NULL, 0));
+ g_assert(!gbinder_writer_malloc0(NULL, 0));
+ g_assert(!gbinder_writer_memdup(&writer, NULL, 0));
+ g_assert(!gbinder_writer_memdup(NULL, &writer, 0));
+}
+
+/*==========================================================================*
+ * cleanup
+ *==========================================================================*/
+
+static
+void
+test_cleanup_fn(
+ gpointer ptr)
+{
+ (*((int*)ptr))++;
+}
+
+static
+void
+test_cleanup(
+ void)
+{
+ GBinderLocalRequest* req = gbinder_local_request_new(&gbinder_io_32, NULL);
+ GBinderWriter writer;
+ int cleanup_count = 0;
+ int value = 42;
+ int* zero;
+ int* copy;
+
+ gbinder_local_request_init_writer(req, &writer);
+ zero = gbinder_writer_new0(&writer, int);
+ copy = gbinder_writer_memdup(&writer, &value, sizeof(value));
+ g_assert(*zero == 0);
+ g_assert(*copy == value);
+ gbinder_writer_add_cleanup(&writer, test_cleanup_fn, &cleanup_count);
+ gbinder_writer_add_cleanup(&writer, test_cleanup_fn, &cleanup_count);
+ gbinder_local_request_unref(req);
+ g_assert(cleanup_count == 2);
}
/*==========================================================================*
@@ -119,6 +164,19 @@
g_assert(!gbinder_output_data_buffers_size(data));
g_assert(data->bytes->len == sizeof(value));
g_assert(!memcmp(data->bytes->data, &value, data->bytes->len));
+
+ const guint32 value2 = 2345678;
+ gbinder_writer_overwrite_int32(&writer, 0, value2);
+ 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(value2));
+ g_assert(!memcmp(data->bytes->data, &value2, data->bytes->len));
+
+ // test overlap over the end of the buffer
+ gbinder_writer_overwrite_int32(&writer, 2, value2);
+ g_assert(data->bytes->len == sizeof(value2));
+
gbinder_local_request_unref(req);
}
@@ -204,9 +262,9 @@
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;
@@ -343,6 +401,75 @@
}
/*==========================================================================*
+ * 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
*==========================================================================*/
@@ -366,15 +493,15 @@
static const TestHidlVecData test_hidl_vec_tests[] = {
{ "32/null", &gbinder_io_32, NULL, 0, 0,
- TEST_ARRAY_AND_COUNT(test_hidl_vec_offsets_0), sizeof(HidlVec) },
+ 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(HidlVec) + 8 /* vec data aligned at 8 bytes boundary */ },
+ 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(HidlVec) },
+ 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(HidlVec) + 8 /* vec data aligned at 8 bytes boundary */ }
+ sizeof(GBinderHidlVec) + 8 /* vec data aligned at 8 bytes boundary */ }
};
static
|