Compare commits

...

11 Commits

Author SHA1 Message Date
Slava Monich
84efc32ac0 Version 1.1.32 2023-01-23 11:49:21 +02:00
Slava Monich
88388de696 [license] Freshened up copyright 2023-01-23 11:46:19 +02:00
Slava Monich
daa062d981 Merge pull request #113 from monich/unit-tests
Improve reliability of unit tests
2023-01-23 11:27:39 +02:00
Slava Monich
85db18f663 [unit] Handle servicemanager requests on looper thread. JB#42956
Because tests are using synchronous calls blocking the main thread,
2023-01-23 01:29:58 +02:00
Slava Monich
af796828a4 [unit] Fixed possible deadlock in proxy_object test. JB#42956
The /proxy_object/param test could be deadlocked by gbinder_ipc_exit()
blocking the main thread and waiting for all client threads to terminate
one of which waiting for the transaction (the one getting cancelled) to
complete on the main thread blocked by gbinder_ipc_exit().

The deadlock is avoided by making sure that both transactions get completed
before gbinder_ipc_exit() is called.
2023-01-22 04:35:22 +02:00
Slava Monich
885d27c12c Version 1.1.31 2023-01-04 19:14:49 +02:00
Slava Monich
38f156a8ba Merge pull request #110 from monich/binder-test
Refactor binder simulation used by unit tests
2023-01-04 19:02:48 +02:00
Slava Monich
d7eacd455f [unit] Refactored binder simulation. JB#42956
The old one was way too hackish and prone to race conditions.
This one is more accurate and hopefully more reliable.
2023-01-04 14:42:19 +02:00
Slava Monich
b1a3dc5c64 [gbinder] Improved handling of multiple gbinder_ipc_exit() calls
Needed primarily for unit testing.
2023-01-03 12:49:04 +02:00
Slava Monich
98ad09e803 Merge pull request #112 from monich/big-endian
Fix serialization issues on big-endian systems
2023-01-03 12:42:44 +02:00
Slava Monich
c94ccbd8bf [gbinder] Fixed serialization issues on big-endian. JB#42956
Note that libhwbinder and libbinder encode TRUE value differently
on big-endian machines (0x01 becomes either first or last of 4 bytes)
but reading uint32 and comparing it with zero works in either case.
2023-01-03 01:56:18 +02:00
29 changed files with 2035 additions and 2081 deletions

View File

@@ -1,5 +1,5 @@
Copyright (C) 2018-2022 Jolla Ltd.
Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
Copyright (C) 2023 Slava Monich <slava@monich.com>
You may use this file under the terms of BSD license as follows:

View File

@@ -16,7 +16,7 @@
VERSION_MAJOR = 1
VERSION_MINOR = 1
VERSION_RELEASE = 30
VERSION_RELEASE = 32
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)

13
debian/changelog vendored
View File

@@ -1,3 +1,16 @@
libgbinder (1.1.32) unstable; urgency=low
* Improved reliability of unit tests
-- Slava Monich <slava@monich.com> Mon, 23 Jan 2023 11:48:00 +0200
libgbinder (1.1.31) unstable; urgency=low
* Fixed serialization issues on big-endian
* Refactored binder simulation for unit tests
-- Slava Monich <slava@monich.com> Wed, 04 Jan 2023 19:10:37 +0200
libgbinder (1.1.30) unstable; urgency=low
* Fixed BC_ACQUIRE_DONE encoding

2
debian/copyright vendored
View File

@@ -1,5 +1,5 @@
Copyright (C) 2018-2022 Jolla Ltd.
Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
Copyright (C) 2023 Slava Monich <slava@monich.com>
You may use this file under the terms of BSD license as follows:

View File

@@ -1,6 +1,6 @@
Name: libgbinder
Version: 1.1.30
Version: 1.1.32
Release: 0
Summary: Binder client library
License: BSD

View File

