Compare commits

...

25 Commits

Author SHA1 Message Date
Slava Monich
ccf3e1237c Version 1.0.41 2020-04-14 12:40:05 +03:00
Slava Monich
e02f00fd41 Merge pull request #45 from monich/idle-pool
Stop using GUtilIdlePool
2020-04-14 12:34:42 +03:00
Slava Monich
e45e640f3c [gbinder] Stop using GUtilIdlePool. JB#49512
It won't work with a non-glib event loop. And one of those objects
turned out to actually be unused.
2020-04-11 02:26:46 +03:00
Slava Monich
75e8015c43 [gbinder] Added internal event loop utilities. JB#49512
gbinder_idle_callback_schedule_new = gbinder_idle_callback_new +
and gbinder_idle_callback_schedule

gbinder_idle_callback_destroy = gbinder_idle_callback_cancel +
gbinder_idle_callback_unref
2020-04-11 02:22:22 +03:00
Slava Monich
2c52fcc156 Version 1.0.40 2020-04-09 17:24:06 +03:00
Slava Monich
dc5b51a41f Merge pull request #44 from monich/event-loop
Pluggable event loop integration
2020-04-09 17:18:29 +03:00
Slava Monich
d12cee4690 [unit] Added eventloop test. JB#49512 2020-04-06 17:22:55 +03:00
Slava Monich
a74c4ac148 [gbinder] Virtualize event loop. JB#49512
This makes it possible to make libgbinder work with e.g. Qt event loop
based on QEventDispatcherUNIX (rather than QEventDispatcherGlib).
2020-04-04 20:26:06 +03:00
Slava Monich
53e50a8107 Version 1.0.39 2020-04-02 18:08:05 +03:00
Slava Monich
e896ba94cc Merge pull request #43 from mer-hybris/side-by-side-linking
Fix linking for side-by-side builds
2020-04-02 18:04:56 +03:00
Matti Lehtimäki
87ff990c73 [build] Fix linking for side-by-side builds. JB#49231 2020-04-02 14:48:16 +00:00
Slava Monich
e406162be2 Version 1.0.38 2020-04-02 00:13:53 +03:00
Slava Monich
2de4120f25 Merge pull request #42 from monich/default_log
Allow to configure log level via environment
2020-04-02 00:10:19 +03:00
Slava Monich
d8dc58a133 [unit] Added gbinder_log test. JB#42956 2020-04-01 21:00:51 +03:00
Slava Monich
8684bffe97 [gbinder] Allow to configure log level via environment. JB#42956
GBINDER_DEFAULT_LOG_LEVEL environment variable configures default
libgbinder log level. Valid (inclusive) range is from -1 (inherit
libglibutil defaults) to 5 (verbose).
2020-04-01 17:35:44 +03:00
Slava Monich
a08513ade0 Version 1.0.37 2020-03-17 20:16:33 +02:00
Slava Monich
1a57e01e07 [gbinder] Fixed compilation warnings. JB#42956 2020-03-17 20:12:45 +02:00
Slava Monich
6d4faf19b8 [build] Allow side-by-side linking with libglibutil. JB#49231 2020-03-17 19:57:22 +02:00
Slava Monich
96e6845e16 Version 1.0.36 2020-03-16 16:16:58 +02:00
Slava Monich
b33adeb708 Merge pull request #41 from krnlyng/jb48037
Allow overwriting CC with a predefined one
2020-03-16 16:13:00 +02:00
Frajo Haider
ea0e294a74 [gbinder] Allow overwriting CC with a predefined one. JB#48037 2020-03-16 16:10:40 +02:00
Slava Monich
2d878c2391 Version 1.0.35 2020-02-25 14:02:35 +02:00
Slava Monich
6dec867cd3 [license] Freshened up copyright 2020-02-25 14:01:52 +02:00
Slava Monich
d8bd7b9366 Merge pull request #40 from monich/master
Add binder-ping
2020-02-25 13:55:50 +02:00
Slava Monich
b52e4c6dee [test] Added binder-ping. JB#42956 2020-02-24 23:57:21 +02:00
34 changed files with 1692 additions and 127 deletions

View File

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

View File

