Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a08513ade0 | ||
|
|
1a57e01e07 | ||
|
|
6d4faf19b8 | ||
|
|
96e6845e16 | ||
|
|
b33adeb708 | ||
|
|
ea0e294a74 | ||
|
|
2d878c2391 | ||
|
|
6dec867cd3 | ||
|
|
d8bd7b9366 | ||
|
|
b52e4c6dee | ||
|
|
21046af42f | ||
|
|
3cbe1d6ac8 | ||
|
|
b4b1a99a27 | ||
|
|
f5a2d481e3 | ||
|
|
da57a15852 | ||
|
|
9d0ac624c5 | ||
|
|
b8ccc80b87 | ||
|
|
27e2dac22e | ||
|
|
a4ec4e382d | ||
|
|
30df5faf64 | ||
|
|
0aa29d8a91 | ||
|
|
3ace986e4a | ||
|
|
064ab48eee | ||
|
|
12c1725ab1 |
4
LICENSE
4
LICENSE
@@ -1,5 +1,5 @@
|
|||||||
Copyright (C) 2018-2019 Jolla Ltd.
|
Copyright (C) 2018-2020 Jolla Ltd.
|
||||||
Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
|
Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||||
|
|
||||||
You may use this file under the terms of BSD license as follows:
|
You may use this file under the terms of BSD license as follows:
|
||||||
|
|
||||||
|
|||||||
56
Makefile
56
Makefile
@@ -1,4 +1,8 @@
|
|||||||
# -*- Mode: makefile-gmake -*-
|
# -*- Mode: makefile-gmake -*-
|
||||||
|
#
|
||||||
|
# LIBGLIBUTIL_PATH can be defined to point to libglibutil root directory
|
||||||
|
# for side-by-side build.
|
||||||
|
#
|
||||||
|
|
||||||
.PHONY: clean all debug release test
|
.PHONY: clean all debug release test
|
||||||
.PHONY: print_debug_so print_release_so
|
.PHONY: print_debug_so print_release_so
|
||||||
@@ -7,10 +11,15 @@
|
|||||||
.PHONY: print_debug_path print_release_path
|
.PHONY: print_debug_path print_release_path
|
||||||
|
|
||||||
#
|
#
|
||||||
# Required packages
|
# Library version
|
||||||
#
|
#
|
||||||
|
|
||||||
PKGS = libglibutil glib-2.0 gobject-2.0
|
VERSION_MAJOR = 1
|
||||||
|
VERSION_MINOR = 0
|
||||||
|
VERSION_RELEASE = 37
|
||||||
|
|
||||||
|
# Version for pkg-config
|
||||||
|
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Default target
|
# Default target
|
||||||
@@ -19,15 +28,34 @@ PKGS = libglibutil glib-2.0 gobject-2.0
|
|||||||
all: debug release pkgconfig
|
all: debug release pkgconfig
|
||||||
|
|
||||||
#
|
#
|
||||||
# Library version
|
# Required packages
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION_MAJOR = 1
|
PKGS = glib-2.0 gobject-2.0
|
||||||
VERSION_MINOR = 0
|
|
||||||
VERSION_RELEASE = 32
|
|
||||||
|
|
||||||
# Version for pkg-config
|
ifeq ($(LIBGLIBUTIL_PATH),)
|
||||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
|
||||||
|
# Assume that libglibutil devel package is installed
|
||||||
|
PKGS += libglibutil
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
# Side-by-side build
|
||||||
|
INCLUDES += -I$(LIBGLIBUTIL_PATH)/include
|
||||||
|
DEBUG_LIBS = -L$(LIBGLIBUTIL_PATH)/build/debug -lglibutil
|
||||||
|
RELEASE_LIBS = -L$(LIBGLIBUTIL_PATH)/build/release -lglibutil
|
||||||
|
DEBUG_DEPS = libglibutil_debug
|
||||||
|
RELEASE_DEPS = libglibutil_release
|
||||||
|
|
||||||
|
.PHONY: libglibutil_debug libglibutil_release
|
||||||
|
|
||||||
|
libglibutil_debug:
|
||||||
|
make -C $(LIBGLIBUTIL_PATH) debug
|
||||||
|
|
||||||
|
libglibutil_release:
|
||||||
|
make -C $(LIBGLIBUTIL_PATH) release
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
# Library name
|
# Library name
|
||||||
@@ -89,10 +117,10 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
|
|||||||
# Tools and flags
|
# Tools and flags
|
||||||
#
|
#
|
||||||
|
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
|
WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
|
||||||
INCLUDES = -I$(INCLUDE_DIR)
|
INCLUDES += -I$(INCLUDE_DIR)
|
||||||
BASE_FLAGS = -fPIC
|
BASE_FLAGS = -fPIC
|
||||||
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
|
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
|
||||||
-MMD -MP $(shell pkg-config --cflags $(PKGS))
|
-MMD -MP $(shell pkg-config --cflags $(PKGS))
|
||||||
@@ -110,8 +138,8 @@ ifneq ($(KEEP_SYMBOLS),0)
|
|||||||
RELEASE_FLAGS += -g
|
RELEASE_FLAGS += -g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
|
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_LIBS) $(DEBUG_FLAGS)
|
||||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
|
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_LIBS) $(RELEASE_FLAGS)
|
||||||
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||||
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
|
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
|
||||||
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
|
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
|
||||||
@@ -137,8 +165,8 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
$(PKGCONFIG): | $(BUILD_DIR)
|
$(PKGCONFIG): | $(BUILD_DIR)
|
||||||
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR)
|
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR) $(DEBUG_DEPS)
|
||||||
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR)
|
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR) $(RELEASE_DEPS)
|
||||||
$(COVERAGE_OBJS) $(COVERAGE_LIB): | $(COVERAGE_BUILD_DIR)
|
$(COVERAGE_OBJS) $(COVERAGE_LIB): | $(COVERAGE_BUILD_DIR)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
32
debian/changelog
vendored
32
debian/changelog
vendored
@@ -1,3 +1,35 @@
|
|||||||
|
libgbinder (1.0.37) unstable; urgency=low
|
||||||
|
|
||||||
|
* Allow side-by-side linking with libglibutil
|
||||||
|
* Fixed compilation warnings
|
||||||
|
|
||||||
|
-- Slava Monich <slava.monich@jolla.com> Tue, 17 Mar 2020 20:15:11 +0200
|
||||||
|
|
||||||
|
libgbinder (1.0.36) unstable; urgency=low
|
||||||
|
|
||||||
|
* Allow overwriting CC
|
||||||
|
|
||||||
|
-- Slava Monich <slava.monich@jolla.com> Mon, 16 Mar 2020 16:15:24 +0200
|
||||||
|
|
||||||
|
libgbinder (1.0.35) unstable; urgency=low
|
||||||
|
|
||||||
|
* Added binder-ping example
|
||||||
|
|
||||||
|
-- Slava Monich <slava.monich@jolla.com> Tue, 25 Feb 2020 13:58:19 +0200
|
||||||
|
|
||||||
|
libgbinder (1.0.34) unstable; urgency=low
|
||||||
|
|
||||||
|
* Better cleanup on unload to prevent crashes on exit
|
||||||
|
* Fixed rare memory leak in GBinderServiceManager
|
||||||
|
|
||||||
|
-- Slava Monich <slava.monich@jolla.com> Mon, 16 Dec 2019 12:25:56 +0200
|
||||||
|
|
||||||
|
libgbinder (1.0.33) unstable; urgency=low
|
||||||
|
|
||||||
|
* Reuse loopers
|
||||||
|
|
||||||
|
-- Slava Monich <slava.monich@jolla.com> Fri, 13 Sep 2019 15:57:47 +0300
|
||||||
|
|
||||||
libgbinder (1.0.32) unstable; urgency=low
|
libgbinder (1.0.32) unstable; urgency=low
|
||||||
|
|
||||||
* Refuse to perform transactions with dead objects
|
* Refuse to perform transactions with dead objects
|
||||||
|
|||||||
10
debian/copyright
vendored
10
debian/copyright
vendored
@@ -1,5 +1,5 @@
|
|||||||
Copyright (C) 2018 Jolla Ltd.
|
Copyright (C) 2018-2020 Jolla Ltd.
|
||||||
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||||
|
|
||||||
You may use this file under the terms of BSD license as follows:
|
You may use this file under the terms of BSD license as follows:
|
||||||
|
|
||||||
@@ -12,9 +12,9 @@ are met:
|
|||||||
2. Redistributions in binary form must reproduce the above copyright
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
notice, this list of conditions and the following disclaimer in the
|
notice, this list of conditions and the following disclaimer in the
|
||||||
documentation and/or other materials provided with the distribution.
|
documentation and/or other materials provided with the distribution.
|
||||||
3. Neither the name of Jolla Ltd nor the names of its contributors may
|
3. Neither the names of the copyright holders nor the names of its
|
||||||
be used to endorse or promote products derived from this software
|
contributors may be used to endorse or promote products derived
|
||||||
without specific prior written permission.
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Name: libgbinder
|
Name: libgbinder
|
||||||
Version: 1.0.32
|
Version: 1.0.37
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: Binder client library
|
Summary: Binder client library
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018-2019 Jolla Ltd.
|
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||||
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
|
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||||
*
|
*
|
||||||
* You may use this file under the terms of BSD license as follows:
|
* You may use this file under the terms of BSD license as follows:
|
||||||
*
|
*
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. Neither the names of the copyright holders nor the names of its
|
* 3. Neither the names of the copyright holders nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived
|
||||||
* this software without specific prior written permission.
|
* from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||||
|
|
||||||
#include "gbinder_ipc.h"
|
#include "gbinder_ipc.h"
|
||||||
#include "gbinder_driver.h"
|
#include "gbinder_driver.h"
|
||||||
#include "gbinder_handler.h"
|
#include "gbinder_handler.h"
|
||||||
@@ -87,7 +89,7 @@ static GHashTable* gbinder_ipc_table = NULL;
|
|||||||
static pthread_mutex_t gbinder_ipc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t gbinder_ipc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
#define GBINDER_IPC_MAX_TX_THREADS (15)
|
#define GBINDER_IPC_MAX_TX_THREADS (15)
|
||||||
#define GBINDER_IPC_MAX_LOOPERS (15)
|
#define GBINDER_IPC_MAX_PRIMARY_LOOPERS (5)
|
||||||
#define GBINDER_IPC_LOOPER_START_TIMEOUT_SEC (2)
|
#define GBINDER_IPC_LOOPER_START_TIMEOUT_SEC (2)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -173,6 +175,7 @@ typedef struct gbinder_ipc_tx_priv {
|
|||||||
GBinderIpcTxPrivFunc fn_exec;
|
GBinderIpcTxPrivFunc fn_exec;
|
||||||
GBinderIpcTxPrivFunc fn_done;
|
GBinderIpcTxPrivFunc fn_done;
|
||||||
GBinderIpcTxPrivFunc fn_free;
|
GBinderIpcTxPrivFunc fn_free;
|
||||||
|
GSource* completion;
|
||||||
} GBinderIpcTxPriv;
|
} GBinderIpcTxPriv;
|
||||||
|
|
||||||
typedef struct gbinder_ipc_tx_internal {
|
typedef struct gbinder_ipc_tx_internal {
|
||||||
@@ -340,7 +343,9 @@ gbinder_remote_request_complete(
|
|||||||
tx->reply = gbinder_local_reply_ref(reply);
|
tx->reply = gbinder_local_reply_ref(reply);
|
||||||
tx->state = GBINDER_IPC_LOOPER_TX_COMPLETE;
|
tx->state = GBINDER_IPC_LOOPER_TX_COMPLETE;
|
||||||
/* Wake up the looper */
|
/* Wake up the looper */
|
||||||
(void)write(tx->pipefd[1], &done, sizeof(done));
|
if (write(tx->pipefd[1], &done, sizeof(done)) <= 0) {
|
||||||
|
GWARN("Failed to wake up the looper");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GWARN("Unexpected state %d in request completion", tx->state);
|
GWARN("Unexpected state %d in request completion", tx->state);
|
||||||
@@ -358,6 +363,48 @@ gbinder_remote_request_complete(
|
|||||||
* GBinderIpcLooper
|
* GBinderIpcLooper
|
||||||
*==========================================================================*/
|
*==========================================================================*/
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gbinder_ipc_looper_free(
|
||||||
|
GBinderIpcLooper* looper)
|
||||||
|
{
|
||||||
|
if (looper->thread) {
|
||||||
|
g_thread_unref(looper->thread);
|
||||||
|
}
|
||||||
|
close(looper->pipefd[0]);
|
||||||
|
close(looper->pipefd[1]);
|
||||||
|
if (looper->txfd[0] >= 0) {
|
||||||
|
close(looper->txfd[0]);
|
||||||
|
close(looper->txfd[1]);
|
||||||
|
}
|
||||||
|
gbinder_driver_unref(looper->driver);
|
||||||
|
g_free(looper->name);
|
||||||
|
g_cond_clear(&looper->start_cond);
|
||||||
|
g_mutex_clear(&looper->mutex);
|
||||||
|
g_slice_free(GBinderIpcLooper, looper);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
GBinderIpcLooper*
|
||||||
|
gbinder_ipc_looper_ref(
|
||||||
|
GBinderIpcLooper* looper)
|
||||||
|
{
|
||||||
|
GASSERT(looper->refcount > 0);
|
||||||
|
g_atomic_int_inc(&looper->refcount);
|
||||||
|
return looper;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gbinder_ipc_looper_unref(
|
||||||
|
GBinderIpcLooper* looper)
|
||||||
|
{
|
||||||
|
GASSERT(looper->refcount > 0);
|
||||||
|
if (g_atomic_int_dec_and_test(&looper->refcount)) {
|
||||||
|
gbinder_ipc_looper_free(looper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
gboolean
|
gboolean
|
||||||
gbinder_ipc_looper_tx_handle(
|
gbinder_ipc_looper_tx_handle(
|
||||||
@@ -430,7 +477,9 @@ gbinder_ipc_looper_tx_handle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* And wake up the looper */
|
/* And wake up the looper */
|
||||||
(void)write(tx->pipefd[1], &done, sizeof(done));
|
if (write(tx->pipefd[1], &done, sizeof(done)) <= 0) {
|
||||||
|
GWARN("Failed to wake up the looper");
|
||||||
|
}
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,6 +491,25 @@ gbinder_ipc_looper_tx_done(
|
|||||||
gbinder_ipc_looper_tx_unref(data, FALSE);
|
gbinder_ipc_looper_tx_unref(data, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gbinder_ipc_looper_start(
|
||||||
|
GBinderIpcLooper* looper)
|
||||||
|
{
|
||||||
|
if (!g_atomic_int_get(&looper->started)) {
|
||||||
|
/* Lock */
|
||||||
|
g_mutex_lock(&looper->mutex);
|
||||||
|
if (!g_atomic_int_get(&looper->started)) {
|
||||||
|
g_cond_wait_until(&looper->start_cond, &looper->mutex,
|
||||||
|
g_get_monotonic_time() + GBINDER_IPC_LOOPER_START_TIMEOUT_SEC *
|
||||||
|
G_TIME_SPAN_SECOND);
|
||||||
|
GASSERT(g_atomic_int_get(&looper->started));
|
||||||
|
}
|
||||||
|
g_mutex_unlock(&looper->mutex);
|
||||||
|
/* Unlock */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
gboolean
|
gboolean
|
||||||
gbinder_ipc_looper_remove_from_list(
|
gbinder_ipc_looper_remove_from_list(
|
||||||
@@ -488,6 +556,18 @@ gbinder_ipc_looper_remove_blocked(
|
|||||||
&looper->ipc->priv->blocked_loopers);
|
&looper->ipc->priv->blocked_loopers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
guint
|
||||||
|
gbinder_ipc_looper_count_primary(
|
||||||
|
GBinderIpcLooper* looper)
|
||||||
|
{
|
||||||
|
const GBinderIpcLooper* ptr = looper->ipc->priv->primary_loopers;
|
||||||
|
guint n = 0;
|
||||||
|
|
||||||
|
for (n = 0; ptr; ptr = ptr->next) n++;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
GBinderLocalReply*
|
GBinderLocalReply*
|
||||||
gbinder_ipc_looper_transact(
|
gbinder_ipc_looper_transact(
|
||||||
@@ -514,12 +594,12 @@ gbinder_ipc_looper_transact(
|
|||||||
struct pollfd fds[2];
|
struct pollfd fds[2];
|
||||||
guint8 done = 0;
|
guint8 done = 0;
|
||||||
GSource* source = g_idle_source_new();
|
GSource* source = g_idle_source_new();
|
||||||
|
gboolean was_blocked = FALSE;
|
||||||
|
|
||||||
/* Let GBinderLocalObject handle the transaction on the main thread */
|
/* Let GBinderLocalObject handle the transaction on the main thread */
|
||||||
g_source_set_callback(source, gbinder_ipc_looper_tx_handle,
|
g_source_set_callback(source, gbinder_ipc_looper_tx_handle,
|
||||||
gbinder_ipc_looper_tx_ref(tx), gbinder_ipc_looper_tx_done);
|
gbinder_ipc_looper_tx_ref(tx), gbinder_ipc_looper_tx_done);
|
||||||
g_source_attach(source, priv->context);
|
g_source_attach(source, priv->context);
|
||||||
g_source_unref(source);
|
|
||||||
|
|
||||||
/* Wait for either transaction completion or looper shutdown */
|
/* Wait for either transaction completion or looper shutdown */
|
||||||
memset(fds, 0, sizeof(fds));
|
memset(fds, 0, sizeof(fds));
|
||||||
@@ -543,29 +623,35 @@ gbinder_ipc_looper_transact(
|
|||||||
* moved to the blocked_loopers list.
|
* moved to the blocked_loopers list.
|
||||||
*/
|
*/
|
||||||
GBinderIpcPriv* priv = looper->ipc->priv;
|
GBinderIpcPriv* priv = looper->ipc->priv;
|
||||||
|
GBinderIpcLooper* new_looper = NULL;
|
||||||
|
|
||||||
/* Lock */
|
/* Lock */
|
||||||
g_mutex_lock(&priv->looper_mutex);
|
g_mutex_lock(&priv->looper_mutex);
|
||||||
if (gbinder_ipc_looper_remove_primary(looper)) {
|
if (gbinder_ipc_looper_remove_primary(looper)) {
|
||||||
GBinderIpcLooper* new_looper;
|
|
||||||
|
|
||||||
GDEBUG("Primary looper %s is blocked", looper->name);
|
GDEBUG("Primary looper %s is blocked", looper->name);
|
||||||
looper->next = priv->blocked_loopers;
|
looper->next = priv->blocked_loopers;
|
||||||
priv->blocked_loopers = looper;
|
priv->blocked_loopers = looper;
|
||||||
|
was_blocked = TRUE;
|
||||||
|
|
||||||
/* Looper will exit once transaction completes */
|
/* If there's no more primary loopers left, create one */
|
||||||
g_atomic_int_set(&looper->exit, 1);
|
if (!priv->primary_loopers) {
|
||||||
|
new_looper = gbinder_ipc_looper_new(ipc);
|
||||||
/* Create new primary looper to replace this one */
|
if (new_looper) {
|
||||||
new_looper = gbinder_ipc_looper_new(ipc);
|
/* Will unref it after it gets started */
|
||||||
if (new_looper) {
|
gbinder_ipc_looper_ref(new_looper);
|
||||||
new_looper->next = priv->primary_loopers;
|
priv->primary_loopers = new_looper;
|
||||||
priv->primary_loopers = new_looper;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_mutex_unlock(&priv->looper_mutex);
|
g_mutex_unlock(&priv->looper_mutex);
|
||||||
/* Unlock */
|
/* Unlock */
|
||||||
|
|
||||||
|
if (new_looper) {
|
||||||
|
/* Wait until it gets started */
|
||||||
|
gbinder_ipc_looper_start(new_looper);
|
||||||
|
gbinder_ipc_looper_unref(new_looper);
|
||||||
|
}
|
||||||
|
|
||||||
/* Block until asynchronous transaction gets completed. */
|
/* Block until asynchronous transaction gets completed. */
|
||||||
done = 0;
|
done = 0;
|
||||||
memset(fds, 0, sizeof(fds));
|
memset(fds, 0, sizeof(fds));
|
||||||
@@ -576,10 +662,12 @@ gbinder_ipc_looper_transact(
|
|||||||
poll(fds, 2, -1);
|
poll(fds, 2, -1);
|
||||||
if ((fds[1].revents & POLLIN) &&
|
if ((fds[1].revents & POLLIN) &&
|
||||||
read(fds[1].fd, &done, sizeof(done)) == 1) {
|
read(fds[1].fd, &done, sizeof(done)) == 1) {
|
||||||
|
GDEBUG("Looper %s is released", looper->name);
|
||||||
GASSERT(done == TX_DONE);
|
GASSERT(done == TX_DONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
GASSERT(done == TX_DONE);
|
GASSERT(done == TX_DONE);
|
||||||
reply = gbinder_local_reply_ref(tx->reply);
|
reply = gbinder_local_reply_ref(tx->reply);
|
||||||
@@ -596,53 +684,32 @@ gbinder_ipc_looper_transact(
|
|||||||
} else {
|
} else {
|
||||||
gbinder_ipc_looper_tx_unref(tx, FALSE);
|
gbinder_ipc_looper_tx_unref(tx, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_source_destroy(source);
|
||||||
|
g_source_unref(source);
|
||||||
|
|
||||||
|
if (was_blocked) {
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
g_mutex_lock(&priv->looper_mutex);
|
||||||
|
n = gbinder_ipc_looper_count_primary(looper);
|
||||||
|
if (n >= GBINDER_IPC_MAX_PRIMARY_LOOPERS) {
|
||||||
|
/* Looper will exit once transaction completes */
|
||||||
|
GDEBUG("Too many primary loopers (%u)", n);
|
||||||
|
g_atomic_int_set(&looper->exit, 1);
|
||||||
|
} else {
|
||||||
|
/* Move it back to the primary list */
|
||||||
|
gbinder_ipc_looper_remove_blocked(looper);
|
||||||
|
looper->next = priv->primary_loopers;
|
||||||
|
priv->primary_loopers = looper;
|
||||||
|
}
|
||||||
|
g_mutex_unlock(&priv->looper_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*result = status;
|
*result = status;
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
gbinder_ipc_looper_free(
|
|
||||||
GBinderIpcLooper* looper)
|
|
||||||
{
|
|
||||||
if (looper->thread) {
|
|
||||||
g_thread_unref(looper->thread);
|
|
||||||
}
|
|
||||||
close(looper->pipefd[0]);
|
|
||||||
close(looper->pipefd[1]);
|
|
||||||
if (looper->txfd[0] >= 0) {
|
|
||||||
close(looper->txfd[0]);
|
|
||||||
close(looper->txfd[1]);
|
|
||||||
}
|
|
||||||
gbinder_driver_unref(looper->driver);
|
|
||||||
g_free(looper->name);
|
|
||||||
g_cond_clear(&looper->start_cond);
|
|
||||||
g_mutex_clear(&looper->mutex);
|
|
||||||
g_slice_free(GBinderIpcLooper, looper);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
GBinderIpcLooper*
|
|
||||||
gbinder_ipc_looper_ref(
|
|
||||||
GBinderIpcLooper* looper)
|
|
||||||
{
|
|
||||||
GASSERT(looper->refcount > 0);
|
|
||||||
g_atomic_int_inc(&looper->refcount);
|
|
||||||
return looper;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
gbinder_ipc_looper_unref(
|
|
||||||
GBinderIpcLooper* looper)
|
|
||||||
{
|
|
||||||
GASSERT(looper->refcount > 0);
|
|
||||||
if (g_atomic_int_dec_and_test(&looper->refcount)) {
|
|
||||||
gbinder_ipc_looper_free(looper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
gpointer
|
gpointer
|
||||||
gbinder_ipc_looper_thread(
|
gbinder_ipc_looper_thread(
|
||||||
@@ -787,27 +854,21 @@ gbinder_ipc_looper_check(
|
|||||||
|
|
||||||
/* Lock */
|
/* Lock */
|
||||||
g_mutex_lock(&priv->looper_mutex);
|
g_mutex_lock(&priv->looper_mutex);
|
||||||
|
if (!priv->primary_loopers) {
|
||||||
|
priv->primary_loopers = gbinder_ipc_looper_new(self);
|
||||||
|
}
|
||||||
looper = priv->primary_loopers;
|
looper = priv->primary_loopers;
|
||||||
if (!looper) {
|
if (looper) {
|
||||||
looper = priv->primary_loopers = gbinder_ipc_looper_new(self);
|
gbinder_ipc_looper_ref(looper);
|
||||||
}
|
}
|
||||||
g_mutex_unlock(&priv->looper_mutex);
|
g_mutex_unlock(&priv->looper_mutex);
|
||||||
/* Unlock */
|
/* Unlock */
|
||||||
|
|
||||||
/* We are not ready to accept incoming transactions until
|
/* We are not ready to accept incoming transactions until
|
||||||
* looper has started. We may need to wait a bit. */
|
* looper has started. We may need to wait a bit. */
|
||||||
if (looper && !g_atomic_int_get(&looper->started)) {
|
if (looper) {
|
||||||
/* Lock */
|
gbinder_ipc_looper_start(looper);
|
||||||
g_mutex_lock(&looper->mutex);
|
gbinder_ipc_looper_unref(looper);
|
||||||
if (!g_atomic_int_get(&looper->started)) {
|
|
||||||
g_cond_wait_until(&looper->start_cond, &looper->mutex,
|
|
||||||
g_get_monotonic_time() +
|
|
||||||
GBINDER_IPC_LOOPER_START_TIMEOUT_SEC *
|
|
||||||
G_TIME_SPAN_SECOND);
|
|
||||||
GASSERT(g_atomic_int_get(&looper->started));
|
|
||||||
}
|
|
||||||
g_mutex_unlock(&looper->mutex);
|
|
||||||
/* Unlock */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1126,6 +1187,38 @@ gbinder_ipc_tx_get_id(
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gbinder_ipc_tx_free(
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GBinderIpcTxPriv* tx = data;
|
||||||
|
GBinderIpcTx* pub = &tx->pub;
|
||||||
|
GBinderIpc* self = pub->ipc;
|
||||||
|
GBinderIpcPriv* priv = self->priv;
|
||||||
|
|
||||||
|
g_source_unref(tx->completion);
|
||||||
|
g_hash_table_remove(priv->tx_table, GINT_TO_POINTER(pub->id));
|
||||||
|
tx->fn_free(tx);
|
||||||
|
|
||||||
|
/* This may actually deallocate GBinderIpc object: */
|
||||||
|
gbinder_ipc_unref(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
gbinder_ipc_tx_done(
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GBinderIpcTxPriv* tx = data;
|
||||||
|
GBinderIpcTx* pub = &tx->pub;
|
||||||
|
|
||||||
|
if (!pub->cancelled) {
|
||||||
|
tx->fn_done(tx);
|
||||||
|
}
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
gbinder_ipc_tx_pub_init(
|
gbinder_ipc_tx_pub_init(
|
||||||
@@ -1139,6 +1232,26 @@ gbinder_ipc_tx_pub_init(
|
|||||||
tx->user_data = user_data;
|
tx->user_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gbinder_ipc_tx_priv_init(
|
||||||
|
GBinderIpcTxPriv* priv,
|
||||||
|
GBinderIpc* self,
|
||||||
|
gulong id,
|
||||||
|
void* user_data,
|
||||||
|
GBinderIpcTxPrivFunc fn_exec,
|
||||||
|
GBinderIpcTxPrivFunc fn_done,
|
||||||
|
GBinderIpcTxPrivFunc fn_free)
|
||||||
|
{
|
||||||
|
gbinder_ipc_tx_pub_init(&priv->pub, self, id, user_data);
|
||||||
|
priv->fn_exec = fn_exec;
|
||||||
|
priv->fn_done = fn_done;
|
||||||
|
priv->fn_free = fn_free;
|
||||||
|
priv->completion = g_idle_source_new();
|
||||||
|
g_source_set_callback(priv->completion, gbinder_ipc_tx_done, priv,
|
||||||
|
gbinder_ipc_tx_free);
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
inline
|
inline
|
||||||
GBinderIpcTxInternal*
|
GBinderIpcTxInternal*
|
||||||
@@ -1220,10 +1333,9 @@ gbinder_ipc_tx_internal_new(
|
|||||||
GBinderIpcTxInternal* tx = g_slice_new0(GBinderIpcTxInternal);
|
GBinderIpcTxInternal* tx = g_slice_new0(GBinderIpcTxInternal);
|
||||||
GBinderIpcTxPriv* priv = &tx->tx;
|
GBinderIpcTxPriv* priv = &tx->tx;
|
||||||
|
|
||||||
gbinder_ipc_tx_pub_init(&priv->pub, self, id, user_data);
|
gbinder_ipc_tx_priv_init(priv, self, id, user_data,
|
||||||
priv->fn_exec = gbinder_ipc_tx_internal_exec;
|
gbinder_ipc_tx_internal_exec, gbinder_ipc_tx_internal_done,
|
||||||
priv->fn_done = gbinder_ipc_tx_internal_done;
|
gbinder_ipc_tx_internal_free);
|
||||||
priv->fn_free = gbinder_ipc_tx_internal_free;
|
|
||||||
|
|
||||||
tx->code = code;
|
tx->code = code;
|
||||||
tx->flags = flags;
|
tx->flags = flags;
|
||||||
@@ -1294,10 +1406,9 @@ gbinder_ipc_tx_custom_new(
|
|||||||
GBinderIpcTxCustom* tx = g_slice_new0(GBinderIpcTxCustom);
|
GBinderIpcTxCustom* tx = g_slice_new0(GBinderIpcTxCustom);
|
||||||
GBinderIpcTxPriv* priv = &tx->tx;
|
GBinderIpcTxPriv* priv = &tx->tx;
|
||||||
|
|
||||||
gbinder_ipc_tx_pub_init(&priv->pub, self, id, user_data);
|
gbinder_ipc_tx_priv_init(priv, self, id, user_data,
|
||||||
priv->fn_exec = gbinder_ipc_tx_custom_exec;
|
gbinder_ipc_tx_custom_exec, gbinder_ipc_tx_custom_done,
|
||||||
priv->fn_done = gbinder_ipc_tx_custom_done;
|
gbinder_ipc_tx_custom_free);
|
||||||
priv->fn_free = gbinder_ipc_tx_custom_free;
|
|
||||||
|
|
||||||
tx->fn_custom_exec = exec;
|
tx->fn_custom_exec = exec;
|
||||||
tx->fn_custom_done = done;
|
tx->fn_custom_done = done;
|
||||||
@@ -1306,41 +1417,6 @@ gbinder_ipc_tx_custom_new(
|
|||||||
return priv;
|
return priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
gbinder_ipc_tx_free(
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GBinderIpcTxPriv* tx = data;
|
|
||||||
GBinderIpcTx* pub = &tx->pub;
|
|
||||||
GBinderIpc* self = pub->ipc;
|
|
||||||
GBinderIpcPriv* priv = self->priv;
|
|
||||||
|
|
||||||
g_hash_table_remove(priv->tx_table, GINT_TO_POINTER(pub->id));
|
|
||||||
tx->fn_free(tx);
|
|
||||||
|
|
||||||
/* This may actually deallocate GBinderIpc object: */
|
|
||||||
gbinder_ipc_unref(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
gboolean
|
|
||||||
gbinder_ipc_tx_done(
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GBinderIpcTxPriv* tx = data;
|
|
||||||
GBinderIpcTx* pub = &tx->pub;
|
|
||||||
GBinderIpc* self = pub->ipc;
|
|
||||||
GBinderIpcPriv* priv = self->priv;
|
|
||||||
|
|
||||||
if (g_hash_table_remove(priv->tx_table, GINT_TO_POINTER(tx->pub.id))) {
|
|
||||||
GASSERT(!pub->cancelled);
|
|
||||||
tx->fn_done(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invoked on a thread from tx_pool */
|
/* Invoked on a thread from tx_pool */
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
@@ -1351,7 +1427,6 @@ gbinder_ipc_tx_proc(
|
|||||||
GBinderIpcTxPriv* tx = data;
|
GBinderIpcTxPriv* tx = data;
|
||||||
GBinderIpc* self = GBINDER_IPC(object);
|
GBinderIpc* self = GBINDER_IPC(object);
|
||||||
GBinderIpcPriv* priv = self->priv;
|
GBinderIpcPriv* priv = self->priv;
|
||||||
GSource* source = g_idle_source_new();
|
|
||||||
|
|
||||||
if (!tx->pub.cancelled) {
|
if (!tx->pub.cancelled) {
|
||||||
tx->fn_exec(tx);
|
tx->fn_exec(tx);
|
||||||
@@ -1360,9 +1435,7 @@ gbinder_ipc_tx_proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The result is handled by the main thread */
|
/* The result is handled by the main thread */
|
||||||
g_source_set_callback(source, gbinder_ipc_tx_done, tx, gbinder_ipc_tx_free);
|
g_source_attach(tx->completion, priv->context);
|
||||||
g_source_attach(source, priv->context);
|
|
||||||
g_source_unref(source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
@@ -1539,7 +1612,6 @@ gbinder_ipc_cancel(
|
|||||||
GBinderIpcTx* tx = g_hash_table_lookup(priv->tx_table, key);
|
GBinderIpcTx* tx = g_hash_table_lookup(priv->tx_table, key);
|
||||||
|
|
||||||
if (tx) {
|
if (tx) {
|
||||||
GVERIFY(g_hash_table_remove(priv->tx_table, key));
|
|
||||||
tx->cancelled = TRUE;
|
tx->cancelled = TRUE;
|
||||||
GVERBOSE_("%lu", id);
|
GVERBOSE_("%lu", id);
|
||||||
} else {
|
} else {
|
||||||
@@ -1579,14 +1651,44 @@ gbinder_ipc_init(
|
|||||||
self->pool = gutil_idle_pool_new();
|
self->pool = gutil_idle_pool_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
gbinder_ipc_stop_loopers(
|
||||||
|
GBinderIpc* self)
|
||||||
|
{
|
||||||
|
GBinderIpcPriv* priv = self->priv;
|
||||||
|
GBinderIpcLooper* loopers = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
GBinderIpcLooper* tmp;
|
||||||
|
|
||||||
|
/* Lock */
|
||||||
|
g_mutex_lock(&priv->looper_mutex);
|
||||||
|
loopers = gbinder_ipc_looper_stop_all(gbinder_ipc_looper_stop_all(NULL,
|
||||||
|
priv->primary_loopers), priv->blocked_loopers);
|
||||||
|
priv->blocked_loopers = NULL;
|
||||||
|
priv->primary_loopers = NULL;
|
||||||
|
g_mutex_unlock(&priv->looper_mutex);
|
||||||
|
/* Unlock */
|
||||||
|
|
||||||
|
tmp = loopers;
|
||||||
|
while (tmp) {
|
||||||
|
GBinderIpcLooper* looper = tmp;
|
||||||
|
|
||||||
|
tmp = looper->next;
|
||||||
|
looper->next = NULL;
|
||||||
|
gbinder_ipc_looper_join(looper);
|
||||||
|
gbinder_ipc_looper_unref(looper);
|
||||||
|
}
|
||||||
|
} while (loopers);
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
gbinder_ipc_dispose(
|
gbinder_ipc_dispose(
|
||||||
GObject* object)
|
GObject* object)
|
||||||
{
|
{
|
||||||
GBinderIpc* self = GBINDER_IPC(object);
|
GBinderIpc* self = GBINDER_IPC(object);
|
||||||
GBinderIpcPriv* priv = self->priv;
|
|
||||||
GBinderIpcLooper* loopers = NULL;
|
|
||||||
|
|
||||||
GVERBOSE_("%s", self->dev);
|
GVERBOSE_("%s", self->dev);
|
||||||
/* Lock */
|
/* Lock */
|
||||||
@@ -1605,24 +1707,7 @@ gbinder_ipc_dispose(
|
|||||||
pthread_mutex_unlock(&gbinder_ipc_mutex);
|
pthread_mutex_unlock(&gbinder_ipc_mutex);
|
||||||
/* Unlock */
|
/* Unlock */
|
||||||
|
|
||||||
/* Lock */
|
gbinder_ipc_stop_loopers(self);
|
||||||
g_mutex_lock(&priv->looper_mutex);
|
|
||||||
loopers = gbinder_ipc_looper_stop_all(loopers, priv->primary_loopers);
|
|
||||||
loopers = gbinder_ipc_looper_stop_all(loopers, priv->blocked_loopers);
|
|
||||||
priv->blocked_loopers = NULL;
|
|
||||||
priv->primary_loopers = NULL;
|
|
||||||
g_mutex_unlock(&priv->looper_mutex);
|
|
||||||
/* Unlock */
|
|
||||||
|
|
||||||
while (loopers) {
|
|
||||||
GBinderIpcLooper* looper = loopers;
|
|
||||||
|
|
||||||
loopers = looper->next;
|
|
||||||
looper->next = NULL;
|
|
||||||
gbinder_ipc_looper_join(looper);
|
|
||||||
gbinder_ipc_looper_unref(looper);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
|
G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1639,7 +1724,9 @@ gbinder_ipc_finalize(
|
|||||||
g_mutex_clear(&priv->looper_mutex);
|
g_mutex_clear(&priv->looper_mutex);
|
||||||
g_mutex_clear(&priv->local_objects_mutex);
|
g_mutex_clear(&priv->local_objects_mutex);
|
||||||
g_mutex_clear(&priv->remote_objects_mutex);
|
g_mutex_clear(&priv->remote_objects_mutex);
|
||||||
g_thread_pool_free(priv->tx_pool, FALSE, TRUE);
|
if (priv->tx_pool) {
|
||||||
|
g_thread_pool_free(priv->tx_pool, FALSE, TRUE);
|
||||||
|
}
|
||||||
GASSERT(!g_hash_table_size(priv->tx_table));
|
GASSERT(!g_hash_table_size(priv->tx_table));
|
||||||
g_hash_table_unref(priv->tx_table);
|
g_hash_table_unref(priv->tx_table);
|
||||||
gutil_idle_pool_unref(self->pool);
|
gutil_idle_pool_unref(self->pool);
|
||||||
@@ -1660,6 +1747,91 @@ gbinder_ipc_class_init(
|
|||||||
object_class->finalize = gbinder_ipc_finalize;
|
object_class->finalize = gbinder_ipc_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Runs at exit */
|
||||||
|
void
|
||||||
|
gbinder_ipc_exit()
|
||||||
|
{
|
||||||
|
GHashTableIter it;
|
||||||
|
gpointer key, value;
|
||||||
|
GSList* ipcs = NULL;
|
||||||
|
GSList* i;
|
||||||
|
|
||||||
|
/* Lock */
|
||||||
|
pthread_mutex_lock(&gbinder_ipc_mutex);
|
||||||
|
if (gbinder_ipc_table) {
|
||||||
|
g_hash_table_iter_init(&it, gbinder_ipc_table);
|
||||||
|
while (g_hash_table_iter_next(&it, NULL, &value)) {
|
||||||
|
ipcs = g_slist_append(ipcs, gbinder_ipc_ref(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&gbinder_ipc_mutex);
|
||||||
|
/* Unlock */
|
||||||
|
|
||||||
|
for (i = ipcs; i; i = i->next) {
|
||||||
|
GBinderIpc* ipc = GBINDER_IPC(i->data);
|
||||||
|
GBinderIpcPriv* priv = ipc->priv;
|
||||||
|
GThreadPool* pool = priv->tx_pool;
|
||||||
|
GSList* local_objs = NULL;
|
||||||
|
GSList* tx_keys = NULL;
|
||||||
|
GSList* k;
|
||||||
|
GSList* l;
|
||||||
|
|
||||||
|
/* Terminate looper threads */
|
||||||
|
GVERBOSE_("%s", ipc->dev);
|
||||||
|
gbinder_ipc_stop_loopers(ipc);
|
||||||
|
|
||||||
|
/* Make sure pooled transaction complete too */
|
||||||
|
priv->tx_pool = NULL;
|
||||||
|
g_thread_pool_free(pool, FALSE, TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since this function is supposed to be invoked on the main thread,
|
||||||
|
* there's no need to synchronize access to priv->tx_table. In any
|
||||||
|
* case, this must be the last thread associated with this object.
|
||||||
|
*/
|
||||||
|
g_hash_table_iter_init(&it, priv->tx_table);
|
||||||
|
while (g_hash_table_iter_next(&it, &key, NULL)) {
|
||||||
|
tx_keys = g_slist_append(tx_keys, key);
|
||||||
|
}
|
||||||
|
for (k = tx_keys; k; k = k->next) {
|
||||||
|
GBinderIpcTxPriv* tx = g_hash_table_lookup(priv->tx_table, k->data);
|
||||||
|
GSource* source = g_source_ref(tx->completion);
|
||||||
|
|
||||||
|
GVERBOSE_("tx %lu", tx->pub.id);
|
||||||
|
g_source_destroy(source);
|
||||||
|
g_source_unref(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The above loop must destroy all uncompleted transactions */
|
||||||
|
GASSERT(!g_hash_table_size(priv->tx_table));
|
||||||
|
g_slist_free(tx_keys);
|
||||||
|
|
||||||
|
/* Lock */
|
||||||
|
g_mutex_lock(&priv->local_objects_mutex);
|
||||||
|
if (priv->local_objects) {
|
||||||
|
g_hash_table_iter_init(&it, priv->local_objects);
|
||||||
|
while (g_hash_table_iter_next(&it, NULL, &value)) {
|
||||||
|
local_objs = g_slist_append(local_objs,
|
||||||
|
gbinder_local_object_ref(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_mutex_unlock(&priv->local_objects_mutex);
|
||||||
|
/* Unlock */
|
||||||
|
|
||||||
|
/* Drop remote references */
|
||||||
|
for (l = local_objs; l; l = l->next) {
|
||||||
|
GBinderLocalObject* obj = GBINDER_LOCAL_OBJECT(l->data);
|
||||||
|
|
||||||
|
while (obj->strong_refs > 0) {
|
||||||
|
obj->strong_refs--;
|
||||||
|
gbinder_local_object_unref(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_slist_free_full(local_objs, g_object_unref);
|
||||||
|
}
|
||||||
|
g_slist_free_full(ipcs, g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* mode: C
|
* mode: C
|
||||||
|
|||||||
@@ -68,43 +68,52 @@ void
|
|||||||
int status,
|
int status,
|
||||||
void* user_data);
|
void* user_data);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
GBinderIpc*
|
GBinderIpc*
|
||||||
gbinder_ipc_new(
|
gbinder_ipc_new(
|
||||||
const char* dev,
|
const char* dev,
|
||||||
const GBinderRpcProtocol* protocol);
|
const GBinderRpcProtocol* protocol);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
GBinderIpc*
|
GBinderIpc*
|
||||||
gbinder_ipc_ref(
|
gbinder_ipc_ref(
|
||||||
GBinderIpc* ipc);
|
GBinderIpc* ipc);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gbinder_ipc_unref(
|
gbinder_ipc_unref(
|
||||||
GBinderIpc* ipc);
|
GBinderIpc* ipc);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gbinder_ipc_looper_check(
|
gbinder_ipc_looper_check(
|
||||||
GBinderIpc* ipc);
|
GBinderIpc* ipc);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
GBinderObjectRegistry*
|
GBinderObjectRegistry*
|
||||||
gbinder_ipc_object_registry(
|
gbinder_ipc_object_registry(
|
||||||
GBinderIpc* ipc);
|
GBinderIpc* ipc);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gbinder_ipc_register_local_object(
|
gbinder_ipc_register_local_object(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
GBinderLocalObject* obj);
|
GBinderLocalObject* obj);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
GBinderRemoteObject*
|
GBinderRemoteObject*
|
||||||
gbinder_ipc_get_remote_object(
|
gbinder_ipc_get_remote_object(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
guint32 handle,
|
guint32 handle,
|
||||||
gboolean maybe_dead);
|
gboolean maybe_dead);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gbinder_ipc_invalidate_remote_handle(
|
gbinder_ipc_invalidate_remote_handle(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
guint32 handle);
|
guint32 handle);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
GBinderRemoteReply*
|
GBinderRemoteReply*
|
||||||
gbinder_ipc_transact_sync_reply(
|
gbinder_ipc_transact_sync_reply(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
@@ -113,6 +122,7 @@ gbinder_ipc_transact_sync_reply(
|
|||||||
GBinderLocalRequest* req,
|
GBinderLocalRequest* req,
|
||||||
int* status);
|
int* status);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
int
|
int
|
||||||
gbinder_ipc_transact_sync_oneway(
|
gbinder_ipc_transact_sync_oneway(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
@@ -120,6 +130,7 @@ gbinder_ipc_transact_sync_oneway(
|
|||||||
guint32 code,
|
guint32 code,
|
||||||
GBinderLocalRequest* req);
|
GBinderLocalRequest* req);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
gulong
|
gulong
|
||||||
gbinder_ipc_transact(
|
gbinder_ipc_transact(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
@@ -131,6 +142,7 @@ gbinder_ipc_transact(
|
|||||||
GDestroyNotify destroy,
|
GDestroyNotify destroy,
|
||||||
void* user_data);
|
void* user_data);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
gulong
|
gulong
|
||||||
gbinder_ipc_transact_custom(
|
gbinder_ipc_transact_custom(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
@@ -139,23 +151,33 @@ gbinder_ipc_transact_custom(
|
|||||||
GDestroyNotify destroy,
|
GDestroyNotify destroy,
|
||||||
void* user_data);
|
void* user_data);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gbinder_ipc_cancel(
|
gbinder_ipc_cancel(
|
||||||
GBinderIpc* ipc,
|
GBinderIpc* ipc,
|
||||||
gulong id);
|
gulong id);
|
||||||
|
|
||||||
/* Internal for GBinderLocalObject */
|
/* Internal for GBinderLocalObject */
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gbinder_ipc_local_object_disposed(
|
gbinder_ipc_local_object_disposed(
|
||||||
GBinderIpc* self,
|
GBinderIpc* self,
|
||||||
GBinderLocalObject* obj);
|
GBinderLocalObject* obj);
|
||||||
|
|
||||||
/* Internal for GBinderRemoteObject */
|
/* Internal for GBinderRemoteObject */
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gbinder_ipc_remote_object_disposed(
|
gbinder_ipc_remote_object_disposed(
|
||||||
GBinderIpc* self,
|
GBinderIpc* self,
|
||||||
GBinderRemoteObject* obj);
|
GBinderRemoteObject* obj);
|
||||||
|
|
||||||
|
/* Declared for unit tests */
|
||||||
|
G_GNUC_INTERNAL
|
||||||
|
__attribute__((destructor))
|
||||||
|
void
|
||||||
|
gbinder_ipc_exit(
|
||||||
|
void);
|
||||||
|
|
||||||
#endif /* GBINDER_IPC_H */
|
#endif /* GBINDER_IPC_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018-2019 Jolla Ltd.
|
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||||
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
|
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||||
*
|
*
|
||||||
* You may use this file under the terms of BSD license as follows:
|
* You may use this file under the terms of BSD license as follows:
|
||||||
*
|
*
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||||
|
|
||||||
#include "gbinder_driver.h"
|
#include "gbinder_driver.h"
|
||||||
#include "gbinder_ipc.h"
|
#include "gbinder_ipc.h"
|
||||||
#include "gbinder_local_object_p.h"
|
#include "gbinder_local_object_p.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018-2019 Jolla Ltd.
|
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||||
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
|
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||||
*
|
*
|
||||||
* You may use this file under the terms of BSD license as follows:
|
* You may use this file under the terms of BSD license as follows:
|
||||||
*
|
*
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||||
|
|
||||||
#include "gbinder_driver.h"
|
#include "gbinder_driver.h"
|
||||||
#include "gbinder_ipc.h"
|
#include "gbinder_ipc.h"
|
||||||
#include "gbinder_remote_object_p.h"
|
#include "gbinder_remote_object_p.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018-2019 Jolla Ltd.
|
* Copyright (C) 2018-2020 Jolla Ltd.
|
||||||
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
|
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
|
||||||
*
|
*
|
||||||
* You may use this file under the terms of BSD license as follows:
|
* You may use this file under the terms of BSD license as follows:
|
||||||
*
|
*
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. Neither the names of the copyright holders nor the names of its
|
* 3. Neither the names of the copyright holders nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived
|
||||||
* this software without specific prior written permission.
|
* from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||||
|
|
||||||
#include "gbinder_servicemanager_p.h"
|
#include "gbinder_servicemanager_p.h"
|
||||||
#include "gbinder_client_p.h"
|
#include "gbinder_client_p.h"
|
||||||
#include "gbinder_local_object_p.h"
|
#include "gbinder_local_object_p.h"
|
||||||
@@ -165,6 +167,7 @@ gbinder_servicemanager_list_tx_done(
|
|||||||
if (!data->func(data->sm, data->result, data->user_data)) {
|
if (!data->func(data->sm, data->result, data->user_data)) {
|
||||||
g_strfreev(data->result);
|
g_strfreev(data->result);
|
||||||
}
|
}
|
||||||
|
data->result = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -174,6 +177,7 @@ gbinder_servicemanager_list_tx_free(
|
|||||||
{
|
{
|
||||||
GBinderServiceManagerListTxData* data = user_data;
|
GBinderServiceManagerListTxData* data = user_data;
|
||||||
|
|
||||||
|
g_strfreev(data->result);
|
||||||
gbinder_servicemanager_unref(data->sm);
|
gbinder_servicemanager_unref(data->sm);
|
||||||
g_slice_free(GBinderServiceManagerListTxData, data);
|
g_slice_free(GBinderServiceManagerListTxData, data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ all:
|
|||||||
@$(MAKE) -C binder-client $*
|
@$(MAKE) -C binder-client $*
|
||||||
@$(MAKE) -C binder-dump $*
|
@$(MAKE) -C binder-dump $*
|
||||||
@$(MAKE) -C binder-list $*
|
@$(MAKE) -C binder-list $*
|
||||||
|
@$(MAKE) -C binder-ping $*
|
||||||
@$(MAKE) -C binder-service $*
|
@$(MAKE) -C binder-service $*
|
||||||
@$(MAKE) -C rild-card-status $*
|
@$(MAKE) -C rild-card-status $*
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
|||||||
# Tools and flags
|
# Tools and flags
|
||||||
#
|
#
|
||||||
|
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
INCLUDES = -I$(LIB_DIR)/include
|
INCLUDES = -I$(LIB_DIR)/include
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
|||||||
# Tools and flags
|
# Tools and flags
|
||||||
#
|
#
|
||||||
|
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
INCLUDES = -I$(LIB_DIR)/include
|
INCLUDES = -I$(LIB_DIR)/include
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
|||||||
# Tools and flags
|
# Tools and flags
|
||||||
#
|
#
|
||||||
|
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
INCLUDES = -I$(LIB_DIR)/include
|
INCLUDES = -I$(LIB_DIR)/include
|
||||||
|
|||||||
140
test/binder-ping/Makefile
Normal file
140
test/binder-ping/Makefile
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# -*- Mode: makefile-gmake -*-
|
||||||
|
|
||||||
|
.PHONY: all debug release clean cleaner
|
||||||
|
.PHONY: libgbinder-release libgbinder-debug
|
||||||
|
|
||||||
|
#
|
||||||
|
# Required packages
|
||||||
|
#
|
||||||
|
|
||||||
|
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
|
||||||
|
|
||||||
|
#
|
||||||
|
# Default target
|
||||||
|
#
|
||||||
|
|
||||||
|
all: debug release
|
||||||
|
|
||||||
|
#
|
||||||
|
# Executable
|
||||||
|
#
|
||||||
|
|
||||||
|
EXE = binder-ping
|
||||||
|
|
||||||
|
#
|
||||||
|
# Sources
|
||||||
|
#
|
||||||
|
|
||||||
|
SRC = $(EXE).c
|
||||||
|
|
||||||
|
#
|
||||||
|
# Directories
|
||||||
|
#
|
||||||
|
|
||||||
|
SRC_DIR = .
|
||||||
|
BUILD_DIR = build
|
||||||
|
LIB_DIR = ../..
|
||||||
|
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||||
|
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tools and flags
|
||||||
|
#
|
||||||
|
|
||||||
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
|
LD = $(CC)
|
||||||
|
WARNINGS = -Wall
|
||||||
|
INCLUDES = -I$(LIB_DIR)/include
|
||||||
|
BASE_FLAGS = -fPIC
|
||||||
|
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||||
|
$(shell pkg-config --cflags $(PKGS))
|
||||||
|
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
|
||||||
|
QUIET_MAKE = make --no-print-directory
|
||||||
|
DEBUG_FLAGS = -g
|
||||||
|
RELEASE_FLAGS =
|
||||||
|
|
||||||
|
ifndef KEEP_SYMBOLS
|
||||||
|
KEEP_SYMBOLS = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(KEEP_SYMBOLS),0)
|
||||||
|
RELEASE_FLAGS += -g
|
||||||
|
SUBMAKE_OPTS += KEEP_SYMBOLS=1
|
||||||
|
endif
|
||||||
|
|
||||||
|
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
|
||||||
|
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
|
||||||
|
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||||
|
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
|
||||||
|
|
||||||
|
#
|
||||||
|
# Files
|
||||||
|
#
|
||||||
|
|
||||||
|
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||||
|
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||||
|
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
|
||||||
|
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
|
||||||
|
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
|
||||||
|
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
|
||||||
|
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
|
||||||
|
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dependencies
|
||||||
|
#
|
||||||
|
|
||||||
|
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||||
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
|
ifneq ($(strip $(DEPS)),)
|
||||||
|
-include $(DEPS)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||||
|
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rules
|
||||||
|
#
|
||||||
|
|
||||||
|
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||||
|
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||||
|
|
||||||
|
debug: libgbinder-debug $(DEBUG_EXE)
|
||||||
|
|
||||||
|
release: libgbinder-release $(RELEASE_EXE)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~
|
||||||
|
rm -fr $(BUILD_DIR)
|
||||||
|
|
||||||
|
cleaner: clean
|
||||||
|
@make -C $(LIB_DIR) clean
|
||||||
|
|
||||||
|
$(DEBUG_BUILD_DIR):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
$(RELEASE_BUILD_DIR):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||||
|
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||||
|
|
||||||
|
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||||
|
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||||
|
|
||||||
|
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
|
||||||
|
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
|
||||||
|
|
||||||
|
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
|
||||||
|
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
|
||||||
|
ifeq ($(KEEP_SYMBOLS),0)
|
||||||
|
strip $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
libgbinder-debug:
|
||||||
|
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
|
||||||
|
|
||||||
|
libgbinder-release:
|
||||||
|
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)
|
||||||
187
test/binder-ping/binder-ping.c
Normal file
187
test/binder-ping/binder-ping.c
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Jolla Ltd.
|
||||||
|
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
|
||||||
|
*
|
||||||
|
* You may use this file under the terms of BSD license as follows:
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the names of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gbinder.h>
|
||||||
|
|
||||||
|
#include <gutil_log.h>
|
||||||
|
|
||||||
|
#define RET_OK (0)
|
||||||
|
#define RET_NOTFOUND (1)
|
||||||
|
#define RET_INVARG (2)
|
||||||
|
#define RET_ERR (3)
|
||||||
|
|
||||||
|
#define DEFAULT_BINDER GBINDER_DEFAULT_HWBINDER
|
||||||
|
#define AIDL_PING_TRANSACTION GBINDER_FOURCC('_','P','N','G')
|
||||||
|
#define HIDL_PING_TRANSACTION GBINDER_FOURCC(0x0f,'P','N','G')
|
||||||
|
|
||||||
|
typedef struct app_options {
|
||||||
|
const char* fqname;
|
||||||
|
char* dev;
|
||||||
|
guint32 ping_code;
|
||||||
|
const char* iface;
|
||||||
|
} AppOptions;
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
app_run(
|
||||||
|
const AppOptions* opt)
|
||||||
|
{
|
||||||
|
int ret = RET_NOTFOUND;
|
||||||
|
GBinderServiceManager* sm = gbinder_servicemanager_new(opt->dev);
|
||||||
|
|
||||||
|
if (sm) {
|
||||||
|
int status = 0;
|
||||||
|
GBinderRemoteObject* remote = gbinder_servicemanager_get_service_sync
|
||||||
|
(sm, opt->fqname, &status);
|
||||||
|
|
||||||
|
if (remote) {
|
||||||
|
int status;
|
||||||
|
GBinderClient* client = gbinder_client_new(remote, opt->iface);
|
||||||
|
GBinderRemoteReply* reply = gbinder_client_transact_sync_reply
|
||||||
|
(client, opt->ping_code, NULL, &status);
|
||||||
|
|
||||||
|
if (reply) {
|
||||||
|
GINFO("OK");
|
||||||
|
ret = RET_OK;
|
||||||
|
} else {
|
||||||
|
GERR("Ping failed (%d)", status);
|
||||||
|
ret = RET_ERR;
|
||||||
|
}
|
||||||
|
gbinder_remote_reply_unref(reply);
|
||||||
|
gbinder_client_unref(client);
|
||||||
|
} else {
|
||||||
|
GERR("%s not found", opt->fqname);
|
||||||
|
}
|
||||||
|
gbinder_servicemanager_unref(sm);
|
||||||
|
} else {
|
||||||
|
GERR("No servicemanager at %s", opt->dev);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
app_log_verbose(
|
||||||
|
const gchar* name,
|
||||||
|
const gchar* value,
|
||||||
|
gpointer data,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
app_log_quiet(
|
||||||
|
const gchar* name,
|
||||||
|
const gchar* value,
|
||||||
|
gpointer data,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
gutil_log_default.level = GLOG_LEVEL_NONE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
app_init(
|
||||||
|
AppOptions* opt,
|
||||||
|
int argc,
|
||||||
|
char* argv[])
|
||||||
|
{
|
||||||
|
gboolean ok = FALSE;
|
||||||
|
GOptionEntry entries[] = {
|
||||||
|
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||||
|
app_log_verbose, "Enable verbose output", NULL },
|
||||||
|
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||||
|
app_log_quiet, "Be quiet", NULL },
|
||||||
|
{ "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
|
||||||
|
"Binder device [" DEFAULT_BINDER "]", "DEVICE" },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
GError* error = NULL;
|
||||||
|
GOptionContext* options = g_option_context_new("[FQNAME]");
|
||||||
|
|
||||||
|
gutil_log_timestamp = FALSE;
|
||||||
|
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||||
|
|
||||||
|
g_option_context_add_main_entries(options, entries, NULL);
|
||||||
|
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||||
|
if (!opt->dev || !opt->dev[0]) {
|
||||||
|
opt->dev = g_strdup(DEFAULT_BINDER);
|
||||||
|
}
|
||||||
|
if (argc == 2) {
|
||||||
|
opt->fqname = argv[1];
|
||||||
|
if (g_strcmp0(opt->dev, GBINDER_DEFAULT_BINDER)) {
|
||||||
|
opt->ping_code = HIDL_PING_TRANSACTION;
|
||||||
|
opt->iface = "android.hidl.base@1.0::IBase";
|
||||||
|
} else {
|
||||||
|
opt->ping_code = AIDL_PING_TRANSACTION;
|
||||||
|
opt->iface = "android.os.IBinder";
|
||||||
|
}
|
||||||
|
ok = TRUE;
|
||||||
|
} else {
|
||||||
|
char* help = g_option_context_get_help(options, TRUE, NULL);
|
||||||
|
|
||||||
|
fprintf(stderr, "%s", help);
|
||||||
|
g_free(help);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GERR("%s", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
g_option_context_free(options);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
AppOptions opt;
|
||||||
|
int ret = RET_INVARG;
|
||||||
|
|
||||||
|
memset(&opt, 0, sizeof(opt));
|
||||||
|
if (app_init(&opt, argc, argv)) {
|
||||||
|
ret = app_run(&opt);
|
||||||
|
}
|
||||||
|
g_free(opt.dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
|||||||
# Tools and flags
|
# Tools and flags
|
||||||
#
|
#
|
||||||
|
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
INCLUDES = -I$(LIB_DIR)/include
|
INCLUDES = -I$(LIB_DIR)/include
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
|||||||
# Tools and flags
|
# Tools and flags
|
||||||
#
|
#
|
||||||
|
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
INCLUDES = -I$(LIB_DIR)/include
|
INCLUDES = -I$(LIB_DIR)/include
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
|
|||||||
# Tools and flags
|
# Tools and flags
|
||||||
#
|
#
|
||||||
|
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
WARNINGS += -Wall
|
WARNINGS += -Wall
|
||||||
INCLUDES += -I$(COMMON_DIR) -I$(LIB_DIR)/src -I$(LIB_DIR)/include
|
INCLUDES += -I$(COMMON_DIR) -I$(LIB_DIR)/src -I$(LIB_DIR)/include
|
||||||
@@ -138,10 +138,10 @@ test_banner:
|
|||||||
@echo "===========" $(EXE) "=========== "
|
@echo "===========" $(EXE) "=========== "
|
||||||
|
|
||||||
test: test_banner debug
|
test: test_banner debug
|
||||||
@LD_LIBRARY_PATH="$(LIB_DIR)/$(DEBUG_LIB_PATH)" $(DEBUG_EXE)
|
@$(DEBUG_EXE)
|
||||||
|
|
||||||
valgrind: test_banner debug
|
valgrind: test_banner debug
|
||||||
@LD_LIBRARY_PATH="$(LIB_DIR)/$(DEBUG_LIB_PATH)" G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind --tool=memcheck --leak-check=full --show-possibly-lost=no $(DEBUG_EXE)
|
@G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind --tool=memcheck --leak-check=full --show-possibly-lost=no $(DEBUG_EXE)
|
||||||
|
|
||||||
$(DEBUG_BUILD_DIR):
|
$(DEBUG_BUILD_DIR):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. Neither the names of the copyright holders nor the names of its
|
* 3. Neither the names of the copyright holders nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived
|
||||||
* this software without specific prior written permission.
|
* from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
@@ -166,6 +166,7 @@ test_dead(
|
|||||||
g_assert(!gbinder_client_transact(client, 0, 0, NULL, NULL, NULL, NULL));
|
g_assert(!gbinder_client_transact(client, 0, 0, NULL, NULL, NULL, NULL));
|
||||||
|
|
||||||
gbinder_client_unref(client);
|
gbinder_client_unref(client);
|
||||||
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. Neither the names of the copyright holders nor the names of its
|
* 3. Neither the names of the copyright holders nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived
|
||||||
* this software without specific prior written permission.
|
* from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#include "gbinder_ipc.h"
|
#include "gbinder_ipc.h"
|
||||||
#include "gbinder_driver.h"
|
#include "gbinder_driver.h"
|
||||||
#include "gbinder_local_object.h"
|
#include "gbinder_local_object_p.h"
|
||||||
#include "gbinder_local_reply_p.h"
|
#include "gbinder_local_reply_p.h"
|
||||||
#include "gbinder_local_request_p.h"
|
#include "gbinder_local_request_p.h"
|
||||||
#include "gbinder_object_registry.h"
|
#include "gbinder_object_registry.h"
|
||||||
@@ -127,6 +127,8 @@ test_basic(
|
|||||||
|
|
||||||
/* Invalid path */
|
/* Invalid path */
|
||||||
g_assert(!gbinder_ipc_new("invalid path", NULL));
|
g_assert(!gbinder_ipc_new("invalid path", NULL));
|
||||||
|
|
||||||
|
gbinder_ipc_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
@@ -188,6 +190,7 @@ test_sync_oneway(
|
|||||||
GBINDER_STATUS_OK);
|
GBINDER_STATUS_OK);
|
||||||
gbinder_local_request_unref(req);
|
gbinder_local_request_unref(req);
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
@@ -231,6 +234,7 @@ test_sync_reply_ok_status(
|
|||||||
gbinder_local_request_unref(req);
|
gbinder_local_request_unref(req);
|
||||||
gbinder_local_reply_unref(reply);
|
gbinder_local_reply_unref(reply);
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -273,6 +277,7 @@ test_sync_reply_error(
|
|||||||
|
|
||||||
gbinder_local_request_unref(req);
|
gbinder_local_request_unref(req);
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
@@ -342,6 +347,7 @@ test_transact_ok(
|
|||||||
gbinder_local_request_unref(req);
|
gbinder_local_request_unref(req);
|
||||||
gbinder_local_reply_unref(reply);
|
gbinder_local_reply_unref(reply);
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,6 +394,7 @@ test_transact_dead(
|
|||||||
gbinder_ipc_cancel(ipc, id);
|
gbinder_ipc_cancel(ipc, id);
|
||||||
gbinder_local_request_unref(req);
|
gbinder_local_request_unref(req);
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,6 +441,7 @@ test_transact_failed(
|
|||||||
gbinder_ipc_cancel(ipc, id);
|
gbinder_ipc_cancel(ipc, id);
|
||||||
gbinder_local_request_unref(req);
|
gbinder_local_request_unref(req);
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,6 +490,7 @@ test_transact_status(
|
|||||||
gbinder_ipc_cancel(ipc, id);
|
gbinder_ipc_cancel(ipc, id);
|
||||||
gbinder_local_request_unref(req);
|
gbinder_local_request_unref(req);
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,6 +520,7 @@ test_transact_custom(
|
|||||||
g_assert(id);
|
g_assert(id);
|
||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
|
gbinder_ipc_exit();
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
@@ -541,10 +551,44 @@ test_transact_custom2(
|
|||||||
g_assert(id);
|
g_assert(id);
|
||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
|
gbinder_ipc_exit();
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*==========================================================================*
|
||||||
|
* transact_custom3
|
||||||
|
*==========================================================================*/
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
test_transact_custom3_exec(
|
||||||
|
const GBinderIpcTx* tx)
|
||||||
|
{
|
||||||
|
GVERBOSE_("");
|
||||||
|
gbinder_ipc_unref(tx->ipc);
|
||||||
|
test_quit_later((GMainLoop*)tx->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
test_transact_custom3(
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||||
|
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||||
|
/* Reusing test_transact_cancel_done and test_transact_cancel_destroy */
|
||||||
|
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_custom3_exec,
|
||||||
|
NULL, NULL, loop);
|
||||||
|
|
||||||
|
g_assert(id);
|
||||||
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
|
/* Reference to GBinderIpc is released by test_transact_custom3_exec */
|
||||||
|
gbinder_ipc_exit();
|
||||||
|
g_main_loop_unref(loop);
|
||||||
|
}
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
* transact_cancel
|
* transact_cancel
|
||||||
*==========================================================================*/
|
*==========================================================================*/
|
||||||
@@ -590,6 +634,7 @@ test_transact_cancel(
|
|||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,6 +679,7 @@ test_transact_cancel2(
|
|||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
gbinder_ipc_unref(ipc);
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,6 +745,7 @@ test_transact_incoming(
|
|||||||
g_idle_add(test_unref_ipc, ipc);
|
g_idle_add(test_unref_ipc, ipc);
|
||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,6 +809,7 @@ test_transact_status_reply(
|
|||||||
g_idle_add(test_unref_ipc, ipc);
|
g_idle_add(test_unref_ipc, ipc);
|
||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,6 +916,7 @@ test_transact_async(
|
|||||||
g_idle_add(test_unref_ipc, ipc);
|
g_idle_add(test_unref_ipc, ipc);
|
||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -940,6 +989,86 @@ test_transact_async_sync(
|
|||||||
g_idle_add(test_unref_ipc, ipc);
|
g_idle_add(test_unref_ipc, ipc);
|
||||||
test_run(&test_opt, loop);
|
test_run(&test_opt, loop);
|
||||||
|
|
||||||
|
gbinder_ipc_exit();
|
||||||
|
g_main_loop_unref(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*==========================================================================*
|
||||||
|
* drop_remote_refs
|
||||||
|
*==========================================================================*/
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
test_drop_remote_refs_cb(
|
||||||
|
GBinderLocalObject* obj,
|
||||||
|
void* user_data)
|
||||||
|
{
|
||||||
|
GVERBOSE_("%d", obj->strong_refs);
|
||||||
|
g_assert(obj->strong_refs == 1);
|
||||||
|
test_quit_later((GMainLoop*)user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
test_drop_remote_refs(
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||||
|
GBinderLocalObject* obj = gbinder_local_object_new
|
||||||
|
(ipc, NULL, NULL, NULL);
|
||||||
|
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||||
|
int fd = gbinder_driver_fd(ipc->driver);
|
||||||
|
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, TRUE);
|
||||||
|
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_exit will drop the remote reference */
|
||||||
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
|
g_main_loop_unref(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*==========================================================================*
|
||||||
|
* cancel_on_exit
|
||||||
|
*==========================================================================*/
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
test_cancel_on_exit_not_reached(
|
||||||
|
GBinderIpc* ipc,
|
||||||
|
GBinderRemoteReply* reply,
|
||||||
|
int status,
|
||||||
|
void* user_data)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
test_cancel_on_exit(
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
|
||||||
|
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||||
|
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||||
|
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||||
|
int fd = gbinder_driver_fd(ipc->driver);
|
||||||
|
|
||||||
|
/* This transaction will be cancelled by gbinder_ipc_exit */
|
||||||
|
test_binder_br_transaction_complete(fd);
|
||||||
|
gbinder_ipc_transact(ipc, 0, 1, GBINDER_TX_FLAG_ONEWAY,
|
||||||
|
req, test_cancel_on_exit_not_reached, NULL, NULL);
|
||||||
|
|
||||||
|
gbinder_local_request_unref(req);
|
||||||
|
gbinder_ipc_unref(ipc);
|
||||||
|
gbinder_ipc_exit();
|
||||||
g_main_loop_unref(loop);
|
g_main_loop_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,12 +1094,15 @@ int main(int argc, char* argv[])
|
|||||||
g_test_add_func(TEST_("transact_status"), test_transact_status);
|
g_test_add_func(TEST_("transact_status"), test_transact_status);
|
||||||
g_test_add_func(TEST_("transact_custom"), test_transact_custom);
|
g_test_add_func(TEST_("transact_custom"), test_transact_custom);
|
||||||
g_test_add_func(TEST_("transact_custom2"), test_transact_custom2);
|
g_test_add_func(TEST_("transact_custom2"), test_transact_custom2);
|
||||||
|
g_test_add_func(TEST_("transact_custom3"), test_transact_custom3);
|
||||||
g_test_add_func(TEST_("transact_cancel"), test_transact_cancel);
|
g_test_add_func(TEST_("transact_cancel"), test_transact_cancel);
|
||||||
g_test_add_func(TEST_("transact_cancel2"), test_transact_cancel2);
|
g_test_add_func(TEST_("transact_cancel2"), test_transact_cancel2);
|
||||||
g_test_add_func(TEST_("transact_incoming"), test_transact_incoming);
|
g_test_add_func(TEST_("transact_incoming"), test_transact_incoming);
|
||||||
g_test_add_func(TEST_("transact_status_reply"), test_transact_status_reply);
|
g_test_add_func(TEST_("transact_status_reply"), test_transact_status_reply);
|
||||||
g_test_add_func(TEST_("transact_async"), test_transact_async);
|
g_test_add_func(TEST_("transact_async"), test_transact_async);
|
||||||
g_test_add_func(TEST_("transact_async_sync"), test_transact_async_sync);
|
g_test_add_func(TEST_("transact_async_sync"), test_transact_async_sync);
|
||||||
|
g_test_add_func(TEST_("drop_remote_refs"), test_drop_remote_refs);
|
||||||
|
g_test_add_func(TEST_("cancel_on_exit"), test_cancel_on_exit);
|
||||||
test_init(&test_opt, argc, argv);
|
test_init(&test_opt, argc, argv);
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ void
|
|||||||
test_string16(
|
test_string16(
|
||||||
void)
|
void)
|
||||||
{
|
{
|
||||||
static const const char input[] = "x";
|
static const char input[] = "x";
|
||||||
static const guint8 output[] = {
|
static const guint8 output[] = {
|
||||||
TEST_INT32_BYTES(1),
|
TEST_INT32_BYTES(1),
|
||||||
TEST_INT16_BYTES('x'), 0x00, 0x00
|
TEST_INT16_BYTES('x'), 0x00, 0x00
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 Jolla Ltd.
|
* Copyright (C) 2018-2019 Jolla Ltd.
|
||||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
|
||||||
*
|
*
|
||||||
* You may use this file under the terms of BSD license as follows:
|
* You may use this file under the terms of BSD license as follows:
|
||||||
*
|
*
|
||||||
@@ -341,7 +341,7 @@ void
|
|||||||
test_string16(
|
test_string16(
|
||||||
void)
|
void)
|
||||||
{
|
{
|
||||||
static const const char input[] = "x";
|
static const char input[] = "x";
|
||||||
static const guint8 output[] = {
|
static const guint8 output[] = {
|
||||||
TEST_INT32_BYTES(1),
|
TEST_INT32_BYTES(1),
|
||||||
TEST_INT16_BYTES('x'), 0x00, 0x00
|
TEST_INT16_BYTES('x'), 0x00, 0x00
|
||||||
|
|||||||
@@ -716,7 +716,6 @@ static const BinderObject64 test_hidl_vec_short_buf [] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* NULL buffer with size 1 */
|
/* NULL buffer with size 1 */
|
||||||
static const guint test_hidl_vec_badnull_offsets [] = {0};
|
|
||||||
static const GBinderHidlVec test_hidl_vec_badnull = {{0}, 1, TRUE};
|
static const GBinderHidlVec test_hidl_vec_badnull = {{0}, 1, TRUE};
|
||||||
static const BinderObject64 test_hidl_vec_badnull_buf [] = {
|
static const BinderObject64 test_hidl_vec_badnull_buf [] = {
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user