@@ -2194,7 +2194,6 @@ gbinder_ipc_exit()
for (i = ipcs; i; i = i->next) {
GBinderIpc* ipc = THIS(i->data);
GBinderIpcPriv* priv = ipc->priv;
GThreadPool* pool = priv->tx_pool;
GSList* local_objs = NULL;
GSList* tx_keys = NULL;
GSList* k;
@@ -2205,8 +2204,12 @@ gbinder_ipc_exit()
gbinder_ipc_stop_loopers(ipc);
/* Make sure pooled transaction complete too */
priv->tx_pool = NULL;
g_thread_pool_free(pool, FALSE, TRUE);
if (priv->tx_pool) {
GThreadPool* pool = priv->tx_pool;
priv->tx_pool = NULL;
g_thread_pool_free(pool, FALSE, TRUE);
}
/*
* Since this function is supposed to be invoked on the main thread,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -124,17 +124,24 @@ gbinder_reader_read_bool(
GBinderReader* reader,
gboolean* value)
{
GBinderReaderPriv* p = gbinder_reader_cast(reader);
/*
* Android's libhwbinder writes bool as a single byte and pads it
* with zeros, but libbinder writes bool as int32 in native byte
* order. The latter becomes either [0x01, 0x00, 0x00, 0x00] or
* [0x00, 0x00, 0x00, 0x01] depending on the byte order. Reading
* uint32 and comparing it with zero works in either case.
*/
if (value) {
guint32 padded;
/* Boolean values are supposed to be padded to 4-byte boundary */
if (gbinder_reader_can_read(p, 4)) {
if (value) {
*value = (p->ptr[0] != 0);
if (gbinder_reader_read_uint32(reader, &padded)) {
*value = (padded != 0);
return TRUE;
} else {
return FALSE;
}
p->ptr += 4;
return TRUE;
} else {
return FALSE;
return gbinder_reader_read_uint32(reader, NULL);
}
}
@@ -151,18 +158,17 @@ gbinder_reader_read_uint8(
GBinderReader* reader,
guint8* value) /* Since 1.1.15 */
{
/* Primitive values are supposed to be padded to 4-byte boundary */
if (value) {
guint32 padded;
GBinderReaderPriv* p = gbinder_reader_cast(reader);
if (gbinder_reader_read_uint32(reader, &padded)) {
*value = (guint8)padded;
return TRUE;
} else {
return FALSE;
/* Primitive values are supposed to be padded to 4-byte boundary */
if (gbinder_reader_can_read(p, 4)) {
if (value) {
*value = p->ptr[0];
}
p->ptr += 4;
return TRUE;
} else {
return gbinder_reader_read_uint32(reader, NULL);
return FALSE;
}
}
@@ -179,18 +185,17 @@ gbinder_reader_read_uint16(
GBinderReader* reader,
guint16* value) /* Since 1.1.15 */
{
/* Primitive values are supposed to be padded to 4-byte boundary */
if (value) {
guint32 padded;
GBinderReaderPriv* p = gbinder_reader_cast(reader);
if (gbinder_reader_read_uint32(reader, &padded)) {
*value = (guint16)padded;
return TRUE;
} else {
return FALSE;
/* Primitive values are supposed to be padded to 4-byte boundary */
if (gbinder_reader_can_read(p, 4)) {
if (value) {
*value = *(guint16*)p->ptr;
}
p->ptr += 4;
return TRUE;
} else {
return gbinder_reader_read_uint32(reader, NULL);
return FALSE;
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -212,6 +212,23 @@ gbinder_writer_bytes_written(
return G_LIKELY(data) ? data->bytes->len : 0;
}
static
void
gbinder_writer_data_append_padded(
GByteArray* buf,
const void* data,
guint size)
{
/* Primitive values are padded to 4-byte boundary */
const guint padded_size = 4;
guint8* ptr;
g_byte_array_set_size(buf, buf->len + padded_size);
ptr = buf->data + (buf->len - padded_size);
memcpy(ptr, data, size);
memset(ptr + size, 0, padded_size - size);
}
void
gbinder_writer_append_bool(
GBinderWriter* self,
@@ -229,8 +246,9 @@ gbinder_writer_data_append_bool(
GBinderWriterData* data,
gboolean value)
{
/* Primitive values are padded to 4-byte boundary */
gbinder_writer_data_append_int32(data, value != FALSE);
const guint8 b = (value != FALSE);
gbinder_writer_data_append_padded(data->bytes, &b, sizeof(b));
}
void
@@ -241,8 +259,7 @@ gbinder_writer_append_int8(
GBinderWriterData* data = gbinder_writer_data(self);
if (G_LIKELY(data)) {
/* Primitive values are padded to 4-byte boundary */
gbinder_writer_data_append_int32(data, value);
gbinder_writer_data_append_padded(data->bytes, &value, sizeof(value));
}
}
@@ -254,8 +271,7 @@ gbinder_writer_append_int16(
GBinderWriterData* data = gbinder_writer_data(self);
if (G_LIKELY(data)) {
/* Primitive values are padded to 4-byte boundary */
gbinder_writer_data_append_int32(data, value);
gbinder_writer_data_append_padded(data->bytes, &value, sizeof(value));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -45,56 +45,72 @@
#define BINDER_OBJECT_SIZE_32 (16)
#define BINDER_OBJECT_SIZE_64 (24)
typedef struct test_binder TestBinder;
typedef enum test_br_thread {
THIS_THREAD = -3,
LOOPER_THREAD = -2,
TX_THREAD = -1,
ANY_THREAD = 0
} TEST_BR_THREAD;
void
test_binder_br_noop(
int fd);
int fd,
TEST_BR_THREAD dest);
void
test_binder_br_increfs(
int fd,
TEST_BR_THREAD dest,
void* ptr);
void
test_binder_br_acquire(
int fd,
TEST_BR_THREAD dest,
void* ptr);
void
test_binder_br_release(
int fd,
TEST_BR_THREAD dest,
void* ptr);
void
test_binder_br_decrefs(
int fd,
TEST_BR_THREAD dest,
void* ptr);
void
test_binder_br_transaction_complete(
int fd);
void
test_binder_br_transaction_complete_later(
int fd);
int fd,
TEST_BR_THREAD dest);
void
test_binder_br_dead_binder(
int fd,
TEST_BR_THREAD dest,
guint handle);
void
test_binder_br_dead_binder_obj(
int fd,
GBinderLocalObject* obj);
void
test_binder_br_dead_reply(
int fd);
int fd,
TEST_BR_THREAD dest);
void
test_binder_br_failed_reply(
int fd);
int fd,
TEST_BR_THREAD dest);
void
test_binder_br_transaction(
int fd,
TEST_BR_THREAD dest,
void* target,
guint32 code,
const GByteArray* bytes);
@@ -102,6 +118,7 @@ test_binder_br_transaction(
void
test_binder_br_reply(
int fd,
TEST_BR_THREAD dest,
guint32 handle,
guint32 code,
const GByteArray* bytes);
@@ -109,35 +126,12 @@ test_binder_br_reply(
void
test_binder_br_reply_status(
int fd,
TEST_BR_THREAD dest,
gint32 status);
void
test_binder_br_reply_later(
int fd,
guint32 handle,
guint32 code,
const GByteArray* bytes);
void
test_binder_br_reply_status_later(
int fd,
gint32 status);
typedef enum test_looper {
TEST_LOOPER_DISABLE,
TEST_LOOPER_ENABLE,
TEST_LOOPER_ENABLE_ONE
} TEST_LOOPER;
void
test_binder_set_looper_enabled(
int fd,
TEST_LOOPER value);
void
test_binder_set_passthrough(
int fd,
gboolean passthrough);
test_binder_ignore_dead_object(
int fd);
int
test_binder_handle(

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2021-2022 Jolla Ltd.
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -277,9 +277,10 @@ test_servicemanager_hidl_add(
const char* sep = strrchr(instance, '/');
GDEBUG("Adding '%s'", instance);
/* Transfer remote_obj reference to the hashtable */
g_hash_table_replace(self->objects, g_strdup(instance), remote_obj);
if (sep) {
/* Alread know the interface */
/* Already know the interface */
char* iface = g_strndup(instance, sep - instance);
test_servicemanager_hidl_notify_all(self, iface, sep + 1, FALSE);
@@ -350,7 +351,7 @@ test_servicemanager_hidl_register_for_notifications(
iface = gbinder_reader_read_hidl_string_c(&reader);
instance = gbinder_reader_read_hidl_string_c(&reader);
watcher = gbinder_reader_read_object(&reader);
if (watcher) {
GBinderClient* wc = gbinder_client_new(watcher, NOTIFICATION_IFACE);
GHashTableIter it;
@@ -481,6 +482,38 @@ test_servicemanager_hidl_lookup(
return object;
}
gboolean
test_servicemanager_hidl_remove(
TestServiceManagerHidl* self,
const char* fqname)
{
gboolean removed = FALSE;
if (self) {
GBinderRemoteObject* obj;
/* Lock */
g_mutex_lock(&self->mutex);
obj = g_hash_table_lookup(self->objects, fqname);
if (obj) {
GHashTableIter it;
gpointer key, value;
g_hash_table_iter_init(&it, self->objects);
while (g_hash_table_iter_next(&it, &key, &value)) {
if (value == obj) {
GDEBUG("Removed name '%s' => %p", (char*) key, value);
g_hash_table_iter_remove(&it);
removed = TRUE;
}
}
}
g_mutex_unlock(&self->mutex);
/* Unlock */
}
return removed;
}
/*==========================================================================*
* Internals
*==========================================================================*/

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2021-2022 Jolla Ltd.
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -58,6 +58,11 @@ test_servicemanager_hidl_lookup(
TestServiceManagerHidl* self,
const char* name);
gboolean
test_servicemanager_hidl_remove(
TestServiceManagerHidl* self,
const char* fqname);
#endif /* TEST_SERVICEMANAGER_HIDL_H */
/*

View File

@@ -52,9 +52,7 @@
static TestOpt test_opt;
#define SRC_DEV "/dev/srcbinder"
#define SRC_PRIV_DEV SRC_DEV "-private"
#define DEST_DEV "/dev/dstbinder"
#define DEST_PRIV_DEV DEST_DEV "-private"
#define TEST_IFACE "gbinder@1.0::ITest"
#define TX_CODE GBINDER_FIRST_CALL_TRANSACTION
@@ -74,75 +72,6 @@ typedef struct test_config {
char* file;
} TestConfig;
/*==========================================================================*
* Test object (registered with two GBinderIpc's)
*==========================================================================*/
typedef GBinderLocalObjectClass TestLocalObjectClass;
typedef struct test_local_object {
GBinderLocalObject parent;
GBinderIpc* ipc2;
} TestLocalObject;
G_DEFINE_TYPE(TestLocalObject, test_local_object, GBINDER_TYPE_LOCAL_OBJECT)
#define TEST_TYPE_LOCAL_OBJECT test_local_object_get_type()
#define TEST_LOCAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
TEST_TYPE_LOCAL_OBJECT, TestLocalObject))
TestLocalObject*
test_local_object_new(
GBinderIpc* ipc,
GBinderIpc* ipc2,
const char* const* ifaces,
GBinderLocalTransactFunc txproc,
void* user_data)
{
TestLocalObject* self = TEST_LOCAL_OBJECT
(gbinder_local_object_new_with_type(TEST_TYPE_LOCAL_OBJECT,
ipc, ifaces, txproc, user_data));
self->ipc2 = gbinder_ipc_ref(ipc2);
gbinder_ipc_register_local_object(ipc2, &self->parent);
return self;
}
static
void
test_local_object_dispose(
GObject* object)
{
TestLocalObject* self = TEST_LOCAL_OBJECT(object);
gbinder_ipc_local_object_disposed(self->ipc2, &self->parent);
G_OBJECT_CLASS(test_local_object_parent_class)->dispose(object);
}
static
void
test_local_object_finalize(
GObject* object)
{
gbinder_ipc_unref(TEST_LOCAL_OBJECT(object)->ipc2);
G_OBJECT_CLASS(test_local_object_parent_class)->finalize(object);
}
static
void
test_local_object_init(
TestLocalObject* self)
{
}
static
void
test_local_object_class_init(
TestLocalObjectClass* klass)
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->dispose = test_local_object_dispose;
object_class->finalize = test_local_object_finalize;
}
/*==========================================================================*
* Common
*==========================================================================*/
@@ -187,7 +116,6 @@ test_servicemanager_impl_new(
const int fd = gbinder_driver_fd(ipc->driver);
TestServiceManagerHidl* sm = test_servicemanager_hidl_new(ipc);
test_binder_set_looper_enabled(fd, TRUE);
test_binder_register_object(fd, GBINDER_LOCAL_OBJECT(sm),
GBINDER_SERVICEMANAGER_HANDLE);
gbinder_ipc_unref(ipc);
@@ -338,18 +266,15 @@ test_basic_run(
GBinderServiceManager* src;
GBinderServiceManager* dest;
GBinderIpc* src_ipc;
GBinderIpc* src_priv_ipc;
GBinderIpc* dest_ipc;
GBinderIpc* dest_priv_ipc;
GBinderBridge* bridge;
TestLocalObject* obj;
GBinderRemoteObject* br_src_obj;
GBinderLocalObject* obj;
GBinderRemoteObject* src_obj;
GBinderLocalRequest* req;
GBinderClient* src_client;
const char* name = "test";
const char* fqname = TEST_IFACE "/test";
int src_fd, dest_fd, h, n = 0;
int src_fd, dest_fd, n = 0;
gulong id;
test_config_init(&config, NULL);
@@ -358,21 +283,14 @@ test_basic_run(
/* obj (DEST) <=> bridge <=> (SRC) mirror */
src_ipc = gbinder_ipc_new(SRC_DEV, NULL);
src_priv_ipc = gbinder_ipc_new(SRC_PRIV_DEV, NULL);
dest_ipc = gbinder_ipc_new(DEST_DEV, NULL);
dest_priv_ipc = gbinder_ipc_new(DEST_PRIV_DEV, NULL);
test.src_impl = test_servicemanager_impl_new(SRC_PRIV_DEV);
dest_impl = test_servicemanager_impl_new(DEST_PRIV_DEV);
test.src_impl = test_servicemanager_impl_new(SRC_DEV);
dest_impl = test_servicemanager_impl_new(DEST_DEV);
src_fd = gbinder_driver_fd(src_ipc->driver);
dest_fd = gbinder_driver_fd(dest_ipc->driver);
obj = test_local_object_new(dest_ipc, dest_priv_ipc, TEST_IFACES,
test_basic_cb, &n);
obj = gbinder_local_object_new(dest_ipc, TEST_IFACES, test_basic_cb, &n);
/* Set up binder simulator */
test_binder_set_passthrough(src_fd, TRUE);
test_binder_set_passthrough(dest_fd, TRUE);
test_binder_set_looper_enabled(src_fd, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(dest_fd, TEST_LOOPER_ENABLE);
src = gbinder_servicemanager_new(SRC_DEV);
dest = gbinder_servicemanager_new(DEST_DEV);
@@ -387,7 +305,7 @@ test_basic_run(
/* Register the object and wait for completion */
GDEBUG("Registering object '%s' => %p", name, obj);
g_assert(gbinder_servicemanager_add_service(dest, name, &obj->parent,
g_assert(gbinder_servicemanager_add_service(dest, name, obj,
test_basic_add_cb, &test));
/* This loop quits after the name is added and notification is received */
@@ -398,25 +316,12 @@ test_basic_run(
gbinder_servicemanager_remove_handler(src, id);
/* Get a remote reference to the object created by the bridge */
br_src_obj = gbinder_servicemanager_get_service_sync(src, fqname, NULL);
g_assert(gbinder_remote_object_ref(br_src_obj)); /* autoreleased */
g_assert(!br_src_obj->dead);
/*
* This is a trick specific to test_binder simulation. We need to
* associate src_obj with the other side of the socket, so that the
* call goes like this:
*
* src_obj (src_priv) => (src) bridge (dest) => (dest_priv) => obj
*
* Note that the original src_obj gets autoreleased and doesn't need
* to be explicitly unreferenced.
*/
src_obj = gbinder_remote_object_new(src_priv_ipc,
br_src_obj->handle, REMOTE_OBJECT_CREATE_ALIVE);
src_obj = gbinder_servicemanager_get_service_sync(src, fqname, NULL);
g_assert(!src_obj->dead);
/* Make a call */
GDEBUG("Submitting a call");
/* src_client will hold a reference to src_obj */
src_client = gbinder_client_new(src_obj, TEST_IFACE);
req = gbinder_client_new_request(src_client);
gbinder_local_request_append_int32(req, TX_PARAM);
@@ -427,40 +332,38 @@ test_basic_run(
/* Wait for completion */
test_run(&test_opt, test.loop);
/* Kill the destination object and wait for auto-created object to die */
g_assert(!br_src_obj->dead);
id = gbinder_remote_object_add_death_handler(br_src_obj, test_basic_death,
/* Kill the objects and wait for one of them to die */
g_assert(!src_obj->dead);
id = gbinder_remote_object_add_death_handler(src_obj, test_basic_death,
test.loop);
h = test_binder_handle(dest_fd, &obj->parent);
g_assert_cmpint(h, > ,0); /* Zero is servicemanager */
GDEBUG("Killing destination object, handle %d", h);
gbinder_local_object_drop(&obj->parent);
test_binder_br_dead_binder(dest_fd, h);
g_assert(test_servicemanager_hidl_remove(dest_impl, fqname));
GDEBUG("Killing destination objects");
/*
* Need these BR_DEAD_BINDER because both servicemanagers and the
* bridge live inside the same process and reference the same objects.
* BR_DEAD_BINDER forces the bridge (proxy) to drop its reference.
*/
test_binder_br_dead_binder_obj(dest_fd, obj);
test_binder_br_dead_binder(src_fd, ANY_THREAD, src_obj->handle);
/* Wait for the auto-created object to die */
test_run(&test_opt, test.loop);
g_assert(br_src_obj->dead);
gbinder_remote_object_remove_handler(br_src_obj, id);
g_assert(src_obj->dead);
gbinder_remote_object_remove_handler(src_obj, id);
GDEBUG("Done");
gbinder_local_object_drop(obj);
gbinder_bridge_free(bridge);
gbinder_remote_object_unref(src_obj);
gbinder_remote_object_unref(br_src_obj);
test_servicemanager_hidl_free(test.src_impl);
test_servicemanager_hidl_free(dest_impl);
gbinder_servicemanager_unref(src);
gbinder_servicemanager_unref(dest);
gbinder_client_unref(src_client);
test_binder_unregister_objects(src_fd);
test_binder_unregister_objects(dest_fd);
gbinder_ipc_unref(src_ipc);
gbinder_ipc_unref(src_priv_ipc);
gbinder_ipc_unref(dest_ipc);
gbinder_ipc_unref(dest_priv_ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, test.loop);
test_config_deinit(&config);
g_main_loop_unref(test.loop);

View File

@@ -114,6 +114,7 @@ test_basic(
gbinder_client_unref(client);
gbinder_remote_object_unref(obj);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -175,6 +176,7 @@ test_interfaces(
gbinder_remote_object_unref(obj);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -189,11 +191,12 @@ test_no_header(
GBinderClient* client = test_client_new(0, NULL);
int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
test_binder_br_transaction_complete(fd);
test_binder_ignore_dead_object(fd);
test_binder_br_transaction_complete(fd, THIS_THREAD);
g_assert(gbinder_client_transact_sync_oneway(client, 0, NULL) ==
GBINDER_STATUS_OK);
gbinder_client_unref(client);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -220,10 +223,9 @@ test_dead(
GBinderRemoteObject* obj = client->remote;
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
const int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
gbinder_remote_object_add_death_handler(obj, test_dead_done, loop);
test_binder_br_dead_binder(fd, handle);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
gbinder_remote_object_add_death_handler(obj, test_dead_done, loop);
test_binder_br_dead_binder(fd, ANY_THREAD, handle);
test_run(&test_opt, loop);
g_assert(gbinder_remote_object_is_dead(obj));
@@ -232,7 +234,6 @@ test_dead(
g_assert(!gbinder_client_transact(client, 0, 0, NULL, NULL, NULL, NULL));
gbinder_client_unref(client);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -251,17 +252,18 @@ test_sync_oneway(
int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
g_assert(req);
test_binder_br_transaction_complete(fd);
test_binder_br_transaction_complete(fd, THIS_THREAD);
g_assert(gbinder_client_transact_sync_oneway(client, 0, req) ==
GBINDER_STATUS_OK);
gbinder_local_request_unref(req);
/* Same but using the internal (empty) request */
test_binder_br_transaction_complete(fd);
test_binder_br_transaction_complete(fd, THIS_THREAD);
g_assert(gbinder_client_transact_sync_oneway(client, 0, NULL) ==
GBINDER_STATUS_OK);
gbinder_client_unref(client);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -291,10 +293,11 @@ test_sync_reply_tx(
data = gbinder_local_reply_data(reply);
g_assert(data);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_noop(fd);
test_binder_br_reply(fd, handle, code, data->bytes);
test_binder_ignore_dead_object(fd);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, handle, code, data->bytes);
tx_reply = gbinder_client_transact_sync_reply(client, 0, req, &status);
g_assert(tx_reply);
@@ -323,6 +326,7 @@ test_sync_reply(
test_sync_reply_tx(client, NULL);
gbinder_client_unref(client);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -393,10 +397,11 @@ test_reply_tx(
data = gbinder_local_reply_data(reply);
g_assert(data);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_noop(fd);
test_binder_br_reply(fd, handle, code, data->bytes);
test_binder_ignore_dead_object(fd);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_transaction_complete(fd, TX_THREAD);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_reply(fd, TX_THREAD, handle, code, data->bytes);
id = gbinder_client_transact(client, 0, 0, req, done, destroy, loop);
g_assert(id);
@@ -424,6 +429,7 @@ test_reply(
test_reply_tx(client, NULL, done, destroy);
gbinder_client_unref(client);
test_binder_exit_wait(&test_opt, NULL);
}
static

View File

@@ -82,6 +82,7 @@ test_basic(
g_assert(!gbinder_handler_transact(NULL, NULL, NULL, 0, 0, NULL));
g_assert(!gbinder_handler_can_loop(NULL));
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -98,11 +99,12 @@ test_noop(
g_assert(driver);
g_assert(fd >= 0);
test_binder_br_noop(fd);
test_binder_br_noop(fd, THIS_THREAD);
g_assert(gbinder_driver_poll(driver, NULL) == POLLIN);
g_assert(gbinder_driver_read(driver, NULL, NULL) == 0);
gbinder_driver_unref(driver);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -131,6 +133,7 @@ test_local_request(
g_assert(!memcmp(data->bytes->data, rpc_header, sizeof(rpc_header)));
gbinder_local_request_unref(req);
gbinder_driver_unref(driver);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*

View File

@@ -180,7 +180,6 @@ test_basic(
/* Invalid path */
g_assert(!gbinder_ipc_new("invalid path", NULL));
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
@@ -203,7 +202,6 @@ test_protocol(
gbinder_ipc_unref(ipc);
gbinder_ipc_unref(ipc2);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
@@ -235,7 +233,7 @@ test_async_oneway(
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
gulong id;
test_binder_br_transaction_complete(fd);
test_binder_br_transaction_complete(fd, TX_THREAD);
id = gbinder_ipc_transact(ipc, 0, 1, GBINDER_TX_FLAG_ONEWAY,
req, test_async_oneway_done, NULL, loop);
g_assert(id);
@@ -259,11 +257,10 @@ test_sync_oneway(
GBinderLocalRequest* req = test_local_request_new(ipc);
const int fd = gbinder_driver_fd(ipc->driver);
test_binder_br_transaction_complete(fd);
test_binder_br_transaction_complete(fd, THIS_THREAD);
g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(ipc, 0, 1, req), == ,0);
gbinder_local_request_unref(req);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
@@ -291,10 +288,10 @@ test_sync_reply_ok_status(
data = gbinder_local_reply_data(reply);
g_assert(data);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_noop(fd);
test_binder_br_reply(fd, handle, code, data->bytes);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, handle, code, data->bytes);
tx_reply = gbinder_ipc_sync_main.sync_reply(ipc, handle, code, req, status);
g_assert(tx_reply);
@@ -307,7 +304,6 @@ test_sync_reply_ok_status(
gbinder_local_request_unref(req);
gbinder_local_reply_unref(reply);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
@@ -341,26 +337,27 @@ test_sync_reply_error(
const gint unexpected_status = GBINDER_STATUS_FAILED;
int status = INT_MAX;
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_noop(fd);
test_binder_br_reply_status(fd, expected_status);
test_binder_ignore_dead_object(fd);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_transaction_complete(fd, TX_THREAD);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_reply_status(fd, TX_THREAD, expected_status);
g_assert(!gbinder_ipc_sync_main.sync_reply(ipc,handle,code,req,&status));
g_assert_cmpint(status, == ,expected_status);
/* GBINDER_STATUS_FAILED gets replaced with -EFAULT */
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_noop(fd);
test_binder_br_reply_status(fd, unexpected_status);
test_binder_ignore_dead_object(fd);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_transaction_complete(fd, TX_THREAD);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_reply_status(fd, TX_THREAD, unexpected_status);
g_assert(!gbinder_ipc_sync_main.sync_reply(ipc,handle,code,req,&status));
g_assert_cmpint(status, == ,-EFAULT);
gbinder_local_request_unref(req);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
@@ -414,10 +411,10 @@ test_transact_ok(
data = gbinder_local_reply_data(reply);
g_assert(data);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_noop(fd);
test_binder_br_reply(fd, handle, code, data->bytes);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_transaction_complete(fd, TX_THREAD);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_reply(fd, TX_THREAD, handle, code, data->bytes);
id = gbinder_ipc_transact(ipc, handle, code, 0, req,
test_transact_ok_done, test_transact_ok_destroy, loop);
@@ -430,7 +427,6 @@ test_transact_ok(
gbinder_local_request_unref(req);
gbinder_local_reply_unref(reply);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -464,8 +460,8 @@ test_transact_dead(
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
gulong id;
test_binder_br_noop(fd);
test_binder_br_dead_reply(fd);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_dead_reply(fd, TX_THREAD);
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_dead_done,
NULL, loop);
@@ -477,7 +473,6 @@ test_transact_dead(
gbinder_ipc_cancel(ipc, id);
gbinder_local_request_unref(req);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -511,8 +506,8 @@ test_transact_failed(
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
gulong id;
test_binder_br_noop(fd);
test_binder_br_failed_reply(fd);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_failed_reply(fd, TX_THREAD);
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_failed_done,
NULL, loop);
@@ -524,7 +519,6 @@ test_transact_failed(
gbinder_ipc_cancel(ipc, id);
gbinder_local_request_unref(req);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -560,8 +554,8 @@ test_transact_status(
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
gulong id;
test_binder_br_noop(fd);
test_binder_br_reply_status(fd, EXPECTED_STATUS);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_reply_status(fd, TX_THREAD, EXPECTED_STATUS);
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_status_done,
NULL, loop);
@@ -573,7 +567,6 @@ test_transact_status(
gbinder_ipc_cancel(ipc, id);
gbinder_local_request_unref(req);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -671,7 +664,6 @@ test_transact_custom3(
test_run(&test_opt, loop);
/* Reference to GBinderIpc is released by test_transact_custom3_exec */
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -721,7 +713,6 @@ test_transact_cancel(
test_run(&test_opt, loop);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -767,7 +758,6 @@ test_transact_cancel2(
test_run(&test_opt, loop);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -831,12 +821,13 @@ test_transact_2way_run(
prot->write_rpc_header(&writer, "test");
gbinder_writer_append_string8(&writer, "message");
test_binder_br_transaction(fd, obj, 2,
test_binder_ignore_dead_object(fd);
test_binder_br_transaction(fd, TX_THREAD, obj, 2,
gbinder_local_request_data(req)->bytes);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_noop(fd);
test_binder_br_reply(fd, handle, code,
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_transaction_complete(fd, TX_THREAD);
test_binder_br_noop(fd, TX_THREAD);
test_binder_br_reply(fd, TX_THREAD, handle, code,
gbinder_local_reply_data(reply)->bytes);
/* NB. Reusing test_transact_ok_done and test_transact_ok_destroy */
@@ -855,7 +846,6 @@ test_transact_2way_run(
g_idle_add(test_unref_ipc, ipc);
test_run(&test_opt, loop);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -895,10 +885,6 @@ test_transact_unhandled_run(
GBinderDriver* driver = ipc->driver;
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderLocalRequest* req = gbinder_driver_local_request_new_ping(driver);
int fd = gbinder_driver_fd(driver);
test_binder_set_passthrough(fd, TRUE);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
g_assert(gbinder_ipc_transact(ipc, 1 /* Non-existent object */,
gbinder_driver_protocol(driver)->ping_tx, 0, req,
@@ -907,7 +893,6 @@ test_transact_unhandled_run(
test_run(&test_opt, loop);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -971,13 +956,12 @@ test_transact_incoming_run(
prot->write_rpc_header(&writer, "test");
gbinder_writer_append_string8(&writer, "message");
test_binder_br_transaction(fd, obj, prot->ping_tx,
test_binder_br_transaction(fd, LOOPER_THREAD, obj, prot->ping_tx,
gbinder_local_request_data(ping)->bytes);
test_binder_br_transaction_complete(fd); /* For reply */
test_binder_br_transaction(fd, obj, 1,
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1,
gbinder_local_request_data(req)->bytes);
test_binder_br_transaction_complete(fd); /* For reply */
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
test_run(&test_opt, loop);
/* Now we need to wait until GBinderIpc is destroyed */
@@ -989,7 +973,6 @@ test_transact_incoming_run(
g_idle_add(test_unref_ipc, ipc);
test_run(&test_opt, loop);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -1049,9 +1032,8 @@ test_transact_status_reply_run(
gbinder_writer_append_string8(&writer, "message");
data = gbinder_local_request_data(req);
test_binder_br_transaction(fd, obj, 1, data->bytes);
test_binder_br_transaction_complete(fd); /* For reply */
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE_ONE);
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1, data->bytes);
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
test_run(&test_opt, loop);
/* Now we need to wait until GBinderIpc is destroyed */
@@ -1062,7 +1044,6 @@ test_transact_status_reply_run(
g_idle_add(test_unref_ipc, ipc);
test_run(&test_opt, loop);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -1165,9 +1146,8 @@ test_transact_async_run(
gbinder_writer_append_string8(&writer, "message");
data = gbinder_local_request_data(req);
test_binder_br_transaction(fd, obj, 1, data->bytes);
test_binder_br_transaction_complete(fd); /* For reply */
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE_ONE);
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1, data->bytes);
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
test_run(&test_opt, loop);
/* Now we need to wait until GBinderIpc is destroyed */
@@ -1178,7 +1158,6 @@ test_transact_async_run(
g_idle_add(test_unref_ipc, ipc);
test_run(&test_opt, loop);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -1247,9 +1226,8 @@ test_transact_async_sync_run(
gbinder_writer_append_string8(&writer, "message");
data = gbinder_local_request_data(req);
test_binder_br_transaction(fd, obj, 1, data->bytes);
test_binder_br_transaction_complete(fd); /* For reply */
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE_ONE);
test_binder_br_transaction(fd, LOOPER_THREAD, obj, 1, data->bytes);
test_binder_br_transaction_complete(fd, LOOPER_THREAD); /* For reply */
test_run(&test_opt, loop);
/* Now we need to wait until GBinderIpc is destroyed */
@@ -1260,7 +1238,6 @@ test_transact_async_sync_run(
g_idle_add(test_unref_ipc, ipc);
test_run(&test_opt, loop);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -1301,8 +1278,7 @@ test_drop_remote_refs_run(
gulong id = gbinder_local_object_add_strong_refs_changed_handler(obj,
test_drop_remote_refs_cb, loop);
test_binder_br_acquire(fd, obj);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_br_acquire(fd, ANY_THREAD, obj);
test_run(&test_opt, loop);
g_assert(obj->strong_refs == 1);
@@ -1350,7 +1326,7 @@ test_cancel_on_exit(
int fd = gbinder_driver_fd(ipc->driver);
/* This transaction will be cancelled by gbinder_ipc_exit */
test_binder_br_transaction_complete(fd);
test_binder_br_transaction_complete(fd, TX_THREAD);
gbinder_ipc_transact(ipc, 0, 1, GBINDER_TX_FLAG_ONEWAY,
req, test_cancel_on_exit_not_reached, NULL, NULL);

View File

@@ -188,6 +188,7 @@ test_basic(
g_assert(gbinder_local_object_ref(bar) == bar);
gbinder_local_object_drop(bar);
gbinder_local_object_unref(bar);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -233,6 +234,7 @@ test_ping(
gbinder_local_object_unref(obj);
gbinder_local_reply_unref(reply);
gbinder_remote_request_unref(req);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -282,6 +284,7 @@ test_interface(
gbinder_local_object_unref(obj);
gbinder_local_reply_unref(reply);
gbinder_remote_request_unref(req);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -332,6 +335,7 @@ test_hidl_ping(
gbinder_local_object_unref(obj);
gbinder_local_reply_unref(reply);
gbinder_remote_request_unref(req);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -385,6 +389,7 @@ test_get_descriptor(
gbinder_local_object_unref(obj);
gbinder_local_reply_unref(reply);
gbinder_remote_request_unref(req);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -436,6 +441,7 @@ test_descriptor_chain(
gbinder_local_object_unref(obj);
gbinder_local_reply_unref(reply);
gbinder_remote_request_unref(req);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -546,6 +552,7 @@ test_custom_iface(
gbinder_local_object_unref(obj);
gbinder_local_reply_unref(reply);
gbinder_remote_request_unref(req);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -603,6 +610,7 @@ test_reply_status(
gbinder_ipc_unref(ipc);
gbinder_local_object_unref(obj);
gbinder_remote_request_unref(req);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -634,16 +642,15 @@ test_increfs_run(
test_increfs_cb, loop);
/* ipc is not an object, will be ignored */
test_binder_br_increfs(fd, ipc);
test_binder_br_increfs(fd, obj);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_br_increfs(fd, ANY_THREAD, ipc);
test_binder_br_increfs(fd, ANY_THREAD, obj);
test_run(&test_opt, loop);
g_assert(obj->weak_refs == 1);
gbinder_local_object_remove_handler(obj, id);
gbinder_local_object_unref(obj);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -685,17 +692,16 @@ test_decrefs_run(
test_decrefs_cb, loop);
/* ipc is not an object, will be ignored */
test_binder_br_decrefs(fd, ipc);
test_binder_br_increfs(fd, obj);
test_binder_br_decrefs(fd, obj);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_br_decrefs(fd, ANY_THREAD, ipc);
test_binder_br_increfs(fd, ANY_THREAD, obj);
test_binder_br_decrefs(fd, ANY_THREAD, obj);
test_run(&test_opt, loop);
g_assert(obj->weak_refs == 0);
gbinder_local_object_remove_handler(obj, id);
gbinder_local_object_unref(obj);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -736,16 +742,15 @@ test_acquire_run(
test_acquire_cb, loop);
/* ipc is not an object, will be ignored */
test_binder_br_acquire(fd, ipc);
test_binder_br_acquire(fd, obj);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_br_acquire(fd, ANY_THREAD, ipc);
test_binder_br_acquire(fd, ANY_THREAD, obj);
test_run(&test_opt, loop);
g_assert(obj->strong_refs == 1);
gbinder_local_object_remove_handler(obj, id);
gbinder_local_object_unref(obj);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -786,17 +791,16 @@ test_release_run(
test_release_cb, loop);
/* ipc is not an object, will be ignored */
test_binder_br_release(fd, ipc);
test_binder_br_acquire(fd, obj);
test_binder_br_release(fd, obj);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_br_release(fd, ANY_THREAD, ipc);
test_binder_br_acquire(fd, ANY_THREAD, obj);
test_binder_br_release(fd, ANY_THREAD, obj);
test_run(&test_opt, loop);
g_assert(obj->strong_refs == 0);
gbinder_local_object_remove_handler(obj, id);
gbinder_local_object_unref(obj);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2021-2022 Jolla Ltd.
* Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -50,9 +50,7 @@
static TestOpt test_opt;
#define DEV "/dev/xbinder"
#define DEV_PRIV DEV "-private"
#define DEV2 "/dev/ybinder"
#define DEV2_PRIV DEV2 "-private"
enum test_tx_codes {
TX_CODE = GBINDER_FIRST_CALL_TRANSACTION,
@@ -190,8 +188,7 @@ test_basic_run(
GBinderLocalObject* obj;
GBinderProxyObject* proxy;
GBinderRemoteObject* remote_obj;
GBinderRemoteObject* remote_proxy;
GBinderClient* proxy_client;
GBinderClient* client;
GBinderIpc* ipc_obj;
GBinderIpc* ipc_proxy;
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
@@ -199,29 +196,20 @@ test_basic_run(
test_config_init(&config, NULL);
ipc_proxy = gbinder_ipc_new(DEV, NULL);
ipc_obj = gbinder_ipc_new(DEV_PRIV, NULL);
ipc_obj = gbinder_ipc_new(DEV2, NULL);
fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
fd_obj = gbinder_driver_fd(ipc_obj->driver);
obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_basic_cb, &n);
remote_obj = gbinder_remote_object_new(ipc_proxy,
remote_obj = gbinder_remote_object_new(ipc_obj,
test_binder_register_object(fd_obj, obj, AUTO_HANDLE),
REMOTE_OBJECT_CREATE_ALIVE);
/* remote_proxy(DEV_PRIV) => proxy (DEV) => obj (DEV) => DEV_PRIV */
g_assert(!gbinder_proxy_object_new(NULL, remote_obj));
g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
remote_proxy = gbinder_remote_object_new(ipc_obj,
test_binder_register_object(fd_proxy, &proxy->parent, AUTO_HANDLE),
REMOTE_OBJECT_CREATE_ALIVE);
proxy_client = gbinder_client_new(remote_proxy, TEST_IFACE);
test_binder_set_passthrough(fd_obj, TRUE);
test_binder_set_passthrough(fd_proxy, TRUE);
test_binder_set_looper_enabled(fd_obj, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_proxy, TEST_LOOPER_ENABLE);
client = gbinder_client_new(proxy->remote, TEST_IFACE);
/* Perform a transaction via proxy */
g_assert(gbinder_client_transact(proxy_client, TX_CODE, 0, NULL,
g_assert(gbinder_client_transact(client, TX_CODE, 0, NULL,
test_basic_reply, NULL, loop));
test_run(&test_opt, loop);
@@ -232,11 +220,9 @@ test_basic_run(
gbinder_local_object_drop(obj);
gbinder_local_object_drop(&proxy->parent);
gbinder_remote_object_unref(remote_obj);
gbinder_remote_object_unref(remote_proxy);
gbinder_client_unref(proxy_client);
gbinder_client_unref(client);
gbinder_ipc_unref(ipc_obj);
gbinder_ipc_unref(ipc_proxy);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
test_config_deinit(&config);
g_main_loop_unref(loop);
@@ -259,6 +245,7 @@ gboolean
test_param_cancel(
gpointer req)
{
GDEBUG("Cancelling request");
gbinder_remote_request_complete(req, NULL, -ECANCELED);
return G_SOURCE_REMOVE;
}
@@ -303,6 +290,20 @@ test_param_cb(
}
}
static
void
test_param_canceled(
GBinderClient* client,
GBinderRemoteReply* reply,
int status,
void* loop)
{
g_assert(!reply);
g_assert_cmpint(status, == ,-ECANCELED);
GDEBUG("Transaction cancelled");
g_main_loop_quit((GMainLoop*)loop);
}
static
void
test_param_reply(
@@ -311,35 +312,19 @@ test_param_reply(
int status,
void* loop)
{
/*
* Due to limitations of our binder simulation, the result can be
* delivered to a wrong thread. As a result, we only known that one
* of the callbacks get NULL result and one gets NULL loop, but we
* don't really know which one gets what, i.e. we have to be ready
* for any combination of these parameters.
*
* It's too difficult to fix (without writing almost a full-blown
* binder implementation), let's just live with it for now :/
*/
if (reply) {
GBinderReader reader;
gint32 result = 0;
GBinderReader reader;
gint32 result = 0;
GDEBUG("Reply received");
g_assert(reply);
g_assert_cmpint(status, == ,0);
GDEBUG("Reply received");
/* Make sure that result got delivered intact */
gbinder_remote_reply_init_reader(reply, &reader);
g_assert(gbinder_reader_read_int32(&reader, &result));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpint(result, == ,TX_RESULT);
} else {
/* The cancelled one */
GDEBUG("Transaction cancelled");
}
if (loop) {
g_main_loop_quit((GMainLoop*)loop);
}
/* Make sure that result got delivered intact */
gbinder_remote_reply_init_reader(reply, &reader);
g_assert(gbinder_reader_read_int32(&reader, &result));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpint(result, == ,TX_RESULT);
g_main_loop_quit((GMainLoop*)loop);
}
static
@@ -351,77 +336,60 @@ test_param_run(
GBinderLocalObject* obj;
GBinderProxyObject* proxy;
GBinderRemoteObject* remote_obj;
GBinderRemoteObject* remote_proxy;
GBinderClient* proxy_client;
GBinderClient* client;
GBinderLocalRequest* req;
GBinderIpc* ipc_obj;
GBinderIpc* ipc_remote_obj;
GBinderIpc* ipc_proxy;
GBinderIpc* ipc_remote_proxy;
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GMainLoop* loop2 = g_main_loop_new(NULL, FALSE);
int fd_obj, fd_proxy, n = 0;
test_config_init(&config, NULL);
ipc_obj = gbinder_ipc_new(DEV, NULL);
ipc_remote_obj = gbinder_ipc_new(DEV_PRIV, NULL);
ipc_proxy = gbinder_ipc_new(DEV2, NULL);
ipc_remote_proxy = gbinder_ipc_new(DEV2_PRIV, NULL);
ipc_obj = gbinder_ipc_new(DEV, NULL);
fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
fd_obj = gbinder_driver_fd(ipc_obj->driver);
obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_param_cb, &n);
remote_obj = gbinder_remote_object_new(ipc_remote_obj,
remote_obj = gbinder_remote_object_new(ipc_obj,
test_binder_register_object(fd_obj, obj, AUTO_HANDLE),
REMOTE_OBJECT_CREATE_ALIVE);
/* remote_proxy(DEV2_PRIV) => proxy (DEV2) => obj (DEV) => DEV_PRIV */
g_assert(!gbinder_proxy_object_new(NULL, remote_obj));
g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
remote_proxy = gbinder_remote_object_new(ipc_remote_proxy,
test_binder_register_object(fd_proxy, &proxy->parent, AUTO_HANDLE),
REMOTE_OBJECT_CREATE_ALIVE);
proxy_client = gbinder_client_new(remote_proxy, TEST_IFACE);
test_binder_set_passthrough(fd_obj, TRUE);
test_binder_set_passthrough(fd_proxy, TRUE);
test_binder_set_looper_enabled(fd_obj, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_proxy, TEST_LOOPER_ENABLE);
client = gbinder_client_new(proxy->remote, TEST_IFACE);
/*
* Perform two transactions via proxy. First one never gets completed
* and eventually is cancelled, and the second one is replied to.
*/
req = gbinder_client_new_request(proxy_client);
req = gbinder_client_new_request(client);
gbinder_local_request_append_int32(req, TX_PARAM_DONT_REPLY);
gbinder_client_transact(proxy_client, TX_CODE, 0, req, test_param_reply,
NULL, NULL);
gbinder_client_transact(client, TX_CODE, 0, req, test_param_canceled,
NULL, loop2);
gbinder_local_request_unref(req);
req = gbinder_client_new_request(proxy_client);
req = gbinder_client_new_request(client);
gbinder_local_request_append_int32(req, TX_PARAM_REPLY);
g_assert(gbinder_client_transact(proxy_client, TX_CODE, 0, req,
g_assert(gbinder_client_transact(client, TX_CODE, 0, req,
test_param_reply, NULL, loop));
gbinder_local_request_unref(req);
test_run(&test_opt, loop);
/* Depending on how callbacks are scheduled, n could be 1 or 2 */
g_assert_cmpint(n, > ,0);
test_run(&test_opt, loop2);
g_assert_cmpint(n, == ,2);
test_binder_unregister_objects(fd_obj);
test_binder_unregister_objects(fd_proxy);
gbinder_local_object_drop(obj);
gbinder_local_object_drop(&proxy->parent);
gbinder_remote_object_unref(remote_obj);
gbinder_remote_object_unref(remote_proxy);
gbinder_client_unref(proxy_client);
gbinder_client_unref(client);
gbinder_ipc_unref(ipc_obj);
gbinder_ipc_unref(ipc_remote_obj);
gbinder_ipc_unref(ipc_proxy);
gbinder_ipc_unref(ipc_remote_proxy);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
test_config_deinit(&config);
g_main_loop_unref(loop);
g_main_loop_unref(loop2);
}
static
@@ -597,62 +565,39 @@ test_obj_run(
GBinderLocalObject* obj2;
GBinderProxyObject* proxy;
GBinderRemoteObject* remote_obj;
GBinderRemoteObject* remote_proxy;
GBinderClient* proxy_client;
GBinderIpc* ipc_remote_obj;
GBinderClient* client;
GBinderIpc* ipc_obj;
GBinderIpc* ipc_proxy;
GBinderIpc* ipc_remote_proxy;
GBinderLocalRequest* req;
int fd_remote_obj, fd_obj, fd_proxy, fd_remote_proxy;
int fd_obj, fd_proxy;
test_config_init(&config, NULL);
memset(&test, 0, sizeof(test));
test.loop = g_main_loop_new(NULL, FALSE);
ipc_remote_obj = gbinder_ipc_new(DEV_PRIV, NULL);
ipc_obj = gbinder_ipc_new(DEV, NULL);
ipc_proxy = gbinder_ipc_new(DEV2, NULL);
ipc_remote_proxy = gbinder_ipc_new(DEV2_PRIV, NULL);
fd_remote_obj = gbinder_driver_fd(ipc_remote_obj->driver);
fd_obj = gbinder_driver_fd(ipc_obj->driver);
ipc_obj = gbinder_ipc_new(DEV, NULL);
fd_proxy = gbinder_driver_fd(ipc_proxy->driver);
fd_remote_proxy = gbinder_driver_fd(ipc_remote_proxy->driver);
fd_obj = gbinder_driver_fd(ipc_obj->driver);
obj = gbinder_local_object_new(ipc_remote_obj, TEST_IFACES,
test_obj_cb, &test);
obj = gbinder_local_object_new(ipc_obj, TEST_IFACES, test_obj_cb, &test);
GDEBUG("obj %p", obj);
remote_obj = gbinder_remote_object_new(ipc_obj,
test_binder_register_object(fd_obj, obj, AUTO_HANDLE),
REMOTE_OBJECT_CREATE_ALIVE);
/* remote_proxy(DEV2_PRIV) => proxy (DEV) => obj(DEV2_PRIV) */
g_assert((proxy = gbinder_proxy_object_new(ipc_proxy, remote_obj)));
GDEBUG("proxy %p", proxy);
remote_proxy = gbinder_remote_object_new(ipc_remote_proxy,
test_binder_register_object(fd_proxy, &proxy->parent, AUTO_HANDLE),
REMOTE_OBJECT_CREATE_ALIVE);
proxy_client = gbinder_client_new(remote_proxy, TEST_IFACE);
test_binder_set_passthrough(fd_remote_obj, TRUE);
test_binder_set_passthrough(fd_obj, TRUE);
test_binder_set_passthrough(fd_proxy, TRUE);
test_binder_set_passthrough(fd_remote_proxy, TRUE);
test_binder_set_looper_enabled(fd_remote_obj, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_obj, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_proxy, TEST_LOOPER_ENABLE);
test_binder_set_looper_enabled(fd_remote_proxy, TEST_LOOPER_ENABLE);
client = gbinder_client_new(proxy->remote, TEST_IFACE);
/* Pass object reference via proxy */
obj2 = gbinder_local_object_new(ipc_remote_proxy, TEST_IFACES2, test_obj2_cb, &test);
obj2 = gbinder_local_object_new(ipc_obj, TEST_IFACES2, test_obj2_cb, &test);
GDEBUG("obj2 %p", obj2);
req = gbinder_client_new_request(proxy_client);
req = gbinder_client_new_request(client);
gbinder_local_request_append_int32(req, TX_PARAM1);
gbinder_local_request_append_local_object(req, obj2);
gbinder_local_request_append_int32(req, TX_PARAM2);
gbinder_client_transact(proxy_client, TX_CODE, 0, req, test_obj_reply,
gbinder_client_transact(client, TX_CODE, 0, req, test_obj_reply,
NULL, &test);
gbinder_local_request_unref(req);
@@ -665,22 +610,16 @@ test_obj_run(
g_assert(test.obj2);
gbinder_local_object_unref(test.obj2);
test_binder_unregister_objects(fd_remote_obj);
test_binder_unregister_objects(fd_obj);
test_binder_unregister_objects(fd_proxy);
test_binder_unregister_objects(fd_remote_proxy);
gbinder_local_object_drop(obj);
gbinder_local_object_drop(obj2);
gbinder_local_object_drop(&proxy->parent);
gbinder_remote_object_unref(remote_obj);
gbinder_remote_object_unref(remote_proxy);
gbinder_client_unref(proxy_client);
gbinder_ipc_unref(ipc_remote_obj);
gbinder_client_unref(client);
gbinder_ipc_unref(ipc_obj);
gbinder_ipc_unref(ipc_proxy);
gbinder_ipc_unref(ipc_remote_proxy);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, test.loop);
test_config_deinit(&config);
g_main_loop_unref(test.loop);

View File

@@ -1,6 +1,7 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -31,6 +32,7 @@
*/
#include "test_common.h"
#include "test_binder.h"
#include "gbinder_buffer_p.h"
#include "gbinder_driver.h"
@@ -59,12 +61,9 @@ typedef struct binder_buffer_object_64 {
} BinderObject64;
#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);
static
@@ -176,7 +175,7 @@ test_byte(
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_byte(&reader, &out));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == out);
g_assert_cmpuint(in, == ,out);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_byte(&reader, NULL));
@@ -215,7 +214,7 @@ test_bool(
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, &out));
g_assert(gbinder_reader_at_end(&reader));
g_assert(out == TRUE);
g_assert_cmpuint(out, == ,TRUE);
/* false */
gbinder_buffer_free(data.buffer);
@@ -244,8 +243,8 @@ void
test_int8(
void)
{
const guint8 in = 42;
const guint8 in4[] = { TEST_INT8_BYTES_4(42) };
const guint8 in = 0x2a;
const guint8 in4[] = { 0x2a, 0x00, 0x00, 0x00 };
guint8 out1 = 0;
gint8 out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
@@ -296,7 +295,7 @@ test_int16(
void)
{
const guint16 in = 42;
const guint8 in4[] = { TEST_INT16_BYTES_4(42) };
const guint8 in4[] = { TEST_INT16_BYTES(42), 0x00, 0x00 };
guint16 out1 = 0;
gint16 out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
@@ -789,6 +788,7 @@ test_hidl_struct(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1024,6 +1024,7 @@ test_hidl_vec(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1105,6 +1106,7 @@ test_hidl_string_err(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
static
@@ -1139,6 +1141,7 @@ test_hidl_string_err_skip(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1182,6 +1185,7 @@ test_fd_ok(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1213,6 +1217,7 @@ test_fd_shortbuf(
g_assert(gbinder_reader_read_fd(&reader) < 0);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1256,6 +1261,7 @@ test_fd_badtype(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1303,6 +1309,7 @@ test_dupfd_ok(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1346,6 +1353,7 @@ test_dupfd_badtype(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1389,6 +1397,7 @@ test_dupfd_badfd(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1429,6 +1438,7 @@ test_hidl_string(
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
static
@@ -1707,6 +1717,7 @@ test_buffer(
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1813,7 +1824,8 @@ test_object(
/* Using 64-bit I/O */
static const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_HANDLE), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(1 /* handle*/), TEST_INT64_BYTES(0)
TEST_INT32_BYTES(1 /* handle*/), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
@@ -1833,12 +1845,13 @@ test_object(
g_assert(gbinder_reader_read_nullable_object(&reader, &obj));
g_assert(obj);
g_assert(obj->handle == 1);
g_assert_cmpuint(obj->handle, == ,1);
g_free(data.objects);
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1895,6 +1908,7 @@ test_object_invalid(
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1947,6 +1961,7 @@ test_vec(
g_free(data.objects);
gbinder_buffer_free(data.buffer);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1983,8 +1998,7 @@ test_hidl_string_vec(
data.objects[i] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
out = gbinder_reader_read_hidl_string_vec(&reader)
;
out = gbinder_reader_read_hidl_string_vec(&reader);
if (out) {
const guint n = g_strv_length(out);
@@ -2002,6 +2016,7 @@ test_hidl_string_vec(
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
static

View File

@@ -89,6 +89,7 @@ test_basic(
gbinder_remote_object_unref(obj1);
gbinder_remote_object_unref(obj2);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -119,8 +120,7 @@ test_dead_run(
gulong id = gbinder_remote_object_add_death_handler
(obj, test_dead_done, loop);
test_binder_br_dead_binder(fd, h);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_br_dead_binder(fd, ANY_THREAD, h);
test_run(&test_opt, loop);
g_assert(gbinder_remote_object_is_dead(obj));
@@ -128,7 +128,7 @@ test_dead_run(
gbinder_remote_object_remove_handler(obj, 0); /* has no effect */
gbinder_remote_object_unref(obj);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}

View File

@@ -133,9 +133,9 @@ test_setup_ping(
{
const int fd = gbinder_driver_fd(ipc->driver);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_reply(fd, 0, 0, NULL);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
}
/*==========================================================================*
@@ -484,6 +484,7 @@ test_invalid(
gbinder_servicemanager_remove_handlers(sm, &id, 0);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -513,7 +514,7 @@ test_basic(
gbinder_servicemanager_unref(sm);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -556,7 +557,7 @@ test_legacy(
gbinder_ipc_unref(ipc);
gbinder_servicemanager_exit();
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -634,6 +635,7 @@ test_config(
gbinder_servicemanager_exit();
gbinder_config_exit();
gbinder_config_file = NULL;
test_binder_exit_wait(&test_opt, NULL);
remove(file);
remove(dir);
@@ -656,7 +658,7 @@ test_not_present(
GBinderServiceManager* sm;
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, -1);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -664,6 +666,7 @@ test_not_present(
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -685,7 +688,7 @@ test_wait(
int count = 0;
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, -1);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -696,13 +699,13 @@ test_wait(
g_assert(id);
/* Make this wait fail */
test_binder_br_reply_status(fd, -1);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
g_assert(!gbinder_servicemanager_wait(sm, 0));
/* This makes presence detection PING succeed */
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_reply(fd, 0, 0, NULL);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
g_assert(gbinder_servicemanager_wait(sm, forever));
/* The next check succeeds too (without any I/O ) */
@@ -714,7 +717,7 @@ test_wait(
gbinder_servicemanager_remove_handler(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -734,7 +737,7 @@ test_wait_long(
int count = 0;
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, -1);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -745,10 +748,10 @@ test_wait_long(
g_assert(id);
/* Make the first presence detection PING fail and second succeed */
test_binder_br_reply_status(fd, -1);
test_binder_br_reply_status_later(fd, -1);
test_binder_br_transaction_complete_later(fd);
test_binder_br_reply_later(fd, 0, 0, NULL);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
test_binder_br_reply_status(fd, TX_THREAD, -1);
test_binder_br_transaction_complete(fd, TX_THREAD);
test_binder_br_reply(fd, TX_THREAD, 0, 0, NULL);
g_assert(gbinder_servicemanager_wait(sm, TEST_TIMEOUT_SEC * 1000));
/* The next check succeeds too (without any I/O ) */
@@ -760,7 +763,7 @@ test_wait_long(
gbinder_servicemanager_remove_handler(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -781,7 +784,7 @@ test_wait_async(
int count = 0;
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, -1);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
sm = gbinder_servicemanager_new(dev);
g_assert(sm);
@@ -794,9 +797,9 @@ test_wait_async(
g_assert(id[1]);
/* Make the first presence detection PING fail and second succeed */
test_binder_br_reply_status(fd, -1);
test_binder_br_transaction_complete_later(fd);
test_binder_br_reply_later(fd, 0, 0, NULL);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
test_binder_br_transaction_complete(fd, TX_THREAD);
test_binder_br_reply(fd, TX_THREAD, 0, 0, NULL);
test_run(&test_opt, loop);
/* The listener must have been invoked exactly once */
@@ -804,7 +807,7 @@ test_wait_async(
gbinder_servicemanager_remove_all_handlers(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -838,9 +841,8 @@ test_death_run()
g_assert(id[1]);
g_assert(id[2]);
/* Generate death notification (need looper for that) */
test_binder_br_dead_binder(fd, 0);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
/* Generate death notification */
test_binder_br_dead_binder(fd, ANY_THREAD, 0);
test_run(&test_opt, loop);
/* No registrations must have occured */
@@ -852,7 +854,6 @@ test_death_run()
gbinder_servicemanager_remove_all_handlers(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -880,11 +881,10 @@ test_reanimate_quit(
} else {
const int fd = gbinder_driver_fd(sm->client->remote->ipc->driver);
/* Disable looper and reanimate the object */
/* Reanimate the object */
GDEBUG("Reanimating...");
test_binder_set_looper_enabled(fd, TEST_LOOPER_DISABLE);
test_binder_br_transaction_complete(fd);
test_binder_br_reply(fd, 0, 0, NULL);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
}
}
@@ -917,9 +917,8 @@ test_reanimate(
g_assert(id[1]);
g_assert(id[2]);
/* Generate death notification (need looper for that) */
test_binder_br_dead_binder(fd, 0);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
/* Generate death notification */
test_binder_br_dead_binder(fd, ANY_THREAD, 0);
test_run(&test_opt, loop);
/* No registrations must have occured */
@@ -932,7 +931,6 @@ test_reanimate(
gbinder_servicemanager_remove_all_handlers(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -991,7 +989,7 @@ test_reuse(
gbinder_ipc_unref(binder_ipc);
gbinder_ipc_unref(vndbinder_ipc);
gbinder_ipc_unref(hwbinder_ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -1036,7 +1034,7 @@ test_notify_type(
gbinder_servicemanager_remove_handler(sm, id2);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
}
static
@@ -1094,7 +1092,7 @@ test_list(
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -1158,7 +1156,7 @@ test_get(
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -1206,7 +1204,7 @@ test_add(
gbinder_local_object_unref(obj);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2020-2022 Jolla Ltd.
* Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -98,7 +98,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidlClass;
typedef struct service_manager_aidl {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl;
#define SERVICE_MANAGER_AIDL_TYPE (service_manager_aidl_get_type())
@@ -110,23 +110,23 @@ G_DEFINE_TYPE(ServiceManagerAidl, service_manager_aidl, \
static
GBinderLocalReply*
servicemanager_aidl_handler(
GBinderLocalObject* obj,
ServiceManagerAidl* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl* self = user_data;
GBinderLocalObject* obj = &self->parent;
GBinderLocalReply* reply = NULL;
GBinderReader reader;
GBinderRemoteObject* remote_obj;
guint32 num;
char* str;
g_assert(!flags);
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
*status = -1;
/* Lock */
g_mutex_lock(&self->mutex);
switch (code) {
case GET_SERVICE_TRANSACTION:
case CHECK_SERVICE_TRANSACTION:
@@ -179,71 +179,39 @@ servicemanager_aidl_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl*
servicemanager_aidl_new(
const char* dev,
gboolean handle_on_looper_thread)
{
ServiceManagerAidl* self = g_object_new(SERVICE_MANAGER_AIDL_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
self->handle_on_looper_thread = handle_on_looper_thread;
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
servicemanager_aidl_handler, self);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
static
void
servicemanager_aidl_free(
ServiceManagerAidl* self)
{
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(self));
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
service_manager_aidl_can_handle_transaction(
GBinderLocalObject* object,
const char* iface,
guint code)
{
ServiceManagerAidl* self = SERVICE_MANAGER_AIDL(object);
if (self->handle_on_looper_thread && !g_strcmp0(SVCMGR_IFACE, iface)) {
return GBINDER_LOCAL_TRANSACTION_LOOPER;
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
can_handle_transaction(object, iface, code);
}
}
static
GBinderLocalReply*
service_manager_aidl_handle_looper_transaction(
GBinderLocalObject* object,
servicemanager_aidl_handle_looper_transaction(
GBinderLocalObject* obj,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status)
{
if (!g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE)) {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
handle_transaction(object, req, code, flags, status);
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
handle_looper_transaction(object, req, code, flags, status);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl_handler(SERVICE_MANAGER_AIDL(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -253,6 +221,7 @@ service_manager_aidl_finalize(
{
ServiceManagerAidl* self = SERVICE_MANAGER_AIDL(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl_parent_class)->finalize(object);
}
@@ -262,6 +231,7 @@ void
service_manager_aidl_init(
ServiceManagerAidl* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -271,14 +241,29 @@ void
service_manager_aidl_class_init(
ServiceManagerAidlClass* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl_finalize;
klass->can_handle_transaction =
servicemanager_aidl_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl_handle_looper_transaction;
}
object->finalize = service_manager_aidl_finalize;
local_object->can_handle_transaction =
service_manager_aidl_can_handle_transaction;
local_object->handle_looper_transaction =
service_manager_aidl_handle_looper_transaction;
static
ServiceManagerAidl*
servicemanager_aidl_new(
const char* dev)
{
ServiceManagerAidl* self = g_object_new(SERVICE_MANAGER_AIDL_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -329,9 +314,8 @@ void
test_get_run()
{
const char* dev = GBINDER_DEFAULT_BINDER;
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(dev);
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
const char* name = "name";
@@ -340,7 +324,6 @@ test_get_run()
/* Set up binder simulator */
test_binder_register_object(fd, obj, AUTO_HANDLE);
test_binder_set_passthrough(fd, TRUE);
sm = gbinder_servicemanager_new(dev);
/* Query the object (it's not there yet) and wait for completion */
@@ -365,11 +348,10 @@ test_get_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(smsvc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(smsvc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -411,9 +393,8 @@ void
test_list_run()
{
const char* dev = GBINDER_DEFAULT_BINDER;
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, FALSE);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(dev);
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
const char* name = "name";
@@ -425,7 +406,6 @@ test_list_run()
/* Set up binder simulator */
test_binder_register_object(fd, obj, AUTO_HANDLE);
test_binder_set_passthrough(fd, TRUE);
sm = gbinder_servicemanager_new(dev);
/* Request the list and wait for completion */
@@ -451,11 +431,10 @@ test_list_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(smsvc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(smsvc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, test.loop);
g_strfreev(test.list);
@@ -490,9 +469,8 @@ void
test_notify_run()
{
const char* dev = GBINDER_DEFAULT_BINDER;
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
ServiceManagerAidl* svc = servicemanager_aidl_new(other_dev, FALSE);
ServiceManagerAidl* svc = servicemanager_aidl_new(dev);
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
const char* name = "name";
@@ -502,7 +480,6 @@ test_notify_run()
/* Set up binder simulator */
test_binder_register_object(fd, obj, AUTO_HANDLE);
test_binder_set_passthrough(fd, TRUE);
sm = gbinder_servicemanager_new(dev);
gbinder_ipc_set_max_threads(ipc, 1);
@@ -522,11 +499,10 @@ test_notify_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(svc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(svc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -547,9 +523,8 @@ void
test_notify2_run()
{
const char* dev = GBINDER_DEFAULT_BINDER;
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(other_dev, TRUE);
ServiceManagerAidl* smsvc = servicemanager_aidl_new(dev);
GBinderLocalObject* obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GBinderServiceManager* sm;
@@ -560,7 +535,6 @@ test_notify2_run()
/* Set up binder simulator */
test_binder_register_object(fd, obj, AUTO_HANDLE);
test_binder_set_passthrough(fd, TRUE);
sm = gbinder_servicemanager_new(dev);
gbinder_ipc_set_max_threads(ipc, 1);
@@ -589,11 +563,10 @@ test_notify2_run()
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
servicemanager_aidl_free(smsvc);
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(smsvc));
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2020-2022 Jolla Ltd.
* Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -58,6 +58,22 @@ gbinder_servicemanager_hidl_get_type()
return 0;
}
GType
gbinder_servicemanager_aidl3_get_type()
{
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl3 */
g_assert_not_reached();
return 0;
}
GType
gbinder_servicemanager_aidl4_get_type()
{
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
g_assert_not_reached();
return 0;
}
/*==========================================================================*
* Test service manager
*==========================================================================*/
@@ -77,7 +93,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidl2Class;
typedef struct service_manager_aidl2 {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl2;
#define SERVICE_MANAGER_AIDL2_TYPE (service_manager_aidl2_get_type())
@@ -89,24 +105,23 @@ G_DEFINE_TYPE(ServiceManagerAidl2, service_manager_aidl2, \
static
GBinderLocalReply*
servicemanager_aidl2_handler(
GBinderLocalObject* obj,
ServiceManagerAidl2* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl2* self = user_data;
GBinderLocalObject* obj = &self->parent;
GBinderLocalReply* reply = NULL;
GBinderReader reader;
GBinderRemoteObject* remote_obj;
guint32 num, allow_isolated, dumpsys_priority;
char* str;
g_assert(!flags);
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
*status = -1;
/* Lock */
g_mutex_lock(&self->mutex);
switch (code) {
case GET_SERVICE_TRANSACTION:
case CHECK_SERVICE_TRANSACTION:
@@ -164,63 +179,39 @@ servicemanager_aidl2_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl2*
servicemanager_aidl2_new(
const char* dev,
gboolean handle_on_looper_thread)
{
ServiceManagerAidl2* self = g_object_new(SERVICE_MANAGER_AIDL2_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
self->handle_on_looper_thread = handle_on_looper_thread;
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
servicemanager_aidl2_handler, self);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
service_manager_aidl2_can_handle_transaction(
GBinderLocalObject* object,
const char* iface,
guint code)
{
ServiceManagerAidl2* self = SERVICE_MANAGER_AIDL2(object);
if (self->handle_on_looper_thread && !g_strcmp0(SVCMGR_IFACE, iface)) {
return GBINDER_LOCAL_TRANSACTION_LOOPER;
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
can_handle_transaction(object, iface, code);
}
}
static
GBinderLocalReply*
service_manager_aidl2_handle_looper_transaction(
GBinderLocalObject* object,
servicemanager_aidl2_handle_looper_transaction(
GBinderLocalObject* obj,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status)
{
if (!g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE)) {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
handle_transaction(object, req, code, flags, status);
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
handle_looper_transaction(object, req, code, flags, status);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl2_handler(SERVICE_MANAGER_AIDL2(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl2_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl2_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -230,6 +221,7 @@ service_manager_aidl2_finalize(
{
ServiceManagerAidl2* self = SERVICE_MANAGER_AIDL2(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl2_parent_class)->finalize(object);
}
@@ -239,6 +231,7 @@ void
service_manager_aidl2_init(
ServiceManagerAidl2* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -248,14 +241,29 @@ void
service_manager_aidl2_class_init(
ServiceManagerAidl2Class* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl2_finalize;
klass->can_handle_transaction =
servicemanager_aidl2_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl2_handle_looper_transaction;
}
object->finalize = service_manager_aidl2_finalize;
local_object->can_handle_transaction =
service_manager_aidl2_can_handle_transaction;
local_object->handle_looper_transaction =
service_manager_aidl2_handle_looper_transaction;
static
ServiceManagerAidl2*
servicemanager_aidl2_new(
const char* dev)
{
ServiceManagerAidl2* self = g_object_new(SERVICE_MANAGER_AIDL2_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -271,6 +279,7 @@ typedef struct test_context {
GBinderLocalObject* object;
ServiceManagerAidl2* service;
GBinderServiceManager* client;
GMainLoop* loop;
int fd;
} TestContext;
@@ -280,11 +289,6 @@ test_context_init(
TestContext* test)
{
const char* dev = GBINDER_DEFAULT_BINDER;
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
/*
* Also set defaults so that both /dev/binder and /dev/binder-private
* use the same protocol.
*/
const char* config =
"[Protocol]\n"
"Default = aidl2\n"
@@ -308,13 +312,10 @@ test_context_init(
ipc = gbinder_ipc_new(dev, NULL);
test->fd = gbinder_driver_fd(ipc->driver);
test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
/* Set up binder simulator */
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
test_binder_set_passthrough(test->fd, TRUE);
test->service = servicemanager_aidl2_new(other_dev, TRUE);
test->service = servicemanager_aidl2_new(dev);
test->client = gbinder_servicemanager_new(dev);
test->loop = g_main_loop_new(NULL, FALSE);
gbinder_ipc_unref(ipc);
}
@@ -323,22 +324,47 @@ void
test_context_deinit(
TestContext* test)
{
test_binder_unregister_objects(test->fd);
test_binder_br_dead_binder_obj(test->fd, test->object);
gbinder_local_object_unref(test->object);
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(test->service));
gbinder_servicemanager_unref(test->client);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
test_binder_exit_wait(&test_opt, test->loop);
remove(test->config_file);
remove(test->config_dir);
g_free(test->config_file);
g_free(test->config_subdir);
g_free(test->config_dir);
g_main_loop_unref(test->loop);
gbinder_config_dir = test->default_config_dir;
gbinder_config_file = test->default_config_file;
gbinder_config_exit();
}
static
void
test_context_wait_ref_cb(
GBinderLocalObject* obj,
void* user_data)
{
GDEBUG("strong_refs %d", obj->strong_refs);
if (obj->strong_refs > 0) {
test_quit_later((GMainLoop*)user_data);
}
}
static
void
test_context_wait_ref(
TestContext* test)
{
/* Wait until the object gets referenced by servicemanager */
gulong id = gbinder_local_object_add_strong_refs_changed_handler
(test->object, test_context_wait_ref_cb, test->loop);
test_run(&test_opt, test->loop);
gbinder_local_object_remove_handler(test->object, id);
}
/*==========================================================================*
* get
*==========================================================================*/
@@ -367,12 +393,16 @@ test_get_run()
g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
g_assert(g_hash_table_contains(test.service->objects, name));
/* Wait until the object gets referenced by servicemanager */
test_context_wait_ref(&test);
/* Query the object (this time it must be there) */
GDEBUG("Querying '%s' again", name);
g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
&status));
g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
GDEBUG("Done");
test_context_deinit(&test);
}
@@ -410,6 +440,9 @@ test_list_run()
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
name, test.object), == ,GBINDER_STATUS_OK);
/* Wait until the object gets referenced by servicemanager */
test_context_wait_ref(&test);
/* Request the list again */
list = gbinder_servicemanager_list_sync(test.client);
@@ -418,6 +451,7 @@ test_list_run()
g_assert_cmpstr(list[0], == ,name);
g_strfreev(list);
GDEBUG("Done");
test_context_deinit(&test);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2020-2022 Jolla Ltd.
* Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -59,6 +59,22 @@ gbinder_servicemanager_hidl_get_type()
return 0;
}
GType
gbinder_servicemanager_aidl2_get_type()
{
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl2 */
g_assert_not_reached();
return 0;
}
GType
gbinder_servicemanager_aidl4_get_type()
{
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl4 */
g_assert_not_reached();
return 0;
}
/*==========================================================================*
* Test service manager
*==========================================================================*/
@@ -78,7 +94,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidl3Class;
typedef struct service_manager_aidl3 {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl3;
#define SERVICE_MANAGER_AIDL3_TYPE (service_manager_aidl3_get_type())
@@ -90,24 +106,23 @@ G_DEFINE_TYPE(ServiceManagerAidl3, service_manager_aidl3, \
static
GBinderLocalReply*
servicemanager_aidl3_handler(
GBinderLocalObject* obj,
ServiceManagerAidl3* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl3* self = user_data;
GBinderLocalObject* obj = &self->parent;
GBinderLocalReply* reply = NULL;
GBinderReader reader;
GBinderRemoteObject* remote_obj;
guint32 allow_isolated, dumpsys_priority;
char* str;
g_assert(!flags);
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
*status = -1;
/* Lock */
g_mutex_lock(&self->mutex);
switch (code) {
case GET_SERVICE_TRANSACTION:
case CHECK_SERVICE_TRANSACTION:
@@ -173,63 +188,39 @@ servicemanager_aidl3_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl3*
servicemanager_aidl3_new(
const char* dev,
gboolean handle_on_looper_thread)
{
ServiceManagerAidl3* self = g_object_new(SERVICE_MANAGER_AIDL3_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
self->handle_on_looper_thread = handle_on_looper_thread;
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
servicemanager_aidl3_handler, self);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
service_manager_aidl3_can_handle_transaction(
GBinderLocalObject* object,
const char* iface,
guint code)
{
ServiceManagerAidl3* self = SERVICE_MANAGER_AIDL3(object);
if (self->handle_on_looper_thread && !g_strcmp0(SVCMGR_IFACE, iface)) {
return GBINDER_LOCAL_TRANSACTION_LOOPER;
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
can_handle_transaction(object, iface, code);
}
}
static
GBinderLocalReply*
service_manager_aidl3_handle_looper_transaction(
GBinderLocalObject* object,
servicemanager_aidl3_handle_looper_transaction(
GBinderLocalObject* obj,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status)
{
if (!g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE)) {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
handle_transaction(object, req, code, flags, status);
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
handle_looper_transaction(object, req, code, flags, status);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl3_handler(SERVICE_MANAGER_AIDL3(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl3_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl3_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -239,6 +230,7 @@ service_manager_aidl3_finalize(
{
ServiceManagerAidl3* self = SERVICE_MANAGER_AIDL3(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl3_parent_class)->finalize(object);
}
@@ -248,6 +240,7 @@ void
service_manager_aidl3_init(
ServiceManagerAidl3* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -257,14 +250,29 @@ void
service_manager_aidl3_class_init(
ServiceManagerAidl3Class* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl3_finalize;
klass->can_handle_transaction =
servicemanager_aidl3_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl3_handle_looper_transaction;
}
object->finalize = service_manager_aidl3_finalize;
local_object->can_handle_transaction =
service_manager_aidl3_can_handle_transaction;
local_object->handle_looper_transaction =
service_manager_aidl3_handle_looper_transaction;
static
ServiceManagerAidl3*
servicemanager_aidl3_new(
const char* dev)
{
ServiceManagerAidl3* self = g_object_new(SERVICE_MANAGER_AIDL3_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -280,6 +288,7 @@ typedef struct test_context {
GBinderLocalObject* object;
ServiceManagerAidl3* service;
GBinderServiceManager* client;
GMainLoop* loop;
int fd;
} TestContext;
@@ -289,11 +298,6 @@ test_context_init(
TestContext* test)
{
const char* dev = GBINDER_DEFAULT_BINDER;
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
/*
* Also set defaults so that both /dev/binder and /dev/binder-private
* use the same protocol.
*/
const char* config =
"[Protocol]\n"
"Default = aidl3\n"
@@ -317,13 +321,10 @@ test_context_init(
ipc = gbinder_ipc_new(dev, NULL);
test->fd = gbinder_driver_fd(ipc->driver);
test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
/* Set up binder simulator */
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
test_binder_set_passthrough(test->fd, TRUE);
test->service = servicemanager_aidl3_new(other_dev, TRUE);
test->service = servicemanager_aidl3_new(dev);
test->client = gbinder_servicemanager_new(dev);
test->loop = g_main_loop_new(NULL, FALSE);
gbinder_ipc_unref(ipc);
}
@@ -332,22 +333,47 @@ void
test_context_deinit(
TestContext* test)
{
test_binder_unregister_objects(test->fd);
test_binder_br_dead_binder_obj(test->fd, test->object);
gbinder_local_object_unref(test->object);
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(test->service));
gbinder_servicemanager_unref(test->client);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
test_binder_exit_wait(&test_opt, test->loop);
remove(test->config_file);
remove(test->config_dir);
g_free(test->config_file);
g_free(test->config_subdir);
g_free(test->config_dir);
g_main_loop_unref(test->loop);
gbinder_config_dir = test->default_config_dir;
gbinder_config_file = test->default_config_file;
gbinder_config_exit();
}
static
void
test_context_wait_ref_cb(
GBinderLocalObject* obj,
void* user_data)
{
GDEBUG("strong_refs %d", obj->strong_refs);
if (obj->strong_refs > 0) {
test_quit_later((GMainLoop*)user_data);
}
}
static
void
test_context_wait_ref(
TestContext* test)
{
/* Wait until the object gets referenced by servicemanager */
gulong id = gbinder_local_object_add_strong_refs_changed_handler
(test->object, test_context_wait_ref_cb, test->loop);
test_run(&test_opt, test->loop);
gbinder_local_object_remove_handler(test->object, id);
}
/*==========================================================================*
* get
*==========================================================================*/
@@ -376,12 +402,16 @@ test_get_run()
g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
g_assert(g_hash_table_contains(test.service->objects, name));
/* Wait until the object gets referenced by servicemanager */
test_context_wait_ref(&test);
/* Query the object (this time it must be there) */
GDEBUG("Querying '%s' again", name);
g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
&status));
g_assert_cmpint(status, == ,GBINDER_STATUS_OK);
GDEBUG("Done");
test_context_deinit(&test);
}
@@ -419,6 +449,9 @@ test_list_run()
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
name, test.object), == ,GBINDER_STATUS_OK);
/* Wait until the object gets referenced by servicemanager */
test_context_wait_ref(&test);
/* Request the list again */
list = gbinder_servicemanager_list_sync(test.client);
@@ -427,6 +460,7 @@ test_list_run()
g_assert_cmpstr(list[0], == ,name);
g_strfreev(list);
GDEBUG("Done");
test_context_deinit(&test);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2020-2022 Jolla Ltd.
* Copyright (C) 2020-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -59,6 +59,14 @@ gbinder_servicemanager_hidl_get_type()
return 0;
}
GType
gbinder_servicemanager_aidl2_get_type()
{
/* Dummy function to avoid pulling in gbinder_servicemanager_aidl2 */
g_assert_not_reached();
return 0;
}
/*==========================================================================*
* Test service manager
*==========================================================================*/
@@ -78,7 +86,7 @@ typedef GBinderLocalObjectClass ServiceManagerAidl4Class;
typedef struct service_manager_aidl4 {
GBinderLocalObject parent;
GHashTable* objects;
gboolean handle_on_looper_thread;
GMutex mutex;
} ServiceManagerAidl4;
#define SERVICE_MANAGER_AIDL4_TYPE (service_manager_aidl4_get_type())
@@ -87,41 +95,26 @@ typedef struct service_manager_aidl4 {
G_DEFINE_TYPE(ServiceManagerAidl4, service_manager_aidl4, \
GBINDER_TYPE_LOCAL_OBJECT)
/* This should be eventually handled at lower level. */
typedef struct category {
/*
* This is the version of the wire protocol associated with the host
* process of a particular binder. As the wire protocol changes, if
* sending a transaction to a binder with an old version, the Parcel
* class must write parcels according to the version documented here.
*/
gint8 version;
gint8 reserved[2];
gint8 level; /* bitmask of Stability::Level */
} Category;
static
GBinderLocalReply*
servicemanager_aidl4_handler(
GBinderLocalObject* obj,
ServiceManagerAidl4* self,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status,
void* user_data)
int* status)
{
ServiceManagerAidl4* self = user_data;
GBinderLocalObject* obj = &self->parent;
GBinderLocalReply* reply = NULL;
GBinderReader reader;
GBinderRemoteObject* remote_obj;
guint32 allow_isolated, dumpsys_priority;
char* str;
Category category;
g_assert(!flags);
GDEBUG("%s %u", gbinder_remote_request_interface(req), code);
g_assert_cmpstr(gbinder_remote_request_interface(req), == ,SVCMGR_IFACE);
*status = -1;
/* Lock */
g_mutex_lock(&self->mutex);
switch (code) {
case GET_SERVICE_TRANSACTION:
case CHECK_SERVICE_TRANSACTION:
@@ -152,10 +145,9 @@ servicemanager_aidl4_handler(
gbinder_remote_request_init_reader(req, &reader);
str = gbinder_reader_read_string16(&reader);
remote_obj = gbinder_reader_read_object(&reader);
gbinder_reader_read_uint32(&reader, (guint32*)&category);
if (str && remote_obj &&
category.level == GBINDER_STABILITY_SYSTEM &&
category.version == 1 &&
/* This field should be eventually handled at lower level. */
gbinder_reader_read_uint32(&reader, NULL) &&
gbinder_reader_read_uint32(&reader, &allow_isolated) &&
gbinder_reader_read_uint32(&reader, &dumpsys_priority)) {
GDEBUG("Adding '%s'", str);
@@ -194,63 +186,39 @@ servicemanager_aidl4_handler(
GDEBUG("Unhandled command %u", code);
break;
}
g_mutex_unlock(&self->mutex);
/* Unlock */
return reply;
}
static
ServiceManagerAidl4*
servicemanager_aidl4_new(
const char* dev,
gboolean handle_on_looper_thread)
{
ServiceManagerAidl4* self = g_object_new(SERVICE_MANAGER_AIDL4_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
self->handle_on_looper_thread = handle_on_looper_thread;
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
servicemanager_aidl4_handler, self);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
service_manager_aidl4_can_handle_transaction(
GBinderLocalObject* object,
const char* iface,
guint code)
{
ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(object);
if (self->handle_on_looper_thread && !g_strcmp0(SVCMGR_IFACE, iface)) {
return GBINDER_LOCAL_TRANSACTION_LOOPER;
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
can_handle_transaction(object, iface, code);
}
}
static
GBinderLocalReply*
service_manager_aidl4_handle_looper_transaction(
GBinderLocalObject* object,
servicemanager_aidl4_handle_looper_transaction(
GBinderLocalObject* obj,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status)
{
if (!g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE)) {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
handle_transaction(object, req, code, flags, status);
} else {
return GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
handle_looper_transaction(object, req, code, flags, status);
}
return !g_strcmp0(gbinder_remote_request_interface(req), SVCMGR_IFACE) ?
servicemanager_aidl4_handler(SERVICE_MANAGER_AIDL4(obj),
req, code, status) :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
handle_looper_transaction(obj, req, code, flags, status);
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
servicemanager_aidl4_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Handle servicemanager transactions on the looper thread */
return !g_strcmp0(iface, SVCMGR_IFACE) ? GBINDER_LOCAL_TRANSACTION_LOOPER :
GBINDER_LOCAL_OBJECT_CLASS(service_manager_aidl4_parent_class)->
can_handle_transaction(self, iface, code);
}
static
@@ -260,6 +228,7 @@ service_manager_aidl4_finalize(
{
ServiceManagerAidl4* self = SERVICE_MANAGER_AIDL4(object);
g_mutex_clear(&self->mutex);
g_hash_table_destroy(self->objects);
G_OBJECT_CLASS(service_manager_aidl4_parent_class)->finalize(object);
}
@@ -269,6 +238,7 @@ void
service_manager_aidl4_init(
ServiceManagerAidl4* self)
{
g_mutex_init(&self->mutex);
self->objects = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify) gbinder_remote_object_unref);
}
@@ -278,14 +248,29 @@ void
service_manager_aidl4_class_init(
ServiceManagerAidl4Class* klass)
{
GObjectClass* object = G_OBJECT_CLASS(klass);
GBinderLocalObjectClass* local_object = GBINDER_LOCAL_OBJECT_CLASS(klass);
G_OBJECT_CLASS(klass)->finalize = service_manager_aidl4_finalize;
klass->can_handle_transaction =
servicemanager_aidl4_can_handle_transaction;
klass->handle_looper_transaction =
servicemanager_aidl4_handle_looper_transaction;
}
object->finalize = service_manager_aidl4_finalize;
local_object->can_handle_transaction =
service_manager_aidl4_can_handle_transaction;
local_object->handle_looper_transaction =
service_manager_aidl4_handle_looper_transaction;
static
ServiceManagerAidl4*
servicemanager_aidl4_new(
const char* dev)
{
ServiceManagerAidl4* self = g_object_new(SERVICE_MANAGER_AIDL4_TYPE, NULL);
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(self);
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
gbinder_local_object_init_base(obj, ipc, servicemanager_aidl_ifaces,
NULL, NULL);
test_binder_register_object(fd, obj, SVCMGR_HANDLE);
gbinder_ipc_register_local_object(ipc, obj);
gbinder_ipc_unref(ipc);
return self;
}
/*==========================================================================*
@@ -301,6 +286,7 @@ typedef struct test_context {
GBinderLocalObject* object;
ServiceManagerAidl4* service;
GBinderServiceManager* client;
GMainLoop* loop;
int fd;
} TestContext;
@@ -310,11 +296,6 @@ test_context_init(
TestContext* test)
{
const char* dev = GBINDER_DEFAULT_BINDER;
const char* other_dev = GBINDER_DEFAULT_BINDER "-private";
/*
* Also set defaults so that both /dev/binder and /dev/binder-private
* use the same protocol.
*/
const char* config =
"[Protocol]\n"
"Default = aidl3\n"
@@ -338,13 +319,10 @@ test_context_init(
ipc = gbinder_ipc_new(dev, NULL);
test->fd = gbinder_driver_fd(ipc->driver);
test->object = gbinder_local_object_new(ipc, NULL, NULL, NULL);
/* Set up binder simulator */
test_binder_register_object(test->fd, test->object, AUTO_HANDLE);
test_binder_set_passthrough(test->fd, TRUE);
test->service = servicemanager_aidl4_new(other_dev, TRUE);
test->service = servicemanager_aidl4_new(dev);
test->client = gbinder_servicemanager_new(dev);
test->loop = g_main_loop_new(NULL, FALSE);
gbinder_ipc_unref(ipc);
}
@@ -355,20 +333,45 @@ test_context_deinit(
{
test_binder_unregister_objects(test->fd);
gbinder_local_object_unref(test->object);
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(test->service));
gbinder_local_object_unref(GBINDER_LOCAL_OBJECT(test->service));
gbinder_servicemanager_unref(test->client);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, NULL);
test_binder_exit_wait(&test_opt, test->loop);
remove(test->config_file);
remove(test->config_dir);
g_free(test->config_file);
g_free(test->config_subdir);
g_free(test->config_dir);
g_main_loop_unref(test->loop);
gbinder_config_dir = test->default_config_dir;
gbinder_config_file = test->default_config_file;
gbinder_config_exit();
}
static
void
test_context_wait_ref_cb(
GBinderLocalObject* obj,
void* user_data)
{
GDEBUG("strong_refs %d", obj->strong_refs);
if (obj->strong_refs > 0) {
test_quit_later((GMainLoop*)user_data);
}
}
static
void
test_context_wait_ref(
TestContext* test)
{
/* Wait until the object gets referenced by servicemanager */
gulong id = gbinder_local_object_add_strong_refs_changed_handler
(test->object, test_context_wait_ref_cb, test->loop);
test_run(&test_opt, test->loop);
gbinder_local_object_remove_handler(test->object, id);
}
/*==========================================================================*
* get
*==========================================================================*/
@@ -397,6 +400,9 @@ test_get_run()
g_assert_cmpuint(g_hash_table_size(test.service->objects), == ,1);
g_assert(g_hash_table_contains(test.service->objects, name));
/* Wait until the object gets referenced by servicemanager */
test_context_wait_ref(&test);
/* Query the object (this time it must be there) */
GDEBUG("Querying '%s' again", name);
g_assert(gbinder_servicemanager_get_service_sync(test.client, name,
@@ -440,6 +446,9 @@ test_list_run()
g_assert_cmpint(gbinder_servicemanager_add_service_sync(test.client,
name, test.object), == ,GBINDER_STATUS_OK);
/* Wait until the object gets referenced by servicemanager */
test_context_wait_ref(&test);
/* Request the list again */
list = gbinder_servicemanager_list_sync(test.client);

View File

@@ -43,15 +43,13 @@
#include <gutil_strv.h>
static TestOpt test_opt;
#define MAIN_DEV GBINDER_DEFAULT_HWBINDER
#define OTHER_DEV GBINDER_DEFAULT_HWBINDER "-private"
#define DEV GBINDER_DEFAULT_HWBINDER
static const char TMP_DIR_TEMPLATE[] = "gbinder-test-svcmgr-hidl-XXXXXX";
static const char DEFAULT_CONFIG_DATA[] =
"[Protocol]\n"
MAIN_DEV " = hidl\n"
OTHER_DEV " = hidl\n"
DEV " = hidl\n"
"[ServiceManager]\n"
MAIN_DEV " = hidl\n";
DEV " = hidl\n";
typedef struct test_config {
char* dir;
@@ -134,7 +132,6 @@ test_servicemanager_impl_new(
const int fd = gbinder_driver_fd(ipc->driver);
TestServiceManagerHidl* sm = test_servicemanager_hidl_new(ipc);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
test_binder_register_object(fd, GBINDER_LOCAL_OBJECT(sm),
GBINDER_SERVICEMANAGER_HANDLE);
gbinder_ipc_unref(ipc);
@@ -199,16 +196,14 @@ test_get_run()
const char* name = "android.hidl.base@1.0::IBase/test";
test_config_init(&config, NULL);
ipc = gbinder_ipc_new(MAIN_DEV, NULL);
smsvc = test_servicemanager_impl_new(OTHER_DEV);
ipc = gbinder_ipc_new(DEV, NULL);
smsvc = test_servicemanager_impl_new(DEV);
obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
fd = gbinder_driver_fd(ipc->driver);
/* Set up binder simulator */
test_binder_register_object(fd, obj, AUTO_HANDLE);
test_binder_set_passthrough(fd, TRUE);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
sm = gbinder_servicemanager_new(MAIN_DEV);
sm = gbinder_servicemanager_new(DEV);
/* This one fails because of unexpected name format */
g_assert(!gbinder_servicemanager_get_service_sync(sm, "test", NULL));
@@ -233,13 +228,11 @@ test_get_run()
g_assert(gbinder_servicemanager_get_service(sm, name, test_get_cb, loop));
test_run(&test_opt, loop);
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
test_servicemanager_hidl_free(smsvc);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
test_config_deinit(&config);
g_main_loop_unref(loop);
@@ -294,16 +287,14 @@ test_list_run()
test.loop = g_main_loop_new(NULL, FALSE);
test_config_init(&config, NULL);
ipc = gbinder_ipc_new(MAIN_DEV, NULL);
smsvc = test_servicemanager_impl_new(OTHER_DEV);
ipc = gbinder_ipc_new(DEV, NULL);
smsvc = test_servicemanager_impl_new(DEV);
obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
fd = gbinder_driver_fd(ipc->driver);
/* Set up binder simulator */
test_binder_register_object(fd, obj, AUTO_HANDLE);
test_binder_set_passthrough(fd, TRUE);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
sm = gbinder_servicemanager_new(MAIN_DEV);
sm = gbinder_servicemanager_new(DEV);
/* Request the list and wait for completion */
g_assert(gbinder_servicemanager_list(sm, test_list_cb, &test));
@@ -326,13 +317,11 @@ test_list_run()
g_assert_cmpuint(gutil_strv_length(test.list), == ,1);
g_assert_cmpstr(test.list[0], == ,name);
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
test_servicemanager_hidl_free(smsvc);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, test.loop);
test_config_deinit(&config);
@@ -422,16 +411,14 @@ test_notify_run()
test.loop = g_main_loop_new(NULL, FALSE);
test_config_init(&config, NULL);
ipc = gbinder_ipc_new(MAIN_DEV, NULL);
test.smsvc = test_servicemanager_impl_new(OTHER_DEV);
ipc = gbinder_ipc_new(DEV, NULL);
test.smsvc = test_servicemanager_impl_new(DEV);
obj = gbinder_local_object_new(ipc, NULL, NULL, NULL);
fd = gbinder_driver_fd(ipc->driver);
/* Set up binder simulator */
test_binder_register_object(fd, obj, AUTO_HANDLE);
test_binder_set_passthrough(fd, TRUE);
test_binder_set_looper_enabled(fd, TEST_LOOPER_ENABLE);
sm = gbinder_servicemanager_new(MAIN_DEV);
sm = gbinder_servicemanager_new(DEV);
/* This one fails because of invalid names */
g_assert(!gbinder_servicemanager_add_registration_handler(sm, NULL,
@@ -455,13 +442,11 @@ test_notify_run()
test_run(&test_opt, test.loop);
gbinder_servicemanager_remove_handler(sm, id);
test_binder_unregister_objects(fd);
gbinder_local_object_unref(obj);
test_servicemanager_hidl_free(test.smsvc);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, test.loop);
test_config_deinit(&config);
g_main_loop_unref(test.loop);

View File

@@ -62,9 +62,9 @@ test_setup_ping(
{
const int fd = gbinder_driver_fd(ipc->driver);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_reply(fd, 0, 0, NULL);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
}
/*==========================================================================*
@@ -145,7 +145,7 @@ test_servicemanager_add_service(
}
} else {
test_binder_br_dead_binder(gbinder_driver_fd(obj->ipc->driver),
GBINDER_SERVICEMANAGER_HANDLE);
ANY_THREAD, GBINDER_SERVICEMANAGER_HANDLE);
}
}
}
@@ -311,7 +311,7 @@ test_basic(
gbinder_local_object_unref(obj);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -345,8 +345,7 @@ test_present(
g_assert_cmpstr(sn->name, == ,obj_name);
/* Immediately generate death notification (need looper for that) */
test_binder_br_dead_binder(fd, GBINDER_SERVICEMANAGER_HANDLE);
test_binder_set_looper_enabled(fd, TRUE);
test_binder_br_dead_binder(fd, ANY_THREAD, GBINDER_SERVICEMANAGER_HANDLE);
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
test_run(&test_opt, loop);
@@ -355,7 +354,6 @@ test_present(
gbinder_servicemanager_remove_handler(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -397,7 +395,7 @@ test_not_present(
gulong id;
/* This makes presence detection PING fail */
test_binder_br_reply_status(fd, -1);
test_binder_br_reply_status(fd, THIS_THREAD, -1);
sm = gbinder_servicemanager_new(dev);
g_assert(!gbinder_servicemanager_is_present(sm));
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
@@ -408,8 +406,8 @@ test_not_present(
g_assert_cmpstr(sn->name, == ,obj_name);
/* Make the next presence detection PING succeed */
test_binder_br_transaction_complete_later(fd);
test_binder_br_reply_later(fd, 0, 0, NULL);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
test_run(&test_opt, loop);
gbinder_servicename_unref(sn);
@@ -417,7 +415,7 @@ test_not_present(
gbinder_servicemanager_remove_handler(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -434,7 +432,6 @@ test_retry(
const char* const ifaces[] = { "interface", NULL };
const char* dev = GBINDER_DEFAULT_BINDER;
GBinderIpc* ipc = gbinder_ipc_new(dev, NULL);
const int fd = gbinder_driver_fd(ipc->driver);
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderLocalObject* obj;
GBinderServiceManager* sm;
@@ -450,8 +447,6 @@ test_retry(
g_assert(sn);
g_assert_cmpstr(sn->name, == ,obj_name);
/* Need looper for death notifications */
test_binder_set_looper_enabled(fd, TRUE);
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
test_run(&test_opt, loop);
@@ -460,7 +455,7 @@ test_retry(
gbinder_servicemanager_remove_handler(sm, id);
gbinder_servicemanager_unref(sm);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -500,9 +495,8 @@ test_cancel(
g_assert(sn);
g_assert_cmpstr(sn->name, == ,obj_name);
/* Immediately generate death notification (need looper for that) */
test_binder_br_dead_binder(fd, GBINDER_SERVICEMANAGER_HANDLE);
test_binder_set_looper_enabled(fd, TRUE);
/* Immediately generate death notification */
test_binder_br_dead_binder(fd, ANY_THREAD, GBINDER_SERVICEMANAGER_HANDLE);
id = gbinder_servicemanager_add_presence_handler(sm, test_quit, loop);
test_run(&test_opt, loop);
@@ -519,7 +513,6 @@ test_cancel(
g_mutex_unlock(&test->mutex);
gbinder_ipc_unref(ipc);
gbinder_ipc_exit();
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}

View File

@@ -52,9 +52,9 @@ test_setup_ping(
{
const int fd = gbinder_driver_fd(ipc->driver);
test_binder_br_noop(fd);
test_binder_br_transaction_complete(fd);
test_binder_br_reply(fd, 0, 0, NULL);
test_binder_br_noop(fd, THIS_THREAD);
test_binder_br_transaction_complete(fd, THIS_THREAD);
test_binder_br_reply(fd, THIS_THREAD, 0, 0, NULL);
}
/*==========================================================================*
@@ -268,6 +268,7 @@ test_basic(
gbinder_servicemanager_unref(manager);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
@@ -352,6 +353,7 @@ test_notify1(
g_assert(!weakptr);
gbinder_servicemanager_unref(manager);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -430,6 +432,7 @@ test_notify2(
g_assert(!weakptr);
gbinder_servicemanager_unref(manager);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}
@@ -478,6 +481,7 @@ test_already_there(
g_assert(!weakptr);
gbinder_servicemanager_unref(manager);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, loop);
g_main_loop_unref(loop);
}

View File

@@ -1,6 +1,7 @@
/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2023 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -252,9 +253,7 @@ void
test_int8(
void)
{
const char encoded[] = {
TEST_INT8_BYTES_4(0x80)
};
const char encoded[] = { 0x80, 0x00, 0x00, 0x00 };
GBinderLocalRequest* req = test_local_request_new();
GBinderOutputData* data;
GBinderWriter writer;
@@ -279,9 +278,7 @@ void
test_int16(
void)
{
const char encoded[] = {
TEST_INT16_BYTES_4(0x80ff)
};
const char encoded[] = { TEST_INT16_BYTES(0x80ff), 0x00, 0x00 };
GBinderLocalRequest* req = test_local_request_new();
GBinderOutputData* data;
GBinderWriter writer;
@@ -417,8 +414,8 @@ test_bool(
{
const char encoded[] = {
TEST_INT8_BYTES_4(0),
TEST_INT8_BYTES_4(1),
TEST_INT8_BYTES_4(1)
0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00
};
GBinderLocalRequest* req = test_local_request_new();
GBinderOutputData* data;