@@ -1,4 +1,8 @@
# -*- 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: print_debug_so print_release_so
@@ -7,10 +11,15 @@
.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 = 41
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
#
# Default target
@@ -19,15 +28,34 @@ PKGS = libglibutil glib-2.0 gobject-2.0
all: debug release pkgconfig
#
# Library version
# Required packages
#
VERSION_MAJOR = 1
VERSION_MINOR = 0
VERSION_RELEASE = 34
PKGS = glib-2.0 gobject-2.0
# Version for pkg-config
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
ifeq ($(LIBGLIBUTIL_PATH),)
# 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
@@ -51,12 +79,14 @@ SRC = \
gbinder_cleanup.c \
gbinder_client.c \
gbinder_driver.c \
gbinder_eventloop.c \
gbinder_io_32.c \
gbinder_io_64.c \
gbinder_ipc.c \
gbinder_local_object.c \
gbinder_local_reply.c \
gbinder_local_request.c \
gbinder_log.c \
gbinder_reader.c \
gbinder_remote_object.c \
gbinder_remote_reply.c \
@@ -89,10 +119,10 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
INCLUDES = -I$(INCLUDE_DIR)
INCLUDES += -I$(INCLUDE_DIR)
BASE_FLAGS = -fPIC
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
-MMD -MP $(shell pkg-config --cflags $(PKGS))
@@ -110,8 +140,8 @@ ifneq ($(KEEP_SYMBOLS),0)
RELEASE_FLAGS += -g
endif
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_LIBS) $(DEBUG_FLAGS)
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_LIBS) $(RELEASE_FLAGS)
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
@@ -137,8 +167,8 @@ endif
endif
$(PKGCONFIG): | $(BUILD_DIR)
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR)
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR)
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR) $(DEBUG_DEPS)
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR) $(RELEASE_DEPS)
$(COVERAGE_OBJS) $(COVERAGE_LIB): | $(COVERAGE_BUILD_DIR)
#
@@ -149,13 +179,15 @@ DEBUG_SO = $(DEBUG_BUILD_DIR)/$(LIB_SO)
RELEASE_SO = $(RELEASE_BUILD_DIR)/$(LIB_SO)
DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1)
RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1)
DEBUG_DEV_LINK = $(DEBUG_BUILD_DIR)/$(LIB_DEV_SYMLINK)
RELEASE_DEV_LINK = $(RELEASE_BUILD_DIR)/$(LIB_DEV_SYMLINK)
DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
COVERAGE_LIB = $(COVERAGE_BUILD_DIR)/$(LIB)
debug: $(DEBUG_SO)
debug: $(DEBUG_SO) $(DEBUG_LINK) $(DEBUG_DEV_LINK)
release: $(RELEASE_SO)
release: $(RELEASE_SO) $(RELEASE_LINK) $(RELEASE_DEV_LINK)
debug_lib: $(DEBUG_LIB)
@@ -228,11 +260,9 @@ $(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
$(DEBUG_SO): $(DEBUG_OBJS)
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@
ln -sf $(LIB_SO) $(DEBUG_LINK)
$(RELEASE_SO): $(RELEASE_OBJS)
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@
ln -sf $(LIB_SO) $(RELEASE_LINK)
ifeq ($(KEEP_SYMBOLS),0)
strip $@
endif
@@ -245,6 +275,18 @@ $(RELEASE_LIB): $(RELEASE_OBJS)
$(AR) rc $@ $?
ranlib $@
$(DEBUG_LINK):
ln -sf $(LIB_SO) $@
$(RELEASE_LINK):
ln -sf $(LIB_SO) $@
$(DEBUG_DEV_LINK):
ln -sf $(LIB_SYMLINK1) $@
$(RELEASE_DEV_LINK):
ln -sf $(LIB_SYMLINK1) $@
$(COVERAGE_LIB): $(COVERAGE_OBJS)
$(AR) rc $@ $?
ranlib $@

43
debian/changelog vendored
View File

@@ -1,3 +1,46 @@
libgbinder (1.0.41) unstable; urgency=low
* Stop using GUtilIdlePool
-- Slava Monich <slava.monich@jolla.com> Tue, 14 Apr 2020 12:36:54 +0300
libgbinder (1.0.40) unstable; urgency=low
* Support integration with non-glib event loops
-- Slava Monich <slava.monich@jolla.com> Thu, 09 Apr 2020 17:22:12 +0300
libgbinder (1.0.39) unstable; urgency=low
* Adapted to side-by-side linking
-- Slava Monich <slava.monich@jolla.com> Thu, 02 Apr 2020 18:07:16 +0300
libgbinder (1.0.38) unstable; urgency=low
* Allow to configure log level via environment
-- Slava Monich <slava.monich@jolla.com> Thu, 02 Apr 2020 00:12:01 +0300
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

10
debian/copyright vendored
View File

@@ -1,5 +1,5 @@
Copyright (C) 2018 Jolla Ltd.
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
Copyright (C) 2018-2020 Jolla Ltd.
Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
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
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Jolla Ltd nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
3. Neither the names of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

194
include/gbinder_eventloop.h Normal file
View File

@@ -0,0 +1,194 @@
/*
* 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.
*/
#ifndef GBINDER_EVENTLOOP_H
#define GBINDER_EVENTLOOP_H
#include "gbinder_types.h"
G_BEGIN_DECLS
/* Since 1.0.40 */
typedef struct gbinder_eventloop_integration GBinderEventLoopIntegration;
typedef void (*GBinderEventLoopCallbackFunc)(gpointer data);
typedef struct gbinder_eventloop_timeout {
const GBinderEventLoopIntegration* eventloop;
} GBinderEventLoopTimeout;
typedef struct gbinder_eventloop_callback {
const GBinderEventLoopIntegration* eventloop;
} GBinderEventLoopCallback;
/**
* Main event loop integration. There is only one main event loop in the
* process (by definition).
*
* By default, GLib event loop is being used for callbacks and timeouts.
*
* It may be necessary to replace it with e.g. Qt event loop. Quite often
* Qt event loop is implemented by QEventDispatcherGlib which is sitting
* on top of GLib event and therefore works with the default implementation.
* But it won't work with e.g. QEventDispatcherUNIX.
*
* For Qt programs that use QEventDispatcherUNIX, it needs to be replaced
* with the one provided by libqbinder.
*/
typedef struct gbinder_eventloop_integration {
/**
* timeout_add
*
* Sets a function to be called at regular intervals (in milliseconds).
* If the function returns G_SOURCE_REMOVE, timeout is automatically
* destroyed (you must not call timeout_remove in this case). If the
* function returns G_SOURCE_CONTINUE, it will be called again after
* the same interval.
*/
GBinderEventLoopTimeout* (*timeout_add)(guint millis, GSourceFunc func,
gpointer data);
/**
* timeout_remove
*
* Removes a pending timeout and destroys it. The caller makes sure that
* argument is not NULL. Note that timeout is automatically destroyed if
* the callback function returns G_SOURCE_REMOVE.
*/
void (*timeout_remove)(GBinderEventLoopTimeout* timeout);
/**
* callback_new
*
* Creates a callback object. It returns you a reference, you must
* eventually pass the returned object to callback_unref to drop
* this reference.
*
* Note that it doesn't automatically schedule the callback. You
* must explicitly call callback_schedule to actually schedule it.
* The finalize function is invoked regardless of whether callback
* was cancelled or not.
*/
GBinderEventLoopCallback* (*callback_new)(GBinderEventLoopCallbackFunc fun,
gpointer data, GDestroyNotify finalize);
/**
* callback_ref
*
* Increments the reference count. That prevents the object from being
* deleted before you drop this reference. The caller makes sure that
* argument is not NULL.
*/
void (*callback_ref)(GBinderEventLoopCallback* cb);
/**
* callback_unref
*
* Decrements the reference count (drops the reference). When reference
* count reaches zero, the object gets deleted. The caller makes sure
* that argument is not NULL.
*
* Note that calling callback_schedule temporarily adds an internal
* reference until the callback is invoked or callback_cancel is called,
* whichever happens first.
*/
void (*callback_unref)(GBinderEventLoopCallback* cb);
/**
* callback_schedule
*
* Schedules the callback to be invoked in the main loop at some point
* in the future (but as soon as possible). The caller makes sure that
* argument is not NULL.
*
* This adds an internal reference to the GBinderEventLoopCallback object
* until the callback is invoked or callback_cancel is called, whichever
* happens first.
*/
void (*callback_schedule)(GBinderEventLoopCallback* cb);
/**
* callback_cancel
*
* Makes sure that callback won't be invoked (if it hasn't been
* invoked yet) and drops the internal reference. Does nothing
* if the callback has already been invoked. The caller makes sure that
* argument is not NULL.
*/
void (*callback_cancel)(GBinderEventLoopCallback* cb);
/**
* cleanup
*
* This function is called when event loop integration is being replaced
* with a different one, or libgbinder is being unloaded.
*/
void (*cleanup)(void);
/* Padding for future expansion */
void (*_reserved1)(void);
void (*_reserved2)(void);
void (*_reserved3)(void);
void (*_reserved4)(void);
void (*_reserved5)(void);
void (*_reserved6)(void);
void (*_reserved7)(void);
void (*_reserved8)(void);
void (*_reserved9)(void);
/*
* api_level will remain zero (and ignored) until we run out of
* the above placeholders. Hopefully, forever.
*/
int api_level;
} GBinderEventLoopIntegration;
/**
* gbinder_eventloop_set should be called before libgbinder creates any of
* its internal threads. And it must be done from the main thread.
*/
void
gbinder_eventloop_set(
const GBinderEventLoopIntegration* loop);
G_END_DECLS
#endif /* GBINDER_EVENTLOOP_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -1,14 +1,16 @@
Name: libgbinder
Version: 1.0.34
Version: 1.0.41
Release: 0
Summary: Binder client library
Group: Development/Libraries
License: BSD
URL: https://github.com/mer-hybris/libgbinder
Source: %{name}-%{version}.tar.bz2
Requires: libglibutil >= 1.0.35
%define libglibutil_version 1.0.35
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libglibutil) >= 1.0.35
BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}
Requires: libglibutil >= %{libglibutil_version}
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* 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
* 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.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -33,6 +33,7 @@
#include "gbinder_servicemanager_p.h"
#include "gbinder_rpc_protocol.h"
#include "gbinder_servicepoll.h"
#include "gbinder_eventloop_p.h"
#include "gbinder_log.h"
#include <gbinder_client.h>
@@ -48,7 +49,7 @@ typedef struct gbinder_defaultservicemanager_watch {
GBinderServicePoll* poll;
char* name;
gulong handler_id;
guint notify_id;
GBinderEventLoopTimeout* notify;
} GBinderDefaultServiceManagerWatch;
typedef GBinderServiceManagerClass GBinderDefaultServiceManagerClass;
@@ -99,9 +100,9 @@ gbinder_defaultservicemanager_watch_proc(
GBinderServiceManager* manager =
gbinder_servicepoll_manager(watch->poll);
if (watch->notify_id) {
g_source_remove(watch->notify_id);
watch->notify_id = 0;
if (watch->notify) {
gbinder_timeout_remove(watch->notify);
watch->notify = NULL;
}
gbinder_servicemanager_service_registered(manager, name_added);
}
@@ -116,8 +117,8 @@ gbinder_defaultservicemanager_watch_notify(
GBinderServiceManager* manager = gbinder_servicepoll_manager(watch->poll);
char* name = g_strdup(watch->name);
GASSERT(watch->notify_id);
watch->notify_id = 0;
GASSERT(watch->notify);
watch->notify = NULL;
gbinder_servicemanager_service_registered(manager, name);
g_free(name);
return G_SOURCE_REMOVE;
@@ -130,9 +131,7 @@ gbinder_defaultservicemanager_watch_free(
{
GBinderDefaultServiceManagerWatch* watch = user_data;
if (watch->notify_id) {
g_source_remove(watch->notify_id);
}
gbinder_timeout_remove(watch->notify);
gbinder_servicepoll_remove_handler(watch->poll, watch->handler_id);
gbinder_servicepoll_unref(watch->poll);
g_free(watch->name);
@@ -258,8 +257,8 @@ gbinder_defaultservicemanager_watch(
g_hash_table_replace(self->watch_table, watch->name, watch);
if (gbinder_servicepoll_is_known_name(watch->poll, name)) {
watch->notify_id =
g_idle_add(gbinder_defaultservicemanager_watch_notify, watch);
watch->notify = gbinder_idle_add
(gbinder_defaultservicemanager_watch_notify, watch);
}
return TRUE;
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* 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
* 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.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -61,9 +61,6 @@
#include <sys/stat.h>
#include <sys/mman.h>
/* Log module */
GLOG_MODULE_DEFINE("gbinder");
/* BINDER_VM_SIZE copied from native/libs/binder/ProcessState.cpp */
#define BINDER_VM_SIZE ((1024*1024) - sysconf(_SC_PAGE_SIZE)*2)

347
src/gbinder_eventloop.c Normal file
View File

@@ -0,0 +1,347 @@
/*
* 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_eventloop_p.h"
#include <gutil_macros.h>
#define GBINDER_DEFAULT_EVENTLOOP (&gbinder_eventloop_glib)
static const GBinderEventLoopIntegration gbinder_eventloop_glib;
/*==========================================================================*
* GLib event loop integration
*==========================================================================*/
typedef struct gbinder_eventloop_glib_timeout {
GBinderEventLoopTimeout timeout;
guint id;
GSourceFunc func;
gpointer data;
} GBinderEventLoopTimeoutGLib;
typedef struct gbinder_eventloop_glib_callback {
GSource source;
GBinderEventLoopCallback callback;
} GBinderEventLoopCallbackGLib;
static
inline
GBinderEventLoopTimeoutGLib*
gbinder_eventloop_glib_timeout_cast(
GBinderEventLoopTimeout* timeout)
{
return G_CAST(timeout,GBinderEventLoopTimeoutGLib,timeout);
}
static
inline
GSource*
gbinder_eventloop_glib_callback_source(
GBinderEventLoopCallback* callback)
{
return &(G_CAST(callback,GBinderEventLoopCallbackGLib,callback)->source);
}
static
gboolean
gbinder_eventloop_glib_timeout_callback(
gpointer data)
{
GBinderEventLoopTimeoutGLib* timeout = data;
return timeout->func(timeout->data);
}
static
void
gbinder_eventloop_glib_timeout_finalize(
gpointer data)
{
g_slice_free1(sizeof(GBinderEventLoopTimeoutGLib), data);
}
static
GBinderEventLoopTimeout*
gbinder_eventloop_glib_timeout_add(
guint interval,
GSourceFunc func,
gpointer data)
{
GBinderEventLoopTimeoutGLib* impl =
g_slice_new(GBinderEventLoopTimeoutGLib);
impl->timeout.eventloop = &gbinder_eventloop_glib;
impl->func = func;
impl->data = data;
impl->id = g_timeout_add_full(G_PRIORITY_DEFAULT, interval,
gbinder_eventloop_glib_timeout_callback, impl,
gbinder_eventloop_glib_timeout_finalize);
return &impl->timeout;
}
static
void
gbinder_eventloop_glib_timeout_remove(
GBinderEventLoopTimeout* timeout)
{
g_source_remove(gbinder_eventloop_glib_timeout_cast(timeout)->id);
}
static
gboolean
gbinder_eventloop_glib_callback_prepare(
GSource* source,
gint* timeout)
{
*timeout = 0;
return TRUE;
}
static
gboolean
gbinder_eventloop_glib_callback_check(
GSource* source)
{
return TRUE;
}
static
gboolean
gbinder_eventloop_glib_callback_dispatch(
GSource* source,
GSourceFunc callback,
gpointer user_data)
{
((GBinderEventLoopCallbackFunc)callback)(user_data);
return G_SOURCE_REMOVE;
}
static
GBinderEventLoopCallback*
gbinder_eventloop_glib_callback_new(
GBinderEventLoopCallbackFunc func,
gpointer data,
GDestroyNotify finalize)
{
static GSourceFuncs callback_funcs = {
gbinder_eventloop_glib_callback_prepare,
gbinder_eventloop_glib_callback_check,
gbinder_eventloop_glib_callback_dispatch
};
GBinderEventLoopCallbackGLib* impl = (GBinderEventLoopCallbackGLib*)
g_source_new(&callback_funcs, sizeof(GBinderEventLoopCallbackGLib));
impl->callback.eventloop = &gbinder_eventloop_glib;
g_source_set_callback(&impl->source, (GSourceFunc) func, data, finalize);
return &impl->callback;
}
static
void
gbinder_eventloop_glib_callback_ref(
GBinderEventLoopCallback* cb)
{
g_source_ref(gbinder_eventloop_glib_callback_source(cb));
}
static
void
gbinder_eventloop_glib_callback_unref(
GBinderEventLoopCallback* cb)
{
g_source_unref(gbinder_eventloop_glib_callback_source(cb));
}
static
void
gbinder_eventloop_glib_callback_schedule(
GBinderEventLoopCallback* cb)
{
static GMainContext* context = NULL;
if (!context) context = g_main_context_default();
g_source_attach(gbinder_eventloop_glib_callback_source(cb), context);
}
static
void
gbinder_eventloop_glib_callback_cancel(
GBinderEventLoopCallback* cb)
{
g_source_destroy(gbinder_eventloop_glib_callback_source(cb));
}
static
void
gbinder_eventloop_glib_cleanup(
void)
{
}
static const GBinderEventLoopIntegration gbinder_eventloop_glib = {
gbinder_eventloop_glib_timeout_add,
gbinder_eventloop_glib_timeout_remove,
gbinder_eventloop_glib_callback_new,
gbinder_eventloop_glib_callback_ref,
gbinder_eventloop_glib_callback_unref,
gbinder_eventloop_glib_callback_schedule,
gbinder_eventloop_glib_callback_cancel,
gbinder_eventloop_glib_cleanup
};
/*==========================================================================*
* Internal interface
*==========================================================================*/
static const GBinderEventLoopIntegration* gbinder_eventloop =
GBINDER_DEFAULT_EVENTLOOP;
GBinderEventLoopTimeout*
gbinder_timeout_add(
guint interval,
GSourceFunc function,
gpointer data)
{
return gbinder_eventloop->timeout_add(interval, function, data);
}
GBinderEventLoopTimeout*
gbinder_idle_add(
GSourceFunc function,
gpointer data)
{
return gbinder_eventloop->timeout_add(0, function, data);
}
void
gbinder_timeout_remove(
GBinderEventLoopTimeout* timeout)
{
if (timeout) {
timeout->eventloop->timeout_remove(timeout);
}
}
GBinderEventLoopCallback*
gbinder_idle_callback_new(
GBinderEventLoopCallbackFunc func,
gpointer data,
GDestroyNotify finalize)
{
return gbinder_eventloop->callback_new(func, data, finalize);
}
GBinderEventLoopCallback*
gbinder_idle_callback_schedule_new(
GBinderEventLoopCallbackFunc func,
gpointer data,
GDestroyNotify finalize)
{
GBinderEventLoopCallback* cb =
gbinder_eventloop->callback_new(func, data, finalize);
gbinder_idle_callback_schedule(cb);
return cb;
}
GBinderEventLoopCallback*
gbinder_idle_callback_ref(
GBinderEventLoopCallback* cb)
{
if (cb) {
cb->eventloop->callback_ref(cb);
return cb;
}
return NULL;
}
void
gbinder_idle_callback_unref(
GBinderEventLoopCallback* cb)
{
if (cb) {
cb->eventloop->callback_unref(cb);
}
}
void
gbinder_idle_callback_schedule(
GBinderEventLoopCallback* cb)
{
if (cb) {
cb->eventloop->callback_schedule(cb);
}
}
void
gbinder_idle_callback_cancel(
GBinderEventLoopCallback* cb)
{
if (cb) {
cb->eventloop->callback_cancel(cb);
}
}
void
gbinder_idle_callback_destroy(
GBinderEventLoopCallback* cb)
{
if (cb) {
const GBinderEventLoopIntegration* eventloop = cb->eventloop;
eventloop->callback_cancel(cb);
eventloop->callback_unref(cb);
}
}
void
gbinder_eventloop_set(
const GBinderEventLoopIntegration* loop)
{
if (!loop) loop = GBINDER_DEFAULT_EVENTLOOP;
if (gbinder_eventloop != loop) {
const GBinderEventLoopIntegration* prev = gbinder_eventloop;
gbinder_eventloop = loop;
prev->cleanup();
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

103
src/gbinder_eventloop_p.h Normal file
View File

@@ -0,0 +1,103 @@
/*
* 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.
*/
#ifndef GBINDER_EVENTLOOP_PRIVATE_H
#define GBINDER_EVENTLOOP_PRIVATE_H
#include "gbinder_eventloop.h"
G_GNUC_INTERNAL
GBinderEventLoopTimeout*
gbinder_timeout_add(
guint millis,
GSourceFunc func,
gpointer data);
G_GNUC_INTERNAL
GBinderEventLoopTimeout*
gbinder_idle_add(
GSourceFunc func,
gpointer data);
G_GNUC_INTERNAL
void
gbinder_timeout_remove(
GBinderEventLoopTimeout* timeout);
G_GNUC_INTERNAL
GBinderEventLoopCallback*
gbinder_idle_callback_new(
GBinderEventLoopCallbackFunc func,
gpointer data,
GDestroyNotify destroy);
G_GNUC_INTERNAL
GBinderEventLoopCallback*
gbinder_idle_callback_schedule_new(
GBinderEventLoopCallbackFunc func,
gpointer data,
GDestroyNotify destroy);
G_GNUC_INTERNAL
GBinderEventLoopCallback*
gbinder_idle_callback_ref(
GBinderEventLoopCallback* cb);
G_GNUC_INTERNAL
void
gbinder_idle_callback_unref(
GBinderEventLoopCallback* cb);
G_GNUC_INTERNAL
void
gbinder_idle_callback_schedule(
GBinderEventLoopCallback* cb);
G_GNUC_INTERNAL
void
gbinder_idle_callback_cancel(
GBinderEventLoopCallback* cb);
G_GNUC_INTERNAL
void
gbinder_idle_callback_destroy(
GBinderEventLoopCallback* cb);
#endif /* GBINDER_EVENTLOOP_PRIVATE_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,6 +30,8 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_ipc.h"
#include "gbinder_driver.h"
#include "gbinder_handler.h"
@@ -41,10 +43,10 @@
#include "gbinder_remote_object_p.h"
#include "gbinder_remote_reply_p.h"
#include "gbinder_remote_request_p.h"
#include "gbinder_eventloop_p.h"
#include "gbinder_writer.h"
#include "gbinder_log.h"
#include <gutil_idlepool.h>
#include <gutil_macros.h>
#include <unistd.h>
@@ -58,7 +60,6 @@ struct gbinder_ipc_priv {
GBinderIpc* self;
GThreadPool* tx_pool;
GHashTable* tx_table;
GMainContext* context;
char* key;
GBinderObjectRegistry object_registry;
@@ -173,7 +174,7 @@ typedef struct gbinder_ipc_tx_priv {
GBinderIpcTxPrivFunc fn_exec;
GBinderIpcTxPrivFunc fn_done;
GBinderIpcTxPrivFunc fn_free;
GSource* completion;
GBinderEventLoopCallback* completion;
} GBinderIpcTxPriv;
typedef struct gbinder_ipc_tx_internal {
@@ -341,7 +342,9 @@ gbinder_remote_request_complete(
tx->reply = gbinder_local_reply_ref(reply);
tx->state = GBINDER_IPC_LOOPER_TX_COMPLETE;
/* Wake up the looper */
(void)write(tx->pipefd[1], &done, sizeof(done));
if (write(tx->pipefd[1], &done, sizeof(done)) <= 0) {
GWARN("Failed to wake up the looper");
}
break;
default:
GWARN("Unexpected state %d in request completion", tx->state);
@@ -402,7 +405,7 @@ gbinder_ipc_looper_unref(
}
static
gboolean
void
gbinder_ipc_looper_tx_handle(
gpointer data)
{
@@ -473,8 +476,9 @@ gbinder_ipc_looper_tx_handle(
}
/* And wake up the looper */
(void)write(tx->pipefd[1], &done, sizeof(done));
return G_SOURCE_REMOVE;
if (write(tx->pipefd[1], &done, sizeof(done)) <= 0) {
GWARN("Failed to wake up the looper");
}
}
static
@@ -587,13 +591,11 @@ gbinder_ipc_looper_transact(
GBinderIpcPriv* priv = ipc->priv;
struct pollfd fds[2];
guint8 done = 0;
GSource* source = g_idle_source_new();
gboolean was_blocked = FALSE;
/* Let GBinderLocalObject handle the transaction on the main thread */
g_source_set_callback(source, gbinder_ipc_looper_tx_handle,
gbinder_ipc_looper_tx_ref(tx), gbinder_ipc_looper_tx_done);
g_source_attach(source, priv->context);
GBinderEventLoopCallback* callback =
gbinder_idle_callback_schedule_new(gbinder_ipc_looper_tx_handle,
gbinder_ipc_looper_tx_ref(tx), gbinder_ipc_looper_tx_done);
/* Wait for either transaction completion or looper shutdown */
memset(fds, 0, sizeof(fds));
@@ -679,8 +681,7 @@ gbinder_ipc_looper_transact(
gbinder_ipc_looper_tx_unref(tx, FALSE);
}
g_source_destroy(source);
g_source_unref(source);
gbinder_idle_callback_destroy(callback);
if (was_blocked) {
guint n;
@@ -1191,7 +1192,7 @@ gbinder_ipc_tx_free(
GBinderIpc* self = pub->ipc;
GBinderIpcPriv* priv = self->priv;
g_source_unref(tx->completion);
gbinder_idle_callback_unref(tx->completion);
g_hash_table_remove(priv->tx_table, GINT_TO_POINTER(pub->id));
tx->fn_free(tx);
@@ -1200,7 +1201,7 @@ gbinder_ipc_tx_free(
}
static
gboolean
void
gbinder_ipc_tx_done(
gpointer data)
{
@@ -1210,7 +1211,6 @@ gbinder_ipc_tx_done(
if (!pub->cancelled) {
tx->fn_done(tx);
}
return G_SOURCE_REMOVE;
}
static
@@ -1241,8 +1241,7 @@ gbinder_ipc_tx_priv_init(
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,
priv->completion = gbinder_idle_callback_new(gbinder_ipc_tx_done, priv,
gbinder_ipc_tx_free);
}
@@ -1419,8 +1418,6 @@ gbinder_ipc_tx_proc(
gpointer object)
{
GBinderIpcTxPriv* tx = data;
GBinderIpc* self = GBINDER_IPC(object);
GBinderIpcPriv* priv = self->priv;
if (!tx->pub.cancelled) {
tx->fn_exec(tx);
@@ -1429,7 +1426,7 @@ gbinder_ipc_tx_proc(
}
/* The result is handled by the main thread */
g_source_attach(tx->completion, priv->context);
gbinder_idle_callback_schedule(tx->completion);
}
/*==========================================================================*
@@ -1635,14 +1632,12 @@ gbinder_ipc_init(
g_mutex_init(&priv->looper_mutex);
g_mutex_init(&priv->local_objects_mutex);
g_mutex_init(&priv->remote_objects_mutex);
priv->context = g_main_context_default();
priv->tx_table = g_hash_table_new(g_direct_hash, g_direct_equal);
priv->tx_pool = g_thread_pool_new(gbinder_ipc_tx_proc, self,
GBINDER_IPC_MAX_TX_THREADS, FALSE, NULL);
priv->object_registry.f = &object_registry_functions;
priv->self = self;
self->priv = priv;
self->pool = gutil_idle_pool_new();
}
static
@@ -1723,7 +1718,6 @@ gbinder_ipc_finalize(
}
GASSERT(!g_hash_table_size(priv->tx_table));
g_hash_table_unref(priv->tx_table);
gutil_idle_pool_unref(self->pool);
gbinder_driver_unref(self->driver);
g_free(priv->key);
G_OBJECT_CLASS(gbinder_ipc_parent_class)->finalize(object);
@@ -1789,11 +1783,9 @@ gbinder_ipc_exit()
}
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);
gbinder_idle_callback_cancel(tx->completion);
}
/* The above loop must destroy all uncompleted transactions */
@@ -1824,6 +1816,7 @@ gbinder_ipc_exit()
g_slist_free_full(local_objs, g_object_unref);
}
g_slist_free_full(ipcs, g_object_unref);
gbinder_eventloop_set(NULL);
}
/*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* 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
* 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.
* 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
@@ -42,7 +42,6 @@ struct gbinder_ipc {
GObject object;
GBinderIpcPriv* priv;
GBinderDriver* driver;
GUtilIdlePool* pool;
const char* dev;
};

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,6 +30,8 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_driver.h"
#include "gbinder_ipc.h"
#include "gbinder_local_object_p.h"

62
src/gbinder_log.c Normal file
View File

@@ -0,0 +1,62 @@
/*
* 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_log.h"
#include <gutil_misc.h>
#include <stdlib.h>
/* Log module */
GLOG_MODULE_DEFINE("gbinder");
/* Initializes the default log level at startup */
void
gbinder_log_init(
void)
{
int level = GLOG_MODULE_NAME.level;
if (gutil_parse_int(getenv("GBINDER_DEFAULT_LOG_LEVEL"), 0, &level) &&
level >= GLOG_LEVEL_INHERIT && level <= GLOG_LEVEL_VERBOSE) {
GINFO("Log level %d", level);
GLOG_MODULE_NAME.level = level;
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -38,6 +38,13 @@
#define GLOG_MODULE_NAME GBINDER_LOG_MODULE
#include <gutil_log.h>
/* Declared for unit tests */
G_GNUC_INTERNAL
__attribute__((constructor))
void
gbinder_log_init(
void);
#endif /* GBINDER_LOG_H */
/*

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -30,6 +30,8 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_driver.h"
#include "gbinder_ipc.h"
#include "gbinder_remote_object_p.h"

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* 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
* 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.
* 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
@@ -30,17 +30,19 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_servicemanager_p.h"
#include "gbinder_client_p.h"
#include "gbinder_local_object_p.h"
#include "gbinder_remote_object_p.h"
#include "gbinder_eventloop_p.h"
#include "gbinder_driver.h"
#include "gbinder_ipc.h"
#include "gbinder_log.h"
#include <gbinder_client.h>
#include <gutil_idlepool.h>
#include <gutil_misc.h>
#include <errno.h>
@@ -60,8 +62,10 @@ struct gbinder_servicemanager_priv {
GHashTable* watch_table;
gulong death_id;
gboolean present;
guint presence_check_id;
GBinderEventLoopTimeout* presence_check;
guint presence_check_delay_ms;
GBinderEventLoopCallback* autorelease_cb;
GSList* autorelease;
};
G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
@@ -273,9 +277,9 @@ gbinder_servicemanager_reanimated(
{
GBinderServiceManagerPriv* priv = self->priv;
if (priv->presence_check_id) {
g_source_remove(priv->presence_check_id);
priv->presence_check_id = 0;
if (priv->presence_check) {
gbinder_timeout_remove(priv->presence_check);
priv->presence_check = NULL;
}
GINFO("Service manager %s has appeared", self->dev);
/* Re-arm the watches */
@@ -315,13 +319,14 @@ gbinder_servicemanager_presense_check_timer(
gbinder_servicemanager_ref(self);
if (gbinder_remote_object_reanimate(remote)) {
/* Done */
priv->presence_check_id = 0;
priv->presence_check = NULL;
gbinder_servicemanager_reanimated(self);
result = G_SOURCE_REMOVE;
} else if (priv->presence_check_delay_ms < PRESENSE_WAIT_MS_MAX) {
priv->presence_check_delay_ms += PRESENSE_WAIT_MS_STEP;
priv->presence_check_id = g_timeout_add(priv->presence_check_delay_ms,
gbinder_servicemanager_presense_check_timer, self);
priv->presence_check =
gbinder_timeout_add(priv->presence_check_delay_ms,
gbinder_servicemanager_presense_check_timer, self);
result = G_SOURCE_REMOVE;
} else {
result = G_SOURCE_CONTINUE;
@@ -337,9 +342,9 @@ gbinder_servicemanager_presence_check_start(
{
GBinderServiceManagerPriv* priv = self->priv;
GASSERT(!priv->presence_check_id);
GASSERT(!priv->presence_check);
priv->presence_check_delay_ms = PRESENSE_WAIT_MS_MIN;
priv->presence_check_id = g_timeout_add(PRESENSE_WAIT_MS_MIN,
priv->presence_check = gbinder_timeout_add(PRESENSE_WAIT_MS_MIN,
gbinder_servicemanager_presense_check_timer, self);
}
@@ -389,6 +394,20 @@ gbinder_servicemanager_sleep_ms(
(wait.tv_sec > 0 || wait.tv_nsec > 0));
}
static
void
gbinder_servicemanager_autorelease_cb(
gpointer data)
{
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(data);
GBinderServiceManagerPriv* priv = self->priv;
GSList* list = priv->autorelease;
priv->autorelease_cb = NULL;
priv->autorelease = NULL;
g_slist_free_full(list, g_object_unref);
}
/*==========================================================================*
* Internal interface
*==========================================================================*/
@@ -673,10 +692,15 @@ gbinder_servicemanager_get_service_sync(
if (G_LIKELY(self) && name) {
obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)->get_service
(self, name, status);
if (!self->pool) {
self->pool = gutil_idle_pool_new();
if (obj) {
GBinderServiceManagerPriv* priv = self->priv;
priv->autorelease = g_slist_prepend(priv->autorelease, obj);
if (!priv->autorelease_cb) {
priv->autorelease_cb = gbinder_idle_callback_schedule_new
(gbinder_servicemanager_autorelease_cb, self, NULL);
}
}
gutil_idle_pool_add_object(self->pool, obj);
} else if (status) {
*status = (-EINVAL);
}
@@ -913,12 +937,11 @@ gbinder_servicemanager_finalize(
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
GBinderServiceManagerPriv* priv = self->priv;
if (priv->presence_check_id) {
g_source_remove(priv->presence_check_id);
}
gbinder_timeout_remove(priv->presence_check);
gbinder_remote_object_remove_handler(self->client->remote, priv->death_id);
gbinder_idle_callback_destroy(priv->autorelease_cb);
g_slist_free_full(priv->autorelease, g_object_unref);
g_hash_table_destroy(priv->watch_table);
gutil_idle_pool_destroy(self->pool);
gbinder_client_unref(self->client);
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* 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
* 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.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -49,7 +49,6 @@ typedef struct gbinder_servicemanager {
GBinderServiceManagerPriv* priv;
const char* dev;
GBinderClient* client;
GUtilIdlePool* pool;
} GBinderServiceManager;
typedef enum gbinder_servicemanager_name_check {

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -32,6 +32,7 @@
#include "gbinder_servicepoll.h"
#include "gbinder_servicemanager.h"
#include "gbinder_eventloop_p.h"
#include <gutil_strv.h>
@@ -46,7 +47,7 @@ struct gbinder_servicepoll {
GBinderServiceManager* manager;
char** list;
gulong list_id;
guint timer_id;
GBinderEventLoopTimeout* timer;
};
G_DEFINE_TYPE(GBinderServicePoll, gbinder_servicepoll, G_TYPE_OBJECT)
@@ -230,7 +231,7 @@ void
gbinder_servicepoll_init(
GBinderServicePoll* self)
{
self->timer_id = g_timeout_add(gbinder_servicepoll_interval_ms,
self->timer = gbinder_timeout_add(gbinder_servicepoll_interval_ms,
gbinder_servicepoll_timer, self);
}
@@ -241,7 +242,7 @@ gbinder_servicepoll_finalize(
{
GBinderServicePoll* self = GBINDER_SERVICEPOLL(object);
g_source_remove(self->timer_id);
gbinder_timeout_remove(self->timer);
gbinder_servicemanager_cancel(self->manager, self->list_id);
gbinder_servicemanager_unref(self->manager);
g_strfreev(self->list);

View File

@@ -5,5 +5,6 @@ all:
@$(MAKE) -C binder-client $*
@$(MAKE) -C binder-dump $*
@$(MAKE) -C binder-list $*
@$(MAKE) -C binder-ping $*
@$(MAKE) -C binder-service $*
@$(MAKE) -C rild-card-status $*

View File

@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
INCLUDES = -I$(LIB_DIR)/include

View File

@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
INCLUDES = -I$(LIB_DIR)/include

View File

@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
INCLUDES = -I$(LIB_DIR)/include

140
test/binder-ping/Makefile Normal file
View 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)

View 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:
*/

View File

@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
INCLUDES = -I$(LIB_DIR)/include

View File

@@ -41,7 +41,7 @@ RELEASE_BUILD_DIR = $(BUILD_DIR)/release
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
INCLUDES = -I$(LIB_DIR)/include

View File

@@ -6,10 +6,12 @@ all:
@$(MAKE) -C unit_cleanup $*
@$(MAKE) -C unit_client $*
@$(MAKE) -C unit_driver $*
@$(MAKE) -C unit_eventloop $*
@$(MAKE) -C unit_ipc $*
@$(MAKE) -C unit_local_object $*
@$(MAKE) -C unit_local_reply $*
@$(MAKE) -C unit_local_request $*
@$(MAKE) -C unit_log $*
@$(MAKE) -C unit_protocol $*
@$(MAKE) -C unit_reader $*
@$(MAKE) -C unit_remote_object $*

View File

@@ -42,7 +42,7 @@ COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
# Tools and flags
#
CC = $(CROSS_COMPILE)gcc
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS += -Wall
INCLUDES += -I$(COMMON_DIR) -I$(LIB_DIR)/src -I$(LIB_DIR)/include

View File

@@ -8,10 +8,12 @@ unit_buffer \
unit_cleanup \
unit_client \
unit_driver \
unit_eventloop \
unit_ipc \
unit_local_object \
unit_local_reply \
unit_local_request \
unit_log \
unit_protocol \
unit_reader \
unit_remote_object \

View File

@@ -0,0 +1,5 @@
# -*- Mode: makefile-gmake -*-
EXE = unit_eventloop
include ../common/Makefile

View File

@@ -0,0 +1,262 @@
/*
* 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 "test_common.h"
#include "gbinder_eventloop_p.h"
static TestOpt test_opt;
static int test_eventloop_timeout_add_called;
static int test_eventloop_callback_new_called;
static int test_eventloop_cleanup_called;
static
gboolean
test_unreached_proc(
gpointer data)
{
g_assert_not_reached();
return G_SOURCE_CONTINUE;
}
/*==========================================================================*
* Test event loop integration
*==========================================================================*/
static
GBinderEventLoopTimeout*
test_eventloop_timeout_add(
guint interval,
GSourceFunc func,
gpointer data)
{
test_eventloop_timeout_add_called++;
return NULL;
}
static
void
test_eventloop_timeout_remove(
GBinderEventLoopTimeout* timeout)
{
g_assert_not_reached();
}
static
GBinderEventLoopCallback*
test_eventloop_callback_new(
GBinderEventLoopCallbackFunc func,
gpointer data,
GDestroyNotify destroy)
{
test_eventloop_callback_new_called++;
return NULL;
}
static
void
test_eventloop_callback_ref(
GBinderEventLoopCallback* cb)
{
g_assert_not_reached();
}
static
void
test_eventloop_callback_unref(
GBinderEventLoopCallback* cb)
{
g_assert_not_reached();
}
static
void
test_eventloop_callback_schedule(
GBinderEventLoopCallback* cb)
{
g_assert_not_reached();
}
static
void
test_eventloop_callback_cancel(
GBinderEventLoopCallback* cb)
{
g_assert_not_reached();
}
static
void
test_eventloop_cleanup(
void)
{
test_eventloop_cleanup_called++;
}
static const GBinderEventLoopIntegration test_eventloop = {
test_eventloop_timeout_add,
test_eventloop_timeout_remove,
test_eventloop_callback_new,
test_eventloop_callback_ref,
test_eventloop_callback_unref,
test_eventloop_callback_schedule,
test_eventloop_callback_cancel,
test_eventloop_cleanup
};
/*==========================================================================*
* replace
*==========================================================================*/
static
void
test_replace(
void)
{
test_eventloop_timeout_add_called = 0;
test_eventloop_callback_new_called = 0;
test_eventloop_cleanup_called = 0;
gbinder_eventloop_set(NULL);
gbinder_eventloop_set(&test_eventloop);
g_assert(!gbinder_timeout_add(0, test_unreached_proc, NULL));
g_assert_cmpint(test_eventloop_timeout_add_called, == ,1);
g_assert(!gbinder_idle_add(test_unreached_proc, NULL));
g_assert_cmpint(test_eventloop_timeout_add_called, == ,2);
gbinder_timeout_remove(NULL);
g_assert(!gbinder_idle_callback_new(NULL, NULL, NULL));
g_assert_cmpint(test_eventloop_callback_new_called, == ,1);
g_assert(!gbinder_idle_callback_ref(NULL));
gbinder_idle_callback_unref(NULL);
gbinder_idle_callback_schedule(NULL);
gbinder_idle_callback_cancel(NULL);
gbinder_eventloop_set(NULL);
g_assert_cmpint(test_eventloop_cleanup_called, == ,1);
}
/*==========================================================================*
* idle
*==========================================================================*/
static
gboolean
test_quit_func(
gpointer data)
{
g_main_loop_quit((GMainLoop*)data);
return G_SOURCE_REMOVE;
}
static
void
test_idle(
void)
{
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
gbinder_eventloop_set(NULL);
g_assert(gbinder_idle_add(test_quit_func, loop));
test_run(&test_opt, loop);
g_main_loop_unref(loop);
}
/*==========================================================================*
* timeout
*==========================================================================*/
static
void
test_timeout(
void)
{
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
gbinder_eventloop_set(NULL);
g_assert(gbinder_timeout_add(10, test_quit_func, loop));
test_run(&test_opt, loop);
g_main_loop_unref(loop);
}
/*==========================================================================*
* callback
*==========================================================================*/
static
void
test_quit_cb(
gpointer data)
{
g_main_loop_quit((GMainLoop*)data);
}
static
void
test_callback(
void)
{
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
GBinderEventLoopCallback* cb;
gbinder_eventloop_set(NULL);
cb = gbinder_idle_callback_new(test_quit_cb, loop, NULL);
gbinder_idle_callback_schedule(cb);
test_run(&test_opt, loop);
gbinder_idle_callback_unref(cb);
g_main_loop_unref(loop);
}
/*==========================================================================*
* Common
*==========================================================================*/
#define TEST_(t) "/eventloop/" t
int main(int argc, char* argv[])
{
g_test_init(&argc, &argv, NULL);
g_test_add_func(TEST_("replace"), test_replace);
g_test_add_func(TEST_("idle"), test_idle);
g_test_add_func(TEST_("timeout"), test_timeout);
g_test_add_func(TEST_("callback"), test_callback);
test_init(&test_opt, argc, argv);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

5
unit/unit_log/Makefile Normal file
View File

@@ -0,0 +1,5 @@
# -*- Mode: makefile-gmake -*-
EXE = unit_log
include ../common/Makefile

146
unit/unit_log/unit_log.c Normal file
View File

@@ -0,0 +1,146 @@
/*
* 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 "test_binder.h"
#include "gbinder_log.h"
#include <stdlib.h>
static TestOpt test_opt;
static const char env[] = "GBINDER_DEFAULT_LOG_LEVEL";
/*==========================================================================*
* empty
*==========================================================================*/
static
void
test_empty(
void)
{
const int level = GLOG_MODULE_NAME.level;
unsetenv(env);
gbinder_log_init();
g_assert_cmpint(level, == ,GLOG_MODULE_NAME.level);
}
/*==========================================================================*
* invalid
*==========================================================================*/
static
void
test_invalid(
void)
{
const int level = GLOG_MODULE_NAME.level;
setenv(env, "-2" /* GLOG_LEVEL_ALWAYS */, TRUE);
gbinder_log_init();
g_assert_cmpint(level, == ,GLOG_MODULE_NAME.level);
setenv(env, "6" /* GLOG_LEVEL_VERBOSE + 1 */, TRUE);
gbinder_log_init();
g_assert_cmpint(level, == ,GLOG_MODULE_NAME.level);
setenv(env, "foo", TRUE);
gbinder_log_init();
g_assert_cmpint(level, == ,GLOG_MODULE_NAME.level);
}
/*==========================================================================*
* level
*==========================================================================*/
typedef struct test_level_data {
const char* test_name;
const char* env_value;
int level;
} TestLevelData;
static
void
test_level(
gconstpointer data)
{
const TestLevelData* test = data;
GLOG_MODULE_NAME.level = GLOG_LEVEL_ALWAYS;
g_assert_cmpint(GLOG_MODULE_NAME.level, != ,test->level);
setenv(env, test->env_value, TRUE);
gbinder_log_init();
g_assert_cmpint(GLOG_MODULE_NAME.level, == ,test->level);
}
/*==========================================================================*
* Common
*==========================================================================*/
#define TEST_PREFIX "/log/"
#define TEST_(t) TEST_PREFIX t
int main(int argc, char* argv[])
{
#define TEST_LEVEL_INIT(X,x) \
{ TEST_(#x), #x, x }
static const TestLevelData level_tests[] = {
{ TEST_("inherit"), "-1", GLOG_LEVEL_INHERIT },
{ TEST_("none"), "0", GLOG_LEVEL_NONE },
{ TEST_("err"), "1", GLOG_LEVEL_ERR },
{ TEST_("warn"), "2", GLOG_LEVEL_WARN },
{ TEST_("info"), "3", GLOG_LEVEL_INFO },
{ TEST_("debug"), "4", GLOG_LEVEL_DEBUG },
{ TEST_("verbose"), "5", GLOG_LEVEL_VERBOSE }
};
guint i;
g_test_init(&argc, &argv, NULL);
g_test_add_func(TEST_("empty"), test_empty);
g_test_add_func(TEST_("invalid"), test_invalid);
for (i = 0; i < G_N_ELEMENTS(level_tests); i++) {
g_test_add_data_func(level_tests[i].test_name, level_tests + i,
test_level);
}
test_init(&test_opt, argc, argv);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/