[gbinder] C interface for Android binder. JB#41335
This commit is contained in:
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
*~
|
||||
debian/files
|
||||
debian/libgbinder-dev.debhelper.log
|
||||
debian/libgbinder-dev.substvars
|
||||
debian/libgbinder-dev
|
||||
debian/libgbinder.debhelper.log
|
||||
debian/libgbinder.postinst.debhelper
|
||||
debian/libgbinder.postrm.debhelper
|
||||
debian/libgbinder.substvars
|
||||
debian/libgbinder
|
||||
debian/tmp
|
||||
documentation.list
|
||||
installroot
|
||||
build
|
||||
RPMS
|
||||
29
LICENSE
Normal file
29
LICENSE
Normal file
@@ -0,0 +1,29 @@
|
||||
Copyright (C) 2018 Jolla Ltd.
|
||||
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
|
||||
You may use this file under the terms of BSD license as follows:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the 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.
|
||||
|
||||
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.
|
||||
284
Makefile
Normal file
284
Makefile
Normal file
@@ -0,0 +1,284 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: clean all debug release test
|
||||
.PHONY: print_debug_so print_release_so
|
||||
.PHONY: print_debug_lib print_release_lib
|
||||
.PHONY: print_debug_link print_release_link
|
||||
.PHONY: print_debug_path print_release_path
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS = libglibutil glib-2.0 gobject-2.0
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release pkgconfig
|
||||
|
||||
#
|
||||
# Library version
|
||||
#
|
||||
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 0
|
||||
VERSION_RELEASE = 0
|
||||
|
||||
# Version for pkg-config
|
||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
|
||||
#
|
||||
# Library name
|
||||
#
|
||||
|
||||
NAME = gbinder
|
||||
LIB_NAME = lib$(NAME)
|
||||
LIB_DEV_SYMLINK = $(LIB_NAME).so
|
||||
LIB_SYMLINK1 = $(LIB_DEV_SYMLINK).$(VERSION_MAJOR)
|
||||
LIB_SYMLINK2 = $(LIB_SYMLINK1).$(VERSION_MINOR)
|
||||
LIB_SONAME = $(LIB_SYMLINK1)
|
||||
LIB_SO = $(LIB_SONAME).$(VERSION_MINOR).$(VERSION_RELEASE)
|
||||
LIB = $(LIB_NAME).a
|
||||
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
|
||||
SRC = \
|
||||
gbinder_buffer.c \
|
||||
gbinder_cleanup.c \
|
||||
gbinder_client.c \
|
||||
gbinder_driver.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_reader.c \
|
||||
gbinder_remote_object.c \
|
||||
gbinder_remote_reply.c \
|
||||
gbinder_remote_request.c \
|
||||
gbinder_rpc_protocol.c \
|
||||
gbinder_writer.c
|
||||
|
||||
SRC += \
|
||||
gbinder_defaultservicemanager.c \
|
||||
gbinder_hwservicemanager.c \
|
||||
gbinder_servicemanager.c
|
||||
|
||||
SRC += \
|
||||
gbinder_system.c
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = src
|
||||
INCLUDE_DIR = include
|
||||
BUILD_DIR = build
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS = -Wall -Wstrict-aliasing -Wunused-result
|
||||
INCLUDES = -I$(INCLUDE_DIR)
|
||||
BASE_FLAGS = -fPIC
|
||||
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
|
||||
-MMD -MP $(shell pkg-config --cflags $(PKGS))
|
||||
FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \
|
||||
$(shell pkg-config --libs $(PKGS)) -lpthread
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
COVERAGE_FLAGS = -g
|
||||
|
||||
ifndef KEEP_SYMBOLS
|
||||
KEEP_SYMBOLS = 0
|
||||
endif
|
||||
|
||||
ifneq ($(KEEP_SYMBOLS),0)
|
||||
RELEASE_FLAGS += -g
|
||||
endif
|
||||
|
||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
|
||||
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
PKGCONFIG = $(BUILD_DIR)/$(LIB_NAME).pc
|
||||
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
COVERAGE_OBJS = $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(PKGCONFIG): | $(BUILD_DIR)
|
||||
$(DEBUG_OBJS) $(DEBUG_SO): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_OBJS) $(RELEASE_SO): | $(RELEASE_BUILD_DIR)
|
||||
$(COVERAGE_OBJS) $(COVERAGE_LIB): | $(COVERAGE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
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_LIB = $(DEBUG_BUILD_DIR)/$(LIB)
|
||||
RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB)
|
||||
COVERAGE_LIB = $(COVERAGE_BUILD_DIR)/$(LIB)
|
||||
|
||||
debug: $(DEBUG_SO)
|
||||
|
||||
release: $(RELEASE_SO)
|
||||
|
||||
debug_lib: $(DEBUG_LIB)
|
||||
|
||||
release_lib: $(RELEASE_LIB)
|
||||
|
||||
coverage_lib: $(COVERAGE_LIB)
|
||||
|
||||
pkgconfig: $(PKGCONFIG)
|
||||
|
||||
print_debug_so:
|
||||
@echo $(DEBUG_SO)
|
||||
|
||||
print_release_so:
|
||||
@echo $(RELEASE_SO)
|
||||
|
||||
print_debug_lib:
|
||||
@echo $(DEBUG_LIB)
|
||||
|
||||
print_release_lib:
|
||||
@echo $(RELEASE_LIB)
|
||||
|
||||
print_coverage_lib:
|
||||
@echo $(COVERAGE_LIB)
|
||||
|
||||
print_debug_link:
|
||||
@echo $(DEBUG_LINK)
|
||||
|
||||
print_release_link:
|
||||
@echo $(RELEASE_LINK)
|
||||
|
||||
print_debug_path:
|
||||
@echo $(DEBUG_BUILD_DIR)
|
||||
|
||||
print_release_path:
|
||||
@echo $(RELEASE_BUILD_DIR)
|
||||
|
||||
clean:
|
||||
make -C test clean
|
||||
make -C unit clean
|
||||
rm -fr test/coverage/results test/coverage/*.gcov
|
||||
rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
|
||||
rm -fr $(BUILD_DIR) RPMS installroot
|
||||
rm -fr debian/tmp debian/libgbinder debian/libgbinder-dev
|
||||
rm -f documentation.list debian/files debian/*.substvars
|
||||
rm -f debian/*.debhelper.log debian/*.debhelper debian/*~
|
||||
|
||||
test:
|
||||
make -C unit test
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(COVERAGE_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 $@
|
||||
|
||||
$(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(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
|
||||
|
||||
$(DEBUG_LIB): $(DEBUG_OBJS)
|
||||
$(AR) rc $@ $?
|
||||
ranlib $@
|
||||
|
||||
$(RELEASE_LIB): $(RELEASE_OBJS)
|
||||
$(AR) rc $@ $?
|
||||
ranlib $@
|
||||
|
||||
$(COVERAGE_LIB): $(COVERAGE_OBJS)
|
||||
$(AR) rc $@ $?
|
||||
ranlib $@
|
||||
|
||||
$(PKGCONFIG): $(LIB_NAME).pc.in
|
||||
sed -e 's/\[version\]/'$(PCVERSION)/g $< > $@
|
||||
|
||||
#
|
||||
# Install
|
||||
#
|
||||
|
||||
INSTALL_PERM = 644
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_DIRS = $(INSTALL) -d
|
||||
INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM)
|
||||
|
||||
INSTALL_LIB_DIR = $(DESTDIR)/usr/lib
|
||||
INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/$(NAME)
|
||||
INSTALL_PKGCONFIG_DIR = $(DESTDIR)/usr/lib/pkgconfig
|
||||
|
||||
install: $(INSTALL_LIB_DIR)
|
||||
$(INSTALL_FILES) $(RELEASE_SO) $(INSTALL_LIB_DIR)
|
||||
ln -sf $(LIB_SO) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2)
|
||||
ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1)
|
||||
|
||||
install-dev: install $(INSTALL_INCLUDE_DIR) $(INSTALL_PKGCONFIG_DIR)
|
||||
$(INSTALL_FILES) $(INCLUDE_DIR)/*.h $(INSTALL_INCLUDE_DIR)
|
||||
$(INSTALL_FILES) $(PKGCONFIG) $(INSTALL_PKGCONFIG_DIR)
|
||||
ln -sf $(LIB_SYMLINK1) $(INSTALL_LIB_DIR)/$(LIB_DEV_SYMLINK)
|
||||
|
||||
$(INSTALL_LIB_DIR):
|
||||
$(INSTALL_DIRS) $@
|
||||
|
||||
$(INSTALL_INCLUDE_DIR):
|
||||
$(INSTALL_DIRS) $@
|
||||
|
||||
$(INSTALL_PKGCONFIG_DIR):
|
||||
$(INSTALL_DIRS) $@
|
||||
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
libgbinder (1.0.0) unstable; urgency=low
|
||||
|
||||
* Initial release
|
||||
|
||||
-- Slava Monich <slava.monich@jolla.com> Thu, 12 Jul 2018 00:37:21 +0300
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
5
|
||||
18
debian/control
vendored
Normal file
18
debian/control
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Source: libgbinder
|
||||
Section: libs
|
||||
Priority: optional
|
||||
Maintainer: Slava Monich <slava.monich@jolla.com>
|
||||
Build-Depends: debhelper (>= 7), libglib2.0-dev (>= 2.0), libglibutil (>= 1.0.29)
|
||||
Standards-Version: 3.8.4
|
||||
|
||||
Package: libgbinder
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Depends: libglibutil (>= 1.0.29), ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Binder client library
|
||||
|
||||
Package: libgbinder-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: libgbinder (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Development files for libgbinder
|
||||
29
debian/copyright
vendored
Normal file
29
debian/copyright
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
Copyright (C) 2018 Jolla Ltd.
|
||||
Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
|
||||
You may use this file under the terms of BSD license as follows:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the 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.
|
||||
|
||||
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.
|
||||
3
debian/libgbinder-dev.install
vendored
Normal file
3
debian/libgbinder-dev.install
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
debian/tmp/usr/lib/libgbinder.so usr/lib
|
||||
include/*.h usr/include/gbinder
|
||||
build/libgbinder.pc usr/lib/pkgconfig
|
||||
1
debian/libgbinder.install
vendored
Normal file
1
debian/libgbinder.install
vendored
Normal file
@@ -0,0 +1 @@
|
||||
debian/tmp/usr/lib/libgbinder.so.* usr/lib
|
||||
11
debian/rules
vendored
Executable file
11
debian/rules
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install -- install-dev
|
||||
|
||||
%:
|
||||
dh $@
|
||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
||||
58
include/gbinder.h
Normal file
58
include/gbinder.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_H
|
||||
#define GBINDER_H
|
||||
|
||||
/* Convenience header to pull in everything at once */
|
||||
|
||||
#include "gbinder_buffer.h"
|
||||
#include "gbinder_client.h"
|
||||
#include "gbinder_local_object.h"
|
||||
#include "gbinder_local_reply.h"
|
||||
#include "gbinder_local_request.h"
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_remote_object.h"
|
||||
#include "gbinder_remote_reply.h"
|
||||
#include "gbinder_remote_request.h"
|
||||
#include "gbinder_servicemanager.h"
|
||||
#include "gbinder_writer.h"
|
||||
|
||||
#endif /* GBINDER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
59
include/gbinder_buffer.h
Normal file
59
include/gbinder_buffer.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_BUFFER_H
|
||||
#define GBINDER_BUFFER_H
|
||||
|
||||
#include <gbinder_types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct gbinder_buffer {
|
||||
void* data;
|
||||
gsize size;
|
||||
};
|
||||
|
||||
void
|
||||
gbinder_buffer_free(
|
||||
GBinderBuffer* buf);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_BUFFER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
103
include/gbinder_client.h
Normal file
103
include/gbinder_client.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_CLIENT_H
|
||||
#define GBINDER_CLIENT_H
|
||||
|
||||
#include <gbinder_types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderClientReplyFunc)(
|
||||
GBinderClient* client,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data);
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_new(
|
||||
GBinderRemoteObject* object,
|
||||
const char* iface);
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_ref(
|
||||
GBinderClient* client);
|
||||
|
||||
void
|
||||
gbinder_client_unref(
|
||||
GBinderClient* client);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_client_new_request(
|
||||
GBinderClient* client);
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_client_transact_sync_reply(
|
||||
GBinderClient* client,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
int* status);
|
||||
|
||||
int
|
||||
gbinder_client_transact_sync_oneway(
|
||||
GBinderClient* client,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req);
|
||||
|
||||
gulong
|
||||
gbinder_client_transact(
|
||||
GBinderClient* client,
|
||||
guint32 code,
|
||||
guint32 flags,
|
||||
GBinderLocalRequest* req,
|
||||
GBinderClientReplyFunc reply,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data);
|
||||
|
||||
void
|
||||
gbinder_client_cancel(
|
||||
GBinderClient* client,
|
||||
gulong id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_CLIENT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
66
include/gbinder_local_object.h
Normal file
66
include/gbinder_local_object.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_LOCAL_OBJECT_H
|
||||
#define GBINDER_LOCAL_OBJECT_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_ref(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_local_object_unref(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_local_object_drop(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_new_reply(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_LOCAL_OBJECT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
110
include/gbinder_local_reply.h
Normal file
110
include/gbinder_local_reply.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_LOCAL_REPLY_H
|
||||
#define GBINDER_LOCAL_REPLY_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_ref(
|
||||
GBinderLocalReply* reply);
|
||||
|
||||
void
|
||||
gbinder_local_reply_unref(
|
||||
GBinderLocalReply* reply);
|
||||
|
||||
void
|
||||
gbinder_local_reply_init_writer(
|
||||
GBinderLocalReply* reply,
|
||||
GBinderWriter* writer);
|
||||
|
||||
void
|
||||
gbinder_local_reply_cleanup(
|
||||
GBinderLocalReply* reply,
|
||||
GDestroyNotify destroy,
|
||||
gpointer pointer);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_int32(
|
||||
GBinderLocalReply* reply,
|
||||
guint32 value);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_int64(
|
||||
GBinderLocalReply* reply,
|
||||
guint64 value);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_string8(
|
||||
GBinderLocalReply* reply,
|
||||
const char* str);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_string16(
|
||||
GBinderLocalReply* reply,
|
||||
const char* utf8);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_hidl_string(
|
||||
GBinderLocalReply* reply,
|
||||
const char* str);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_hidl_string_vec(
|
||||
GBinderLocalReply* reply,
|
||||
const char* strv[],
|
||||
gssize count);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_local_object(
|
||||
GBinderLocalReply* reply,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_remote_object(
|
||||
GBinderLocalReply* reply,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_LOCAL_OBJECT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
110
include/gbinder_local_request.h
Normal file
110
include/gbinder_local_request.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_LOCAL_REQUEST_H
|
||||
#define GBINDER_LOCAL_REQUEST_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_ref(
|
||||
GBinderLocalRequest* request);
|
||||
|
||||
void
|
||||
gbinder_local_request_unref(
|
||||
GBinderLocalRequest* request);
|
||||
|
||||
void
|
||||
gbinder_local_request_init_writer(
|
||||
GBinderLocalRequest* request,
|
||||
GBinderWriter* writer);
|
||||
|
||||
void
|
||||
gbinder_local_request_cleanup(
|
||||
GBinderLocalRequest* request,
|
||||
GDestroyNotify destroy,
|
||||
gpointer pointer);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_int32(
|
||||
GBinderLocalRequest* request,
|
||||
guint32 value);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_int64(
|
||||
GBinderLocalRequest* request,
|
||||
guint64 value);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_string8(
|
||||
GBinderLocalRequest* request,
|
||||
const char* str);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_string16(
|
||||
GBinderLocalRequest* request,
|
||||
const char* utf8);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_hidl_string(
|
||||
GBinderLocalRequest* request,
|
||||
const char* str);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_hidl_string_vec(
|
||||
GBinderLocalRequest* request,
|
||||
const char* strv[],
|
||||
gssize count);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_local_object(
|
||||
GBinderLocalRequest* request,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_remote_object(
|
||||
GBinderLocalRequest* request,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_LOCAL_OBJECT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
155
include/gbinder_reader.h
Normal file
155
include/gbinder_reader.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_READER_H
|
||||
#define GBINDER_READER_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Normally, the reader is initialized by gbinder_remote_reply_init_reader or
|
||||
* gbinder_remote_request_init_reader function. Note that the reader doesn't
|
||||
* copy the data nor does it reference the object which initialized it. The
|
||||
* caller must make sure that the data outlive the reader.
|
||||
*
|
||||
* Also, these functions are not NULL tolerant. The reader is normally
|
||||
* allocated on stack.
|
||||
*/
|
||||
|
||||
struct gbinder_reader {
|
||||
gconstpointer d[6];
|
||||
};
|
||||
|
||||
gboolean
|
||||
gbinder_reader_at_end(
|
||||
GBinderReader* reader);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_byte(
|
||||
GBinderReader* reader,
|
||||
guchar* value);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_bool(
|
||||
GBinderReader* reader,
|
||||
gboolean* value);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int32(
|
||||
GBinderReader* reader,
|
||||
gint32* value);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint32(
|
||||
GBinderReader* reader,
|
||||
guint32* value);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int64(
|
||||
GBinderReader* reader,
|
||||
gint64* value);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint64(
|
||||
GBinderReader* reader,
|
||||
guint64* value);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_object(
|
||||
GBinderReader* reader,
|
||||
GBinderRemoteObject** obj);
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_reader_read_object(
|
||||
GBinderReader* reader)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
#define gbinder_reader_skip_object(reader) \
|
||||
gbinder_reader_read_nullable_object(reader, NULL)
|
||||
|
||||
GBinderBuffer*
|
||||
gbinder_reader_read_buffer(
|
||||
GBinderReader* reader)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
char*
|
||||
gbinder_reader_read_hidl_string(
|
||||
GBinderReader* reader)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
char**
|
||||
gbinder_reader_read_hidl_string_vec(
|
||||
GBinderReader* reader);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_skip_buffer(
|
||||
GBinderReader* reader);
|
||||
|
||||
const char*
|
||||
gbinder_reader_read_string8(
|
||||
GBinderReader* reader);
|
||||
|
||||
char*
|
||||
gbinder_reader_read_string16(
|
||||
GBinderReader* reader)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_string16(
|
||||
GBinderReader* reader,
|
||||
char** out);
|
||||
|
||||
gboolean
|
||||
gbinder_reader_skip_string16(
|
||||
GBinderReader* reader);
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_read(
|
||||
GBinderReader* reader);
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_remaining(
|
||||
GBinderReader* reader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_READER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
79
include/gbinder_remote_object.h
Normal file
79
include/gbinder_remote_object.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_REMOTE_OBJECT_H
|
||||
#define GBINDER_REMOTE_OBJECT_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderRemoteObjectNotifyFunc)(
|
||||
GBinderRemoteObject* obj,
|
||||
void* user_data);
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_object_ref(
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
void
|
||||
gbinder_remote_object_unref(
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_object_is_dead(
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
gulong
|
||||
gbinder_remote_object_add_death_handler(
|
||||
GBinderRemoteObject* obj,
|
||||
GBinderRemoteObjectNotifyFunc func,
|
||||
void* user_data);
|
||||
|
||||
void
|
||||
gbinder_remote_object_remove_handler(
|
||||
GBinderRemoteObject* obj,
|
||||
gulong id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_REMOTE_OBJECT_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
99
include/gbinder_remote_reply.h
Normal file
99
include/gbinder_remote_reply.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_REMOTE_REPLY_H
|
||||
#define GBINDER_REMOTE_REPLY_H
|
||||
|
||||
#include <gbinder_reader.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_remote_reply_ref(
|
||||
GBinderRemoteReply* reply);
|
||||
|
||||
void
|
||||
gbinder_remote_reply_unref(
|
||||
GBinderRemoteReply* reply);
|
||||
|
||||
void
|
||||
gbinder_remote_reply_init_reader(
|
||||
GBinderRemoteReply* reply,
|
||||
GBinderReader* reader);
|
||||
|
||||
/* Convenience function to decode replies with just one data item */
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_int32(
|
||||
GBinderRemoteReply* reply,
|
||||
gint32* value);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_uint32(
|
||||
GBinderRemoteReply* reply,
|
||||
guint32* value);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_int64(
|
||||
GBinderRemoteReply* reply,
|
||||
gint64* value);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_uint64(
|
||||
GBinderRemoteReply* reply,
|
||||
guint64* value);
|
||||
|
||||
const char*
|
||||
gbinder_remote_reply_read_string8(
|
||||
GBinderRemoteReply* reply);
|
||||
|
||||
char*
|
||||
gbinder_remote_reply_read_string16(
|
||||
GBinderRemoteReply* reply)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_reply_read_object(
|
||||
GBinderRemoteReply* reply)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_REMOTE_REPLY_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
103
include/gbinder_remote_request.h
Normal file
103
include/gbinder_remote_request.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_REMOTE_REQUEST_H
|
||||
#define GBINDER_REMOTE_REQUEST_H
|
||||
|
||||
#include <gbinder_reader.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
const char*
|
||||
gbinder_remote_request_interface(
|
||||
GBinderRemoteRequest* req);
|
||||
|
||||
GBinderRemoteRequest*
|
||||
gbinder_remote_request_ref(
|
||||
GBinderRemoteRequest* req);
|
||||
|
||||
void
|
||||
gbinder_remote_request_unref(
|
||||
GBinderRemoteRequest* req);
|
||||
|
||||
void
|
||||
gbinder_remote_request_init_reader(
|
||||
GBinderRemoteRequest* req,
|
||||
GBinderReader* reader);
|
||||
|
||||
/* Convenience function to decode requests with just one data item */
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_int32(
|
||||
GBinderRemoteRequest* req,
|
||||
gint32* value);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_uint32(
|
||||
GBinderRemoteRequest* req,
|
||||
guint32* value);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_int64(
|
||||
GBinderRemoteRequest* req,
|
||||
gint64* value);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_uint64(
|
||||
GBinderRemoteRequest* req,
|
||||
guint64* value);
|
||||
|
||||
const char*
|
||||
gbinder_remote_request_read_string8(
|
||||
GBinderRemoteRequest* req);
|
||||
|
||||
char*
|
||||
gbinder_remote_request_read_string16(
|
||||
GBinderRemoteRequest* req)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_request_read_object(
|
||||
GBinderRemoteRequest* self)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_REMOTE_REQUEST_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
143
include/gbinder_servicemanager.h
Normal file
143
include/gbinder_servicemanager.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_SERVICEMANAGER_H
|
||||
#define GBINDER_SERVICEMANAGER_H
|
||||
|
||||
#include <gbinder_types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* GBinderServiceManagerListFunc callback returns TRUE to keep the services
|
||||
* list, otherwise the caller will deallocate it. */
|
||||
typedef
|
||||
gboolean
|
||||
(*GBinderServiceManagerListFunc)(
|
||||
GBinderServiceManager* sm,
|
||||
char** services,
|
||||
void* user_data);
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderServiceManagerGetServiceFunc)(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderRemoteObject* obj,
|
||||
int status,
|
||||
void* user_data);
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderServiceManagerAddServiceFunc)(
|
||||
GBinderServiceManager* sm,
|
||||
int status,
|
||||
void* user_data);
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new(
|
||||
const char* dev);
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_defaultservicemanager_new(
|
||||
const char* dev);
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
const char* dev);
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_servicemanager_new_local_object(
|
||||
GBinderServiceManager* sm,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc handler,
|
||||
void* user_data);
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_ref(
|
||||
GBinderServiceManager* sm);
|
||||
|
||||
void
|
||||
gbinder_servicemanager_unref(
|
||||
GBinderServiceManager* sm);
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_list(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderServiceManagerListFunc func,
|
||||
void* user_data);
|
||||
|
||||
char**
|
||||
gbinder_servicemanager_list_sync(
|
||||
GBinderServiceManager* sm);
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_get_service(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
GBinderServiceManagerGetServiceFunc func,
|
||||
void* user_data);
|
||||
|
||||
GBinderRemoteObject* /* autoreleased */
|
||||
gbinder_servicemanager_get_service_sync(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
int* status);
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_service(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj,
|
||||
GBinderServiceManagerAddServiceFunc func,
|
||||
void* user_data);
|
||||
|
||||
int
|
||||
gbinder_servicemanager_add_service_sync(
|
||||
GBinderServiceManager* sm,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_servicemanager_cancel(
|
||||
GBinderServiceManager* sm,
|
||||
gulong id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
124
include/gbinder_types.h
Normal file
124
include/gbinder_types.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_TYPES_H
|
||||
#define GBINDER_TYPES_H
|
||||
|
||||
#include <gutil_types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GBINDER_LOG_MODULE gbinder_log
|
||||
|
||||
/*
|
||||
* Terminology:
|
||||
*
|
||||
* 1. RemoteObject is the one we sent requests to.
|
||||
* 2. LocalObjects may receive incoming transactions (and reply to them)
|
||||
* 3. We must have a RemoteObject to initiate a transaction.
|
||||
* We send LocalRequest and receive RemoteReply:
|
||||
*
|
||||
* LocalObject --- (LocalRequest) --> Client(RemoteObject)
|
||||
* LocalObject <-- (RemoteReply) -- RemoteObject
|
||||
*
|
||||
* 4. LocalObject knows caller's pid (and therefore credentials)
|
||||
*
|
||||
* LocalObject <-- (RemoteRequest) --- (pid)
|
||||
* LocalObject --- (LocalReply) --> (pid)
|
||||
*
|
||||
* 5. Writer prepares the data for LocalRequest and LocalReply
|
||||
* 6. Reader parses the data coming with RemoteRequest and RemoteReply
|
||||
*/
|
||||
|
||||
typedef struct gbinder_buffer GBinderBuffer;
|
||||
typedef struct gbinder_client GBinderClient;
|
||||
typedef struct gbinder_local_object GBinderLocalObject;
|
||||
typedef struct gbinder_local_reply GBinderLocalReply;
|
||||
typedef struct gbinder_local_request GBinderLocalRequest;
|
||||
typedef struct gbinder_reader GBinderReader;
|
||||
typedef struct gbinder_remote_object GBinderRemoteObject;
|
||||
typedef struct gbinder_remote_reply GBinderRemoteReply;
|
||||
typedef struct gbinder_remote_request GBinderRemoteRequest;
|
||||
typedef struct gbinder_servicemanager GBinderServiceManager;
|
||||
typedef struct gbinder_writer GBinderWriter;
|
||||
typedef struct gbinder_parent GBinderParent;
|
||||
|
||||
/*
|
||||
* Each RPC call is identified by the interface name returned
|
||||
* by gbinder_remote_request_interface() the the transaction code.
|
||||
* Transaction code itself is not unique.
|
||||
*
|
||||
* The value return from GBinderLocalTransactFunc callbacl will be
|
||||
* ignored for one-way transactions. If GBINDER_TX_FLAG_ONEWAY is
|
||||
* passed in, the callback should return NULL and that won't be
|
||||
* interpreted as an error.
|
||||
*/
|
||||
typedef
|
||||
GBinderLocalReply*
|
||||
(*GBinderLocalTransactFunc)(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data);
|
||||
|
||||
#define GBINDER_TX_FLAG_ONEWAY (0x01)
|
||||
|
||||
typedef enum gbinder_status {
|
||||
GBINDER_STATUS_OK = 0,
|
||||
GBINDER_STATUS_FAILED,
|
||||
GBINDER_STATUS_DEAD_OBJECT
|
||||
} GBINDER_STATUS;
|
||||
|
||||
#define GBINDER_FOURCC(c1,c2,c3,c4) \
|
||||
(((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
|
||||
|
||||
#define GBINDER_FIRST_CALL_TRANSACTION (0x00000001)
|
||||
|
||||
/* Default binder devices */
|
||||
#define GBINDER_DEFAULT_BINDER "/dev/binder"
|
||||
#define GBINDER_DEFAULT_HWBINDER "/dev/hwbinder"
|
||||
|
||||
extern GLogModule GBINDER_LOG_MODULE;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_TYPES_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
145
include/gbinder_writer.h
Normal file
145
include/gbinder_writer.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_WRITER_H
|
||||
#define GBINDER_WRITER_H
|
||||
|
||||
#include <gbinder_types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Writers are initialized by LocalRequest and LocalReply objects.
|
||||
* Note that writers directly update the objects which initialized
|
||||
* them but don't reference those object. The caller must make sure
|
||||
* that objects outlive their writers.
|
||||
*
|
||||
* Writers are normally allocated on stack.
|
||||
*/
|
||||
|
||||
struct gbinder_writer {
|
||||
gconstpointer d[4];
|
||||
};
|
||||
|
||||
struct gbinder_parent {
|
||||
guint32 index;
|
||||
guint32 offset;
|
||||
};
|
||||
|
||||
void
|
||||
gbinder_writer_append_int32(
|
||||
GBinderWriter* writer,
|
||||
guint32 value);
|
||||
|
||||
void
|
||||
gbinder_writer_append_int64(
|
||||
GBinderWriter* writer,
|
||||
guint64 value);
|
||||
|
||||
void
|
||||
gbinder_writer_append_string16(
|
||||
GBinderWriter* writer,
|
||||
const char* utf8);
|
||||
|
||||
void
|
||||
gbinder_writer_append_string16_len(
|
||||
GBinderWriter* writer,
|
||||
const char* utf8,
|
||||
gssize num_bytes);
|
||||
|
||||
void
|
||||
gbinder_writer_append_string8(
|
||||
GBinderWriter* writer,
|
||||
const char* str);
|
||||
|
||||
void
|
||||
gbinder_writer_append_string8_len(
|
||||
GBinderWriter* writer,
|
||||
const char* str,
|
||||
gsize len);
|
||||
|
||||
void
|
||||
gbinder_writer_append_bool(
|
||||
GBinderWriter* writer,
|
||||
gboolean value);
|
||||
|
||||
void
|
||||
gbinder_writer_append_bytes(
|
||||
GBinderWriter* writer,
|
||||
const void* data,
|
||||
gsize size);
|
||||
|
||||
guint
|
||||
gbinder_writer_append_buffer_object_with_parent(
|
||||
GBinderWriter* writer,
|
||||
const void* buf,
|
||||
gsize len,
|
||||
const GBinderParent* parent);
|
||||
|
||||
guint
|
||||
gbinder_writer_append_buffer_object(
|
||||
GBinderWriter* writer,
|
||||
const void* buf,
|
||||
gsize len);
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string(
|
||||
GBinderWriter* writer,
|
||||
const char* str);
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string_vec(
|
||||
GBinderWriter* writer,
|
||||
const char* data[],
|
||||
gssize count);
|
||||
|
||||
void
|
||||
gbinder_writer_append_local_object(
|
||||
GBinderWriter* writer,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_writer_append_remote_object(
|
||||
GBinderWriter* writer,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GBINDER_WRITER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
10
libgbinder.pc.in
Normal file
10
libgbinder.pc.in
Normal file
@@ -0,0 +1,10 @@
|
||||
name=gbinder
|
||||
libdir=/usr/lib
|
||||
includedir=/usr/include
|
||||
|
||||
Name: libgbinder
|
||||
Description: Binder client library
|
||||
Version: [version]
|
||||
Requires: glib-2.0 libglibutil
|
||||
Libs: -L${libdir} -l${name}
|
||||
Cflags: -I${includedir} -I${includedir}/${name}
|
||||
51
rpm/libgbinder.spec
Normal file
51
rpm/libgbinder.spec
Normal file
@@ -0,0 +1,51 @@
|
||||
Name: libgbinder
|
||||
Version: 1.0.0
|
||||
Release: 0
|
||||
Summary: Binder client library
|
||||
Group: Development/Libraries
|
||||
License: BSD
|
||||
URL: https://git.merproject.org/mer-core/libgbinder
|
||||
Source: %{name}-%{version}.tar.bz2
|
||||
Requires: libglibutil >= 1.0.29
|
||||
BuildRequires: pkgconfig(glib-2.0)
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.29
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
|
||||
%description
|
||||
C interfaces for Android binder
|
||||
|
||||
%package devel
|
||||
Summary: Development library for %{name}
|
||||
Requires: %{name} = %{version}
|
||||
Requires: pkgconfig
|
||||
|
||||
%description devel
|
||||
This package contains the development library for %{name}.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
make KEEP_SYMBOLS=1 release pkgconfig
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
make install-dev DESTDIR=%{buildroot}
|
||||
|
||||
%check
|
||||
make -C unit test
|
||||
|
||||
%post -p /sbin/ldconfig
|
||||
|
||||
%postun -p /sbin/ldconfig
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/%{name}.so.*
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pkgconfig/*.pc
|
||||
%{_libdir}/%{name}.so
|
||||
%{_includedir}/gbinder/*.h
|
||||
202
src/binder.h
Normal file
202
src/binder.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/****************************************************************************
|
||||
****************************************************************************
|
||||
***
|
||||
*** This header was automatically generated from a Linux kernel header
|
||||
*** of the same name, to make information necessary for userspace to
|
||||
*** call into the kernel available to libc. It contains only constants,
|
||||
*** structures, and macros generated from the original header, and thus,
|
||||
*** contains no copyrightable information.
|
||||
***
|
||||
*** To edit the content of this header, modify the corresponding
|
||||
*** source file (e.g. under external/kernel-headers/original/) then
|
||||
*** run bionic/libc/kernel/tools/update_all.py
|
||||
***
|
||||
*** Any manual change here will be lost the next time this script will
|
||||
*** be run. You've been warned!
|
||||
***
|
||||
****************************************************************************
|
||||
****************************************************************************/
|
||||
#ifndef _UAPI_LINUX_BINDER_H
|
||||
#define _UAPI_LINUX_BINDER_H
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
#define B_PACK_CHARS(c1,c2,c3,c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4))
|
||||
#define B_TYPE_LARGE 0x85
|
||||
enum {
|
||||
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE),
|
||||
BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
|
||||
};
|
||||
enum {
|
||||
FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
|
||||
FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
|
||||
};
|
||||
#ifdef BINDER_IPC_32BIT
|
||||
typedef __u32 binder_size_t;
|
||||
typedef __u32 binder_uintptr_t;
|
||||
#else
|
||||
typedef __u64 binder_size_t;
|
||||
typedef __u64 binder_uintptr_t;
|
||||
#endif
|
||||
struct binder_object_header {
|
||||
__u32 type;
|
||||
};
|
||||
struct flat_binder_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 flags;
|
||||
union {
|
||||
binder_uintptr_t binder;
|
||||
__u32 handle;
|
||||
};
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
struct binder_fd_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 pad_flags;
|
||||
union {
|
||||
binder_uintptr_t pad_binder;
|
||||
__u32 fd;
|
||||
};
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
struct binder_buffer_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 flags;
|
||||
binder_uintptr_t buffer;
|
||||
binder_size_t length;
|
||||
binder_size_t parent;
|
||||
binder_size_t parent_offset;
|
||||
};
|
||||
enum {
|
||||
BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
|
||||
};
|
||||
struct binder_fd_array_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 pad;
|
||||
binder_size_t num_fds;
|
||||
binder_size_t parent;
|
||||
binder_size_t parent_offset;
|
||||
};
|
||||
struct binder_write_read {
|
||||
binder_size_t write_size;
|
||||
binder_size_t write_consumed;
|
||||
binder_uintptr_t write_buffer;
|
||||
binder_size_t read_size;
|
||||
binder_size_t read_consumed;
|
||||
binder_uintptr_t read_buffer;
|
||||
};
|
||||
struct binder_version {
|
||||
__s32 protocol_version;
|
||||
};
|
||||
#ifdef BINDER_IPC_32BIT
|
||||
#define BINDER_CURRENT_PROTOCOL_VERSION 7
|
||||
#else
|
||||
#define BINDER_CURRENT_PROTOCOL_VERSION 8
|
||||
#endif
|
||||
struct binder_node_debug_info {
|
||||
binder_uintptr_t ptr;
|
||||
binder_uintptr_t cookie;
|
||||
__u32 has_strong_ref;
|
||||
__u32 has_weak_ref;
|
||||
};
|
||||
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
|
||||
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
|
||||
#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
|
||||
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32)
|
||||
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32)
|
||||
#define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
|
||||
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
|
||||
#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
|
||||
enum transaction_flags {
|
||||
TF_ONE_WAY = 0x01,
|
||||
TF_ROOT_OBJECT = 0x04,
|
||||
TF_STATUS_CODE = 0x08,
|
||||
TF_ACCEPT_FDS = 0x10,
|
||||
};
|
||||
struct binder_transaction_data {
|
||||
union {
|
||||
__u32 handle;
|
||||
binder_uintptr_t ptr;
|
||||
} target;
|
||||
binder_uintptr_t cookie;
|
||||
__u32 code;
|
||||
__u32 flags;
|
||||
pid_t sender_pid;
|
||||
uid_t sender_euid;
|
||||
binder_size_t data_size;
|
||||
binder_size_t offsets_size;
|
||||
union {
|
||||
struct {
|
||||
binder_uintptr_t buffer;
|
||||
binder_uintptr_t offsets;
|
||||
} ptr;
|
||||
__u8 buf[8];
|
||||
} data;
|
||||
};
|
||||
struct binder_transaction_data_sg {
|
||||
struct binder_transaction_data transaction_data;
|
||||
binder_size_t buffers_size;
|
||||
};
|
||||
struct binder_ptr_cookie {
|
||||
binder_uintptr_t ptr;
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
struct binder_handle_cookie {
|
||||
__u32 handle;
|
||||
binder_uintptr_t cookie;
|
||||
} __attribute__((packed));
|
||||
struct binder_pri_desc {
|
||||
__s32 priority;
|
||||
__u32 desc;
|
||||
};
|
||||
struct binder_pri_ptr_cookie {
|
||||
__s32 priority;
|
||||
binder_uintptr_t ptr;
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
enum binder_driver_return_protocol {
|
||||
BR_ERROR = _IOR('r', 0, __s32),
|
||||
BR_OK = _IO('r', 1),
|
||||
BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
|
||||
BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
|
||||
BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
|
||||
BR_DEAD_REPLY = _IO('r', 5),
|
||||
BR_TRANSACTION_COMPLETE = _IO('r', 6),
|
||||
BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
|
||||
BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
|
||||
BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
|
||||
BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
|
||||
BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
|
||||
BR_NOOP = _IO('r', 12),
|
||||
BR_SPAWN_LOOPER = _IO('r', 13),
|
||||
BR_FINISHED = _IO('r', 14),
|
||||
BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
|
||||
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
|
||||
BR_FAILED_REPLY = _IO('r', 17),
|
||||
};
|
||||
enum binder_driver_command_protocol {
|
||||
BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
|
||||
BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
|
||||
BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
|
||||
BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
|
||||
BC_INCREFS = _IOW('c', 4, __u32),
|
||||
BC_ACQUIRE = _IOW('c', 5, __u32),
|
||||
BC_RELEASE = _IOW('c', 6, __u32),
|
||||
BC_DECREFS = _IOW('c', 7, __u32),
|
||||
BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
|
||||
BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
|
||||
BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
|
||||
BC_REGISTER_LOOPER = _IO('c', 11),
|
||||
BC_ENTER_LOOPER = _IO('c', 12),
|
||||
BC_EXIT_LOOPER = _IO('c', 13),
|
||||
BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie),
|
||||
BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie),
|
||||
BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
|
||||
BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
|
||||
BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
|
||||
};
|
||||
#endif
|
||||
182
src/gbinder_buffer.c
Normal file
182
src/gbinder_buffer.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
typedef struct gbinder_buffer_memory {
|
||||
gint refcount;
|
||||
void* buffer;
|
||||
gsize size;
|
||||
GBinderDriver* driver;
|
||||
} GBinderBufferMemory;
|
||||
|
||||
typedef struct gbinder_buffer_priv {
|
||||
GBinderBuffer pub;
|
||||
GBinderBufferMemory* memory;
|
||||
} GBinderBufferPriv;
|
||||
|
||||
static inline GBinderBufferPriv* gbinder_buffer_cast(GBinderBuffer* buf)
|
||||
{ return G_CAST(buf, GBinderBufferPriv, pub); }
|
||||
|
||||
/*==========================================================================*
|
||||
* GBinderBufferMemory
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
GBinderBufferMemory*
|
||||
gbinder_buffer_memory_new(
|
||||
GBinderDriver* driver,
|
||||
void* buffer,
|
||||
gsize size)
|
||||
{
|
||||
GBinderBufferMemory* self = g_slice_new0(GBinderBufferMemory);
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
self->buffer = buffer;
|
||||
self->size = size;
|
||||
self->driver = gbinder_driver_ref(driver);
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_buffer_memory_free(
|
||||
GBinderBufferMemory* self)
|
||||
{
|
||||
gbinder_driver_free_buffer(self->driver, self->buffer);
|
||||
gbinder_driver_unref(self->driver);
|
||||
g_slice_free(GBinderBufferMemory, self);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderBufferMemory*
|
||||
gbinder_buffer_memory_ref(
|
||||
GBinderBufferMemory* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
g_atomic_int_inc(&self->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_buffer_memory_unref(
|
||||
GBinderBufferMemory* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->refcount)) {
|
||||
gbinder_buffer_memory_free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* GBinderBuffer
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
GBinderBuffer*
|
||||
gbinder_buffer_alloc(
|
||||
GBinderBufferMemory* memory,
|
||||
void* data,
|
||||
gsize size)
|
||||
{
|
||||
GBinderBufferPriv* priv = g_slice_new0(GBinderBufferPriv);
|
||||
GBinderBuffer* self = &priv->pub;
|
||||
|
||||
priv->memory = memory;
|
||||
self->data = data;
|
||||
self->size = size;
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_buffer_free(
|
||||
GBinderBuffer* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderBufferPriv* priv = gbinder_buffer_cast(self);
|
||||
|
||||
gbinder_buffer_memory_unref(priv->memory);
|
||||
g_slice_free(GBinderBufferPriv, priv);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderBuffer*
|
||||
gbinder_buffer_new(
|
||||
GBinderDriver* driver,
|
||||
void* data,
|
||||
gsize size)
|
||||
{
|
||||
return gbinder_buffer_alloc((driver && data) ?
|
||||
gbinder_buffer_memory_new(driver, data, size) : NULL, data, size);
|
||||
}
|
||||
|
||||
GBinderBuffer*
|
||||
gbinder_buffer_new_with_parent(
|
||||
GBinderBuffer* parent,
|
||||
void* data,
|
||||
gsize size)
|
||||
{
|
||||
return gbinder_buffer_alloc(parent ?
|
||||
gbinder_buffer_memory_ref(gbinder_buffer_cast(parent)->memory) : NULL,
|
||||
data, size);
|
||||
}
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_buffer_driver(
|
||||
GBinderBuffer* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderBufferPriv* priv = gbinder_buffer_cast(self);
|
||||
|
||||
if (priv->memory) {
|
||||
return priv->memory->driver;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
67
src/gbinder_buffer_p.h
Normal file
67
src/gbinder_buffer_p.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_BUFFER_PRIVATE_H
|
||||
#define GBINDER_BUFFER_PRIVATE_H
|
||||
|
||||
#include <gbinder_buffer.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
GBinderBuffer*
|
||||
gbinder_buffer_new(
|
||||
GBinderDriver* driver,
|
||||
void* data,
|
||||
gsize size);
|
||||
|
||||
GBinderBuffer*
|
||||
gbinder_buffer_new_with_parent(
|
||||
GBinderBuffer* parent,
|
||||
void* data,
|
||||
gsize size);
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_buffer_driver(
|
||||
GBinderBuffer* buf);
|
||||
|
||||
#define gbinder_buffer_io(buf) \
|
||||
gbinder_driver_io(gbinder_buffer_driver(buf))
|
||||
|
||||
#endif /* GBINDER_BUFFER_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
97
src/gbinder_cleanup.c
Normal file
97
src/gbinder_cleanup.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_cleanup.h"
|
||||
|
||||
typedef struct gbinder_cleanup_item {
|
||||
GDestroyNotify destroy;
|
||||
gpointer pointer;
|
||||
} GBinderCleanupItem;
|
||||
|
||||
/*
|
||||
* This is basically a GArray providing better type safety at compile time.
|
||||
*/
|
||||
struct gbinder_cleanup {
|
||||
GBinderCleanupItem* items;
|
||||
guint count;
|
||||
};
|
||||
|
||||
G_STATIC_ASSERT(sizeof(GBinderCleanup) == sizeof(GArray));
|
||||
#define ELEMENT_SIZE (sizeof(GBinderCleanupItem))
|
||||
|
||||
static
|
||||
GBinderCleanup*
|
||||
gbinder_cleanup_new()
|
||||
{
|
||||
return (GBinderCleanup*)g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 0);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_cleanup_free(
|
||||
GBinderCleanup* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < self->count; i++) {
|
||||
self->items[i].destroy(self->items[i].pointer);
|
||||
}
|
||||
g_array_free((GArray*)self, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderCleanup*
|
||||
gbinder_cleanup_add(
|
||||
GBinderCleanup* self,
|
||||
GDestroyNotify destroy,
|
||||
gpointer pointer)
|
||||
{
|
||||
if (G_LIKELY(destroy)) {
|
||||
GBinderCleanupItem item;
|
||||
|
||||
item.destroy = destroy;
|
||||
item.pointer = pointer;
|
||||
if (!self) {
|
||||
self = gbinder_cleanup_new();
|
||||
}
|
||||
g_array_append_vals((GArray*)self, (void*)&item, 1);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
56
src/gbinder_cleanup.h
Normal file
56
src/gbinder_cleanup.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_CLEANUP_H
|
||||
#define GBINDER_CLEANUP_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
void
|
||||
gbinder_cleanup_free(
|
||||
GBinderCleanup* cleanup);
|
||||
|
||||
GBinderCleanup*
|
||||
gbinder_cleanup_add(
|
||||
GBinderCleanup* cleanup,
|
||||
GDestroyNotify destroy,
|
||||
gpointer pointer);
|
||||
|
||||
#endif /* GBINDER_CLEANUP_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
271
src/gbinder_client.c
Normal file
271
src/gbinder_client.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_client_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct gbinder_client_priv {
|
||||
GBinderClient pub;
|
||||
guint32 refcount;
|
||||
char* iface;
|
||||
GBytes* rpc_header;
|
||||
GBinderLocalRequest* basic_req;
|
||||
} GBinderClientPriv;
|
||||
|
||||
typedef struct gbinder_client_tx {
|
||||
GBinderClient* client;
|
||||
GBinderClientReplyFunc reply;
|
||||
GDestroyNotify destroy;
|
||||
void* user_data;
|
||||
} GBinderClientTx;
|
||||
|
||||
static inline GBinderClientPriv* gbinder_client_cast(GBinderClient* client)
|
||||
{ return G_CAST(client, GBinderClientPriv, pub); }
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_client_free(
|
||||
GBinderClientPriv* priv)
|
||||
{
|
||||
GBinderClient* self = &priv->pub;
|
||||
|
||||
gbinder_remote_object_unref(self->remote);
|
||||
gbinder_local_request_unref(priv->basic_req);
|
||||
g_free(priv->iface);
|
||||
g_bytes_unref(priv->rpc_header);
|
||||
g_slice_free(GBinderClientPriv, priv);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_client_transact_reply(
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* data)
|
||||
{
|
||||
GBinderClientTx* tx = data;
|
||||
|
||||
if (tx->reply) {
|
||||
tx->reply(tx->client, reply, status, tx->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_client_transact_destroy(
|
||||
gpointer data)
|
||||
{
|
||||
GBinderClientTx* tx = data;
|
||||
|
||||
if (tx->destroy) {
|
||||
tx->destroy(tx->user_data);
|
||||
}
|
||||
gbinder_client_unref(tx->client);
|
||||
g_slice_free(GBinderClientTx, tx);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_new(
|
||||
GBinderRemoteObject* remote,
|
||||
const char* iface)
|
||||
{
|
||||
if (G_LIKELY(remote) && G_LIKELY(iface)) {
|
||||
GBinderClientPriv* priv = g_slice_new0(GBinderClientPriv);
|
||||
GBinderClient* self = &priv->pub;
|
||||
GBinderIpc* ipc = remote->ipc;
|
||||
GBinderOutputData* hdr;
|
||||
|
||||
g_atomic_int_set(&priv->refcount, 1);
|
||||
|
||||
/*
|
||||
* Generate basic request (without additional parameters) and pull
|
||||
* header data out of it. The basic request can be reused for those
|
||||
* transactions which has no additional parameters. The header data
|
||||
* are needed for building non-trivial requests.
|
||||
*/
|
||||
priv->basic_req = gbinder_driver_local_request_new(ipc->driver, iface);
|
||||
hdr = gbinder_local_request_data(priv->basic_req);
|
||||
priv->rpc_header = g_bytes_new(hdr->bytes->data, hdr->bytes->len);
|
||||
|
||||
self->remote = gbinder_remote_object_ref(remote);
|
||||
self->iface = priv->iface = g_strdup(iface);
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderClient*
|
||||
gbinder_client_ref(
|
||||
GBinderClient* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderClientPriv* priv = gbinder_client_cast(self);
|
||||
|
||||
GASSERT(priv->refcount > 0);
|
||||
g_atomic_int_inc(&priv->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_client_unref(
|
||||
GBinderClient* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderClientPriv* priv = gbinder_client_cast(self);
|
||||
|
||||
GASSERT(priv->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&priv->refcount)) {
|
||||
gbinder_client_free(priv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_client_new_request(
|
||||
GBinderClient* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderClientPriv* priv = gbinder_client_cast(self);
|
||||
const GBinderIo* io = gbinder_driver_io(self->remote->ipc->driver);
|
||||
return gbinder_local_request_new(io, priv->rpc_header);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_client_transact_sync_reply(
|
||||
GBinderClient* self,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
int* status)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
|
||||
if (!req) {
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
req = gbinder_client_cast(self)->basic_req;
|
||||
}
|
||||
return gbinder_ipc_transact_sync_reply(obj->ipc, obj->handle,
|
||||
code, req, status);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_client_transact_sync_oneway(
|
||||
GBinderClient* self,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
|
||||
if (!req) {
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
req = gbinder_client_cast(self)->basic_req;
|
||||
}
|
||||
return gbinder_ipc_transact_sync_oneway(obj->ipc, obj->handle,
|
||||
code, req);
|
||||
} else {
|
||||
return (-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_client_transact(
|
||||
GBinderClient* self,
|
||||
guint32 code,
|
||||
guint32 flags,
|
||||
GBinderLocalRequest* req,
|
||||
GBinderClientReplyFunc reply,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderRemoteObject* obj = self->remote;
|
||||
GBinderClientTx* tx = g_slice_new0(GBinderClientTx);
|
||||
|
||||
tx->client = gbinder_client_ref(self);
|
||||
tx->reply = reply;
|
||||
tx->destroy = destroy;
|
||||
tx->user_data = user_data;
|
||||
|
||||
if (!req) {
|
||||
/* Default empty request (just the header, no parameters) */
|
||||
req = gbinder_client_cast(self)->basic_req;
|
||||
}
|
||||
|
||||
return gbinder_ipc_transact(obj->ipc, obj->handle, code, flags, req,
|
||||
gbinder_client_transact_reply, gbinder_client_transact_destroy, tx);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_client_cancel(
|
||||
GBinderClient* self,
|
||||
gulong id)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_ipc_cancel(gbinder_client_ipc(self), id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
55
src/gbinder_client_p.h
Normal file
55
src/gbinder_client_p.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_CLIENT_PRIVATE_H
|
||||
#define GBINDER_CLIENT_PRIVATE_H
|
||||
|
||||
#include <gbinder_client.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
struct gbinder_client {
|
||||
const char* iface;
|
||||
GBinderRemoteObject* remote;
|
||||
};
|
||||
|
||||
#define gbinder_client_ipc(client) ((client)->remote->ipc)
|
||||
|
||||
#endif /* GBINDER_CLIENT_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
180
src/gbinder_defaultservicemanager.c
Normal file
180
src/gbinder_defaultservicemanager.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_servicemanager_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef GBinderServiceManager GBinderDefaultServiceManager;
|
||||
typedef GBinderServiceManagerClass GBinderDefaultServiceManagerClass;
|
||||
|
||||
G_DEFINE_TYPE(GBinderDefaultServiceManager,
|
||||
gbinder_defaultservicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
enum gbinder_defaultservicemanager_calls {
|
||||
GET_SERVICE_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
CHECK_SERVICE_TRANSACTION,
|
||||
ADD_SERVICE_TRANSACTION,
|
||||
LIST_SERVICES_TRANSACTION
|
||||
};
|
||||
|
||||
/* As a special case, ServiceManager's handle is zero */
|
||||
#define DEFAULTSERVICEMANAGER_HANDLE (0)
|
||||
#define DEFAULTSERVICEMANAGER_IFACE "android.os.IServiceManager"
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_defaultservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_defaultservicemanager_get_type(), dev);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalRequest*
|
||||
gbinder_servicemanager_list_services_req(
|
||||
GBinderServiceManager* self,
|
||||
gint32 index)
|
||||
{
|
||||
return gbinder_local_request_append_int32
|
||||
(gbinder_client_new_request(self->client), index);
|
||||
}
|
||||
|
||||
static
|
||||
char**
|
||||
gbinder_defaultservicemanager_list(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
GBinderLocalRequest* req = gbinder_servicemanager_list_services_req(self,0);
|
||||
GBinderRemoteReply* reply;
|
||||
|
||||
while ((reply = gbinder_client_transact_sync_reply(self->client,
|
||||
LIST_SERVICES_TRANSACTION, req, NULL)) != NULL) {
|
||||
char* service = gbinder_remote_reply_read_string16(reply);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
if (service) {
|
||||
g_ptr_array_add(list, service);
|
||||
gbinder_local_request_unref(req);
|
||||
req = gbinder_servicemanager_list_services_req(self, list->len);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
g_ptr_array_add(list, NULL);
|
||||
return (char**)g_ptr_array_free(list, FALSE);
|
||||
}
|
||||
|
||||
static
|
||||
GBinderRemoteObject*
|
||||
gbinder_defaultservicemanager_get_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
int* status)
|
||||
{
|
||||
GBinderRemoteObject* obj;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
CHECK_SERVICE_TRANSACTION, req, status);
|
||||
|
||||
obj = gbinder_remote_reply_read_object(reply);
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
gbinder_defaultservicemanager_add_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
int status;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
|
||||
gbinder_local_request_append_string16(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
gbinder_local_request_append_int32(req, 0);
|
||||
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
ADD_SERVICE_TRANSACTION, req, &status);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_init(
|
||||
GBinderDefaultServiceManager* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_defaultservicemanager_class_init(
|
||||
GBinderDefaultServiceManagerClass* klass)
|
||||
{
|
||||
klass->handle = DEFAULTSERVICEMANAGER_HANDLE;
|
||||
klass->iface = DEFAULTSERVICEMANAGER_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_BINDER;
|
||||
|
||||
klass->list = gbinder_defaultservicemanager_list;
|
||||
klass->get_service = gbinder_defaultservicemanager_get_service;
|
||||
klass->add_service = gbinder_defaultservicemanager_add_service;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
1029
src/gbinder_driver.c
Normal file
1029
src/gbinder_driver.c
Normal file
File diff suppressed because it is too large
Load Diff
140
src/gbinder_driver.h
Normal file
140
src/gbinder_driver.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_DRIVER_H
|
||||
#define GBINDER_DRIVER_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
struct pollfd;
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_driver_new(
|
||||
const char* dev);
|
||||
|
||||
GBinderDriver*
|
||||
gbinder_driver_ref(
|
||||
GBinderDriver* driver);
|
||||
|
||||
void
|
||||
gbinder_driver_unref(
|
||||
GBinderDriver* driver);
|
||||
|
||||
int
|
||||
gbinder_driver_fd(
|
||||
GBinderDriver* driver);
|
||||
|
||||
int
|
||||
gbinder_driver_poll(
|
||||
GBinderDriver* driver,
|
||||
struct pollfd* pollfd);
|
||||
|
||||
const char*
|
||||
gbinder_driver_dev(
|
||||
GBinderDriver* driver);
|
||||
|
||||
const GBinderIo*
|
||||
gbinder_driver_io(
|
||||
GBinderDriver* driver);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_request_death_notification(
|
||||
GBinderDriver* driver,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_clear_death_notification(
|
||||
GBinderDriver* driver,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_increfs(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_decrefs(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_acquire(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_release(
|
||||
GBinderDriver* driver,
|
||||
guint32 handle);
|
||||
|
||||
void
|
||||
gbinder_driver_free_buffer(
|
||||
GBinderDriver* driver,
|
||||
void* buffer);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_enter_looper(
|
||||
GBinderDriver* driver);
|
||||
|
||||
gboolean
|
||||
gbinder_driver_exit_looper(
|
||||
GBinderDriver* driver);
|
||||
|
||||
int
|
||||
gbinder_driver_read(
|
||||
GBinderDriver* driver,
|
||||
GBinderObjectRegistry* reg,
|
||||
GBinderHandler* handler);
|
||||
|
||||
int
|
||||
gbinder_driver_transact(
|
||||
GBinderDriver* driver,
|
||||
GBinderObjectRegistry* reg,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* request,
|
||||
GBinderRemoteReply* reply);
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_driver_local_request_new(
|
||||
GBinderDriver* self,
|
||||
const char* iface);
|
||||
|
||||
#endif /* GBINDER_DRIVER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
72
src/gbinder_handler.h
Normal file
72
src/gbinder_handler.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_HANDLER_H
|
||||
#define GBINDER_HANDLER_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef struct gbinder_handler_functions {
|
||||
GBinderLocalReply* (*transact)(GBinderHandler* handler,
|
||||
GBinderLocalObject* obj, GBinderRemoteRequest* req, guint code,
|
||||
guint flags, int* status);
|
||||
} GBinderHandlerFunctions;
|
||||
|
||||
struct gbinder_handler {
|
||||
const GBinderHandlerFunctions* f;
|
||||
};
|
||||
|
||||
/* Inline wrappers */
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderLocalReply*
|
||||
gbinder_handler_transact(
|
||||
GBinderHandler* self,
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
return self ? self->f->transact(self, obj, req, code, flags, status) :
|
||||
NULL;
|
||||
}
|
||||
|
||||
#endif /* GBINDER_HANDLER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
199
src/gbinder_hwservicemanager.c
Normal file
199
src/gbinder_hwservicemanager.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_servicemanager_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
#include <gbinder_local_request.h>
|
||||
#include <gbinder_remote_reply.h>
|
||||
#include <gbinder_reader.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef GBinderServiceManager GBinderHwServiceManager;
|
||||
typedef GBinderServiceManagerClass GBinderHwServiceManagerClass;
|
||||
|
||||
G_DEFINE_TYPE(GBinderHwServiceManager,
|
||||
gbinder_hwservicemanager,
|
||||
GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
enum gbinder_hwservicemanager_calls {
|
||||
GET_TRANSACTION = GBINDER_FIRST_CALL_TRANSACTION,
|
||||
ADD_TRANSACTION,
|
||||
GET_TRANSPORT_TRANSACTION,
|
||||
LIST_TRANSACTION,
|
||||
LIST_BY_INTERFACE_TRANSACTION,
|
||||
REGISTER_FOR_NOTIFICATIONS_TRANSACTION,
|
||||
DEBUG_DUMP_TRANSACTION,
|
||||
REGISTER_PASSTHROUGH_CLIENT_TRANSACTION
|
||||
};
|
||||
|
||||
/* As a special case, ServiceManager's handle is zero */
|
||||
#define HWSERVICEMANAGER_HANDLE (0)
|
||||
#define HWSERVICEMANAGER_IFACE "android.hidl.manager@1.0::IServiceManager"
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_hwservicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
return gbinder_servicemanager_new_with_type
|
||||
(gbinder_hwservicemanager_get_type(), dev);
|
||||
}
|
||||
|
||||
static
|
||||
char**
|
||||
gbinder_hwservicemanager_list(
|
||||
GBinderHwServiceManager* self)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
GBinderRemoteReply* reply = gbinder_client_transact_sync_reply
|
||||
(self->client, LIST_TRANSACTION, req, NULL);
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
if (reply) {
|
||||
GBinderReader reader;
|
||||
char** result = NULL;
|
||||
int status = -1;
|
||||
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
|
||||
/* Read status */
|
||||
GVERIFY(gbinder_reader_read_int32(&reader, &status));
|
||||
GASSERT(status == GBINDER_STATUS_OK);
|
||||
|
||||
/* Followed by hidl_vec<string> */
|
||||
result = gbinder_reader_read_hidl_string_vec(&reader);
|
||||
gbinder_remote_reply_unref(reply);
|
||||
return result;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderRemoteObject*
|
||||
gbinder_hwservicemanager_get_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* fqinstance,
|
||||
int* status)
|
||||
{
|
||||
/* e.g. "android.hardware.radio@1.1::IRadio/slot1" */
|
||||
const char* sep = strchr(fqinstance, '/');
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
if (sep) {
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
char* fqname = g_strndup(fqinstance, sep - fqinstance);
|
||||
const char* name = sep + 1;
|
||||
|
||||
gbinder_local_request_append_hidl_string(req, fqname);
|
||||
gbinder_local_request_append_hidl_string(req, name);
|
||||
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
GET_TRANSACTION, req, status);
|
||||
|
||||
if (reply) {
|
||||
GBinderReader reader;
|
||||
int status = -1;
|
||||
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
|
||||
/* Read status */
|
||||
GVERIFY(gbinder_reader_read_int32(&reader, &status));
|
||||
GASSERT(status == GBINDER_STATUS_OK);
|
||||
|
||||
/* Read the object */
|
||||
obj = gbinder_reader_read_object(&reader);
|
||||
gbinder_remote_reply_unref(reply);
|
||||
}
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
g_free(fqname);
|
||||
} else {
|
||||
GERR("Invalid instance \"%s\"", fqinstance);
|
||||
if (status) *status = (-EINVAL);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
gbinder_hwservicemanager_add_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
int status;
|
||||
GBinderRemoteReply* reply;
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(self->client);
|
||||
|
||||
/* add(string name, interface service) generates (bool success); */
|
||||
gbinder_local_request_append_hidl_string(req, name);
|
||||
gbinder_local_request_append_local_object(req, obj);
|
||||
|
||||
reply = gbinder_client_transact_sync_reply(self->client,
|
||||
ADD_TRANSACTION, req, &status);
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
gbinder_local_request_unref(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_init(
|
||||
GBinderHwServiceManager* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_hwservicemanager_class_init(
|
||||
GBinderHwServiceManagerClass* klass)
|
||||
{
|
||||
klass->handle = HWSERVICEMANAGER_HANDLE;
|
||||
klass->iface = HWSERVICEMANAGER_IFACE;
|
||||
klass->default_device = GBINDER_DEFAULT_HWBINDER;
|
||||
|
||||
klass->list = gbinder_hwservicemanager_list;
|
||||
klass->get_service = gbinder_hwservicemanager_get_service;
|
||||
klass->add_service = gbinder_hwservicemanager_add_service;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
486
src/gbinder_io.c
Normal file
486
src/gbinder_io.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_io.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_writer.h"
|
||||
#include "gbinder_system.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include "binder.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* This file is included from gbinder_io_32.c and gbinder_io_64.c to
|
||||
* generate the code for different ioctl codes and structure sizes.
|
||||
*/
|
||||
|
||||
#define GBINDER_POINTER_SIZE sizeof(binder_uintptr_t)
|
||||
|
||||
#define GBINDER_IO_FN__(prefix,suffix) prefix##_##suffix
|
||||
#define GBINDER_IO_FN_(prefix,suffix) GBINDER_IO_FN__(prefix,suffix)
|
||||
#define GBINDER_IO_FN(fn) GBINDER_IO_FN_(GBINDER_IO_PREFIX,fn)
|
||||
|
||||
static
|
||||
int
|
||||
GBINDER_IO_FN(write_read)(
|
||||
int fd,
|
||||
GBinderIoBuf* write,
|
||||
GBinderIoBuf* read)
|
||||
{
|
||||
int ret;
|
||||
struct binder_write_read bwr;
|
||||
|
||||
memset(&bwr, 0, sizeof(bwr));
|
||||
if (write) {
|
||||
bwr.write_buffer = write->ptr + write->consumed;
|
||||
bwr.write_size = write->size - write->consumed;
|
||||
}
|
||||
if (read) {
|
||||
bwr.read_buffer = read->ptr + read->consumed;
|
||||
bwr.read_size = read->size - read->consumed;
|
||||
}
|
||||
ret = gbinder_system_ioctl(fd, BINDER_WRITE_READ, &bwr);
|
||||
if (ret >= 0) {
|
||||
if (write) {
|
||||
write->consumed += bwr.write_consumed;
|
||||
}
|
||||
if (read) {
|
||||
read->consumed += bwr.read_consumed;
|
||||
}
|
||||
} else {
|
||||
GERR("binder_write_read: %s", strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Writes pointer to the buffer */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_pointer)(
|
||||
void* out,
|
||||
const void* pointer)
|
||||
{
|
||||
binder_uintptr_t* dest = out;
|
||||
|
||||
*dest = (uintptr_t)pointer;
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Encodes flat_buffer_object */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_local_object)(
|
||||
void* out,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
struct flat_binder_object* dest = out;
|
||||
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
dest->hdr.type = BINDER_TYPE_BINDER;
|
||||
dest->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->binder = (uintptr_t)obj;
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_remote_object)(
|
||||
void* out,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
struct flat_binder_object* dest = out;
|
||||
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
if (obj) {
|
||||
dest->hdr.type = BINDER_TYPE_HANDLE;
|
||||
dest->flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
|
||||
dest->handle = obj->handle;
|
||||
} else {
|
||||
dest->hdr.type = BINDER_TYPE_BINDER;
|
||||
}
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Encodes binder_buffer_object */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_buffer_object)(
|
||||
void* out,
|
||||
const void* data,
|
||||
gsize size,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
struct binder_buffer_object* dest = out;
|
||||
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
dest->hdr.type = BINDER_TYPE_PTR;
|
||||
dest->buffer = (uintptr_t)data;
|
||||
dest->length = size;
|
||||
if (parent) {
|
||||
dest->flags |= BINDER_BUFFER_FLAG_HAS_PARENT;
|
||||
dest->parent = parent->index;
|
||||
dest->parent_offset = parent->offset;
|
||||
}
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_death_notification)(
|
||||
void* out,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
struct binder_handle_cookie* dest = out;
|
||||
|
||||
/* We find the object by handle, so we use handle as a cookie */
|
||||
dest->handle = obj->handle;
|
||||
dest->cookie = obj->handle;
|
||||
return sizeof(*dest);
|
||||
}
|
||||
|
||||
/* Encodes BC_TRANSACTION data */
|
||||
static
|
||||
void
|
||||
GBINDER_IO_FN(fill_transaction_data)(
|
||||
struct binder_transaction_data* tr,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* payload,
|
||||
guint flags,
|
||||
GUtilIntArray* offsets,
|
||||
void** offsets_buf)
|
||||
{
|
||||
memset(tr, 0, sizeof(*tr));
|
||||
tr->target.handle = handle;
|
||||
tr->code = code;
|
||||
tr->data_size = payload->len;
|
||||
tr->data.ptr.buffer = (uintptr_t)payload->data;
|
||||
if (flags & GBINDER_TX_FLAG_ONEWAY) {
|
||||
tr->flags |= TF_ONE_WAY;
|
||||
}
|
||||
if (offsets && offsets->count) {
|
||||
guint i;
|
||||
binder_size_t* tx_offsets = g_new(binder_size_t, offsets->count);
|
||||
|
||||
tr->offsets_size = offsets->count * sizeof(binder_size_t);
|
||||
tr->data.ptr.offsets = (uintptr_t)tx_offsets;
|
||||
for (i = 0; i < offsets->count; i++) {
|
||||
tx_offsets[i] = offsets->data[i];
|
||||
}
|
||||
*offsets_buf = tx_offsets;
|
||||
} else {
|
||||
*offsets_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_transaction)(
|
||||
void* out,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* payload,
|
||||
guint flags,
|
||||
GUtilIntArray* offsets,
|
||||
void** offsets_buf)
|
||||
{
|
||||
struct binder_transaction_data* tr = out;
|
||||
|
||||
GBINDER_IO_FN(fill_transaction_data)(tr, handle, code, payload, flags,
|
||||
offsets, offsets_buf);
|
||||
return sizeof(*tr);
|
||||
}
|
||||
|
||||
/* Encodes BC_TRANSACTION_SG data */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_transaction_sg)(
|
||||
void* out,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* payload,
|
||||
guint flags,
|
||||
GUtilIntArray* offsets,
|
||||
void** offsets_buf,
|
||||
gsize buffers_size)
|
||||
{
|
||||
struct binder_transaction_data_sg* sg = out;
|
||||
|
||||
GBINDER_IO_FN(fill_transaction_data)(&sg->transaction_data, handle, code,
|
||||
payload, flags, offsets, offsets_buf);
|
||||
/* The driver seems to require buffers to be 8-byte aligned */
|
||||
sg->buffers_size = G_ALIGN8(buffers_size);
|
||||
return sizeof(*sg);
|
||||
}
|
||||
|
||||
/* Encode BC_REPLY */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(encode_status_reply)(
|
||||
void* out,
|
||||
gint32* status)
|
||||
{
|
||||
struct binder_transaction_data* tr = out;
|
||||
|
||||
memset(tr, 0, sizeof(*tr));
|
||||
tr->flags = TF_STATUS_CODE;
|
||||
tr->data_size = sizeof(*status);
|
||||
tr->data.ptr.buffer = (uintptr_t)status;
|
||||
return sizeof(*tr);
|
||||
}
|
||||
|
||||
/* Decode BR_REPLY and BR_TRANSACTION */
|
||||
static
|
||||
void
|
||||
GBINDER_IO_FN(decode_transaction_data)(
|
||||
const void* data,
|
||||
GBinderIoTxData* tx)
|
||||
{
|
||||
const struct binder_transaction_data* tr = data;
|
||||
|
||||
tx->objects = NULL;
|
||||
tx->code = tr->code;
|
||||
tx->flags = 0;
|
||||
tx->target = (void*)(uintptr_t)tr->target.ptr;
|
||||
tx->data = (void*)(uintptr_t)tr->data.ptr.buffer;
|
||||
if (tr->flags & TF_STATUS_CODE) {
|
||||
GASSERT(tr->data_size == 4);
|
||||
tx->status = *((gint32*)tx->data);
|
||||
tx->size = 0;
|
||||
} else {
|
||||
guint objcount = tr->offsets_size/sizeof(binder_size_t);
|
||||
const binder_size_t* offsets = (void*)(uintptr_t)tr->data.ptr.offsets;
|
||||
|
||||
tx->status = GBINDER_STATUS_OK;
|
||||
tx->size = tr->data_size;
|
||||
if (tr->flags & TF_ONE_WAY) {
|
||||
tx->flags |= GBINDER_TX_FLAG_ONEWAY;
|
||||
}
|
||||
|
||||
if (objcount > 0) {
|
||||
binder_size_t min_offset = 0;
|
||||
guint i;
|
||||
|
||||
/* Validate the offsets */
|
||||
for (i = 0; i < objcount; i++) {
|
||||
if (offsets[i] < min_offset || (offsets[i] +
|
||||
sizeof(struct flat_binder_object)) > tx->size) {
|
||||
GWARN("Invalid offset");
|
||||
objcount = 0;
|
||||
break;
|
||||
}
|
||||
min_offset = offsets[i] + sizeof(struct flat_binder_object);
|
||||
}
|
||||
|
||||
if (objcount > 0) {
|
||||
tx->objects = g_new(void*, objcount + 1);
|
||||
for (i = 0; i < objcount; i++) {
|
||||
tx->objects[i] = (guint8*)tx->data + offsets[i];
|
||||
}
|
||||
tx->objects[objcount] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode binder_uintptr_t */
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(decode_cookie)(
|
||||
const void* data,
|
||||
guint64* cookie)
|
||||
{
|
||||
const binder_uintptr_t* ptr = data;
|
||||
|
||||
if (cookie) *cookie = *ptr;
|
||||
return sizeof(*ptr);
|
||||
}
|
||||
|
||||
/* Decode struct binder_ptr_cookie */
|
||||
static
|
||||
void*
|
||||
GBINDER_IO_FN(decode_binder_ptr_cookie)(
|
||||
const void* data)
|
||||
{
|
||||
const struct binder_ptr_cookie* ptr = data;
|
||||
|
||||
/* We never send cookie and don't expect it back */
|
||||
GASSERT(!ptr->cookie);
|
||||
return (void*)(uintptr_t)ptr->ptr;
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(decode_binder_object)(
|
||||
const void* data,
|
||||
gsize size,
|
||||
GBinderObjectRegistry* reg,
|
||||
GBinderRemoteObject** out)
|
||||
{
|
||||
const struct flat_binder_object* obj = data;
|
||||
|
||||
if (size >= sizeof(*obj)) {
|
||||
switch (obj->hdr.type) {
|
||||
case BINDER_TYPE_HANDLE:
|
||||
if (out) {
|
||||
*out = gbinder_object_registry_get_remote(reg, obj->handle);
|
||||
}
|
||||
return sizeof(*obj);
|
||||
default:
|
||||
GERR("Unsupported binder object type 0x%08x", obj->hdr.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (out) *out = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
GBINDER_IO_FN(decode_buffer_object)(
|
||||
GBinderBuffer* buf,
|
||||
gsize offset,
|
||||
GBinderBuffer** out)
|
||||
{
|
||||
const void* data = (guint8*)buf->data + offset;
|
||||
const gsize size = (offset < buf->size) ? (buf->size - offset) : 0;
|
||||
const struct binder_buffer_object* flat = data;
|
||||
|
||||
if (size >= sizeof(*flat) && flat->hdr.type == BINDER_TYPE_PTR) {
|
||||
if (out) {
|
||||
*out = gbinder_buffer_new_with_parent(buf,
|
||||
(void*)(uintptr_t)flat->buffer, flat->length);
|
||||
}
|
||||
return sizeof(*flat);
|
||||
}
|
||||
if (out) *out = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const GBinderIo GBINDER_IO_PREFIX = {
|
||||
.version = BINDER_CURRENT_PROTOCOL_VERSION,
|
||||
.pointer_size = GBINDER_POINTER_SIZE,
|
||||
|
||||
/* Driver command protocol */
|
||||
.bc = {
|
||||
.transaction = BC_TRANSACTION,
|
||||
.reply = BC_REPLY,
|
||||
.acquire_result = BC_ACQUIRE_RESULT,
|
||||
.free_buffer = BC_FREE_BUFFER,
|
||||
.increfs = BC_INCREFS,
|
||||
.acquire = BC_ACQUIRE,
|
||||
.release = BC_RELEASE,
|
||||
.decrefs = BC_DECREFS,
|
||||
.increfs_done = BC_INCREFS_DONE,
|
||||
.acquire_done = BC_ACQUIRE_DONE,
|
||||
.attempt_acquire = BC_ATTEMPT_ACQUIRE,
|
||||
.register_looper = BC_REGISTER_LOOPER,
|
||||
.enter_looper = BC_ENTER_LOOPER,
|
||||
.exit_looper = BC_EXIT_LOOPER,
|
||||
.request_death_notification = BC_REQUEST_DEATH_NOTIFICATION,
|
||||
.clear_death_notification = BC_CLEAR_DEATH_NOTIFICATION,
|
||||
.dead_binder_done = BC_DEAD_BINDER_DONE,
|
||||
.transaction_sg = BC_TRANSACTION_SG,
|
||||
.reply_sg = BC_REPLY_SG
|
||||
},
|
||||
|
||||
/* Driver return protocol */
|
||||
.br = {
|
||||
.error = BR_ERROR,
|
||||
.ok = BR_OK,
|
||||
.transaction = BR_TRANSACTION,
|
||||
.reply = BR_REPLY,
|
||||
.acquire_result = BR_ACQUIRE_RESULT,
|
||||
.dead_reply = BR_DEAD_REPLY,
|
||||
.transaction_complete = BR_TRANSACTION_COMPLETE,
|
||||
.increfs = BR_INCREFS,
|
||||
.acquire = BR_ACQUIRE,
|
||||
.release = BR_RELEASE,
|
||||
.decrefs = BR_DECREFS,
|
||||
.attempt_acquire = BR_ATTEMPT_ACQUIRE,
|
||||
.noop = BR_NOOP,
|
||||
.spawn_looper = BR_SPAWN_LOOPER,
|
||||
.finished = BR_FINISHED,
|
||||
.dead_binder = BR_DEAD_BINDER,
|
||||
.clear_death_notification_done = BR_CLEAR_DEATH_NOTIFICATION_DONE,
|
||||
.failed_reply = BR_FAILED_REPLY
|
||||
},
|
||||
|
||||
/* Encoders */
|
||||
.encode_pointer = GBINDER_IO_FN(encode_pointer),
|
||||
.encode_local_object = GBINDER_IO_FN(encode_local_object),
|
||||
.encode_remote_object = GBINDER_IO_FN(encode_remote_object),
|
||||
.encode_buffer_object = GBINDER_IO_FN(encode_buffer_object),
|
||||
.encode_death_notification = GBINDER_IO_FN(encode_death_notification),
|
||||
.encode_transaction = GBINDER_IO_FN(encode_transaction),
|
||||
.encode_transaction_sg = GBINDER_IO_FN(encode_transaction_sg),
|
||||
.encode_status_reply = GBINDER_IO_FN(encode_status_reply),
|
||||
|
||||
/* Decoders */
|
||||
.decode_transaction_data = GBINDER_IO_FN(decode_transaction_data),
|
||||
.decode_cookie = GBINDER_IO_FN(decode_cookie),
|
||||
.decode_binder_ptr_cookie = GBINDER_IO_FN(decode_binder_ptr_cookie),
|
||||
.decode_binder_object = GBINDER_IO_FN(decode_binder_object),
|
||||
.decode_buffer_object = GBINDER_IO_FN(decode_buffer_object),
|
||||
|
||||
/* ioctl wrappers */
|
||||
.write_read = GBINDER_IO_FN(write_read)
|
||||
};
|
||||
|
||||
/* Compile time constraints */
|
||||
G_STATIC_ASSERT(GBINDER_POINTER_SIZE <= GBINDER_MAX_POINTER_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct flat_binder_object) <=
|
||||
GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_buffer_object) <=
|
||||
GBINDER_MAX_BUFFER_OBJECT_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_handle_cookie) <=
|
||||
GBINDER_MAX_DEATH_NOTIFICATION_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_transaction_data) <=
|
||||
GBINDER_MAX_BC_TRANSACTION_SIZE);
|
||||
G_STATIC_ASSERT(sizeof(struct binder_transaction_data_sg) <=
|
||||
GBINDER_MAX_BC_TRANSACTION_SG_SIZE);
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
181
src/gbinder_io.h
Normal file
181
src/gbinder_io.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_IO_H
|
||||
#define GBINDER_IO_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct gbinder_io_buf {
|
||||
uintptr_t ptr;
|
||||
gsize size;
|
||||
gsize consumed;
|
||||
} GBinderIoBuf;
|
||||
|
||||
typedef struct gbinder_io_tx_data {
|
||||
int status;
|
||||
guint32 code;
|
||||
guint32 flags; /* GBINDER_TX_FLAG_xxx */
|
||||
void* target;
|
||||
void* data;
|
||||
gsize size;
|
||||
void** objects;
|
||||
} GBinderIoTxData;
|
||||
|
||||
/* Read buffer size (allocated on stack, shouldn't be too large) */
|
||||
#define GBINDER_IO_READ_BUFFER_SIZE (128)
|
||||
|
||||
/*
|
||||
* There are (at least) 2 versions of the binder ioctl API, implemented
|
||||
* 32-bit and 64-bit kernels. The ioctl codes, transaction commands - many
|
||||
* of those are derived from the sizes of the structures being passed
|
||||
* between the driver and the user space client. All these differences
|
||||
* are abstracted away by the GBinderIo interfaces.
|
||||
*
|
||||
* The API version is returned by BINDER_VERSION ioctl which itself doesn't
|
||||
* depend on the API version (it would be very strange if it did).
|
||||
*/
|
||||
|
||||
struct gbinder_io {
|
||||
int version;
|
||||
guint pointer_size;
|
||||
|
||||
/* Driver command protocol */
|
||||
struct gbinder_io_command_codes {
|
||||
guint transaction;
|
||||
guint reply;
|
||||
guint acquire_result;
|
||||
guint free_buffer;
|
||||
guint increfs;
|
||||
guint acquire;
|
||||
guint release;
|
||||
guint decrefs;
|
||||
guint increfs_done;
|
||||
guint acquire_done;
|
||||
guint attempt_acquire;
|
||||
guint register_looper;
|
||||
guint enter_looper;
|
||||
guint exit_looper;
|
||||
guint request_death_notification;
|
||||
guint clear_death_notification;
|
||||
guint dead_binder_done;
|
||||
guint transaction_sg;
|
||||
guint reply_sg;
|
||||
} bc;
|
||||
|
||||
/* Driver return protocol */
|
||||
struct gbinder_io_return_codes {
|
||||
guint error;
|
||||
guint ok;
|
||||
guint transaction;
|
||||
guint reply;
|
||||
guint acquire_result;
|
||||
guint dead_reply;
|
||||
guint transaction_complete;
|
||||
guint increfs;
|
||||
guint acquire;
|
||||
guint release;
|
||||
guint decrefs;
|
||||
guint attempt_acquire;
|
||||
guint noop;
|
||||
guint spawn_looper;
|
||||
guint finished;
|
||||
guint dead_binder;
|
||||
guint clear_death_notification_done;
|
||||
guint failed_reply;
|
||||
} br;
|
||||
|
||||
/* Writes pointer to the buffer. The destination buffer must have
|
||||
* at least GBINDER_IO_MAX_POINTER_SIZE bytes available. The
|
||||
* actual size is returned. */
|
||||
#define GBINDER_MAX_POINTER_SIZE (8)
|
||||
guint (*encode_pointer)(void* out, const void* pointer);
|
||||
|
||||
/* Encode flat_buffer_object */
|
||||
#define GBINDER_MAX_BINDER_OBJECT_SIZE (24)
|
||||
guint (*encode_local_object)(void* out, GBinderLocalObject* obj);
|
||||
guint (*encode_remote_object)(void* out, GBinderRemoteObject* obj);
|
||||
|
||||
/* Encode binder_buffer_object */
|
||||
#define GBINDER_MAX_BUFFER_OBJECT_SIZE (40)
|
||||
guint (*encode_buffer_object)(void* out, const void* data, gsize size,
|
||||
const GBinderParent* parent);
|
||||
|
||||
/* Encode death notification */
|
||||
#define GBINDER_MAX_DEATH_NOTIFICATION_SIZE (12)
|
||||
guint (*encode_death_notification)(void* out, GBinderRemoteObject* obj);
|
||||
|
||||
/* Encode BC_TRANSACTION/REPLY data */
|
||||
#define GBINDER_MAX_BC_TRANSACTION_SIZE (64)
|
||||
guint (*encode_transaction)(void* out, guint32 handle, guint32 code,
|
||||
const GByteArray* data, guint flags /* See below */,
|
||||
GUtilIntArray* offsets, void** offsets_buf);
|
||||
|
||||
/* Encode BC_TRANSACTION_SG/REPLY_SG data */
|
||||
#define GBINDER_MAX_BC_TRANSACTION_SG_SIZE (72)
|
||||
guint (*encode_transaction_sg)(void* out, guint32 handle, guint32 code,
|
||||
const GByteArray* data, guint flags /* GBINDER_TX_FLAG_xxx */,
|
||||
GUtilIntArray* offsets, void** offsets_buf,
|
||||
gsize buffers_size);
|
||||
|
||||
/* Encode BC_REPLY */
|
||||
guint (*encode_status_reply)(void* out, gint32* status);
|
||||
|
||||
/* Decoders */
|
||||
void (*decode_transaction_data)(const void* data, GBinderIoTxData* tx);
|
||||
|
||||
#define GBINDER_MAX_PTR_COOKIE_SIZE (16)
|
||||
void* (*decode_binder_ptr_cookie)(const void* data);
|
||||
guint (*decode_cookie)(const void* data, guint64* cookie);
|
||||
guint (*decode_binder_object)(const void* data, gsize size,
|
||||
GBinderObjectRegistry* reg, GBinderRemoteObject** obj);
|
||||
guint (*decode_buffer_object)(GBinderBuffer* buf, gsize offset,
|
||||
GBinderBuffer** out);
|
||||
|
||||
/* ioctl wrappers */
|
||||
int (*write_read)(int fd, GBinderIoBuf* write, GBinderIoBuf* read);
|
||||
};
|
||||
|
||||
extern const GBinderIo gbinder_io_32;
|
||||
extern const GBinderIo gbinder_io_64;
|
||||
|
||||
#endif /* GBINDER_IO_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
44
src/gbinder_io_32.c
Normal file
44
src/gbinder_io_32.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BINDER_IPC_32BIT
|
||||
#define GBINDER_IO_PREFIX gbinder_io_32
|
||||
|
||||
#include "gbinder_io.c"
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
44
src/gbinder_io_64.c
Normal file
44
src/gbinder_io_64.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#undef BINDER_IPC_32BIT
|
||||
#define GBINDER_IO_PREFIX gbinder_io_64
|
||||
|
||||
#include "gbinder_io.c"
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
1279
src/gbinder_ipc.c
Normal file
1279
src/gbinder_ipc.c
Normal file
File diff suppressed because it is too large
Load Diff
162
src/gbinder_ipc.h
Normal file
162
src/gbinder_ipc.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_IPC_H
|
||||
#define GBINDER_IPC_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
typedef struct gbinder_ipc_priv GBinderIpcPriv;
|
||||
struct gbinder_ipc {
|
||||
GObject object;
|
||||
GBinderIpcPriv* priv;
|
||||
GBinderDriver* driver;
|
||||
GUtilIdlePool* pool;
|
||||
const char* dev;
|
||||
};
|
||||
|
||||
typedef struct gbinder_ipc_tx GBinderIpcTx;
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderIpcTxFunc)(
|
||||
const GBinderIpcTx* tx);
|
||||
|
||||
struct gbinder_ipc_tx {
|
||||
gulong id;
|
||||
gboolean cancelled;
|
||||
GBinderIpc* ipc;
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderIpcReplyFunc)(
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data);
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_new(
|
||||
const char* dev);
|
||||
|
||||
GBinderIpc*
|
||||
gbinder_ipc_ref(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
void
|
||||
gbinder_ipc_unref(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
void
|
||||
gbinder_ipc_looper_check(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
GBinderObjectRegistry*
|
||||
gbinder_ipc_object_registry(
|
||||
GBinderIpc* ipc);
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_ipc_new_local_object(
|
||||
GBinderIpc* ipc,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* data);
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_ipc_get_remote_object(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle);
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_ipc_transact_sync_reply(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req,
|
||||
int* status);
|
||||
|
||||
int
|
||||
gbinder_ipc_transact_sync_oneway(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
GBinderLocalRequest* req);
|
||||
|
||||
gulong
|
||||
gbinder_ipc_transact(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
guint32 flags, /* GBINDER_TX_FLAG_xxx */
|
||||
GBinderLocalRequest* req,
|
||||
GBinderIpcReplyFunc func,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data);
|
||||
|
||||
gulong
|
||||
gbinder_ipc_transact_custom(
|
||||
GBinderIpc* ipc,
|
||||
GBinderIpcTxFunc exec,
|
||||
GBinderIpcTxFunc done,
|
||||
GDestroyNotify destroy,
|
||||
void* user_data);
|
||||
|
||||
void
|
||||
gbinder_ipc_cancel(
|
||||
GBinderIpc* ipc,
|
||||
gulong id);
|
||||
|
||||
/* Internal for GBinderLocalObject */
|
||||
void
|
||||
gbinder_ipc_local_object_disposed(
|
||||
GBinderIpc* self,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
/* Internal for GBinderRemoteObject */
|
||||
void
|
||||
gbinder_ipc_remote_object_disposed(
|
||||
GBinderIpc* self,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
#endif /* GBINDER_IPC_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
529
src/gbinder_local_object.c
Normal file
529
src/gbinder_local_object.c
Normal file
@@ -0,0 +1,529 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_remote_request.h"
|
||||
#include "gbinder_writer.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
struct gbinder_local_object_priv {
|
||||
GMainContext* context;
|
||||
char* iface;
|
||||
GBinderLocalTransactFunc txproc;
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GBinderLocalObject, gbinder_local_object, G_TYPE_OBJECT)
|
||||
|
||||
#define GBINDER_LOCAL_OBJECT_GET_CLASS(obj) \
|
||||
G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_LOCAL_OBJECT, \
|
||||
GBinderLocalObjectClass)
|
||||
|
||||
enum gbinder_local_object_signal {
|
||||
SIGNAL_WEAK_REFS_CHANGED,
|
||||
SIGNAL_STRONG_REFS_CHANGED,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
#define SIGNAL_WEAK_REFS_CHANGED_NAME "weak_refs_changed"
|
||||
#define SIGNAL_STRONG_REFS_CHANGED_NAME "strong_refs_changed"
|
||||
|
||||
static guint gbinder_local_object_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
static const char hidl_base_interface[] = "android.hidl.base@1.0::IBase";
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
gbinder_local_object_default_can_handle_transaction(
|
||||
GBinderLocalObject* self,
|
||||
const char* iface,
|
||||
guint code)
|
||||
{
|
||||
switch (code) {
|
||||
case HIDL_PING_TRANSACTION:
|
||||
case HIDL_GET_DESCRIPTOR_TRANSACTION:
|
||||
case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
|
||||
if (!g_strcmp0(iface, hidl_base_interface)) {
|
||||
return GBINDER_LOCAL_TRANSACTION_LOOPER;
|
||||
}
|
||||
/* no break */
|
||||
default:
|
||||
return self->priv->txproc ? GBINDER_LOCAL_TRANSACTION_SUPPORTED :
|
||||
GBINDER_LOCAL_TRANSACTION_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_default_handle_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
if (priv->txproc) {
|
||||
return priv->txproc(self, req, code, flags, status, priv->user_data);
|
||||
} else {
|
||||
if (status) *status = (-EBADMSG);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_hidl_ping_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
int* status)
|
||||
{
|
||||
/*android.hidl.base@1.0::IBase interfaceDescriptor() */
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderWriter writer;
|
||||
|
||||
GVERBOSE(" HIDL_PING_TRANSACTION \"%s\"",
|
||||
gbinder_remote_request_interface(req));
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_hidl_get_descriptor_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
int* status)
|
||||
{
|
||||
/*android.hidl.base@1.0::IBase interfaceDescriptor() */
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderWriter writer;
|
||||
|
||||
GVERBOSE(" HIDL_GET_DESCRIPTOR_TRANSACTION \"%s\"",
|
||||
gbinder_remote_request_interface(req));
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_hidl_string(&writer, self->iface ? self->iface :
|
||||
hidl_base_interface);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_hidl_descriptor_chain_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
int* status)
|
||||
{
|
||||
/*android.hidl.base@1.0::IBase interfaceChain() */
|
||||
const GBinderIo* io = gbinder_local_object_io(self);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderWriter writer;
|
||||
const char* chain[2];
|
||||
int n = 0;
|
||||
|
||||
GVERBOSE(" HIDL_DESCRIPTOR_CHAIN_TRANSACTION \"%s\"",
|
||||
gbinder_remote_request_interface(req));
|
||||
if (self->iface) chain[n++] = self->iface;
|
||||
chain[n++] = hidl_base_interface;
|
||||
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, GBINDER_STATUS_OK);
|
||||
gbinder_writer_append_hidl_string_vec(&writer, chain, n);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_default_handle_looper_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
switch (code) {
|
||||
case HIDL_PING_TRANSACTION:
|
||||
GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
|
||||
return gbinder_local_object_hidl_ping_transaction
|
||||
(self, req, status);
|
||||
case HIDL_GET_DESCRIPTOR_TRANSACTION:
|
||||
GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
|
||||
return gbinder_local_object_hidl_get_descriptor_transaction
|
||||
(self, req, status);
|
||||
case HIDL_DESCRIPTOR_CHAIN_TRANSACTION:
|
||||
GASSERT(!(flags & GBINDER_TX_FLAG_ONEWAY));
|
||||
return gbinder_local_object_hidl_descriptor_chain_transaction
|
||||
(self, req, status);
|
||||
default:
|
||||
if (status) *status = (-EBADMSG);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_handle_later(
|
||||
GBinderLocalObject* self,
|
||||
GSourceFunc function)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
g_main_context_invoke_full(priv->context, G_PRIORITY_DEFAULT, function,
|
||||
gbinder_local_object_ref(self), g_object_unref);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_increfs_proc(
|
||||
gpointer local)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
|
||||
self->weak_refs++;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_WEAK_REFS_CHANGED], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_decrefs_proc(
|
||||
gpointer local)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
|
||||
GASSERT(self->weak_refs > 0);
|
||||
self->weak_refs--;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_WEAK_REFS_CHANGED], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_acquire_proc(
|
||||
gpointer local)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
|
||||
self->strong_refs++;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_STRONG_REFS_CHANGED], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_local_object_handle_release_proc(
|
||||
gpointer local)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
|
||||
GASSERT(self->strong_refs > 0);
|
||||
self->strong_refs--;
|
||||
g_signal_emit(self, gbinder_local_object_signals
|
||||
[SIGNAL_STRONG_REFS_CHANGED], 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_new(
|
||||
GBinderIpc* ipc,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
{
|
||||
/* Should only be called from gbinder_ipc_new_local_local_object() */
|
||||
if (G_LIKELY(ipc)) {
|
||||
GBinderLocalObject* self = g_object_new
|
||||
(GBINDER_TYPE_LOCAL_OBJECT, NULL);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
self->ipc = gbinder_ipc_ref(ipc);
|
||||
self->iface = priv->iface = g_strdup(iface);
|
||||
priv->txproc = txproc;
|
||||
priv->user_data = user_data;
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_ref(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(GBINDER_LOCAL_OBJECT(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_unref(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_LOCAL_OBJECT(self));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_drop(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
/* Clear the transaction callback */
|
||||
priv->txproc = NULL;
|
||||
priv->user_data = NULL;
|
||||
g_object_unref(GBINDER_LOCAL_OBJECT(self));
|
||||
}
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_new_reply(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return gbinder_local_reply_new(gbinder_local_object_io(self));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_local_object_add_weak_refs_changed_handler(
|
||||
GBinderLocalObject* self,
|
||||
GBinderLocalObjectFunc func,
|
||||
void* user_data)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(func)) ? g_signal_connect(self,
|
||||
SIGNAL_WEAK_REFS_CHANGED_NAME, G_CALLBACK(func), user_data) : 0;
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_local_object_add_strong_refs_changed_handler(
|
||||
GBinderLocalObject* self,
|
||||
GBinderLocalObjectFunc func,
|
||||
void* user_data)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(func)) ? g_signal_connect(self,
|
||||
SIGNAL_STRONG_REFS_CHANGED_NAME, G_CALLBACK(func), user_data) : 0;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_remove_handler(
|
||||
GBinderLocalObject* self,
|
||||
gulong id)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
g_signal_handler_disconnect(self, id);
|
||||
}
|
||||
}
|
||||
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
gbinder_local_object_can_handle_transaction(
|
||||
GBinderLocalObject* self,
|
||||
const char* iface,
|
||||
guint code)
|
||||
{
|
||||
return G_LIKELY(self) ?
|
||||
GBINDER_LOCAL_OBJECT_GET_CLASS(self)->can_handle_transaction
|
||||
(self, iface, code) : GBINDER_LOCAL_TRANSACTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_handle_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return GBINDER_LOCAL_OBJECT_GET_CLASS(self)->handle_transaction
|
||||
(self, req, code, flags, status);
|
||||
} else {
|
||||
if (status) *status = (-EBADMSG);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_handle_looper_transaction(
|
||||
GBinderLocalObject* self,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return GBINDER_LOCAL_OBJECT_GET_CLASS(self)->handle_looper_transaction
|
||||
(self, req, code, flags, status);
|
||||
} else {
|
||||
if (status) *status = -EBADMSG;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_increfs(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_increfs_proc);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_decrefs(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_decrefs_proc);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_acquire(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_acquire_proc);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_release(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
gbinder_local_object_handle_later(self,
|
||||
gbinder_local_object_handle_release_proc);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_init(
|
||||
GBinderLocalObject* self)
|
||||
{
|
||||
GBinderLocalObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObjectPriv);
|
||||
|
||||
priv->context = g_main_context_default();
|
||||
self->priv = priv;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_dispose(
|
||||
GObject* local)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
|
||||
gbinder_ipc_local_object_disposed(self->ipc, self);
|
||||
G_OBJECT_CLASS(gbinder_local_object_parent_class)->dispose(local);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_finalize(
|
||||
GObject* local)
|
||||
{
|
||||
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
|
||||
GBinderLocalObjectPriv* priv = self->priv;
|
||||
|
||||
gbinder_ipc_unref(self->ipc);
|
||||
g_free(priv->iface);
|
||||
G_OBJECT_CLASS(gbinder_local_object_parent_class)->finalize(local);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_object_class_init(
|
||||
GBinderLocalObjectClass* klass)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = gbinder_local_object_dispose;
|
||||
object_class->finalize = gbinder_local_object_finalize;
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GBinderLocalObjectPriv));
|
||||
klass->handle_transaction =
|
||||
gbinder_local_object_default_handle_transaction;
|
||||
klass->handle_looper_transaction =
|
||||
gbinder_local_object_default_handle_looper_transaction;
|
||||
klass->can_handle_transaction =
|
||||
gbinder_local_object_default_can_handle_transaction;
|
||||
|
||||
gbinder_local_object_signals[SIGNAL_WEAK_REFS_CHANGED] =
|
||||
g_signal_new(SIGNAL_WEAK_REFS_CHANGED_NAME,
|
||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, 0,
|
||||
NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
gbinder_local_object_signals[SIGNAL_STRONG_REFS_CHANGED] =
|
||||
g_signal_new(SIGNAL_STRONG_REFS_CHANGED_NAME,
|
||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, 0,
|
||||
NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
161
src/gbinder_local_object_p.h
Normal file
161
src/gbinder_local_object_p.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_LOCAL_OBJECT_PRIVATE_H
|
||||
#define GBINDER_LOCAL_OBJECT_PRIVATE_H
|
||||
|
||||
#include <gbinder_local_object.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
/*
|
||||
* Some if this stuff may become public if we decide to allow the clients
|
||||
* to derive their classes from GBinderLocalObject
|
||||
*/
|
||||
|
||||
typedef
|
||||
void
|
||||
(*GBinderLocalObjectFunc)(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data);
|
||||
|
||||
typedef struct gbinder_local_object_priv GBinderLocalObjectPriv;
|
||||
struct gbinder_local_object {
|
||||
GObject object;
|
||||
GBinderLocalObjectPriv* priv;
|
||||
GBinderIpc* ipc;
|
||||
const char* iface;
|
||||
gint weak_refs;
|
||||
gint strong_refs;
|
||||
};
|
||||
|
||||
typedef enum gbinder_local_transaction_support {
|
||||
GBINDER_LOCAL_TRANSACTION_NOT_SUPPORTED,
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORTED, /* On the main thread */
|
||||
GBINDER_LOCAL_TRANSACTION_LOOPER /* On the looper thread */
|
||||
} GBINDER_LOCAL_TRANSACTION_SUPPORT;
|
||||
|
||||
typedef struct gbinder_local_object_class {
|
||||
GObjectClass parent;
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT (*can_handle_transaction)
|
||||
(GBinderLocalObject* self, const char* iface, guint code);
|
||||
GBinderLocalReply* (*handle_transaction)
|
||||
(GBinderLocalObject* self, GBinderRemoteRequest* req, guint code,
|
||||
guint flags, int* status);
|
||||
GBinderLocalReply* (*handle_looper_transaction)
|
||||
(GBinderLocalObject* self, GBinderRemoteRequest* req, guint code,
|
||||
guint flags, int* status);
|
||||
/* Need to add some placeholders if this class becomes public */
|
||||
} GBinderLocalObjectClass;
|
||||
|
||||
GType gbinder_local_object_get_type(void);
|
||||
#define GBINDER_TYPE_LOCAL_OBJECT (gbinder_local_object_get_type())
|
||||
#define GBINDER_LOCAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_LOCAL_OBJECT, GBinderLocalObject))
|
||||
|
||||
#define gbinder_local_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
|
||||
#define gbinder_local_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
|
||||
|
||||
/* Should only be called from gbinder_ipc_new_local_object() */
|
||||
GBinderLocalObject*
|
||||
gbinder_local_object_new(
|
||||
GBinderIpc* ipc,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc handler,
|
||||
void* user_data);
|
||||
|
||||
gulong
|
||||
gbinder_local_object_add_weak_refs_changed_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderLocalObjectFunc func,
|
||||
void* user_data);
|
||||
|
||||
gulong
|
||||
gbinder_local_object_add_strong_refs_changed_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderLocalObjectFunc func,
|
||||
void* user_data);
|
||||
|
||||
void
|
||||
gbinder_local_object_remove_handler(
|
||||
GBinderLocalObject* obj,
|
||||
gulong id);
|
||||
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORT
|
||||
gbinder_local_object_can_handle_transaction(
|
||||
GBinderLocalObject* self,
|
||||
const char* iface,
|
||||
guint code);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_handle_transaction(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status);
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_object_handle_looper_transaction(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status);
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_increfs(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_decrefs(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_acquire(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_local_object_handle_release(
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
#endif /* GBINDER_LOCAL_OBJECT_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
258
src/gbinder_local_reply.c
Normal file
258
src/gbinder_local_reply.c
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_local_reply_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_writer_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
struct gbinder_local_reply {
|
||||
gint refcount;
|
||||
GBinderWriterData data;
|
||||
GBinderOutputData out;
|
||||
};
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_output_cast(
|
||||
GBinderOutputData* out)
|
||||
{
|
||||
return G_CAST(out, GBinderLocalReply, out);
|
||||
}
|
||||
|
||||
static
|
||||
GUtilIntArray*
|
||||
gbinder_local_reply_output_offsets(
|
||||
GBinderOutputData* out)
|
||||
{
|
||||
return gbinder_local_reply_output_cast(out)->data.offsets;
|
||||
}
|
||||
|
||||
static
|
||||
gsize
|
||||
gbinder_local_reply_output_buffers_size(
|
||||
GBinderOutputData* out)
|
||||
{
|
||||
return gbinder_local_reply_output_cast(out)->data.buffers_size;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new(
|
||||
const GBinderIo* io)
|
||||
{
|
||||
GASSERT(io);
|
||||
if (io) {
|
||||
GBinderLocalReply* self = g_slice_new0(GBinderLocalReply);
|
||||
GBinderWriterData* data = &self->data;
|
||||
GBinderOutputData* out = &self->out;
|
||||
|
||||
static const GBinderOutputDataFunctions local_reply_output_fn = {
|
||||
.offsets = gbinder_local_reply_output_offsets,
|
||||
.buffers_size = gbinder_local_reply_output_buffers_size
|
||||
};
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
data->io = io;
|
||||
out->bytes = data->bytes = g_byte_array_new();
|
||||
out->f = &local_reply_output_fn;
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_reply_free(
|
||||
GBinderLocalReply* self)
|
||||
{
|
||||
GBinderWriterData* data = &self->data;
|
||||
|
||||
gutil_int_array_free(data->offsets, TRUE);
|
||||
g_byte_array_free(data->bytes, TRUE);
|
||||
gbinder_cleanup_free(data->cleanup);
|
||||
g_slice_free(GBinderLocalReply, self);
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_ref(
|
||||
GBinderLocalReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
g_atomic_int_inc(&self->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_reply_unref(
|
||||
GBinderLocalReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->refcount)) {
|
||||
gbinder_local_reply_free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GBinderOutputData*
|
||||
gbinder_local_reply_data(
|
||||
GBinderLocalReply* self)
|
||||
{
|
||||
return G_LIKELY(self) ? &self->out : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_reply_cleanup(
|
||||
GBinderLocalReply* self,
|
||||
GDestroyNotify destroy,
|
||||
gpointer pointer)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderWriterData* data = &self->data;
|
||||
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, destroy, pointer);
|
||||
} else if (destroy) {
|
||||
destroy(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_reply_init_writer(
|
||||
GBinderLocalReply* self,
|
||||
GBinderWriter* writer)
|
||||
{
|
||||
if (G_LIKELY(writer)) {
|
||||
gbinder_writer_init(writer, G_LIKELY(self) ? &self->data : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_int32(
|
||||
GBinderLocalReply* self,
|
||||
guint32 value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_int32(&self->data, value);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_int64(
|
||||
GBinderLocalReply* self,
|
||||
guint64 value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_int64(&self->data, value);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_string8(
|
||||
GBinderLocalReply* self,
|
||||
const char* str)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_string8(&self->data, str);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_string16(
|
||||
GBinderLocalReply* self,
|
||||
const char* utf8)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_string16(&self->data, utf8);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_hidl_string(
|
||||
GBinderLocalReply* self,
|
||||
const char* str)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_hidl_string(&self->data, str);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_hidl_string_vec(
|
||||
GBinderLocalReply* self,
|
||||
const char* strv[],
|
||||
gssize count)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_hidl_string_vec(&self->data, strv, count);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_local_object(
|
||||
GBinderLocalReply* self,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_local_object(&self->data, obj);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_append_remote_object(
|
||||
GBinderLocalReply* self,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_remote_object(&self->data, obj);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
56
src/gbinder_local_reply_p.h
Normal file
56
src/gbinder_local_reply_p.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_LOCAL_REPLY_PRIVATE_H
|
||||
#define GBINDER_LOCAL_REPLY_PRIVATE_H
|
||||
|
||||
#include <gbinder_local_reply.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
GBinderLocalReply*
|
||||
gbinder_local_reply_new(
|
||||
const GBinderIo* io);
|
||||
|
||||
GBinderOutputData*
|
||||
gbinder_local_reply_data(
|
||||
GBinderLocalReply* reply);
|
||||
|
||||
#endif /* GBINDER_LOCAL_REPLY_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
267
src/gbinder_local_request.c
Normal file
267
src/gbinder_local_request.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_local_request_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_writer_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
struct gbinder_local_request {
|
||||
gint refcount;
|
||||
GBinderWriterData data;
|
||||
GBinderOutputData out;
|
||||
};
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_output_cast(
|
||||
GBinderOutputData* out)
|
||||
{
|
||||
return G_CAST(out, GBinderLocalRequest, out);
|
||||
}
|
||||
|
||||
static
|
||||
GUtilIntArray*
|
||||
gbinder_local_request_output_offsets(
|
||||
GBinderOutputData* out)
|
||||
{
|
||||
return gbinder_local_request_output_cast(out)->data.offsets;
|
||||
}
|
||||
|
||||
static
|
||||
gsize
|
||||
gbinder_local_request_output_buffers_size(
|
||||
GBinderOutputData* out)
|
||||
{
|
||||
return gbinder_local_request_output_cast(out)->data.buffers_size;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new(
|
||||
const GBinderIo* io,
|
||||
GBytes* init)
|
||||
{
|
||||
GASSERT(io);
|
||||
if (io) {
|
||||
GBinderLocalRequest* self = g_slice_new0(GBinderLocalRequest);
|
||||
GBinderWriterData* writer = &self->data;
|
||||
GBinderOutputData* out = &self->out;
|
||||
|
||||
static const GBinderOutputDataFunctions local_request_output_fn = {
|
||||
.offsets = gbinder_local_request_output_offsets,
|
||||
.buffers_size = gbinder_local_request_output_buffers_size
|
||||
};
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
writer->io = io;
|
||||
if (init) {
|
||||
gsize size;
|
||||
gconstpointer data = g_bytes_get_data(init, &size);
|
||||
writer->bytes = g_byte_array_sized_new(size);
|
||||
g_byte_array_append(writer->bytes, data, size);
|
||||
} else {
|
||||
writer->bytes = g_byte_array_new();
|
||||
}
|
||||
out->f = &local_request_output_fn;
|
||||
out->bytes = writer->bytes;
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_local_request_free(
|
||||
GBinderLocalRequest* self)
|
||||
{
|
||||
GBinderWriterData* data = &self->data;
|
||||
|
||||
g_byte_array_free(data->bytes, TRUE);
|
||||
gutil_int_array_free(data->offsets, TRUE);
|
||||
gbinder_cleanup_free(data->cleanup);
|
||||
g_slice_free(GBinderLocalRequest, self);
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_ref(
|
||||
GBinderLocalRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
g_atomic_int_inc(&self->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_request_unref(
|
||||
GBinderLocalRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->refcount)) {
|
||||
gbinder_local_request_free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GBinderOutputData*
|
||||
gbinder_local_request_data(
|
||||
GBinderLocalRequest* self)
|
||||
{
|
||||
return G_LIKELY(self) ? &self->out : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_request_cleanup(
|
||||
GBinderLocalRequest* self,
|
||||
GDestroyNotify destroy,
|
||||
gpointer pointer)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderWriterData* data = &self->data;
|
||||
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, destroy, pointer);
|
||||
} else if (destroy) {
|
||||
destroy(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_local_request_init_writer(
|
||||
GBinderLocalRequest* self,
|
||||
GBinderWriter* writer)
|
||||
{
|
||||
if (G_LIKELY(writer)) {
|
||||
gbinder_writer_init(writer, G_LIKELY(self) ? &self->data : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_int32(
|
||||
GBinderLocalRequest* self,
|
||||
guint32 value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_int32(&self->data, value);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_int64(
|
||||
GBinderLocalRequest* self,
|
||||
guint64 value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_int64(&self->data, value);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_string8(
|
||||
GBinderLocalRequest* self,
|
||||
const char* str)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_string8(&self->data, str);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_string16(
|
||||
GBinderLocalRequest* self,
|
||||
const char* utf8)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_string16(&self->data, utf8);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_hidl_string(
|
||||
GBinderLocalRequest* self,
|
||||
const char* str)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_hidl_string(&self->data, str);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_hidl_string_vec(
|
||||
GBinderLocalRequest* self,
|
||||
const char* strv[],
|
||||
gssize count)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_hidl_string_vec(&self->data, strv, count);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_local_object(
|
||||
GBinderLocalRequest* self,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_local_object(&self->data, obj);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_append_remote_object(
|
||||
GBinderLocalRequest* self,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_writer_data_append_remote_object(&self->data, obj);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
57
src/gbinder_local_request_p.h
Normal file
57
src/gbinder_local_request_p.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_LOCAL_REQUEST_PRIVATE_H
|
||||
#define GBINDER_LOCAL_REQUEST_PRIVATE_H
|
||||
|
||||
#include <gbinder_local_request.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
GBinderLocalRequest*
|
||||
gbinder_local_request_new(
|
||||
const GBinderIo* io,
|
||||
GBytes* init);
|
||||
|
||||
GBinderOutputData*
|
||||
gbinder_local_request_data(
|
||||
GBinderLocalRequest* req);
|
||||
|
||||
#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
49
src/gbinder_log.h
Normal file
49
src/gbinder_log.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_LOG_H
|
||||
#define GBINDER_LOG_H
|
||||
|
||||
#include "gbinder_types.h"
|
||||
|
||||
#define GLOG_MODULE_NAME GBINDER_LOG_MODULE
|
||||
#include <gutil_log.h>
|
||||
|
||||
#endif /* GBINDER_LOG_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
97
src/gbinder_object_registry.h
Normal file
97
src/gbinder_object_registry.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_OBJECT_REGISTRY_H
|
||||
#define GBINDER_OBJECT_REGISTRY_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef struct gbinder_object_registry_functions {
|
||||
void (*ref)(GBinderObjectRegistry* reg);
|
||||
void (*unref)(GBinderObjectRegistry* reg);
|
||||
GBinderLocalObject* (*get_local)(GBinderObjectRegistry* reg,
|
||||
void* pointer);
|
||||
GBinderRemoteObject* (*get_remote)(GBinderObjectRegistry* reg,
|
||||
guint32 handle);
|
||||
} GBinderObjectRegistryFunctions;
|
||||
|
||||
struct gbinder_object_registry {
|
||||
const GBinderObjectRegistryFunctions* f;
|
||||
const GBinderIo* io;
|
||||
};
|
||||
|
||||
/* Inline wrappers */
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderObjectRegistry*
|
||||
gbinder_object_registry_ref(
|
||||
GBinderObjectRegistry* reg)
|
||||
{
|
||||
if (reg) reg->f->ref(reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
void
|
||||
gbinder_object_registry_unref(
|
||||
GBinderObjectRegistry* reg)
|
||||
{
|
||||
if (reg) reg->f->unref(reg);
|
||||
}
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderLocalObject*
|
||||
gbinder_object_registry_get_local(
|
||||
GBinderObjectRegistry* reg,
|
||||
void* pointer)
|
||||
{
|
||||
return reg ? reg->f->get_local(reg, pointer) : NULL;
|
||||
}
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GBinderRemoteObject*
|
||||
gbinder_object_registry_get_remote(
|
||||
GBinderObjectRegistry* reg,
|
||||
guint32 handle)
|
||||
{
|
||||
return reg ? reg->f->get_remote(reg, handle) : NULL;
|
||||
}
|
||||
|
||||
#endif /* GBINDER_OBJECT_REGISTRY_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
76
src/gbinder_output_data.h
Normal file
76
src/gbinder_output_data.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_OUTPUT_DATA_H
|
||||
#define GBINDER_OUTPUT_DATA_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef struct gbinder_output_data_functions GBinderOutputDataFunctions;
|
||||
|
||||
struct gbinder_output_data {
|
||||
const GBinderOutputDataFunctions* f;
|
||||
const GByteArray* bytes;
|
||||
};
|
||||
|
||||
struct gbinder_output_data_functions {
|
||||
GUtilIntArray* (*offsets)(GBinderOutputData* data);
|
||||
gsize (*buffers_size)(GBinderOutputData* data);
|
||||
};
|
||||
|
||||
/* Inline wrappers */
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
GUtilIntArray*
|
||||
gbinder_output_data_offsets(
|
||||
GBinderOutputData* data)
|
||||
{
|
||||
return data ? data->f->offsets(data) : NULL;
|
||||
}
|
||||
|
||||
GBINDER_INLINE_FUNC
|
||||
gsize
|
||||
gbinder_output_data_buffers_size(
|
||||
GBinderOutputData* data)
|
||||
{
|
||||
return data ? data->f->buffers_size(data) : 0;
|
||||
}
|
||||
|
||||
#endif /* GBINDER_OUTPUT_DATA_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
471
src/gbinder_reader.c
Normal file
471
src/gbinder_reader.c
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_reader_p.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
#include "gbinder_io.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
typedef struct gbinder_reader_priv {
|
||||
const guint8* start;
|
||||
const guint8* end;
|
||||
const guint8* ptr;
|
||||
const GBinderReaderData* data;
|
||||
void** objects;
|
||||
} GBinderReaderPriv;
|
||||
|
||||
G_STATIC_ASSERT(sizeof(GBinderReader) >= sizeof(GBinderReaderPriv));
|
||||
|
||||
static inline GBinderReaderPriv* gbinder_reader_cast(GBinderReader* reader)
|
||||
{ return (GBinderReaderPriv*)reader; }
|
||||
|
||||
void
|
||||
gbinder_reader_init(
|
||||
GBinderReader* reader,
|
||||
GBinderReaderData* data,
|
||||
gsize offset,
|
||||
gsize len)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
p->data = data;
|
||||
if (G_LIKELY(data)) {
|
||||
GBinderBuffer* buffer = data->buffer;
|
||||
|
||||
if (buffer) {
|
||||
/* We are assuming that the caller has checked offset and size */
|
||||
GASSERT(!buffer || (offset + len <= buffer->size));
|
||||
p->ptr = p->start = (guint8*)buffer->data + offset;
|
||||
p->end = p->ptr + len;
|
||||
} else {
|
||||
p->ptr = p->start = p->end = NULL;
|
||||
}
|
||||
p->objects = data->objects;
|
||||
} else {
|
||||
p->ptr = p->start = p->end = NULL;
|
||||
p->objects = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_at_end(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
return p->ptr >= p->end;
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
gboolean
|
||||
gbinder_reader_can_read(
|
||||
GBinderReaderPriv* p,
|
||||
gsize len)
|
||||
{
|
||||
return (p->end - p->ptr) >= len;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_byte(
|
||||
GBinderReader* reader,
|
||||
guchar* value)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
if (p->ptr < p->end) {
|
||||
if (value) *value = *p->ptr;
|
||||
p->ptr++;
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_bool(
|
||||
GBinderReader* reader,
|
||||
gboolean* value)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
/* Boolean values are supposed to be padded to 4-byte boundary */
|
||||
if (gbinder_reader_can_read(p, 4)) {
|
||||
if (value) {
|
||||
*value = (p->ptr[0] != 0);
|
||||
}
|
||||
p->ptr += 4;
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int32(
|
||||
GBinderReader* reader,
|
||||
gint32* value)
|
||||
{
|
||||
return gbinder_reader_read_uint32(reader, (guint32*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint32(
|
||||
GBinderReader* reader,
|
||||
guint32* value)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
if (gbinder_reader_can_read(p, sizeof(*value))) {
|
||||
if (value) {
|
||||
const gint32* ptr = (void*)p->ptr;
|
||||
|
||||
*value = *ptr;
|
||||
}
|
||||
p->ptr += sizeof(*value);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_int64(
|
||||
GBinderReader* reader,
|
||||
gint64* value)
|
||||
{
|
||||
return gbinder_reader_read_uint64(reader, (guint64*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_uint64(
|
||||
GBinderReader* reader,
|
||||
guint64* value)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
if (gbinder_reader_can_read(p, sizeof(*value))) {
|
||||
if (value) {
|
||||
const gint64* ptr = (void*)p->ptr;
|
||||
|
||||
*value = *ptr;
|
||||
}
|
||||
p->ptr += sizeof(*value);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_object(
|
||||
GBinderReader* reader,
|
||||
GBinderRemoteObject** out)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
const GBinderReaderData* data = p->data;
|
||||
|
||||
if (data && data->reg && p->objects && p->objects[0] &&
|
||||
p->ptr == p->objects[0]) {
|
||||
const guint eaten = data->reg->io->decode_binder_object(p->ptr,
|
||||
gbinder_reader_bytes_remaining(reader), data->reg, out);
|
||||
|
||||
if (eaten) {
|
||||
p->ptr += eaten;
|
||||
p->objects++;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (out) *out = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_reader_read_object(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
|
||||
gbinder_reader_read_nullable_object(reader, &obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_reader_read_buffer_impl(
|
||||
GBinderReader* reader,
|
||||
GBinderBuffer** out)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
const GBinderReaderData* data = p->data;
|
||||
|
||||
if (data && data->reg && p->objects && p->objects[0] &&
|
||||
p->ptr == p->objects[0]) {
|
||||
GBinderBuffer* buf = data->buffer;
|
||||
const GBinderIo* io = data->reg->io;
|
||||
const gsize offset = p->ptr - (guint8*)buf->data;
|
||||
const guint eaten = io->decode_buffer_object(buf, offset, out);
|
||||
|
||||
if (eaten) {
|
||||
p->ptr += eaten;
|
||||
p->objects++;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (out) *out = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GBinderBuffer*
|
||||
gbinder_reader_read_buffer(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderBuffer* buf = NULL;
|
||||
|
||||
gbinder_reader_read_buffer_impl(reader, &buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_skip_buffer(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
return gbinder_reader_read_buffer_impl(reader, NULL);
|
||||
}
|
||||
|
||||
char*
|
||||
gbinder_reader_read_hidl_string(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
char* str = NULL;
|
||||
|
||||
if (buf && buf->size == sizeof(HidlString)) {
|
||||
const HidlString* s = buf->data;
|
||||
GBinderBuffer* sbuf = gbinder_reader_read_buffer(reader);
|
||||
|
||||
if (sbuf && sbuf->size == s->len + 1 &&
|
||||
sbuf->data == s->data.str &&
|
||||
s->data.str[s->len] == 0) {
|
||||
str = g_strdup(s->data.str);
|
||||
}
|
||||
gbinder_buffer_free(sbuf);
|
||||
}
|
||||
gbinder_buffer_free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
char**
|
||||
gbinder_reader_read_hidl_string_vec(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderBuffer* buf = gbinder_reader_read_buffer(reader);
|
||||
|
||||
/* First buffer contains hidl_vector */
|
||||
if (buf && buf->size == sizeof(HidlVec)) {
|
||||
HidlVec* vec = buf->data;
|
||||
const guint n = vec->count;
|
||||
const void* next = vec->data.ptr;
|
||||
|
||||
gbinder_buffer_free(buf);
|
||||
if (!next && !n) {
|
||||
char** out = g_new(char*, 1);
|
||||
|
||||
out[0] = NULL;
|
||||
return out;
|
||||
} else {
|
||||
/* The second buffer (if any) contains n hidl_string's */
|
||||
buf = gbinder_reader_read_buffer(reader);
|
||||
if (buf && buf->data == next && buf->size == sizeof(HidlString)*n) {
|
||||
const HidlString* strings = buf->data;
|
||||
GBinderBuffer* sbuf;
|
||||
GPtrArray* list = g_ptr_array_new();
|
||||
guint i;
|
||||
|
||||
/* Now we expect n buffers containing the actual data */
|
||||
for (i=0; i<n &&
|
||||
(sbuf = gbinder_reader_read_buffer(reader)); i++) {
|
||||
const HidlString* s = strings + i;
|
||||
if (sbuf->size == s->len + 1 &&
|
||||
sbuf->data == s->data.str &&
|
||||
s->data.str[s->len] == 0) {
|
||||
char* name = g_strdup(s->data.str);
|
||||
|
||||
g_ptr_array_add(list, name);
|
||||
GVERBOSE_("%u. %s", i + 1, name);
|
||||
gbinder_buffer_free(sbuf);
|
||||
} else {
|
||||
GWARN("Unexpected hidl_string buffer %p/%u vs %p/%u",
|
||||
sbuf->data, (guint)sbuf->size, s->data.str, s->len);
|
||||
gbinder_buffer_free(sbuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == n) {
|
||||
gbinder_buffer_free(buf);
|
||||
g_ptr_array_add(list, NULL);
|
||||
return (char**)g_ptr_array_free(list, FALSE);
|
||||
}
|
||||
|
||||
g_ptr_array_set_free_func(list, g_free);
|
||||
g_ptr_array_free(list, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
GWARN("Invalid hidl_vec<string>");
|
||||
gbinder_buffer_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_reader_read_string8(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
const guint8* ptr = p->ptr;
|
||||
|
||||
/* Calculate the length */
|
||||
while (ptr < p->end && *ptr) ptr++;
|
||||
if (ptr < p->end) {
|
||||
/* Zero terminator has been found within the bounds */
|
||||
const gsize len = ptr - p->ptr;
|
||||
const gsize size = G_ALIGN4(len+1);
|
||||
|
||||
if (p->ptr + size <= p->end) {
|
||||
const char* str = (char*)p->ptr;
|
||||
|
||||
p->ptr += size;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_read_nullable_string16(
|
||||
GBinderReader* reader,
|
||||
char** out)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
if ((p->ptr + 4) <= p->end) {
|
||||
const gint32* len_ptr = (gint32*)p->ptr;
|
||||
const gint32 len = *len_ptr;
|
||||
|
||||
if (len == -1) {
|
||||
/* NULL string */
|
||||
p->ptr += 4;
|
||||
if (out) {
|
||||
*out = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
} else if (len >= 0) {
|
||||
const guint32 padded_len = G_ALIGN4((len+1)*2);
|
||||
const gunichar2* utf16 = (const gunichar2*)(p->ptr + 4);
|
||||
|
||||
if ((p->ptr + padded_len + 4) <= p->end) {
|
||||
p->ptr += padded_len + 4;
|
||||
if (out) {
|
||||
*out = g_utf16_to_utf8(utf16, len, NULL, NULL, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char*
|
||||
gbinder_reader_read_string16(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
char* str = NULL;
|
||||
|
||||
gbinder_reader_read_nullable_string16(reader, &str);
|
||||
return str;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_reader_skip_string16(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
if ((p->ptr + 4) <= p->end) {
|
||||
const gint32* len_ptr = (gint32*)p->ptr;
|
||||
const gint32 len = *len_ptr;
|
||||
|
||||
if (len == -1) {
|
||||
/* NULL string */
|
||||
p->ptr += 4;
|
||||
return TRUE;
|
||||
} else if (len >= 0) {
|
||||
const guint32 padded_len = G_ALIGN4((len+1)*2);
|
||||
|
||||
if ((p->ptr + padded_len + 4) <= p->end) {
|
||||
p->ptr += padded_len + 4;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_read(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
return p->ptr - p->start;
|
||||
}
|
||||
|
||||
gsize
|
||||
gbinder_reader_bytes_remaining(
|
||||
GBinderReader* reader)
|
||||
{
|
||||
GBinderReaderPriv* p = gbinder_reader_cast(reader);
|
||||
|
||||
return p->end - p->ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
61
src/gbinder_reader_p.h
Normal file
61
src/gbinder_reader_p.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_READER_PRIVATE_H
|
||||
#define GBINDER_READER_PRIVATE_H
|
||||
|
||||
#include <gbinder_reader.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
typedef struct gbinder_reader_data {
|
||||
GBinderBuffer* buffer;
|
||||
GBinderObjectRegistry* reg;
|
||||
void** objects;
|
||||
} GBinderReaderData;
|
||||
|
||||
void
|
||||
gbinder_reader_init(
|
||||
GBinderReader* reader,
|
||||
GBinderReaderData* data,
|
||||
gsize offset,
|
||||
gsize len);
|
||||
|
||||
#endif /* GBINDER_READER_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
231
src/gbinder_remote_object.c
Normal file
231
src/gbinder_remote_object.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
struct gbinder_remote_object_priv {
|
||||
GMainContext* context;
|
||||
};
|
||||
|
||||
typedef GObjectClass GBinderRemoteObjectClass;
|
||||
G_DEFINE_TYPE(GBinderRemoteObject, gbinder_remote_object, G_TYPE_OBJECT)
|
||||
|
||||
GType gbinder_remote_object_get_type(void);
|
||||
#define GBINDER_TYPE_REMOTE_OBJECT (gbinder_remote_object_get_type())
|
||||
#define GBINDER_REMOTE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GBINDER_TYPE_REMOTE_OBJECT, GBinderRemoteObject))
|
||||
|
||||
enum gbinder_remote_object_signal {
|
||||
SIGNAL_DEATH,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
#define SIGNAL_DEATH_NAME "death"
|
||||
|
||||
static guint gbinder_remote_object_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_died_on_main_thread(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
GASSERT(!self->dead);
|
||||
self->dead = TRUE;
|
||||
g_signal_emit(self, gbinder_remote_object_signals[SIGNAL_DEATH], 0);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
gbinder_remote_object_died_handle(
|
||||
gpointer self)
|
||||
{
|
||||
gbinder_remote_object_died_on_main_thread(GBINDER_REMOTE_OBJECT(self));
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_object_new(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle)
|
||||
{
|
||||
if (G_LIKELY(ipc) && gbinder_driver_acquire(ipc->driver, handle)) {
|
||||
GBinderRemoteObject* self = g_object_new
|
||||
(GBINDER_TYPE_REMOTE_OBJECT, NULL);
|
||||
|
||||
self->ipc = gbinder_ipc_ref(ipc);
|
||||
self->handle = handle;
|
||||
gbinder_driver_request_death_notification(ipc->driver, self);
|
||||
return self;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_object_ref(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(GBINDER_REMOTE_OBJECT(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_object_unref(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_REMOTE_OBJECT(self));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_object_is_dead(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
return G_UNLIKELY(!self) || self->dead;
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_remote_object_add_death_handler(
|
||||
GBinderRemoteObject* self,
|
||||
GBinderRemoteObjectNotifyFunc fn,
|
||||
void* data)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(fn)) {
|
||||
/* To receive the notifications, we need to have looper running */
|
||||
gbinder_ipc_looper_check(self->ipc);
|
||||
return g_signal_connect(self, SIGNAL_DEATH_NAME, G_CALLBACK(fn), data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_object_remove_handler(
|
||||
GBinderRemoteObject* self,
|
||||
gulong id)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
g_signal_handler_disconnect(self, id);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_object_handle_death_notification(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
/* This function is invoked from the looper thread, the caller has
|
||||
* checked the object pointer */
|
||||
GVERBOSE_("%p %u", self, self->handle);
|
||||
g_main_context_invoke_full(self->priv->context, G_PRIORITY_DEFAULT,
|
||||
gbinder_remote_object_died_handle, gbinder_remote_object_ref(self),
|
||||
g_object_unref);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_init(
|
||||
GBinderRemoteObject* self)
|
||||
{
|
||||
GBinderRemoteObjectPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
GBINDER_TYPE_REMOTE_OBJECT, GBinderRemoteObjectPriv);
|
||||
|
||||
priv->context = g_main_context_default();
|
||||
self->priv = priv;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_dispose(
|
||||
GObject* remote)
|
||||
{
|
||||
GBinderRemoteObject* self = GBINDER_REMOTE_OBJECT(remote);
|
||||
|
||||
gbinder_ipc_remote_object_disposed(self->ipc, self);
|
||||
G_OBJECT_CLASS(gbinder_remote_object_parent_class)->dispose(remote);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_finalize(
|
||||
GObject* remote)
|
||||
{
|
||||
GBinderRemoteObject* self = GBINDER_REMOTE_OBJECT(remote);
|
||||
GBinderIpc* ipc = self->ipc;
|
||||
GBinderDriver* driver = ipc->driver;
|
||||
|
||||
gbinder_driver_clear_death_notification(driver, self);
|
||||
gbinder_driver_release(driver, self->handle);
|
||||
gbinder_ipc_unref(ipc);
|
||||
G_OBJECT_CLASS(gbinder_remote_object_parent_class)->finalize(remote);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_object_class_init(
|
||||
GBinderRemoteObjectClass* klass)
|
||||
{
|
||||
GObjectClass* remote_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(klass, sizeof(GBinderRemoteObjectPriv));
|
||||
remote_class->dispose = gbinder_remote_object_dispose;
|
||||
remote_class->finalize = gbinder_remote_object_finalize;
|
||||
|
||||
gbinder_remote_object_signals[SIGNAL_DEATH] =
|
||||
g_signal_new(SIGNAL_DEATH_NAME, G_OBJECT_CLASS_TYPE(klass),
|
||||
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
71
src/gbinder_remote_object_p.h
Normal file
71
src/gbinder_remote_object_p.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_REMOTE_OBJECT_PRIVATE_H
|
||||
#define GBINDER_REMOTE_OBJECT_PRIVATE_H
|
||||
|
||||
#include <gbinder_remote_object.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
typedef struct gbinder_remote_object_priv GBinderRemoteObjectPriv;
|
||||
struct gbinder_remote_object {
|
||||
GObject object;
|
||||
GBinderRemoteObjectPriv* priv;
|
||||
GBinderIpc* ipc;
|
||||
guint32 handle;
|
||||
gboolean dead;
|
||||
};
|
||||
|
||||
#define gbinder_remote_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
|
||||
#define gbinder_remote_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_object_new(
|
||||
GBinderIpc* ipc,
|
||||
guint32 handle);
|
||||
|
||||
void
|
||||
gbinder_remote_object_handle_death_notification(
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
#endif /* GBINDER_REMOTE_OBJECT_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
239
src/gbinder_remote_reply.c
Normal file
239
src/gbinder_remote_reply.c
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_remote_reply_p.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_buffer.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
struct gbinder_remote_reply {
|
||||
gint refcount;
|
||||
GBinderReaderData data;
|
||||
};
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_remote_reply_new(
|
||||
GBinderObjectRegistry* reg)
|
||||
{
|
||||
GBinderRemoteReply* self = g_slice_new0(GBinderRemoteReply);
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
data->reg = gbinder_object_registry_ref(reg);
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_reply_free(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
gbinder_object_registry_unref(data->reg);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
g_free(data->objects);
|
||||
g_slice_free(GBinderRemoteReply, self);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_reply_set_data(
|
||||
GBinderRemoteReply* self,
|
||||
GBinderBuffer* buffer,
|
||||
void** objects)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
g_free(data->objects);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
data->buffer = buffer;
|
||||
data->objects = objects;
|
||||
} else {
|
||||
gbinder_buffer_free(buffer);
|
||||
g_free(objects);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_remote_reply_ref(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
g_atomic_int_inc(&self->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_reply_unref(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->refcount)) {
|
||||
gbinder_remote_reply_free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_is_empty(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
return !self || !self->data.buffer || !self->data.buffer->size;
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
void
|
||||
gbinder_remote_reply_init_reader2(
|
||||
GBinderRemoteReply* self,
|
||||
GBinderReader* p)
|
||||
{
|
||||
/* The caller has already checked the reply for NULL */
|
||||
GBinderReaderData* data = &self->data;
|
||||
GBinderBuffer* buffer = data->buffer;
|
||||
|
||||
if (buffer) {
|
||||
gbinder_reader_init(p, data, 0, buffer->size);
|
||||
} else {
|
||||
gbinder_reader_init(p, data, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_reply_init_reader(
|
||||
GBinderRemoteReply* self,
|
||||
GBinderReader* reader)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_remote_reply_init_reader2(self, reader);
|
||||
} else {
|
||||
gbinder_reader_init(reader, NULL, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_int32(
|
||||
GBinderRemoteReply* self,
|
||||
gint32* value)
|
||||
{
|
||||
return gbinder_remote_reply_read_uint32(self, (guint32*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_uint32(
|
||||
GBinderRemoteReply* self,
|
||||
guint32* value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_reply_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_uint32(&reader, value);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_int64(
|
||||
GBinderRemoteReply* self,
|
||||
gint64* value)
|
||||
{
|
||||
return gbinder_remote_reply_read_uint64(self, (guint64*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_read_uint64(
|
||||
GBinderRemoteReply* self,
|
||||
guint64* value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_reply_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_uint64(&reader, value);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_remote_reply_read_string8(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_reply_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_string8(&reader);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char*
|
||||
gbinder_remote_reply_read_string16(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_reply_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_string16(&reader);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_reply_read_object(
|
||||
GBinderRemoteReply* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_reply_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_object(&reader);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
62
src/gbinder_remote_reply_p.h
Normal file
62
src/gbinder_remote_reply_p.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_REMOTE_REPLY_PRIVATE_H
|
||||
#define GBINDER_REMOTE_REPLY_PRIVATE_H
|
||||
|
||||
#include <gbinder_remote_reply.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
GBinderRemoteReply*
|
||||
gbinder_remote_reply_new(
|
||||
GBinderObjectRegistry* reg);
|
||||
|
||||
void
|
||||
gbinder_remote_reply_set_data(
|
||||
GBinderRemoteReply* reply,
|
||||
GBinderBuffer* buffer,
|
||||
void** objects);
|
||||
|
||||
gboolean
|
||||
gbinder_remote_reply_is_empty(
|
||||
GBinderRemoteReply* reply);
|
||||
|
||||
#endif /* GBINDER_REMOTE_REPLY_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
256
src/gbinder_remote_request.c
Normal file
256
src/gbinder_remote_request.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_remote_request_p.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_buffer.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
struct gbinder_remote_request {
|
||||
gint refcount;
|
||||
const GBinderRpcProtocol* protocol;
|
||||
const char* iface;
|
||||
char* iface2;
|
||||
gsize header_size;
|
||||
GBinderReaderData data;
|
||||
};
|
||||
|
||||
GBinderRemoteRequest*
|
||||
gbinder_remote_request_new(
|
||||
GBinderObjectRegistry* reg,
|
||||
const GBinderRpcProtocol* protocol)
|
||||
{
|
||||
GBinderRemoteRequest* self = g_slice_new0(GBinderRemoteRequest);
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
g_atomic_int_set(&self->refcount, 1);
|
||||
self->protocol = protocol;
|
||||
data->reg = gbinder_object_registry_ref(reg);
|
||||
return self;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_remote_request_free(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
GBinderReaderData* data = &self->data;
|
||||
|
||||
gbinder_object_registry_unref(data->reg);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
g_free(data->objects);
|
||||
g_free(self->iface2);
|
||||
g_slice_free(GBinderRemoteRequest, self);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
void
|
||||
gbinder_remote_request_init_reader2(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderReader* p)
|
||||
{
|
||||
/* The caller has already checked the request for NULL */
|
||||
GBinderReaderData* data = &self->data;
|
||||
GBinderBuffer* buffer = data->buffer;
|
||||
|
||||
if (buffer) {
|
||||
gbinder_reader_init(p, data, self->header_size,
|
||||
buffer->size - self->header_size);
|
||||
} else {
|
||||
gbinder_reader_init(p, data, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_request_set_data(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderBuffer* buffer,
|
||||
void** objects)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReaderData* data = &self->data;
|
||||
GBinderReader reader;
|
||||
|
||||
g_free(self->iface2);
|
||||
g_free(data->objects);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
data->buffer = buffer;
|
||||
data->objects = objects;
|
||||
|
||||
/* Parse RPC header */
|
||||
self->header_size = 0;
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
self->iface = self->protocol->read_rpc_header(&reader, &self->iface2);
|
||||
self->header_size = gbinder_reader_bytes_read(&reader);
|
||||
} else {
|
||||
gbinder_buffer_free(buffer);
|
||||
g_free(objects);
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_remote_request_interface(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
return G_LIKELY(self) ? self->iface : NULL;
|
||||
}
|
||||
|
||||
GBinderRemoteRequest*
|
||||
gbinder_remote_request_ref(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
g_atomic_int_inc(&self->refcount);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_request_unref(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GASSERT(self->refcount > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->refcount)) {
|
||||
gbinder_remote_request_free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_remote_request_init_reader(
|
||||
GBinderRemoteRequest* self,
|
||||
GBinderReader* reader)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_remote_request_init_reader2(self, reader);
|
||||
} else {
|
||||
gbinder_reader_init(reader, NULL, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_int32(
|
||||
GBinderRemoteRequest* self,
|
||||
gint32* value)
|
||||
{
|
||||
return gbinder_remote_request_read_uint32(self, (guint32*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_uint32(
|
||||
GBinderRemoteRequest* self,
|
||||
guint32* value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_uint32(&reader, value);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_int64(
|
||||
GBinderRemoteRequest* self,
|
||||
gint64* value)
|
||||
{
|
||||
return gbinder_remote_request_read_uint64(self, (guint64*)value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gbinder_remote_request_read_uint64(
|
||||
GBinderRemoteRequest* self,
|
||||
guint64* value)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_uint64(&reader, value);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char*
|
||||
gbinder_remote_request_read_string8(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_string8(&reader);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char*
|
||||
gbinder_remote_request_read_string16(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_string16(&reader);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderRemoteObject*
|
||||
gbinder_remote_request_read_object(
|
||||
GBinderRemoteRequest* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
GBinderReader reader;
|
||||
|
||||
gbinder_remote_request_init_reader2(self, &reader);
|
||||
return gbinder_reader_read_object(&reader);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
59
src/gbinder_remote_request_p.h
Normal file
59
src/gbinder_remote_request_p.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_REMOTE_REQUEST_PRIVATE_H
|
||||
#define GBINDER_REMOTE_REQUEST_PRIVATE_H
|
||||
|
||||
#include <gbinder_remote_request.h>
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
GBinderRemoteRequest*
|
||||
gbinder_remote_request_new(
|
||||
GBinderObjectRegistry* reg,
|
||||
const GBinderRpcProtocol* protocol);
|
||||
|
||||
void
|
||||
gbinder_remote_request_set_data(
|
||||
GBinderRemoteRequest* request,
|
||||
GBinderBuffer* buffer,
|
||||
void** objects);
|
||||
|
||||
#endif /* GBINDER_REMOTE_REQUEST_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
136
src/gbinder_rpc_protocol.c
Normal file
136
src/gbinder_rpc_protocol.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_rpc_protocol.h"
|
||||
#include "gbinder_reader.h"
|
||||
#include "gbinder_writer.h"
|
||||
|
||||
/*==========================================================================*
|
||||
* GBinderIpcProtocol callbacks (see Parcel::writeInterfaceToken in Android)
|
||||
* Note that there are two slightly different kinds of Parcels:
|
||||
*
|
||||
* platform/system/libhwbinder/Parcel.cpp
|
||||
* platform/frameworks/native/libs/binder/Parcel.cpp
|
||||
*==========================================================================*/
|
||||
|
||||
/*==========================================================================*
|
||||
* /dev/binder
|
||||
*==========================================================================*/
|
||||
|
||||
/* No idea what that is... */
|
||||
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
|
||||
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_binder_write_rpc_header(
|
||||
GBinderWriter* writer,
|
||||
const char* iface)
|
||||
{
|
||||
/*
|
||||
* writeInt32(IPCThreadState::self()->getStrictModePolicy() |
|
||||
* STRICT_MODE_PENALTY_GATHER);
|
||||
* writeString16(interface);
|
||||
*/
|
||||
gbinder_writer_append_int32(writer, BINDER_RPC_FLAGS);
|
||||
gbinder_writer_append_string16(writer, iface);
|
||||
}
|
||||
|
||||
static
|
||||
const char*
|
||||
gbinder_rpc_protocol_binder_read_rpc_header(
|
||||
GBinderReader* reader,
|
||||
char** iface)
|
||||
{
|
||||
if (gbinder_reader_read_int32(reader, NULL)) {
|
||||
*iface = gbinder_reader_read_string16(reader);
|
||||
} else {
|
||||
*iface = NULL;
|
||||
}
|
||||
return *iface;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* /dev/hwbinder
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_rpc_protocol_hwbinder_write_rpc_header(
|
||||
GBinderWriter* writer,
|
||||
const char* iface)
|
||||
{
|
||||
/*
|
||||
* writeCString(interface);
|
||||
*/
|
||||
gbinder_writer_append_string8(writer, iface);
|
||||
}
|
||||
|
||||
static
|
||||
const char*
|
||||
gbinder_rpc_protocol_hwbinder_read_rpc_header(
|
||||
GBinderReader* reader,
|
||||
char** iface)
|
||||
{
|
||||
*iface = NULL;
|
||||
return gbinder_reader_read_string8(reader);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_for_device(
|
||||
const char* dev)
|
||||
{
|
||||
static const GBinderRpcProtocol protocol_binder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_binder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_binder_write_rpc_header
|
||||
};
|
||||
|
||||
static const GBinderRpcProtocol protocol_hwbinder = {
|
||||
.read_rpc_header = gbinder_rpc_protocol_hwbinder_read_rpc_header,
|
||||
.write_rpc_header = gbinder_rpc_protocol_hwbinder_write_rpc_header
|
||||
};
|
||||
|
||||
return (dev && !strcmp(dev, GBINDER_DEFAULT_HWBINDER)) ?
|
||||
&protocol_hwbinder : &protocol_binder;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
60
src/gbinder_rpc_protocol.h
Normal file
60
src/gbinder_rpc_protocol.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_RPC_PROTOCOL_H
|
||||
#define GBINDER_RPC_PROTOCOL_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
/*
|
||||
* For whatever reason services communicating via /dev/binder
|
||||
* and /dev/hwbinder use slightly different RPC headers.
|
||||
*/
|
||||
|
||||
struct gbinder_rpc_protocol {
|
||||
const char* (*read_rpc_header)(GBinderReader* reader, char** iface);
|
||||
void (*write_rpc_header)(GBinderWriter* writer, const char* iface);
|
||||
};
|
||||
|
||||
const GBinderRpcProtocol*
|
||||
gbinder_rpc_protocol_for_device(
|
||||
const char* dev);
|
||||
|
||||
#endif /* GBINDER_RPC_PROTOCOL_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
521
src/gbinder_servicemanager.c
Normal file
521
src/gbinder_servicemanager.c
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_servicemanager_p.h"
|
||||
#include "gbinder_client_p.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gbinder_client.h>
|
||||
|
||||
#include <gutil_idlepool.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(GBinderServiceManager, gbinder_servicemanager,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
#define PARENT_CLASS gbinder_servicemanager_parent_class
|
||||
#define GBINDER_SERVICEMANAGER(obj) \
|
||||
G_TYPE_CHECK_INSTANCE_CAST((obj), GBINDER_TYPE_SERVICEMANAGER, \
|
||||
GBinderServiceManager)
|
||||
#define GBINDER_SERVICEMANAGER_CLASS(klass) \
|
||||
G_TYPE_CHECK_CLASS_CAST((klass), GBINDER_TYPE_SERVICEMANAGER, \
|
||||
GBinderServiceManagerClass)
|
||||
#define GBINDER_SERVICEMANAGER_GET_CLASS(obj) \
|
||||
G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_SERVICEMANAGER, \
|
||||
GBinderServiceManagerClass)
|
||||
#define GBINDER_IS_SERVICEMANAGER_TYPE(klass) \
|
||||
G_TYPE_CHECK_CLASS_TYPE(klass, GBINDER_TYPE_SERVICEMANAGER)
|
||||
|
||||
/*==========================================================================*
|
||||
* Implementation
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
GBinderServiceManagerClass*
|
||||
gbinder_servicemanager_class_ref(
|
||||
GType type)
|
||||
{
|
||||
if (G_LIKELY(type)) {
|
||||
GTypeClass* klass = g_type_class_ref(type);
|
||||
if (klass) {
|
||||
if (GBINDER_IS_SERVICEMANAGER_TYPE(klass)) {
|
||||
return GBINDER_SERVICEMANAGER_CLASS(klass);
|
||||
}
|
||||
g_type_class_unref(klass);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev)
|
||||
{
|
||||
GBinderServiceManager* self = NULL;
|
||||
GBinderServiceManagerClass* klass = gbinder_servicemanager_class_ref(type);
|
||||
|
||||
if (klass) {
|
||||
GBinderIpc* ipc;
|
||||
|
||||
if (!dev) dev = klass->default_device;
|
||||
ipc = gbinder_ipc_new(dev);
|
||||
if (ipc) {
|
||||
GBinderRemoteObject* object = gbinder_ipc_get_remote_object
|
||||
(ipc, klass->handle);
|
||||
|
||||
if (object) {
|
||||
/* Lock */
|
||||
g_mutex_lock(&klass->mutex);
|
||||
if (klass->table) {
|
||||
self = g_hash_table_lookup(klass->table, dev);
|
||||
}
|
||||
if (self) {
|
||||
gbinder_servicemanager_ref(self);
|
||||
} else {
|
||||
char* key = g_strdup(dev); /* Owned by the hashtable */
|
||||
|
||||
GVERBOSE_("%s", dev);
|
||||
self = g_object_new(type, NULL);
|
||||
self->client = gbinder_client_new(object, klass->iface);
|
||||
self->dev = gbinder_remote_object_dev(object);
|
||||
if (!klass->table) {
|
||||
klass->table = g_hash_table_new_full(g_str_hash,
|
||||
g_str_equal, g_free, NULL);
|
||||
}
|
||||
g_hash_table_replace(klass->table, key, self);
|
||||
}
|
||||
g_mutex_unlock(&klass->mutex);
|
||||
/* Unlock */
|
||||
gbinder_remote_object_unref(object);
|
||||
}
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
g_type_class_unref(klass);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
typedef struct gbinder_servicemanager_list_tx_data {
|
||||
GBinderServiceManager* sm;
|
||||
GBinderServiceManagerListFunc func;
|
||||
char** result;
|
||||
void* user_data;
|
||||
} GBinderServiceManagerListTxData;
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_list_tx_exec(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GBinderServiceManagerListTxData* data = tx->user_data;
|
||||
|
||||
data->result = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->list(data->sm);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_list_tx_done(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GBinderServiceManagerListTxData* data = tx->user_data;
|
||||
|
||||
if (!data->func(data->sm, data->result, data->user_data)) {
|
||||
g_strfreev(data->result);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_list_tx_free(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServiceManagerListTxData* data = user_data;
|
||||
|
||||
gbinder_servicemanager_unref(data->sm);
|
||||
g_slice_free(GBinderServiceManagerListTxData, data);
|
||||
}
|
||||
|
||||
typedef struct gbinder_servicemanager_get_service_tx {
|
||||
GBinderServiceManager* sm;
|
||||
GBinderServiceManagerGetServiceFunc func;
|
||||
GBinderRemoteObject* obj;
|
||||
int status;
|
||||
char* name;
|
||||
void* user_data;
|
||||
} GBinderServiceManagerGetServiceTxData;
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_get_service_tx_exec(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GBinderServiceManagerGetServiceTxData* data = tx->user_data;
|
||||
|
||||
data->obj = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->get_service
|
||||
(data->sm, data->name, &data->status);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_get_service_tx_done(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GBinderServiceManagerGetServiceTxData* data = tx->user_data;
|
||||
|
||||
data->func(data->sm, data->obj, data->status, data->user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_get_service_tx_free(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServiceManagerGetServiceTxData* data = user_data;
|
||||
|
||||
gbinder_servicemanager_unref(data->sm);
|
||||
gbinder_remote_object_unref(data->obj);
|
||||
g_free(data->name);
|
||||
g_slice_free(GBinderServiceManagerGetServiceTxData, data);
|
||||
}
|
||||
|
||||
typedef struct gbinder_servicemanager_add_service_tx {
|
||||
GBinderServiceManager* sm;
|
||||
GBinderServiceManagerAddServiceFunc func;
|
||||
GBinderLocalObject* obj;
|
||||
int status;
|
||||
char* name;
|
||||
void* user_data;
|
||||
} GBinderServiceManagerAddServiceTxData;
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_add_service_tx_exec(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GBinderServiceManagerAddServiceTxData* data = tx->user_data;
|
||||
|
||||
data->status = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->add_service
|
||||
(data->sm, data->name, data->obj);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_add_service_tx_done(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GBinderServiceManagerAddServiceTxData* data = tx->user_data;
|
||||
|
||||
data->func(data->sm, data->status, data->user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_add_service_tx_free(
|
||||
gpointer user_data)
|
||||
{
|
||||
GBinderServiceManagerAddServiceTxData* data = user_data;
|
||||
|
||||
gbinder_servicemanager_unref(data->sm);
|
||||
gbinder_local_object_unref(data->obj);
|
||||
g_free(data->name);
|
||||
g_slice_free(GBinderServiceManagerAddServiceTxData, data);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Interface
|
||||
*==========================================================================*/
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new(
|
||||
const char* dev)
|
||||
{
|
||||
if (!g_strcmp0(dev, GBINDER_DEFAULT_HWBINDER)) {
|
||||
return gbinder_hwservicemanager_new(dev);
|
||||
} else {
|
||||
return gbinder_defaultservicemanager_new(dev);
|
||||
}
|
||||
}
|
||||
|
||||
GBinderLocalObject*
|
||||
gbinder_servicemanager_new_local_object(
|
||||
GBinderServiceManager* self,
|
||||
const char* iface,
|
||||
GBinderLocalTransactFunc txproc,
|
||||
void* user_data)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return gbinder_ipc_new_local_object(gbinder_client_ipc(self->client),
|
||||
iface, txproc, user_data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_ref(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(GBINDER_SERVICEMANAGER(self));
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_servicemanager_unref(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(GBINDER_SERVICEMANAGER(self));
|
||||
}
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_list(
|
||||
GBinderServiceManager* self,
|
||||
GBinderServiceManagerListFunc func,
|
||||
void* user_data)
|
||||
{
|
||||
if (G_LIKELY(self) && func) {
|
||||
GBinderServiceManagerListTxData* data =
|
||||
g_slice_new0(GBinderServiceManagerListTxData);
|
||||
|
||||
data->sm = gbinder_servicemanager_ref(self);
|
||||
data->func = func;
|
||||
data->user_data = user_data;
|
||||
|
||||
return gbinder_ipc_transact_custom(gbinder_client_ipc(self->client),
|
||||
gbinder_servicemanager_list_tx_exec,
|
||||
gbinder_servicemanager_list_tx_done,
|
||||
gbinder_servicemanager_list_tx_free, data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char**
|
||||
gbinder_servicemanager_list_sync(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
return GBINDER_SERVICEMANAGER_GET_CLASS(self)->list(self);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_get_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderServiceManagerGetServiceFunc func,
|
||||
void* user_data)
|
||||
{
|
||||
if (G_LIKELY(self) && func && name) {
|
||||
GBinderServiceManagerGetServiceTxData* data =
|
||||
g_slice_new0(GBinderServiceManagerGetServiceTxData);
|
||||
|
||||
data->sm = gbinder_servicemanager_ref(self);
|
||||
data->func = func;
|
||||
data->name = g_strdup(name);
|
||||
data->user_data = user_data;
|
||||
data->status = (-EFAULT);
|
||||
|
||||
return gbinder_ipc_transact_custom(gbinder_client_ipc(self->client),
|
||||
gbinder_servicemanager_get_service_tx_exec,
|
||||
gbinder_servicemanager_get_service_tx_done,
|
||||
gbinder_servicemanager_get_service_tx_free, data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GBinderRemoteObject* /* autoreleased */
|
||||
gbinder_servicemanager_get_service_sync(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
int* status)
|
||||
{
|
||||
GBinderRemoteObject* obj = NULL;
|
||||
|
||||
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();
|
||||
}
|
||||
gutil_idle_pool_add_object(self->pool, obj);
|
||||
} else if (status) {
|
||||
*status = (-EINVAL);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
gulong
|
||||
gbinder_servicemanager_add_service(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj,
|
||||
GBinderServiceManagerAddServiceFunc func,
|
||||
void* user_data)
|
||||
{
|
||||
if (G_LIKELY(self) && func && name) {
|
||||
GBinderServiceManagerAddServiceTxData* data =
|
||||
g_slice_new0(GBinderServiceManagerAddServiceTxData);
|
||||
|
||||
data->sm = gbinder_servicemanager_ref(self);
|
||||
data->obj = gbinder_local_object_ref(obj);
|
||||
data->func = func;
|
||||
data->name = g_strdup(name);
|
||||
data->user_data = user_data;
|
||||
data->status = (-EFAULT);
|
||||
|
||||
return gbinder_ipc_transact_custom(gbinder_client_ipc(self->client),
|
||||
gbinder_servicemanager_add_service_tx_exec,
|
||||
gbinder_servicemanager_add_service_tx_done,
|
||||
gbinder_servicemanager_add_service_tx_free, data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_servicemanager_add_service_sync(
|
||||
GBinderServiceManager* self,
|
||||
const char* name,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
if (G_LIKELY(self) && name && obj) {
|
||||
return GBINDER_SERVICEMANAGER_GET_CLASS(self)->add_service
|
||||
(self, name, obj);
|
||||
} else {
|
||||
return (-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_servicemanager_cancel(
|
||||
GBinderServiceManager* self,
|
||||
gulong id)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
gbinder_ipc_cancel(gbinder_client_ipc(self->client), id);
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Internals
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_init(
|
||||
GBinderServiceManager* self)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_dispose(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
|
||||
GBinderServiceManagerClass* klass =
|
||||
GBINDER_SERVICEMANAGER_GET_CLASS(self);
|
||||
|
||||
GVERBOSE_("%s", self->dev);
|
||||
/* Lock */
|
||||
g_mutex_lock(&klass->mutex);
|
||||
|
||||
/*
|
||||
* The follow can happen:
|
||||
*
|
||||
* 1. Last reference goes away.
|
||||
* 2. gbinder_servicemanager_dispose() is invoked by glib
|
||||
* 3. Before gbinder_servicemanager_dispose() grabs the
|
||||
* lock, gbinder_servicemanager_new() gets there first,
|
||||
* finds the object in the hashtable, bumps its refcount
|
||||
* (under the lock) and returns the reference to the caller.
|
||||
* 4. gbinder_servicemanager_dispose() gets its lock, finds
|
||||
* that the object's refcount is greater than zero and leaves
|
||||
* the object in the table.
|
||||
*
|
||||
* It's OK for a GObject to get re-referenced in dispose.
|
||||
* glib will recheck the refcount once dispose returns,
|
||||
* gbinder_servicemanager_finalize() will not be called
|
||||
* this time around.
|
||||
*/
|
||||
if (klass->table && object->ref_count == 0) {
|
||||
g_hash_table_remove(klass->table, self->dev);
|
||||
if (g_hash_table_size(klass->table) == 0) {
|
||||
g_hash_table_unref(klass->table);
|
||||
klass->table = NULL;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock(&klass->mutex);
|
||||
/* Unlock */
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_finalize(
|
||||
GObject* object)
|
||||
{
|
||||
GBinderServiceManager* self = GBINDER_SERVICEMANAGER(object);
|
||||
|
||||
gutil_idle_pool_drain(self->pool);
|
||||
gutil_idle_pool_unref(self->pool);
|
||||
gbinder_client_unref(self->client);
|
||||
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_servicemanager_class_init(
|
||||
GBinderServiceManagerClass* klass)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
g_mutex_init(&klass->mutex);
|
||||
object_class->dispose = gbinder_servicemanager_dispose;
|
||||
object_class->finalize = gbinder_servicemanager_finalize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
83
src/gbinder_servicemanager_p.h
Normal file
83
src/gbinder_servicemanager_p.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_SERVICEMANAGER_PRIVATE_H
|
||||
#define GBINDER_SERVICEMANAGER_PRIVATE_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
#include <gbinder_servicemanager.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
typedef struct gbinder_servicemanager {
|
||||
GObject parent;
|
||||
const char* dev;
|
||||
GBinderClient* client;
|
||||
GUtilIdlePool* pool;
|
||||
} GBinderServiceManager;
|
||||
|
||||
typedef struct gbinder_servicemanager_class {
|
||||
GObjectClass parent;
|
||||
GMutex mutex;
|
||||
GHashTable* table;
|
||||
|
||||
guint32 handle;
|
||||
const char* iface;
|
||||
const char* default_device;
|
||||
|
||||
/* Methods (synchronous) */
|
||||
char** (*list)(GBinderServiceManager* self);
|
||||
GBinderRemoteObject* (*get_service)
|
||||
(GBinderServiceManager* self, const char* name, int* status);
|
||||
int (*add_service)
|
||||
(GBinderServiceManager* self, const char* name,
|
||||
GBinderLocalObject* obj);
|
||||
} GBinderServiceManagerClass;
|
||||
|
||||
GType gbinder_servicemanager_get_type(void);
|
||||
#define GBINDER_TYPE_SERVICEMANAGER (gbinder_servicemanager_get_type())
|
||||
|
||||
GBinderServiceManager*
|
||||
gbinder_servicemanager_new_with_type(
|
||||
GType type,
|
||||
const char* dev);
|
||||
|
||||
#endif /* GBINDER_SERVICEMANAGER_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
88
src/gbinder_system.c
Normal file
88
src/gbinder_system.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_system.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
int
|
||||
gbinder_system_open(
|
||||
const char* path,
|
||||
int flags)
|
||||
{
|
||||
return open(path, flags);
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_system_close(
|
||||
int fd)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_system_ioctl(
|
||||
int fd,
|
||||
int request,
|
||||
void* data)
|
||||
{
|
||||
return ioctl(fd, request, data);
|
||||
}
|
||||
|
||||
void*
|
||||
gbinder_system_mmap(
|
||||
size_t length,
|
||||
int prot,
|
||||
int flags,
|
||||
int fd)
|
||||
{
|
||||
return mmap(NULL, length, prot, flags, fd, 0);
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_system_munmap(
|
||||
void* addr,
|
||||
size_t length)
|
||||
{
|
||||
return munmap(addr, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
73
src/gbinder_system.h
Normal file
73
src/gbinder_system.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_SYSTEM_H
|
||||
#define GBINDER_SYSTEM_H
|
||||
|
||||
#include "gbinder_types_p.h"
|
||||
|
||||
int
|
||||
gbinder_system_open(
|
||||
const char* path,
|
||||
int flags);
|
||||
|
||||
int
|
||||
gbinder_system_close(
|
||||
int fd);
|
||||
|
||||
int
|
||||
gbinder_system_ioctl(
|
||||
int fd,
|
||||
int request,
|
||||
void* data);
|
||||
|
||||
void*
|
||||
gbinder_system_mmap(
|
||||
size_t length,
|
||||
int prot,
|
||||
int flags,
|
||||
int fd);
|
||||
|
||||
int
|
||||
gbinder_system_munmap(
|
||||
void* addr,
|
||||
size_t length);
|
||||
|
||||
#endif /* GBINDER_SYSTEM_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
99
src/gbinder_types_p.h
Normal file
99
src/gbinder_types_p.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_TYPES_PRIVATE_H
|
||||
#define GBINDER_TYPES_PRIVATE_H
|
||||
|
||||
#include <gbinder_types.h>
|
||||
|
||||
typedef struct gbinder_cleanup GBinderCleanup;
|
||||
typedef struct gbinder_driver GBinderDriver;
|
||||
typedef struct gbinder_handler GBinderHandler;
|
||||
typedef struct gbinder_io GBinderIo;
|
||||
typedef struct gbinder_ipc GBinderIpc;
|
||||
typedef struct gbinder_object_registry GBinderObjectRegistry;
|
||||
typedef struct gbinder_output_data GBinderOutputData;
|
||||
typedef struct gbinder_rpc_protocol GBinderRpcProtocol;
|
||||
|
||||
typedef struct hidl_vec {
|
||||
union {
|
||||
guint64 value;
|
||||
const void* ptr;
|
||||
} data;
|
||||
guint32 count;
|
||||
guint32 owns_buffer;
|
||||
} HidlVec;
|
||||
|
||||
#define HIDL_VEC_BUFFER_OFFSET (0)
|
||||
|
||||
typedef struct hidl_string {
|
||||
union {
|
||||
guint64 value;
|
||||
const char* str;
|
||||
} data;
|
||||
guint32 len;
|
||||
guint32 owns_buffer;
|
||||
} HidlString;
|
||||
|
||||
#define HIDL_STRING_BUFFER_OFFSET (0)
|
||||
|
||||
#define GBINDER_INLINE_FUNC static inline
|
||||
|
||||
#define GBINDER_TRANSACTION(c2,c3,c4) GBINDER_FOURCC('_',c2,c3,c4)
|
||||
#define GBINDER_PING_TRANSACTION GBINDER_TRANSACTION('P','N','G')
|
||||
#define GBINDER_DUMP_TRANSACTION GBINDER_TRANSACTION('D','M','P')
|
||||
#define GBINDER_SHELL_COMMAND_TRANSACTION GBINDER_TRANSACTION('C','M','D')
|
||||
#define GBINDER_INTERFACE_TRANSACTION GBINDER_TRANSACTION('N','T','F')
|
||||
#define GBINDER_SYSPROPS_TRANSACTION GBINDER_TRANSACTION('S','P','R')
|
||||
|
||||
/* platform/system/tools/hidl/Interface.cpp */
|
||||
#define HIDL_FOURCC(c2,c3,c4) GBINDER_FOURCC(0x0f,c2,c3,c4)
|
||||
#define HIDL_PING_TRANSACTION HIDL_FOURCC('P','N','G')
|
||||
#define HIDL_DESCRIPTOR_CHAIN_TRANSACTION HIDL_FOURCC('C','H','N')
|
||||
#define HIDL_GET_DESCRIPTOR_TRANSACTION HIDL_FOURCC('D','S','C')
|
||||
#define HIDL_SYSPROPS_CHANGED_TRANSACTION HIDL_FOURCC('S','Y','S')
|
||||
#define HIDL_LINK_TO_DEATH_TRANSACTION HIDL_FOURCC('L','T','D')
|
||||
#define HIDL_UNLINK_TO_DEATH_TRANSACTION HIDL_FOURCC('U','T','D')
|
||||
#define HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION HIDL_FOURCC('I','N','T')
|
||||
#define HIDL_GET_REF_INFO_TRANSACTION HIDL_FOURCC('R','E','F')
|
||||
#define HIDL_DEBUG_TRANSACTION HIDL_FOURCC('D','B','G')
|
||||
#define HIDL_HASH_CHAIN_TRANSACTION HIDL_FOURCC('H','S','H')
|
||||
|
||||
#endif /* GBINDER_TYPES_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
569
src/gbinder_writer.c
Normal file
569
src/gbinder_writer.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_writer_p.h"
|
||||
#include "gbinder_io.h"
|
||||
#include "gbinder_log.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_macros.h>
|
||||
#include <gutil_strv.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct gbinder_writer_priv {
|
||||
GBinderWriterData* data;
|
||||
} GBinderWriterPriv;
|
||||
|
||||
G_STATIC_ASSERT(sizeof(GBinderWriter) >= sizeof(GBinderWriterPriv));
|
||||
|
||||
GBINDER_INLINE_FUNC GBinderWriterPriv* gbinder_writer_cast(GBinderWriter* pub)
|
||||
{ return (GBinderWriterPriv*)pub; }
|
||||
GBINDER_INLINE_FUNC GBinderWriterData* gbinder_writer_data(GBinderWriter* pub)
|
||||
{ return G_LIKELY(pub) ? gbinder_writer_cast(pub)->data : NULL; }
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_record_offset(
|
||||
GBinderWriterData* data,
|
||||
guint offset)
|
||||
{
|
||||
if (!data->offsets) {
|
||||
data->offsets = gutil_int_array_new();
|
||||
}
|
||||
gutil_int_array_append(data->offsets, offset);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gbinder_writer_data_write_buffer_object(
|
||||
GBinderWriterData* data,
|
||||
const void* ptr,
|
||||
gsize size,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
GByteArray* dest = data->bytes;
|
||||
const guint offset = dest->len;
|
||||
guint n;
|
||||
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(dest, offset + GBINDER_MAX_BUFFER_OBJECT_SIZE);
|
||||
/* Write the object */
|
||||
n = data->io->encode_buffer_object(dest->data + offset, ptr, size, parent);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(dest, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
/* The driver seems to require each buffer to be 8-byte aligned */
|
||||
data->buffers_size += G_ALIGN8(size);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_init(
|
||||
GBinderWriter* self,
|
||||
GBinderWriterData* data)
|
||||
{
|
||||
memset(self, 0, sizeof(*self));
|
||||
gbinder_writer_cast(self)->data = data;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_int32(
|
||||
GBinderWriter* self,
|
||||
guint32 value)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_int32(data, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_int32(
|
||||
GBinderWriterData* data,
|
||||
guint32 value)
|
||||
{
|
||||
guint32* ptr;
|
||||
|
||||
g_byte_array_set_size(data->bytes, data->bytes->len + sizeof(*ptr));
|
||||
ptr = (void*)(data->bytes->data + (data->bytes->len - sizeof(*ptr)));
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_int64(
|
||||
GBinderWriter* self,
|
||||
guint64 value)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_int64(data, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_int64(
|
||||
GBinderWriterData* data,
|
||||
guint64 value)
|
||||
{
|
||||
guint64* ptr;
|
||||
|
||||
g_byte_array_set_size(data->bytes, data->bytes->len + sizeof(*ptr));
|
||||
ptr = (void*)(data->bytes->data + (data->bytes->len - sizeof(*ptr)));
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_string8(
|
||||
GBinderWriter* self,
|
||||
const char* str)
|
||||
{
|
||||
gbinder_writer_append_string8_len(self, str, str ? strlen(str) : 0);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_string8_len(
|
||||
GBinderWriter* self,
|
||||
const char* str,
|
||||
gsize len)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_string8_len(data, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string8(
|
||||
GBinderWriterData* data,
|
||||
const char* str)
|
||||
{
|
||||
gbinder_writer_data_append_string8_len(data, str, str ? strlen(str) : 0);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string8_len(
|
||||
GBinderWriterData* data,
|
||||
const char* str,
|
||||
gsize len)
|
||||
{
|
||||
if (G_LIKELY(str)) {
|
||||
const gsize old_size = data->bytes->len;
|
||||
gsize padded_len = G_ALIGN4(len + 1);
|
||||
guint32* dest;
|
||||
|
||||
/* Preallocate space */
|
||||
g_byte_array_set_size(data->bytes, old_size + padded_len);
|
||||
|
||||
/* Zero the last word */
|
||||
dest = (guint32*)(data->bytes->data + old_size);
|
||||
dest[padded_len/4 - 1] = 0;
|
||||
|
||||
/* Copy the data */
|
||||
memcpy(dest, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_string16(
|
||||
GBinderWriter* self,
|
||||
const char* utf8)
|
||||
{
|
||||
gbinder_writer_append_string16_len(self, utf8, utf8 ? strlen(utf8) : 0);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_string16_len(
|
||||
GBinderWriter* self,
|
||||
const char* utf8,
|
||||
gssize num_bytes)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_string16_len(data, utf8, num_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string16(
|
||||
GBinderWriterData* data,
|
||||
const char* utf8)
|
||||
{
|
||||
gbinder_writer_data_append_string16_len(data, utf8, utf8? strlen(utf8) : 0);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string16_len(
|
||||
GBinderWriterData* data,
|
||||
const char* utf8,
|
||||
gssize num_bytes)
|
||||
{
|
||||
const gsize old_size = data->bytes->len;
|
||||
|
||||
if (utf8) {
|
||||
const char* end = utf8;
|
||||
|
||||
g_utf8_validate(utf8, num_bytes, &end);
|
||||
num_bytes = end - utf8;
|
||||
} else {
|
||||
num_bytes = 0;
|
||||
}
|
||||
|
||||
if (num_bytes > 0) {
|
||||
glong len = g_utf8_strlen(utf8, num_bytes);
|
||||
gsize padded_len = G_ALIGN4((len+1)*2);
|
||||
guint32* len_ptr;
|
||||
gunichar2* utf16_ptr;
|
||||
|
||||
/* Preallocate space */
|
||||
g_byte_array_set_size(data->bytes, old_size + padded_len + 4);
|
||||
len_ptr = (guint32*)(data->bytes->data + old_size);
|
||||
utf16_ptr = (gunichar2*)(len_ptr + 1);
|
||||
|
||||
/* TODO: this could be optimized for ASCII strings, i.e. if
|
||||
* len equals num_bytes */
|
||||
if (len > 0) {
|
||||
glong utf16_len = 0;
|
||||
gunichar2* utf16 = g_utf8_to_utf16(utf8, num_bytes, NULL,
|
||||
&utf16_len, NULL);
|
||||
|
||||
if (utf16) {
|
||||
len = utf16_len;
|
||||
padded_len = G_ALIGN4((len+1)*2);
|
||||
memcpy(utf16_ptr, utf16, (len+1)*2);
|
||||
g_free(utf16);
|
||||
}
|
||||
}
|
||||
|
||||
/* Actual length */
|
||||
*len_ptr = len;
|
||||
|
||||
/* Zero padding */
|
||||
if (padded_len - (len + 1)*2) {
|
||||
memset(utf16_ptr + (len + 1), 0, padded_len - (len + 1)*2);
|
||||
}
|
||||
|
||||
/* Correct the packet size if necessaary */
|
||||
g_byte_array_set_size(data->bytes, old_size + padded_len + 4);
|
||||
} else if (utf8) {
|
||||
/* Empty string */
|
||||
guint16* ptr16;
|
||||
|
||||
g_byte_array_set_size(data->bytes, old_size + 8);
|
||||
ptr16 = (guint16*)(data->bytes->data + old_size);
|
||||
ptr16[0] = ptr16[1] = ptr16[2] = 0; ptr16[3] = 0xffff;
|
||||
} else {
|
||||
/* NULL string */
|
||||
gbinder_writer_data_append_int32(data, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_bool(
|
||||
GBinderWriter* self,
|
||||
gboolean value)
|
||||
{
|
||||
guint8 padded[4];
|
||||
|
||||
/* Boolean values are padded to 4-byte boundary */
|
||||
padded[0] = (value != FALSE);
|
||||
padded[1] = padded[2] = padded[3] = 0xff;
|
||||
gbinder_writer_append_bytes(self, padded, sizeof(padded));
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_bytes(
|
||||
GBinderWriter* self,
|
||||
const void* ptr,
|
||||
gsize size)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
g_byte_array_append(data->bytes, ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
guint
|
||||
gbinder_writer_data_prepare(
|
||||
GBinderWriterData* data)
|
||||
{
|
||||
if (!data->offsets) {
|
||||
data->offsets = gutil_int_array_new();
|
||||
}
|
||||
return data->offsets->count;
|
||||
}
|
||||
|
||||
guint
|
||||
gbinder_writer_append_buffer_object_with_parent(
|
||||
GBinderWriter* self,
|
||||
const void* buf,
|
||||
gsize len,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
return gbinder_writer_data_append_buffer_object(data, buf, len, parent);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
guint
|
||||
gbinder_writer_append_buffer_object(
|
||||
GBinderWriter* self,
|
||||
const void* buf,
|
||||
gsize len)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
return gbinder_writer_data_append_buffer_object(data, buf, len, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
guint
|
||||
gbinder_writer_data_append_buffer_object(
|
||||
GBinderWriterData* data,
|
||||
const void* ptr,
|
||||
gsize size,
|
||||
const GBinderParent* parent)
|
||||
{
|
||||
guint index = gbinder_writer_data_prepare(data);
|
||||
|
||||
gbinder_writer_data_write_buffer_object(data, ptr, size, parent);
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string(
|
||||
GBinderWriter* self,
|
||||
const char* str)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_hidl_string(data, str);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_string(
|
||||
GBinderWriterData* data,
|
||||
const char* str)
|
||||
{
|
||||
GBinderParent str_parent;
|
||||
HidlString* hidl_string = g_new0(HidlString, 1);
|
||||
const gsize len = str ? strlen(str) : 0;
|
||||
|
||||
/* Prepare parent descriptor for the string data */
|
||||
str_parent.index = gbinder_writer_data_prepare(data);
|
||||
str_parent.offset = HIDL_STRING_BUFFER_OFFSET;
|
||||
|
||||
/* Fill in the string descriptor and store it */
|
||||
hidl_string->data.str = str;
|
||||
hidl_string->len = len;
|
||||
hidl_string->owns_buffer = TRUE;
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, hidl_string);
|
||||
|
||||
/* Write the buffer object pointing to the string descriptor */
|
||||
gbinder_writer_data_write_buffer_object(data, hidl_string,
|
||||
sizeof(*hidl_string), NULL);
|
||||
|
||||
/* Not sure what's the right way to deal with NULL strings... */
|
||||
if (str) {
|
||||
/* Write the buffer pointing to the string data including the
|
||||
* NULL terminator, referencing string descriptor as a parent. */
|
||||
gbinder_writer_data_write_buffer_object(data, str, len+1, &str_parent);
|
||||
GVERBOSE_("\"%s\" %u %u %u", str, (guint)len, (guint)str_parent.index,
|
||||
(guint)data->buffers_size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_hidl_string_vec(
|
||||
GBinderWriter* self,
|
||||
const char* strv[],
|
||||
gssize count)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_hidl_string_vec(data, strv, count);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_string_vec(
|
||||
GBinderWriterData* data,
|
||||
const char* strv[],
|
||||
gssize count)
|
||||
{
|
||||
GBinderParent vec_parent;
|
||||
HidlVec* vec = g_new0(HidlVec, 1);
|
||||
HidlString* strings = NULL;
|
||||
int i;
|
||||
|
||||
if (count < 0) {
|
||||
/* Assume NULL terminated array */
|
||||
count = gutil_strv_length((char**)strv);
|
||||
}
|
||||
|
||||
/* Prepare parent descriptor for the vector data */
|
||||
vec_parent.index = gbinder_writer_data_prepare(data);
|
||||
vec_parent.offset = HIDL_VEC_BUFFER_OFFSET;
|
||||
|
||||
/* Fill in the vector descriptor */
|
||||
if (count > 0) {
|
||||
strings = g_new0(HidlString, count);
|
||||
vec->data.ptr = strings;
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, strings);
|
||||
}
|
||||
vec->count = count;
|
||||
vec->owns_buffer = TRUE;
|
||||
data->cleanup = gbinder_cleanup_add(data->cleanup, g_free, vec);
|
||||
|
||||
/* Fill in string descriptors */
|
||||
for (i = 0; i < count; i++) {
|
||||
const char* str = strv[i];
|
||||
HidlString* hidl_str = strings + i;
|
||||
|
||||
if ((hidl_str->data.str = str) != NULL) {
|
||||
hidl_str->len = strlen(str);
|
||||
hidl_str->owns_buffer = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the vector object */
|
||||
gbinder_writer_data_write_buffer_object(data, vec, sizeof(*vec), NULL);
|
||||
if (strings) {
|
||||
GBinderParent str_parent;
|
||||
|
||||
/* Prepare parent descriptor for the string data */
|
||||
str_parent.index = data->offsets->count;
|
||||
str_parent.offset = HIDL_STRING_BUFFER_OFFSET;
|
||||
|
||||
/* Write the vector data (it's parent for the string data) */
|
||||
gbinder_writer_data_write_buffer_object(data, strings,
|
||||
sizeof(*strings) * count, &vec_parent);
|
||||
|
||||
/* Write the string data */
|
||||
for (i = 0; i < count; i++) {
|
||||
HidlString* hidl_str = strings + i;
|
||||
|
||||
if (hidl_str->data.str) {
|
||||
gbinder_writer_data_write_buffer_object(data,
|
||||
hidl_str->data.str, hidl_str->len + 1, &str_parent);
|
||||
GVERBOSE_("%d. \"%s\" %u %u %u", i + 1, hidl_str->data.str,
|
||||
(guint)hidl_str->len, (guint)str_parent.index,
|
||||
(guint)data->buffers_size);
|
||||
}
|
||||
str_parent.offset += sizeof(HidlString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_local_object(
|
||||
GBinderWriter* self,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_local_object(data, obj);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_local_object(
|
||||
GBinderWriterData* data,
|
||||
GBinderLocalObject* obj)
|
||||
{
|
||||
GByteArray* dest = data->bytes;
|
||||
const guint offset = dest->len;
|
||||
guint n;
|
||||
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(dest, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
/* Write the object */
|
||||
n = data->io->encode_local_object(dest->data + offset, obj);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(dest, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_append_remote_object(
|
||||
GBinderWriter* self,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
GBinderWriterData* data = gbinder_writer_data(self);
|
||||
|
||||
if (G_LIKELY(data)) {
|
||||
gbinder_writer_data_append_remote_object(data, obj);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_remote_object(
|
||||
GBinderWriterData* data,
|
||||
GBinderRemoteObject* obj)
|
||||
{
|
||||
GByteArray* dest = data->bytes;
|
||||
const guint offset = dest->len;
|
||||
guint n;
|
||||
|
||||
/* Preallocate enough space */
|
||||
g_byte_array_set_size(dest, offset + GBINDER_MAX_BINDER_OBJECT_SIZE);
|
||||
/* Write the object */
|
||||
n = data->io->encode_remote_object(dest->data + offset, obj);
|
||||
/* Fix the data size */
|
||||
g_byte_array_set_size(dest, offset + n);
|
||||
/* Record the offset */
|
||||
gbinder_writer_data_record_offset(data, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
121
src/gbinder_writer_p.h
Normal file
121
src/gbinder_writer_p.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
|
||||
*
|
||||
* You may use this file under the terms of BSD license as follows:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the 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.
|
||||
*
|
||||
* 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_WRITER_PRIVATE_H
|
||||
#define GBINDER_WRITER_PRIVATE_H
|
||||
|
||||
#include <gbinder_writer.h>
|
||||
|
||||
#include "gbinder_cleanup.h"
|
||||
|
||||
typedef struct gbinder_writer_data {
|
||||
const GBinderIo* io;
|
||||
GByteArray* bytes;
|
||||
GUtilIntArray* offsets;
|
||||
gsize buffers_size;
|
||||
GBinderCleanup* cleanup;
|
||||
} GBinderWriterData;
|
||||
|
||||
void
|
||||
gbinder_writer_init(
|
||||
GBinderWriter* writer,
|
||||
GBinderWriterData* data);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_int32(
|
||||
GBinderWriterData* data,
|
||||
guint32 value);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_int64(
|
||||
GBinderWriterData* data,
|
||||
guint64 value);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string8(
|
||||
GBinderWriterData* data,
|
||||
const char* str);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string8_len(
|
||||
GBinderWriterData* data,
|
||||
const char* str,
|
||||
gsize len);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string16(
|
||||
GBinderWriterData* data,
|
||||
const char* utf8);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_string16_len(
|
||||
GBinderWriterData* data,
|
||||
const char* utf8,
|
||||
gssize num_bytes);
|
||||
|
||||
guint
|
||||
gbinder_writer_data_append_buffer_object(
|
||||
GBinderWriterData* data,
|
||||
const void* ptr,
|
||||
gsize size,
|
||||
const GBinderParent* parent);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_string(
|
||||
GBinderWriterData* data,
|
||||
const char* str);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_hidl_string_vec(
|
||||
GBinderWriterData* data,
|
||||
const char* strv[],
|
||||
gssize count);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_local_object(
|
||||
GBinderWriterData* data,
|
||||
GBinderLocalObject* obj);
|
||||
|
||||
void
|
||||
gbinder_writer_data_append_remote_object(
|
||||
GBinderWriterData* data,
|
||||
GBinderRemoteObject* obj);
|
||||
|
||||
#endif /* GBINDER_WRITER_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
8
test/Makefile
Normal file
8
test/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
all:
|
||||
%:
|
||||
@$(MAKE) -C binder-client $*
|
||||
@$(MAKE) -C binder-list $*
|
||||
@$(MAKE) -C binder-service $*
|
||||
@$(MAKE) -C rild-card-status $*
|
||||
140
test/binder-client/Makefile
Normal file
140
test/binder-client/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-client
|
||||
|
||||
#
|
||||
# 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)
|
||||
331
test/binder-client/binder-client.c
Normal file
331
test/binder-client/binder-client.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <gbinder.h>
|
||||
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <glib-unix.h>
|
||||
|
||||
#define RET_OK (0)
|
||||
#define RET_NOTFOUND (1)
|
||||
#define RET_INVARG (2)
|
||||
#define RET_ERR (3)
|
||||
|
||||
#define DEFAULT_DEVICE "/dev/binder"
|
||||
#define DEFAULT_NAME "test"
|
||||
#define DEFAULT_IFACE "test@1.0"
|
||||
|
||||
typedef struct app_options {
|
||||
char* dev;
|
||||
char* iface;
|
||||
char* fqname;
|
||||
const char* name;
|
||||
} AppOptions;
|
||||
|
||||
typedef struct app {
|
||||
const AppOptions* opt;
|
||||
GMainLoop* loop;
|
||||
GBinderServiceManager* sm;
|
||||
GBinderLocalObject* local;
|
||||
GBinderClient* client;
|
||||
int ret;
|
||||
} App;
|
||||
|
||||
typedef struct app_input {
|
||||
App* app;
|
||||
char* str;
|
||||
} AppInput;
|
||||
|
||||
static const char pname[] = "binder-client";
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_signal(
|
||||
gpointer user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
GINFO("Caught signal, shutting down...");
|
||||
g_main_loop_quit(app->loop);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_remote_died(
|
||||
GBinderRemoteObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
GINFO("Remote has died, exiting...");
|
||||
g_main_loop_quit(app->loop);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_call(
|
||||
App* app,
|
||||
char* str)
|
||||
{
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(app->client);
|
||||
GBinderRemoteReply* reply;
|
||||
int status;
|
||||
|
||||
gbinder_local_request_append_string16(req, str);
|
||||
reply = gbinder_client_transact_sync_reply(app->client,
|
||||
GBINDER_FIRST_CALL_TRANSACTION, req, &status);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
if (status == GBINDER_STATUS_OK) {
|
||||
GBinderReader reader;
|
||||
char* ret;
|
||||
|
||||
gbinder_remote_reply_init_reader(reply, &reader);
|
||||
ret = gbinder_reader_read_string16(&reader);
|
||||
GDEBUG_("Reply: \"%s\"", ret);
|
||||
g_free(ret);
|
||||
} else {
|
||||
GERR_("status %d", status);
|
||||
}
|
||||
|
||||
gbinder_remote_reply_unref(reply);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_input(
|
||||
void* user_data)
|
||||
{
|
||||
AppInput* input = user_data;
|
||||
|
||||
GDEBUG_("\"%s\"", input->str);
|
||||
app_call(input->app, input->str);
|
||||
g_free(input->str);
|
||||
g_free(input);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gpointer
|
||||
app_input_thread(
|
||||
gpointer data)
|
||||
{
|
||||
int c;
|
||||
App* app = data;
|
||||
GString* buf = g_string_new("");
|
||||
|
||||
while ((c = getc(stdin)) != EOF) {
|
||||
if (c == '\n' || c == '\r') {
|
||||
AppInput* input = g_new0(AppInput, 1);
|
||||
|
||||
input->app = app;
|
||||
input->str = g_strdup(buf->str);
|
||||
g_idle_add(app_input, input);
|
||||
g_string_truncate(buf, 0);
|
||||
|
||||
while (c == '\n' || c == '\r') c = getc(stdin);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
} else {
|
||||
ungetc(c, stdin);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
g_string_append_c(buf, (char)c);
|
||||
}
|
||||
}
|
||||
|
||||
GDEBUG_("Input thread exiting...");
|
||||
g_string_free(buf, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_run(
|
||||
App* app)
|
||||
{
|
||||
const AppOptions* opt = app->opt;
|
||||
char* fqname = opt->fqname ? g_strdup(opt->fqname) :
|
||||
strchr(opt->name, '/') ? g_strdup(opt->name) :
|
||||
g_strconcat(opt->iface, "/", opt->name, NULL);
|
||||
int status = 0;
|
||||
GBinderRemoteObject* remote = gbinder_remote_object_ref
|
||||
(gbinder_servicemanager_get_service_sync(app->sm, fqname, &status));
|
||||
if (remote) {
|
||||
guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, app);
|
||||
guint sigint = g_unix_signal_add(SIGINT, app_signal, app);
|
||||
gulong death_id = gbinder_remote_object_add_death_handler
|
||||
(remote, app_remote_died, app);
|
||||
GThread* thread = g_thread_new("input", app_input_thread, app);
|
||||
|
||||
GINFO("Connected to %s\n", fqname);
|
||||
|
||||
app->client = gbinder_client_new(remote, opt->iface);
|
||||
app->ret = RET_OK;
|
||||
app->loop = g_main_loop_new(NULL, TRUE);
|
||||
g_main_loop_run(app->loop);
|
||||
|
||||
g_source_remove(sigtrm);
|
||||
g_source_remove(sigint);
|
||||
g_main_loop_unref(app->loop);
|
||||
|
||||
gbinder_remote_object_remove_handler(remote, death_id);
|
||||
gbinder_remote_object_unref(remote);
|
||||
|
||||
/* Not the cleanest exit, just dropping the thread... */
|
||||
g_thread_unref(thread);
|
||||
app->loop = NULL;
|
||||
} else {
|
||||
GERR("No such service: %s (%d)", fqname, status);
|
||||
}
|
||||
g_free(fqname);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_verbose(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_quiet(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_ERR;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_init(
|
||||
AppOptions* opt,
|
||||
int argc,
|
||||
char* argv[])
|
||||
{
|
||||
gboolean ok = FALSE;
|
||||
GOptionEntry entries[] = {
|
||||
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_verbose, "Enable verbose output", NULL },
|
||||
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_quiet, "Be quiet", NULL },
|
||||
{ "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
|
||||
"Binder device [" DEFAULT_DEVICE "]", "DEVICE" },
|
||||
{ "interface", 'i', 0, G_OPTION_ARG_STRING, &opt->iface,
|
||||
"Interface name [" DEFAULT_IFACE "]", "IFACE" },
|
||||
{ "fqname", 'n', 0, G_OPTION_ARG_STRING, &opt->fqname,
|
||||
"Fully qualified name [IFACE/NAME]", "FQNAME" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
GError* error = NULL;
|
||||
GOptionContext* options = g_option_context_new("[NAME]");
|
||||
|
||||
memset(opt, 0, sizeof(*opt));
|
||||
|
||||
gutil_log_timestamp = FALSE;
|
||||
gutil_log_set_type(GLOG_TYPE_STDERR, pname);
|
||||
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||
|
||||
g_option_context_add_main_entries(options, entries, NULL);
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
char* help;
|
||||
|
||||
if (!opt->dev || !opt->dev[0]) opt->dev = g_strdup(DEFAULT_DEVICE);
|
||||
if (!opt->iface || !opt->iface[0]) opt->iface = g_strdup(DEFAULT_IFACE);
|
||||
switch (argc) {
|
||||
case 2:
|
||||
opt->name = argv[1];
|
||||
ok = TRUE;
|
||||
break;
|
||||
case 1:
|
||||
opt->name = DEFAULT_NAME;
|
||||
ok = TRUE;
|
||||
break;
|
||||
default:
|
||||
help = g_option_context_get_help(options, TRUE, NULL);
|
||||
fprintf(stderr, "%s", help);
|
||||
g_free(help);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GERR("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
g_option_context_free(options);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
App app;
|
||||
AppOptions opt;
|
||||
|
||||
memset(&app, 0, sizeof(app));
|
||||
app.ret = RET_INVARG;
|
||||
app.opt = &opt;
|
||||
if (app_init(&opt, argc, argv)) {
|
||||
app.sm = gbinder_servicemanager_new(opt.dev);
|
||||
if (app.sm) {
|
||||
app.local = gbinder_servicemanager_new_local_object(app.sm,
|
||||
NULL, NULL, NULL);
|
||||
app_run(&app);
|
||||
gbinder_local_object_unref(app.local);
|
||||
gbinder_client_unref(app.client);
|
||||
gbinder_servicemanager_unref(app.sm);
|
||||
}
|
||||
}
|
||||
g_free(opt.fqname);
|
||||
g_free(opt.iface);
|
||||
g_free(opt.dev);
|
||||
return app.ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
140
test/binder-list/Makefile
Normal file
140
test/binder-list/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-list
|
||||
|
||||
#
|
||||
# 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)
|
||||
267
test/binder-list/binder-list.c
Normal file
267
test/binder-list/binder-list.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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 DEV_DEFAULT "/dev/binder"
|
||||
|
||||
typedef struct app_options {
|
||||
char* dev;
|
||||
const char* service;
|
||||
gboolean async;
|
||||
} AppOptions;
|
||||
|
||||
typedef struct app {
|
||||
const AppOptions* opt;
|
||||
GMainLoop* loop;
|
||||
GBinderServiceManager* sm;
|
||||
int ret;
|
||||
} App;
|
||||
|
||||
static const char pname[] = "binder-list";
|
||||
|
||||
static
|
||||
void
|
||||
app_print_strings(
|
||||
char** strv)
|
||||
{
|
||||
if (strv) {
|
||||
while (*strv) {
|
||||
printf("%s\n", *strv);
|
||||
strv++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_list_done(
|
||||
GBinderServiceManager* sm,
|
||||
char** services,
|
||||
void* user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
if (services) {
|
||||
app_print_strings(services);
|
||||
app->ret = RET_OK;
|
||||
}
|
||||
|
||||
g_main_loop_quit(app->loop);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_get_service_done(
|
||||
GBinderServiceManager* sm,
|
||||
GBinderRemoteObject* obj,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
if (obj) {
|
||||
printf("%s\n", app->opt->service);
|
||||
app->ret = RET_OK;
|
||||
} else {
|
||||
GERR("No such service: %s (%d)", app->opt->service, status);
|
||||
}
|
||||
|
||||
g_main_loop_quit(app->loop);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_async(
|
||||
App* app)
|
||||
{
|
||||
const char* name = app->opt->service;
|
||||
|
||||
app->loop = g_main_loop_new(NULL, TRUE);
|
||||
|
||||
if (name) {
|
||||
gbinder_servicemanager_get_service(app->sm, name,
|
||||
app_get_service_done, app);
|
||||
} else {
|
||||
gbinder_servicemanager_list(app->sm, app_list_done, app);
|
||||
}
|
||||
|
||||
g_main_loop_run(app->loop);
|
||||
g_main_loop_unref(app->loop);
|
||||
app->loop = NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_sync(
|
||||
App* app)
|
||||
{
|
||||
const AppOptions* opt = app->opt;
|
||||
if (opt->service) {
|
||||
int status = 0;
|
||||
GBinderRemoteObject* obj = gbinder_servicemanager_get_service_sync
|
||||
(app->sm, opt->service, &status);
|
||||
|
||||
if (obj) {
|
||||
printf("%s\n", opt->service);
|
||||
app->ret = RET_OK;
|
||||
} else {
|
||||
GERR("No such service: %s (%d)", opt->service, status);
|
||||
}
|
||||
} else {
|
||||
char** services = gbinder_servicemanager_list_sync(app->sm);
|
||||
|
||||
if (services) {
|
||||
app_print_strings(services);
|
||||
g_strfreev(services);
|
||||
app->ret = RET_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_verbose(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_quiet(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_ERR;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_init(
|
||||
AppOptions* opt,
|
||||
int argc,
|
||||
char* argv[])
|
||||
{
|
||||
gboolean ok = FALSE;
|
||||
GOptionEntry entries[] = {
|
||||
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_verbose, "Enable verbose output", NULL },
|
||||
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_quiet, "Be quiet", NULL },
|
||||
{ "async", 'a', 0, G_OPTION_ARG_NONE, &opt->async,
|
||||
"Parform operations asynchronously", NULL },
|
||||
{ "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
|
||||
"Binder device [" DEV_DEFAULT "]", "DEVICE" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
GError* error = NULL;
|
||||
GOptionContext* options = g_option_context_new("[SERVICE]");
|
||||
|
||||
memset(opt, 0, sizeof(*opt));
|
||||
|
||||
gutil_log_timestamp = FALSE;
|
||||
gutil_log_set_type(GLOG_TYPE_STDERR, pname);
|
||||
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||
|
||||
g_option_context_add_main_entries(options, entries, NULL);
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
char* help;
|
||||
|
||||
if (!opt->dev || !opt->dev[0]) opt->dev = g_strdup(DEV_DEFAULT);
|
||||
switch (argc) {
|
||||
case 2:
|
||||
opt->service = argv[1];
|
||||
/* no break */
|
||||
case 1:
|
||||
ok = TRUE;
|
||||
break;
|
||||
default:
|
||||
help = g_option_context_get_help(options, TRUE, NULL);
|
||||
fprintf(stderr, "%s", help);
|
||||
g_free(help);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GERR("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
g_option_context_free(options);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
App app;
|
||||
AppOptions opt;
|
||||
|
||||
memset(&app, 0, sizeof(app));
|
||||
app.ret = RET_INVARG;
|
||||
app.opt = &opt;
|
||||
if (app_init(&opt, argc, argv)) {
|
||||
app.sm = gbinder_servicemanager_new(opt.dev);
|
||||
if (app.sm) {
|
||||
if (opt.async) {
|
||||
app_async(&app);
|
||||
} else {
|
||||
app_sync(&app);
|
||||
}
|
||||
gbinder_servicemanager_unref(app.sm);
|
||||
}
|
||||
}
|
||||
g_free(opt.dev);
|
||||
return app.ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
140
test/binder-service/Makefile
Normal file
140
test/binder-service/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-service
|
||||
|
||||
#
|
||||
# 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)
|
||||
248
test/binder-service/binder-service.c
Normal file
248
test/binder-service/binder-service.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <gbinder.h>
|
||||
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <glib-unix.h>
|
||||
|
||||
#define RET_OK (0)
|
||||
#define RET_NOTFOUND (1)
|
||||
#define RET_INVARG (2)
|
||||
#define RET_ERR (3)
|
||||
|
||||
#define DEFAULT_DEVICE "/dev/binder"
|
||||
#define DEFAULT_NAME "test"
|
||||
#define DEFAULT_IFACE "test@1.0"
|
||||
|
||||
typedef struct app_options {
|
||||
char* dev;
|
||||
char* iface;
|
||||
const char* name;
|
||||
} AppOptions;
|
||||
|
||||
typedef struct app {
|
||||
const AppOptions* opt;
|
||||
GMainLoop* loop;
|
||||
GBinderServiceManager* sm;
|
||||
GBinderLocalObject* obj;
|
||||
int ret;
|
||||
} App;
|
||||
|
||||
static const char pname[] = "binder-service";
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_signal(
|
||||
gpointer user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
GINFO("Caught signal, shutting down...");
|
||||
g_main_loop_quit(app->loop);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
app_reply(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
char* str = gbinder_remote_request_read_string16(req);
|
||||
GBinderLocalReply* reply = gbinder_local_object_new_reply(obj);
|
||||
|
||||
GVERBOSE("\"%s\" %u", gbinder_remote_request_interface(req), code);
|
||||
GDEBUG("\"%s\"", str);
|
||||
gbinder_local_reply_append_string16(reply, str);
|
||||
g_free(str);
|
||||
*status = 0;
|
||||
return reply;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_add_service_done(
|
||||
GBinderServiceManager* sm,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
if (status == GBINDER_STATUS_OK) {
|
||||
printf("Added \"%s\"\n", app->opt->name);
|
||||
app->ret = RET_OK;
|
||||
} else {
|
||||
GERR("Failed to add \"%s\" (%d)", app->opt->name, status);
|
||||
g_main_loop_quit(app->loop);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_run(
|
||||
App* app)
|
||||
{
|
||||
const char* name = app->opt->name;
|
||||
guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, app);
|
||||
guint sigint = g_unix_signal_add(SIGINT, app_signal, app);
|
||||
|
||||
app->loop = g_main_loop_new(NULL, TRUE);
|
||||
|
||||
gbinder_servicemanager_add_service(app->sm, name, app->obj,
|
||||
app_add_service_done, app);
|
||||
|
||||
g_main_loop_run(app->loop);
|
||||
|
||||
if (sigtrm) g_source_remove(sigtrm);
|
||||
if (sigint) g_source_remove(sigint);
|
||||
g_main_loop_unref(app->loop);
|
||||
app->loop = NULL;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_verbose(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_quiet(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_ERR;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_init(
|
||||
AppOptions* opt,
|
||||
int argc,
|
||||
char* argv[])
|
||||
{
|
||||
gboolean ok = FALSE;
|
||||
GOptionEntry entries[] = {
|
||||
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_verbose, "Enable verbose output", NULL },
|
||||
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_quiet, "Be quiet", NULL },
|
||||
{ "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
|
||||
"Binder device [" DEFAULT_DEVICE "]", "DEVICE" },
|
||||
{ "interface", 'i', 0, G_OPTION_ARG_STRING, &opt->iface,
|
||||
"Local interface [" DEFAULT_IFACE "]", "IFACE" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
GError* error = NULL;
|
||||
GOptionContext* options = g_option_context_new("[NAME]");
|
||||
|
||||
memset(opt, 0, sizeof(*opt));
|
||||
|
||||
gutil_log_timestamp = FALSE;
|
||||
gutil_log_set_type(GLOG_TYPE_STDERR, pname);
|
||||
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||
|
||||
g_option_context_add_main_entries(options, entries, NULL);
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
char* help;
|
||||
|
||||
if (!opt->dev || !opt->dev[0]) opt->dev = g_strdup(DEFAULT_DEVICE);
|
||||
if (!opt->iface) opt->iface = g_strdup(DEFAULT_IFACE);
|
||||
switch (argc) {
|
||||
case 2:
|
||||
opt->name = argv[1];
|
||||
ok = TRUE;
|
||||
break;
|
||||
case 1:
|
||||
opt->name = DEFAULT_NAME;
|
||||
ok = TRUE;
|
||||
break;
|
||||
default:
|
||||
help = g_option_context_get_help(options, TRUE, NULL);
|
||||
fprintf(stderr, "%s", help);
|
||||
g_free(help);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GERR("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
g_option_context_free(options);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
App app;
|
||||
AppOptions opt;
|
||||
|
||||
memset(&app, 0, sizeof(app));
|
||||
app.ret = RET_INVARG;
|
||||
app.opt = &opt;
|
||||
if (app_init(&opt, argc, argv)) {
|
||||
app.sm = gbinder_servicemanager_new(opt.dev);
|
||||
if (app.sm) {
|
||||
app.obj = gbinder_servicemanager_new_local_object
|
||||
(app.sm, opt.iface, app_reply, &app);
|
||||
app_run(&app);
|
||||
gbinder_local_object_unref(app.obj);
|
||||
gbinder_servicemanager_unref(app.sm);
|
||||
}
|
||||
}
|
||||
g_free(opt.iface);
|
||||
g_free(opt.dev);
|
||||
return app.ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
140
test/rild-card-status/Makefile
Normal file
140
test/rild-card-status/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 = rild-card-status
|
||||
|
||||
#
|
||||
# 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)
|
||||
440
test/rild-card-status/rild-card-status.c
Normal file
440
test/rild-card-status/rild-card-status.c
Normal file
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_misc.h>
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <glib-unix.h>
|
||||
|
||||
#define RET_OK (0)
|
||||
#define RET_NOTFOUND (1)
|
||||
#define RET_INVARG (2)
|
||||
#define RET_ERR (3)
|
||||
|
||||
#define DEFAULT_DEVICE "/dev/hwbinder"
|
||||
#define DEFAULT_NAME "slot1"
|
||||
|
||||
#define IFACE_RADIO "android.hardware.radio@1.0::IRadio"
|
||||
#define IFACE_RESPONSE "android.hardware.radio@1.0::IRadioResponse"
|
||||
#define IFACE_INDICATION "android.hardware.radio@1.0::IRadioIndication"
|
||||
|
||||
/* android.hardware.radio@1.0::IRadio */
|
||||
#define REQ_RADIO_SET_RESPONSE_FUNCTIONS (1)
|
||||
#define REQ_RADIO_GET_ICC_CARD_STATUS (2)
|
||||
|
||||
/* android.hardware.radio@1.0::IRadioResponse */
|
||||
#define RESP_GET_ICC_CARD_STATUS_RESPONSE (1)
|
||||
|
||||
typedef struct app_options {
|
||||
char* dev;
|
||||
char* fqname;
|
||||
const char* name;
|
||||
} AppOptions;
|
||||
|
||||
typedef struct app {
|
||||
const AppOptions* opt;
|
||||
GMainLoop* loop;
|
||||
GBinderServiceManager* sm;
|
||||
GBinderLocalObject* response;
|
||||
GBinderLocalObject* indication;
|
||||
int ret;
|
||||
} App;
|
||||
|
||||
typedef struct radio_response_info {
|
||||
guint32 type;
|
||||
guint32 serial;
|
||||
guint32 error;
|
||||
} RadioResponseInfo;
|
||||
|
||||
typedef struct radio_string {
|
||||
union {
|
||||
guint64 value;
|
||||
const char* str;
|
||||
} data;
|
||||
guint32 len;
|
||||
guint32 owns_buffer;
|
||||
} RadioString;
|
||||
|
||||
typedef struct radio_app_status {
|
||||
guint32 appType;
|
||||
guint32 appState;
|
||||
guint32 persoSubstate;
|
||||
guint32 unused1;
|
||||
RadioString aid;
|
||||
RadioString label;
|
||||
guint32 pinReplaced;
|
||||
guint32 pin1;
|
||||
guint32 pin2;
|
||||
guint32 unused2;
|
||||
} RadioAppStatus;
|
||||
|
||||
typedef struct radio_card_status {
|
||||
guint32 cardState;
|
||||
guint32 universalPinState;
|
||||
guint32 gsmUmtsSubscriptionAppIndex;
|
||||
guint32 cdmaSubscriptionAppIndex;
|
||||
guint32 imsSubscriptionAppIndex;
|
||||
guint32 unused1;
|
||||
union {
|
||||
guint64 value;
|
||||
const RadioAppStatus* array;
|
||||
} apps;
|
||||
guint32 numApps;
|
||||
guint32 unused2;
|
||||
} RadioCardStatus;
|
||||
|
||||
static const char pname[] = "binder-client";
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_signal(
|
||||
gpointer user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
GINFO("Caught signal, shutting down...");
|
||||
g_main_loop_quit(app->loop);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_remote_died(
|
||||
GBinderRemoteObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
|
||||
GINFO("Remote has died, exiting...");
|
||||
g_main_loop_quit(app->loop);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
app_dump(
|
||||
const void* buf,
|
||||
gsize len)
|
||||
{
|
||||
const guint8* ptr = buf;
|
||||
while (len > 0) {
|
||||
char line[GUTIL_HEXDUMP_BUFSIZE];
|
||||
const guint consumed = gutil_hexdump(line, ptr, len);
|
||||
|
||||
GDEBUG(" %s", line);
|
||||
len -= consumed;
|
||||
ptr += consumed;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_decode_card_status(
|
||||
GBinderRemoteRequest* req)
|
||||
{
|
||||
GBinderReader reader;
|
||||
GBinderBuffer* buf;
|
||||
|
||||
gbinder_remote_request_init_reader(req, &reader);
|
||||
/* RadioResponseInfo */
|
||||
buf = gbinder_reader_read_buffer(&reader);
|
||||
if (buf) {
|
||||
const RadioResponseInfo* info = buf->data;
|
||||
|
||||
GASSERT(sizeof(*info) == buf->size);
|
||||
GDEBUG("RadioResponseInfo: type=%d serial=%d error=%d",
|
||||
(int)info->type, (int)info->serial, (int)info->error);
|
||||
app_dump(buf->data, buf->size);
|
||||
gbinder_buffer_free(buf);
|
||||
|
||||
/* CardStatus */
|
||||
buf = gbinder_reader_read_buffer(&reader);
|
||||
if (buf) {
|
||||
guint i;
|
||||
const RadioCardStatus* status = buf->data;
|
||||
|
||||
GINFO("CardStatus: state=%d pinState=%d gsmSubIndex=%d "
|
||||
"cdmsSubIndex=%d imsSubIndex=%d appCount=%u",
|
||||
(int)status->cardState, (int)status->universalPinState,
|
||||
(int)status->gsmUmtsSubscriptionAppIndex,
|
||||
(int)status->cdmaSubscriptionAppIndex,
|
||||
(int)status->imsSubscriptionAppIndex, status->numApps);
|
||||
GASSERT(sizeof(*status) == buf->size);
|
||||
app_dump(buf->data, buf->size);
|
||||
gbinder_buffer_free(buf);
|
||||
|
||||
for (i = 0; i < status->numApps; i++) {
|
||||
const RadioAppStatus* app = status->apps.array + i;
|
||||
|
||||
buf = gbinder_reader_read_buffer(&reader);
|
||||
GASSERT(buf->size == sizeof(RadioAppStatus));
|
||||
GINFO("AppStatus: type=%u state=%u substate=%u aid=%s "
|
||||
"label=%s pin_replaced=%u pin1=%u pin2=%u",
|
||||
app->appType, app->appState, app->persoSubstate,
|
||||
app->aid.data.str, app->label.data.str,
|
||||
app->pinReplaced, app->pin1, app->pin2);
|
||||
app_dump(buf->data, buf->size);
|
||||
gbinder_buffer_free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
IRadioIndication_transact(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
const char* iface = gbinder_remote_request_interface(req);
|
||||
|
||||
GDEBUG("%s %u", iface, code);
|
||||
if (!g_strcmp0(iface, IFACE_INDICATION)) {
|
||||
/* Those should all be one-way */
|
||||
GASSERT(flags & GBINDER_TX_FLAG_ONEWAY);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
} else {
|
||||
*status = GBINDER_STATUS_FAILED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
IRadioResponse_transact(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
App* app = user_data;
|
||||
const char* iface = gbinder_remote_request_interface(req);
|
||||
|
||||
if (!g_strcmp0(iface, IFACE_RESPONSE)) {
|
||||
/* Those should all be one-way */
|
||||
GASSERT(flags & GBINDER_TX_FLAG_ONEWAY);
|
||||
if (code == RESP_GET_ICC_CARD_STATUS_RESPONSE) {
|
||||
GDEBUG("%s getIccCardStatusResponse", iface);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
app_decode_card_status(req);
|
||||
g_main_loop_quit(app->loop);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
GDEBUG("%s %u", iface, code);
|
||||
*status = GBINDER_STATUS_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
app_run(
|
||||
App* app)
|
||||
{
|
||||
const AppOptions* opt = app->opt;
|
||||
char* fqname = opt->fqname ? g_strdup(opt->fqname) :
|
||||
strchr(opt->name, '/') ? g_strdup(opt->name) :
|
||||
g_strconcat(IFACE_RADIO "/", opt->name, NULL);
|
||||
int status = 0;
|
||||
GBinderRemoteObject* remote = gbinder_remote_object_ref
|
||||
(gbinder_servicemanager_get_service_sync(app->sm, fqname, &status));
|
||||
if (remote) {
|
||||
guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, app);
|
||||
guint sigint = g_unix_signal_add(SIGINT, app_signal, app);
|
||||
gulong death_id = gbinder_remote_object_add_death_handler
|
||||
(remote, app_remote_died, app);
|
||||
GBinderClient* client = gbinder_client_new(remote, IFACE_RADIO);
|
||||
GBinderLocalRequest* req;
|
||||
GBinderRemoteReply* reply;
|
||||
int status;
|
||||
|
||||
GINFO("Connected to %s", fqname);
|
||||
|
||||
app->ret = RET_OK;
|
||||
app->loop = g_main_loop_new(NULL, TRUE);
|
||||
|
||||
/* IRadio::setResponseFunctions */
|
||||
req = gbinder_client_new_request(client);
|
||||
gbinder_local_request_append_local_object(req, app->response);
|
||||
gbinder_local_request_append_local_object(req, app->indication);
|
||||
reply = gbinder_client_transact_sync_reply(client,
|
||||
REQ_RADIO_SET_RESPONSE_FUNCTIONS, req, &status);
|
||||
GDEBUG("setResponseFunctions status %d", status);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_remote_reply_unref(reply);
|
||||
|
||||
/* IRadio::getIccCardStatus */
|
||||
req = gbinder_client_new_request(client);
|
||||
gbinder_local_request_append_int32(req, 1 /* serial */);
|
||||
status = gbinder_client_transact_sync_oneway(client,
|
||||
REQ_RADIO_GET_ICC_CARD_STATUS, req);
|
||||
GDEBUG("getIccCardStatus status %d", status);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
g_main_loop_run(app->loop);
|
||||
|
||||
g_source_remove(sigtrm);
|
||||
g_source_remove(sigint);
|
||||
g_main_loop_unref(app->loop);
|
||||
|
||||
gbinder_remote_object_remove_handler(remote, death_id);
|
||||
gbinder_remote_object_unref(remote);
|
||||
gbinder_client_unref(client);
|
||||
app->loop = NULL;
|
||||
} else {
|
||||
GERR("No such service: %s (%d)", fqname, status);
|
||||
}
|
||||
g_free(fqname);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_verbose(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_log_quiet(
|
||||
const gchar* name,
|
||||
const gchar* value,
|
||||
gpointer data,
|
||||
GError** error)
|
||||
{
|
||||
gutil_log_default.level = GLOG_LEVEL_ERR;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
app_init(
|
||||
AppOptions* opt,
|
||||
int argc,
|
||||
char* argv[])
|
||||
{
|
||||
gboolean ok = FALSE;
|
||||
GOptionEntry entries[] = {
|
||||
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_verbose, "Enable verbose output", NULL },
|
||||
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
|
||||
app_log_quiet, "Be quiet", NULL },
|
||||
{ "device", 'd', 0, G_OPTION_ARG_STRING, &opt->dev,
|
||||
"Binder device [" DEFAULT_DEVICE "]", "DEVICE" },
|
||||
{ "fqname", 'n', 0, G_OPTION_ARG_STRING, &opt->fqname,
|
||||
"Fully qualified name", "FQNAME" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
GError* error = NULL;
|
||||
GOptionContext* options = g_option_context_new("[NAME]");
|
||||
|
||||
memset(opt, 0, sizeof(*opt));
|
||||
|
||||
gutil_log_timestamp = FALSE;
|
||||
gutil_log_set_type(GLOG_TYPE_STDERR, pname);
|
||||
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
|
||||
|
||||
g_option_context_add_main_entries(options, entries, NULL);
|
||||
if (g_option_context_parse(options, &argc, &argv, &error)) {
|
||||
char* help;
|
||||
|
||||
if (!opt->dev || !opt->dev[0]) opt->dev = g_strdup(DEFAULT_DEVICE);
|
||||
switch (argc) {
|
||||
case 2:
|
||||
opt->name = argv[1];
|
||||
ok = TRUE;
|
||||
break;
|
||||
case 1:
|
||||
opt->name = DEFAULT_NAME;
|
||||
ok = TRUE;
|
||||
break;
|
||||
default:
|
||||
help = g_option_context_get_help(options, TRUE, NULL);
|
||||
fprintf(stderr, "%s", help);
|
||||
g_free(help);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GERR("%s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
g_option_context_free(options);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
App app;
|
||||
AppOptions opt;
|
||||
|
||||
memset(&app, 0, sizeof(app));
|
||||
app.ret = RET_INVARG;
|
||||
app.opt = &opt;
|
||||
if (app_init(&opt, argc, argv)) {
|
||||
app.sm = gbinder_servicemanager_new(opt.dev);
|
||||
if (app.sm) {
|
||||
app.indication = gbinder_servicemanager_new_local_object(app.sm,
|
||||
IFACE_INDICATION, IRadioIndication_transact, &app);
|
||||
app.response = gbinder_servicemanager_new_local_object(app.sm,
|
||||
IFACE_RESPONSE, IRadioResponse_transact, &app);
|
||||
app_run(&app);
|
||||
gbinder_local_object_unref(app.indication);
|
||||
gbinder_local_object_unref(app.response);
|
||||
gbinder_servicemanager_unref(app.sm);
|
||||
}
|
||||
}
|
||||
g_free(opt.fqname);
|
||||
g_free(opt.dev);
|
||||
return app.ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
21
unit/Makefile
Normal file
21
unit/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
all:
|
||||
%:
|
||||
@$(MAKE) -C unit_buffer $*
|
||||
@$(MAKE) -C unit_client $*
|
||||
@$(MAKE) -C unit_driver $*
|
||||
@$(MAKE) -C unit_ipc $*
|
||||
@$(MAKE) -C unit_local_object $*
|
||||
@$(MAKE) -C unit_local_reply $*
|
||||
@$(MAKE) -C unit_local_request $*
|
||||
@$(MAKE) -C unit_protocol $*
|
||||
@$(MAKE) -C unit_reader $*
|
||||
@$(MAKE) -C unit_remote_object $*
|
||||
@$(MAKE) -C unit_remote_reply $*
|
||||
@$(MAKE) -C unit_remote_request $*
|
||||
@$(MAKE) -C unit_writer $*
|
||||
|
||||
clean: unitclean
|
||||
rm -f coverage/*.gcov
|
||||
rm -fr coverage/report
|
||||
185
unit/common/Makefile
Normal file
185
unit/common/Makefile
Normal file
@@ -0,0 +1,185 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
.PHONY: clean all debug release coverage
|
||||
.PHONY: debug_lib release_lib coverage_lib
|
||||
|
||||
#
|
||||
# Real test makefile defines EXE (and possibly SRC) and includes this one.
|
||||
#
|
||||
|
||||
ifndef EXE
|
||||
${error EXE not defined}
|
||||
endif
|
||||
|
||||
SRC ?= $(EXE).c
|
||||
COMMON_SRC ?= test_binder.c test_main.c
|
||||
|
||||
#
|
||||
# Required packages
|
||||
#
|
||||
|
||||
PKGS += libglibutil glib-2.0 gobject-2.0
|
||||
|
||||
#
|
||||
# Default target
|
||||
#
|
||||
|
||||
all: debug release
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
SRC_DIR = .
|
||||
LIB_DIR = ../..
|
||||
COMMON_DIR = ../common
|
||||
BUILD_DIR = build
|
||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
|
||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
|
||||
COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
|
||||
|
||||
#
|
||||
# Tools and flags
|
||||
#
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CC)
|
||||
WARNINGS += -Wall
|
||||
INCLUDES += -I$(COMMON_DIR) -I$(LIB_DIR)/src -I$(LIB_DIR)/include
|
||||
BASE_FLAGS = -fPIC
|
||||
BASE_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS)
|
||||
BASE_CFLAGS = $(BASE_FLAGS) $(CFLAGS)
|
||||
FULL_CFLAGS = $(BASE_CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
|
||||
$(shell pkg-config --cflags $(PKGS))
|
||||
FULL_LDFLAGS = $(BASE_LDFLAGS)
|
||||
LIBS = $(shell pkg-config --libs $(PKGS))
|
||||
QUIET_MAKE = make --no-print-directory
|
||||
DEBUG_FLAGS = -g
|
||||
RELEASE_FLAGS =
|
||||
COVERAGE_FLAGS = -g
|
||||
|
||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
|
||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
|
||||
COVERAGE_LDFLAGS = $(FULL_LDFLAGS) $(COVERAGE_FLAGS) --coverage
|
||||
|
||||
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
|
||||
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
|
||||
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
|
||||
|
||||
DEBUG_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_lib)
|
||||
RELEASE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_lib)
|
||||
COVERAGE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_coverage_lib)
|
||||
|
||||
DEBUG_LIB = $(LIB_DIR)/$(DEBUG_LIB_FILE)
|
||||
RELEASE_LIB = $(LIB_DIR)/$(RELEASE_LIB_FILE)
|
||||
COVERAGE_LIB = $(LIB_DIR)/$(COVERAGE_LIB_FILE)
|
||||
|
||||
DEBUG_LIBS = $(DEBUG_LIB) $(LIBS)
|
||||
RELEASE_LIBS = $(RELEASE_LIB) $(LIBS)
|
||||
COVERAGE_LIBS = $(COVERAGE_LIB) $(LIBS)
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
|
||||
DEBUG_OBJS = \
|
||||
$(COMMON_SRC:%.c=$(DEBUG_BUILD_DIR)/common_%.o) \
|
||||
$(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
|
||||
RELEASE_OBJS = \
|
||||
$(COMMON_SRC:%.c=$(RELEASE_BUILD_DIR)/common_%.o) \
|
||||
$(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
|
||||
COVERAGE_OBJS = \
|
||||
$(COMMON_SRC:%.c=$(COVERAGE_BUILD_DIR)/common_%.o) \
|
||||
$(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o)
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(strip $(DEPS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(DEBUG_EXE) $(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
|
||||
$(RELEASE_EXE) $(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
|
||||
$(COVERAGE_EXE) $(COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR)
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
|
||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
|
||||
COVERAGE_EXE = $(COVERAGE_BUILD_DIR)/$(EXE)
|
||||
|
||||
debug: debug_lib $(DEBUG_EXE)
|
||||
|
||||
release: release_lib $(RELEASE_EXE)
|
||||
|
||||
coverage: coverage_lib $(COVERAGE_EXE)
|
||||
|
||||
unitclean:
|
||||
rm -f *~
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
clean: unitclean
|
||||
|
||||
cleaner: unitclean
|
||||
@make -C $(LIB_DIR) clean
|
||||
|
||||
test_banner:
|
||||
@echo "===========" $(EXE) "=========== "
|
||||
|
||||
test: test_banner debug
|
||||
@LD_LIBRARY_PATH="$(LIB_DIR)/$(DEBUG_LIB_PATH)" $(DEBUG_EXE)
|
||||
|
||||
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)
|
||||
|
||||
$(DEBUG_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(RELEASE_BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
$(COVERAGE_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 $@
|
||||
|
||||
$(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
|
||||
$(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c
|
||||
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(RELEASE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c
|
||||
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(COVERAGE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c
|
||||
$(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
|
||||
|
||||
$(DEBUG_EXE): $(DEBUG_PLUGIN_LIB) $(DEBUG_OBJS)
|
||||
$(LD) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) $(DEBUG_LIBS) -o $@
|
||||
|
||||
$(RELEASE_EXE): $(RELEASE_PLUGIN_LIB) $(RELEASE_OBJS)
|
||||
$(LD) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) $(RELEASE_LIBS) -o $@
|
||||
|
||||
$(COVERAGE_EXE): $(COVERAGE_PLUGIN_LIB) $(COVERAGE_OBJS)
|
||||
$(LD) $(COVERAGE_LDFLAGS) $(COVERAGE_OBJS) $(COVERAGE_LIBS) -o $@
|
||||
|
||||
debug_lib:
|
||||
$(MAKE) -C $(LIB_DIR) $@
|
||||
|
||||
release_lib:
|
||||
$(MAKE) -C $(LIB_DIR) $@
|
||||
|
||||
coverage_lib:
|
||||
$(MAKE) -C $(LIB_DIR) $@
|
||||
548
unit/common/test_binder.c
Normal file
548
unit/common/test_binder.c
Normal file
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_system.h"
|
||||
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
static GHashTable* test_fd_map = NULL;
|
||||
static GHashTable* test_node_map = NULL;
|
||||
|
||||
#define public_fd fd[0]
|
||||
#define private_fd fd[1]
|
||||
|
||||
#define BINDER_VERSION _IOWR('b', 9, gint32)
|
||||
#define BINDER_SET_MAX_THREADS _IOW('b', 5, guint32)
|
||||
|
||||
#define TF_ONE_WAY 0x01
|
||||
#define TF_ROOT_OBJECT 0x04
|
||||
#define TF_STATUS_CODE 0x08
|
||||
#define TF_ACCEPT_FDS 0x10
|
||||
|
||||
typedef struct test_binder_io TestBinderIo;
|
||||
|
||||
typedef struct test_binder_node {
|
||||
char* path;
|
||||
int refcount;
|
||||
const TestBinderIo* io;
|
||||
} TestBinderNode;
|
||||
|
||||
typedef struct test_binder {
|
||||
TestBinderNode* node;
|
||||
int fd[2];
|
||||
} TestBinder;
|
||||
|
||||
struct test_binder_io {
|
||||
int version;
|
||||
int write_read_request;
|
||||
int (*handle_write_read)(TestBinder* binder, void* data);
|
||||
};
|
||||
|
||||
typedef struct binder_write_read_64 {
|
||||
guint64 write_size;
|
||||
guint64 write_consumed;
|
||||
guint64 write_buffer;
|
||||
guint64 read_size;
|
||||
guint64 read_consumed;
|
||||
guint64 read_buffer;
|
||||
} BinderWriteRead64;
|
||||
|
||||
typedef struct binder_transaction_data_64 {
|
||||
guint64 handle;
|
||||
guint64 cookie;
|
||||
guint32 code;
|
||||
guint32 flags;
|
||||
gint32 sender_pid;
|
||||
gint32 sender_euid;
|
||||
guint64 data_size;
|
||||
guint64 offsets_size;
|
||||
guint64 data_buffer;
|
||||
guint64 data_offsets;
|
||||
} BinderTransactionData64;
|
||||
|
||||
typedef struct binder_pre_cookie_64 {
|
||||
guint64 ptr;
|
||||
guint64 cookie;
|
||||
} BinderPtrCookie64;
|
||||
|
||||
#define BC_TRANSACTION_64 _IOW('c', 0, BinderTransactionData64)
|
||||
#define BC_REPLY_64 _IOW('c', 1, BinderTransactionData64)
|
||||
#define BC_FREE_BUFFER_64 _IOW('c', 3, guint64)
|
||||
#define BC_INCREFS _IOW('c', 4, guint32)
|
||||
#define BC_ACQUIRE _IOW('c', 5, guint32)
|
||||
#define BC_RELEASE _IOW('c', 6, guint32)
|
||||
#define BC_DECREFS _IOW('c', 7, guint32)
|
||||
#define BC_ENTER_LOOPER _IO('c', 12)
|
||||
#define BC_EXIT_LOOPER _IO('c', 13)
|
||||
|
||||
#define BR_TRANSACTION_64 _IOR('r', 2, BinderTransactionData64)
|
||||
#define BR_REPLY_64 _IOR('r', 3, BinderTransactionData64)
|
||||
#define BR_DEAD_REPLY _IO('r', 5)
|
||||
#define BR_TRANSACTION_COMPLETE _IO('r', 6)
|
||||
#define BR_INCREFS_64 _IOR('r', 7, BinderPtrCookie64)
|
||||
#define BR_ACQUIRE_64 _IOR('r', 8, BinderPtrCookie64)
|
||||
#define BR_RELEASE_64 _IOR('r', 9, BinderPtrCookie64)
|
||||
#define BR_DECREFS_64 _IOR('r', 10, BinderPtrCookie64)
|
||||
#define BR_NOOP _IO('r', 12)
|
||||
#define BR_DEAD_BINDER_64 _IOR('r', 15, guint64)
|
||||
#define BR_FAILED_REPLY _IO('r', 17)
|
||||
|
||||
static
|
||||
int
|
||||
test_io_handle_write_read_64(
|
||||
TestBinder* binder,
|
||||
void* data)
|
||||
{
|
||||
int err, bytes_available = 0;
|
||||
BinderWriteRead64* wr = data;
|
||||
gssize bytes_left = wr->write_size - wr->write_consumed;
|
||||
const guint8* write_ptr = (void*)(gsize)
|
||||
(wr->write_buffer + wr->write_consumed);
|
||||
|
||||
while (bytes_left >= sizeof(guint32)) {
|
||||
const guint cmd = *(guint32*)write_ptr;
|
||||
const guint cmdsize = _IOC_SIZE(cmd);
|
||||
|
||||
GASSERT(bytes_left >= (sizeof(guint32) + cmdsize));
|
||||
if (bytes_left >= (sizeof(guint32) + cmdsize)) {
|
||||
wr->write_consumed += sizeof(guint32);
|
||||
write_ptr += sizeof(guint32);
|
||||
bytes_left -= sizeof(guint32);
|
||||
|
||||
switch (cmd) {
|
||||
case BC_TRANSACTION_64:
|
||||
case BC_REPLY_64:
|
||||
/* Is there anything special about transactions and replies? */
|
||||
break;
|
||||
case BC_FREE_BUFFER_64:
|
||||
g_free((void*)(gsize)(*(guint64*)write_ptr));
|
||||
break;
|
||||
case BC_INCREFS:
|
||||
case BC_ACQUIRE:
|
||||
case BC_RELEASE:
|
||||
case BC_DECREFS:
|
||||
case BC_ENTER_LOOPER:
|
||||
case BC_EXIT_LOOPER:
|
||||
break;
|
||||
default:
|
||||
#pragma message("TODO: implement more BINDER_WRITE_READ commands")
|
||||
GDEBUG("Unhandled command 0x%08x", cmd);
|
||||
break;
|
||||
}
|
||||
wr->write_consumed += cmdsize;
|
||||
write_ptr += cmdsize;
|
||||
bytes_left -= cmdsize;
|
||||
} else {
|
||||
/* Partial command in the buffer */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now read the data from the socket */
|
||||
err = ioctl(binder->public_fd, FIONREAD, &bytes_available);
|
||||
if (err >= 0) {
|
||||
int bytes_read = 0;
|
||||
if (bytes_available > 0) {
|
||||
bytes_read = read(binder->public_fd,
|
||||
(void*)(gsize)(wr->read_buffer + wr->read_consumed),
|
||||
wr->read_size - wr->read_consumed);
|
||||
}
|
||||
|
||||
if (bytes_read >= 0) {
|
||||
wr->read_consumed += bytes_read;
|
||||
return 0;
|
||||
} else {
|
||||
err = bytes_read;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static const TestBinderIo test_io_64 = {
|
||||
.version = 8,
|
||||
.write_read_request = _IOWR('b', 1, BinderWriteRead64),
|
||||
.handle_write_read = test_io_handle_write_read_64
|
||||
};
|
||||
|
||||
static
|
||||
int
|
||||
test_binder_ioctl_version(
|
||||
TestBinder* binder,
|
||||
int* version)
|
||||
{
|
||||
*version = binder->node->io->version;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_binder_node_unref(
|
||||
TestBinderNode* node)
|
||||
{
|
||||
node->refcount--;
|
||||
if (!node->refcount) {
|
||||
g_hash_table_remove(test_node_map, node->path);
|
||||
g_free(node->path);
|
||||
g_free(node);
|
||||
}
|
||||
if (!g_hash_table_size(test_node_map)) {
|
||||
g_hash_table_unref(test_node_map);
|
||||
test_node_map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_binder_push_data(
|
||||
int fd,
|
||||
const void* data)
|
||||
{
|
||||
GASSERT(test_fd_map);
|
||||
if (test_fd_map) {
|
||||
gpointer key = GINT_TO_POINTER(fd);
|
||||
TestBinder* binder = g_hash_table_lookup(test_fd_map, key);
|
||||
|
||||
GASSERT(binder);
|
||||
if (binder) {
|
||||
const guint32* cmd = data;
|
||||
const int len = sizeof(*cmd) + _IOC_SIZE(*cmd);
|
||||
|
||||
return write(binder->private_fd, data, len) == len;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_binder_fill_transaction_data(
|
||||
BinderTransactionData64* tr,
|
||||
guint64 handle,
|
||||
guint32 code,
|
||||
const GByteArray* bytes)
|
||||
{
|
||||
g_assert(bytes);
|
||||
|
||||
memset(tr, 0, sizeof(*tr));
|
||||
tr->handle = handle;
|
||||
tr->code = code;
|
||||
tr->data_size = bytes->len;
|
||||
/* This memory should eventually get deallocated with BC_FREE_BUFFER_64 */
|
||||
tr->data_buffer = (gsize)g_memdup(bytes->data, bytes->len);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_push_ptr_cookie(
|
||||
int fd,
|
||||
guint32 cmd,
|
||||
void* ptr)
|
||||
{
|
||||
guint8 buf[sizeof(guint32) + sizeof(BinderPtrCookie64)];
|
||||
BinderPtrCookie64* data = (void*)(buf + sizeof(cmd));
|
||||
|
||||
memcpy(buf, &cmd, sizeof(cmd));
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->ptr = (gsize)ptr;
|
||||
return test_binder_push_data(fd, buf);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_noop(
|
||||
int fd)
|
||||
{
|
||||
guint32 cmd = BR_NOOP;
|
||||
|
||||
return test_binder_push_data(fd, &cmd);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_increfs(
|
||||
int fd,
|
||||
void* ptr)
|
||||
{
|
||||
return test_binder_push_ptr_cookie(fd, BR_INCREFS_64, ptr);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_acquire(
|
||||
int fd,
|
||||
void* ptr)
|
||||
{
|
||||
return test_binder_push_ptr_cookie(fd, BR_ACQUIRE_64, ptr);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_release(
|
||||
int fd,
|
||||
void* ptr)
|
||||
{
|
||||
return test_binder_push_ptr_cookie(fd, BR_RELEASE_64, ptr);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_decrefs(
|
||||
int fd,
|
||||
void* ptr)
|
||||
{
|
||||
return test_binder_push_ptr_cookie(fd, BR_DECREFS_64, ptr);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_transaction_complete(
|
||||
int fd)
|
||||
{
|
||||
guint32 cmd = BR_TRANSACTION_COMPLETE;
|
||||
|
||||
return test_binder_push_data(fd, &cmd);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_dead_binder(
|
||||
int fd,
|
||||
guint handle)
|
||||
{
|
||||
const guint64 handle64 = handle;
|
||||
guint32 buf[3];
|
||||
|
||||
buf[0] = BR_DEAD_BINDER_64;
|
||||
memcpy(buf + 1, &handle64, sizeof(handle64));
|
||||
|
||||
return test_binder_push_data(fd, buf);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_dead_reply(
|
||||
int fd)
|
||||
{
|
||||
guint32 cmd = BR_DEAD_REPLY;
|
||||
|
||||
return test_binder_push_data(fd, &cmd);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_failed_reply(
|
||||
int fd)
|
||||
{
|
||||
guint32 cmd = BR_FAILED_REPLY;
|
||||
|
||||
return test_binder_push_data(fd, &cmd);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_transaction(
|
||||
int fd,
|
||||
void* target,
|
||||
guint32 code,
|
||||
const GByteArray* bytes)
|
||||
{
|
||||
guint32 cmd = BR_TRANSACTION_64;
|
||||
guint8 buf[sizeof(guint32) + sizeof(BinderTransactionData64)];
|
||||
|
||||
memcpy(buf, &cmd, sizeof(cmd));
|
||||
test_binder_fill_transaction_data((void*)(buf + sizeof(cmd)),
|
||||
(gsize)target, code, bytes);
|
||||
|
||||
return test_binder_push_data(fd, buf);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_reply(
|
||||
int fd,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* bytes)
|
||||
{
|
||||
guint32 cmd = BR_REPLY_64;
|
||||
guint8 buf[sizeof(guint32) + sizeof(BinderTransactionData64)];
|
||||
|
||||
memcpy(buf, &cmd, sizeof(cmd));
|
||||
test_binder_fill_transaction_data((void*)(buf + sizeof(cmd)),
|
||||
handle, code, bytes);
|
||||
|
||||
return test_binder_push_data(fd, buf);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_binder_br_reply_status(
|
||||
int fd,
|
||||
gint32 status)
|
||||
{
|
||||
guint8 buf[sizeof(guint32) + sizeof(BinderTransactionData64)];
|
||||
guint32* cmd = (void*)buf;
|
||||
BinderTransactionData64* tr = (void*)(buf + sizeof(*cmd));
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
*cmd = BR_REPLY_64;
|
||||
tr->flags = TF_STATUS_CODE;
|
||||
tr->data_size = sizeof(status);
|
||||
/* This memory should eventually get deallocated with BC_FREE_BUFFER_64 */
|
||||
tr->data_buffer = (gsize)g_memdup(&status, sizeof(status));
|
||||
return test_binder_push_data(fd, buf);
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_system_open(
|
||||
const char* path,
|
||||
int flags)
|
||||
{
|
||||
if (path && g_str_has_prefix(path, "/dev") &&
|
||||
g_str_has_suffix(path, "binder")) {
|
||||
TestBinderNode* node = NULL;
|
||||
TestBinder* binder = NULL;
|
||||
int fd;
|
||||
|
||||
if (test_node_map) {
|
||||
node = g_hash_table_lookup(test_node_map, path);
|
||||
}
|
||||
if (node) {
|
||||
node->refcount++;
|
||||
} else {
|
||||
node = g_new0(TestBinderNode, 1);
|
||||
node->path = g_strdup(path);
|
||||
node->refcount = 1;
|
||||
node->io = &test_io_64;
|
||||
if (!test_node_map) {
|
||||
test_node_map = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
}
|
||||
g_hash_table_replace(test_node_map, node->path, node);
|
||||
}
|
||||
|
||||
binder = g_new0(TestBinder, 1);
|
||||
binder->node = node;
|
||||
socketpair(AF_UNIX, SOCK_STREAM, 0, binder->fd);
|
||||
fd = binder->public_fd;
|
||||
|
||||
if (!test_fd_map) {
|
||||
test_fd_map = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
}
|
||||
g_hash_table_replace(test_fd_map, GINT_TO_POINTER(fd), binder);
|
||||
return fd;
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_system_close(
|
||||
int fd)
|
||||
{
|
||||
GASSERT(test_fd_map);
|
||||
if (test_fd_map) {
|
||||
gpointer key = GINT_TO_POINTER(fd);
|
||||
TestBinder* binder = g_hash_table_lookup(test_fd_map, key);
|
||||
|
||||
GASSERT(binder);
|
||||
if (binder) {
|
||||
g_hash_table_remove(test_fd_map, key);
|
||||
if (!g_hash_table_size(test_fd_map)) {
|
||||
g_hash_table_unref(test_fd_map);
|
||||
test_fd_map = NULL;
|
||||
}
|
||||
test_binder_node_unref(binder->node);
|
||||
close(binder->public_fd);
|
||||
close(binder->private_fd);
|
||||
g_free(binder);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_system_ioctl(
|
||||
int fd,
|
||||
int request,
|
||||
void* data)
|
||||
{
|
||||
GASSERT(test_fd_map);
|
||||
if (test_fd_map) {
|
||||
gpointer key = GINT_TO_POINTER(fd);
|
||||
TestBinder* binder = g_hash_table_lookup(test_fd_map, key);
|
||||
|
||||
GASSERT(binder);
|
||||
if (binder) {
|
||||
const TestBinderIo* io = binder->node->io;
|
||||
|
||||
switch (request) {
|
||||
case BINDER_VERSION:
|
||||
return test_binder_ioctl_version(binder, data);
|
||||
case BINDER_SET_MAX_THREADS:
|
||||
return 0;
|
||||
default:
|
||||
if (request == io->write_read_request) {
|
||||
return io->handle_write_read(binder, data);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void*
|
||||
gbinder_system_mmap(
|
||||
size_t length,
|
||||
int prot,
|
||||
int flags,
|
||||
int fd)
|
||||
{
|
||||
return g_malloc(length);
|
||||
}
|
||||
|
||||
int
|
||||
gbinder_system_munmap(
|
||||
void* addr,
|
||||
size_t length)
|
||||
{
|
||||
g_free(addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
106
unit/common/test_binder.h
Normal file
106
unit/common/test_binder.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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 TEST_BINDER_H
|
||||
#define TEST_BINDER_H
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
gboolean
|
||||
test_binder_br_noop(
|
||||
int fd);
|
||||
|
||||
gboolean
|
||||
test_binder_br_increfs(
|
||||
int fd,
|
||||
void* ptr);
|
||||
|
||||
gboolean
|
||||
test_binder_br_acquire(
|
||||
int fd,
|
||||
void* ptr);
|
||||
|
||||
gboolean
|
||||
test_binder_br_release(
|
||||
int fd,
|
||||
void* ptr);
|
||||
|
||||
gboolean
|
||||
test_binder_br_decrefs(
|
||||
int fd,
|
||||
void* ptr);
|
||||
|
||||
gboolean
|
||||
test_binder_br_transaction_complete(
|
||||
int fd);
|
||||
|
||||
gboolean
|
||||
test_binder_br_dead_binder(
|
||||
int fd,
|
||||
guint handle);
|
||||
|
||||
gboolean
|
||||
test_binder_br_dead_reply(
|
||||
int fd);
|
||||
|
||||
gboolean
|
||||
test_binder_br_failed_reply(
|
||||
int fd);
|
||||
|
||||
gboolean
|
||||
test_binder_br_transaction(
|
||||
int fd,
|
||||
void* target,
|
||||
guint32 code,
|
||||
const GByteArray* bytes);
|
||||
|
||||
gboolean
|
||||
test_binder_br_reply(
|
||||
int fd,
|
||||
guint32 handle,
|
||||
guint32 code,
|
||||
const GByteArray* bytes);
|
||||
|
||||
gboolean
|
||||
test_binder_br_reply_status(
|
||||
int fd,
|
||||
gint32 status);
|
||||
|
||||
#endif /* TEST_BINDER_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
102
unit/common/test_common.h
Normal file
102
unit/common/test_common.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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 TEST_COMMON_H
|
||||
#define TEST_COMMON_H
|
||||
|
||||
#include <gbinder_types.h>
|
||||
|
||||
#define TEST_FLAG_DEBUG (0x01)
|
||||
typedef struct test_opt {
|
||||
int flags;
|
||||
} TestOpt;
|
||||
|
||||
/* Should be invoked after g_test_init */
|
||||
void
|
||||
test_init(
|
||||
TestOpt* opt,
|
||||
int argc,
|
||||
char* argv[]);
|
||||
|
||||
/* Run loop with a timeout */
|
||||
void
|
||||
test_run(
|
||||
const TestOpt* opt,
|
||||
GMainLoop* loop);
|
||||
|
||||
/* Quits the event loop on the next iteration */
|
||||
void
|
||||
test_quit_later(
|
||||
GMainLoop* loop);
|
||||
|
||||
#define TEST_TIMEOUT_SEC (20)
|
||||
|
||||
/* Helper macros */
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
# define TEST_INT16_BYTES(v) \
|
||||
(guint8)(v), (guint8)((v) >> 8)
|
||||
# define TEST_INT32_BYTES(v) \
|
||||
(guint8)(v), (guint8)((v) >> 8), \
|
||||
(guint8)((v) >> 16), (guint8)((v) >> 24)
|
||||
# define TEST_INT64_BYTES(v) \
|
||||
(guint8)(v), (guint8)((v) >> 8), \
|
||||
(guint8)((v) >> 16), (guint8)((v) >> 24), \
|
||||
(guint8)(((guint64)(v)) >> 32), (guint8)(((guint64)(v)) >> 40), \
|
||||
(guint8)(((guint64)(v)) >> 48), (guint8)(((guint64)(v)) >> 56)
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
# define TEST_INT16_BYTES(v) \
|
||||
(guint8)((v) >> 8), (guint8)(v)
|
||||
# define TEST_INT32_BYTES(v) \
|
||||
(guint8)((v) >> 24), (guint8)((v) >> 16), \
|
||||
(guint8)((v) >> 8), (guint8)(v)
|
||||
# define TEST_INT64_BYTES(v) \
|
||||
(guint8)(((guint64)(v)) >> 56), (guint8)(((guint64)(v)) >> 48), \
|
||||
(guint8)(((guint64)(v)) >> 40), (guint8)(((guint64)(v)) >> 32), \
|
||||
(guint8)((v) >> 24), (guint8)((v) >> 16), \
|
||||
(guint8)((v) >> 8), (guint8)(v)
|
||||
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||
#error unknown ENDIAN type
|
||||
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||
|
||||
#define TEST_ARRAY_AND_COUNT(a) a, G_N_ELEMENTS(a)
|
||||
#define TEST_ARRAY_AND_SIZE(a) a, sizeof(a)
|
||||
|
||||
#endif /* TEST_COMMON_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
116
unit/common/test_main.c
Normal file
116
unit/common/test_main.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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 <gutil_log.h>
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_timeout_expired(
|
||||
gpointer data)
|
||||
{
|
||||
g_assert(!"TIMEOUT");
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_quit_later_cb(
|
||||
gpointer data)
|
||||
{
|
||||
g_main_loop_quit((GMainLoop*)data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
test_quit_later(
|
||||
GMainLoop* loop)
|
||||
{
|
||||
g_idle_add(test_quit_later_cb, loop);
|
||||
}
|
||||
|
||||
void
|
||||
test_run(
|
||||
const TestOpt* opt,
|
||||
GMainLoop* loop)
|
||||
{
|
||||
if (opt->flags & TEST_FLAG_DEBUG) {
|
||||
g_main_loop_run(loop);
|
||||
} else {
|
||||
const guint timeout_id = g_timeout_add_seconds(TEST_TIMEOUT_SEC,
|
||||
test_timeout_expired, NULL);
|
||||
g_main_loop_run(loop);
|
||||
g_source_remove(timeout_id);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_init(
|
||||
TestOpt* opt,
|
||||
int argc,
|
||||
char* argv[])
|
||||
{
|
||||
const char* sep1;
|
||||
const char* sep2;
|
||||
int i;
|
||||
|
||||
memset(opt, 0, sizeof(*opt));
|
||||
for (i=1; i<argc; i++) {
|
||||
const char* arg = argv[i];
|
||||
if (!strcmp(arg, "-d") || !strcmp(arg, "--debug")) {
|
||||
opt->flags |= TEST_FLAG_DEBUG;
|
||||
} else if (!strcmp(arg, "-v")) {
|
||||
GTestConfig* config = (GTestConfig*)g_test_config_vars;
|
||||
config->test_verbose = TRUE;
|
||||
} else {
|
||||
GWARN("Unsupported command line option %s", arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup logging */
|
||||
sep1 = strrchr(argv[0], '/');
|
||||
sep2 = strrchr(argv[0], '\\');
|
||||
gutil_log_default.name = (sep1 && sep2) ? (MAX(sep1, sep2) + 1) :
|
||||
sep1 ? (sep1 + 1) : sep2 ? (sep2 + 1) : argv[0];
|
||||
gutil_log_default.level = g_test_verbose() ?
|
||||
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
|
||||
gutil_log_timestamp = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
2
unit/coverage/.gitignore
vendored
Normal file
2
unit/coverage/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
report
|
||||
*.gcov
|
||||
60
unit/coverage/run
Executable file
60
unit/coverage/run
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This script requires lcov, dirname
|
||||
#
|
||||
|
||||
TESTS="\
|
||||
unit_buffer \
|
||||
unit_client \
|
||||
unit_driver \
|
||||
unit_ipc \
|
||||
unit_local_object \
|
||||
unit_local_reply \
|
||||
unit_local_request \
|
||||
unit_protocol \
|
||||
unit_reader \
|
||||
unit_remote_object \
|
||||
unit_remote_reply \
|
||||
unit_remote_request \
|
||||
unit_writer"
|
||||
|
||||
function err() {
|
||||
echo "*** ERROR!" $1
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check the required tools
|
||||
which lcov >> /dev/null || err "Please install lcov"
|
||||
which dirname >> /dev/null || err "Please install dirname"
|
||||
|
||||
# LCOV 1.10 has branch coverage disabled per default
|
||||
# Previous versions didn't have the --rc option
|
||||
if [ ! -z "$(lcov --help | grep ' --rc ')" ] ; then
|
||||
LCOV_OPT="--rc lcov_branch_coverage=1"
|
||||
GENHTML_OPT="--branch-coverage"
|
||||
fi
|
||||
|
||||
pushd `dirname $0` > /dev/null
|
||||
COV_DIR="$PWD"
|
||||
pushd .. > /dev/null
|
||||
TEST_DIR="$PWD"
|
||||
pushd .. > /dev/null
|
||||
TOP_DIR="$PWD"
|
||||
popd > /dev/null
|
||||
popd > /dev/null
|
||||
popd > /dev/null
|
||||
|
||||
make -C "$TOP_DIR" clean
|
||||
for t in $TESTS ; do
|
||||
pushd "$TEST_DIR/$t"
|
||||
make -C "$TEST_DIR/$t" clean coverage || exit 1
|
||||
build/coverage/$t || exit 1
|
||||
popd
|
||||
done
|
||||
|
||||
FULL_COV="$COV_DIR/full.gcov"
|
||||
LIB_COV="$COV_DIR/lib.gcov"
|
||||
rm -f "$FULL_COV" "$LIB_COV"
|
||||
lcov $LCOV_OPT -c -d "$TOP_DIR/build/coverage" -b "$TOP_DIR/src" -o "$FULL_COV" || exit 1
|
||||
lcov $LCOV_OPT -e "$FULL_COV" "$TOP_DIR/src/*" -o "$LIB_COV" || exit 1
|
||||
genhtml $GENHTML_OPT "$LIB_COV" -t "libgbinder" --output-directory "$COV_DIR/report" || exit 1
|
||||
5
unit/unit_buffer/Makefile
Normal file
5
unit/unit_buffer/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_buffer
|
||||
|
||||
include ../common/Makefile
|
||||
115
unit/unit_buffer/unit_buffer.c
Normal file
115
unit/unit_buffer/unit_buffer.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_driver.h"
|
||||
#include "gbinder_buffer_p.h"
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(NULL, NULL, 0);
|
||||
GBinderBuffer* buf2;
|
||||
|
||||
gbinder_buffer_free(buf);
|
||||
|
||||
/* No need to reference the driver if there's no data */
|
||||
buf = gbinder_buffer_new(driver, NULL, 0);
|
||||
g_assert(!gbinder_buffer_driver(buf));
|
||||
gbinder_buffer_free(buf);
|
||||
|
||||
buf = gbinder_buffer_new_with_parent(NULL, NULL, 0);
|
||||
buf2 = gbinder_buffer_new_with_parent(buf, NULL, 0);
|
||||
g_assert(!gbinder_buffer_driver(buf));
|
||||
g_assert(!gbinder_buffer_driver(buf2));
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_buffer_free(buf2);
|
||||
|
||||
gbinder_buffer_free(NULL);
|
||||
g_assert(!gbinder_buffer_driver(NULL));
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* parent
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_parent(
|
||||
void)
|
||||
{
|
||||
static const guint8 data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
|
||||
void* ptr = g_memdup(data, sizeof(data));
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderBuffer* parent = gbinder_buffer_new(driver, ptr, sizeof(data));
|
||||
GBinderBuffer* buf = gbinder_buffer_new_with_parent
|
||||
(parent, ptr, sizeof(data));
|
||||
|
||||
g_assert(gbinder_buffer_driver(buf) == driver);
|
||||
gbinder_buffer_free(buf);
|
||||
gbinder_buffer_free(parent);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/buffer/"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "parent", test_parent);
|
||||
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_client/Makefile
Normal file
5
unit/unit_client/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_client
|
||||
|
||||
include ../common/Makefile
|
||||
350
unit/unit_client/unit_client.c
Normal file
350
unit/unit_client/unit_client.c
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_client_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_local_request.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_remote_object_p.h"
|
||||
#include "gbinder_remote_reply.h"
|
||||
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
static
|
||||
GBinderClient*
|
||||
test_client_new(
|
||||
guint handle,
|
||||
const char* iface)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, handle);
|
||||
GBinderClient* client = gbinder_client_new(obj, iface);
|
||||
|
||||
g_assert(client);
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
return client;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
GBinderClient* null = NULL;
|
||||
|
||||
g_assert(!gbinder_client_new(NULL, NULL));
|
||||
g_assert(!gbinder_client_ref(null));
|
||||
gbinder_client_unref(null);
|
||||
g_assert(!gbinder_client_new_request(NULL));
|
||||
g_assert(!gbinder_client_transact_sync_reply(null, 0, NULL, NULL));
|
||||
g_assert(gbinder_client_transact_sync_oneway(null, 0, NULL) == (-EINVAL));
|
||||
g_assert(!gbinder_client_transact(null, 0, 0, NULL, NULL, NULL, NULL));
|
||||
gbinder_client_cancel(null, 0);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* basic
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteObject* obj = gbinder_object_registry_get_remote(reg, 0);
|
||||
GBinderClient* client = gbinder_client_new(obj, "foo");
|
||||
|
||||
g_assert(!gbinder_client_new(obj, NULL));
|
||||
g_assert(client);
|
||||
g_assert(gbinder_client_ref(client) == client);
|
||||
gbinder_client_unref(client);
|
||||
gbinder_client_cancel(client, 0); /* does nothing */
|
||||
|
||||
gbinder_client_unref(client);
|
||||
gbinder_remote_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* sync_oneway
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_sync_oneway(
|
||||
void)
|
||||
{
|
||||
GBinderClient* client = test_client_new(0, "foo");
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
int fd = gbinder_driver_fd(gbinder_client_ipc(client)->driver);
|
||||
|
||||
g_assert(req);
|
||||
test_binder_br_transaction_complete(fd);
|
||||
g_assert(gbinder_client_transact_sync_oneway(client, 0, req) ==
|
||||
GBINDER_STATUS_OK);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
/* Same but using the internal (empty) request */
|
||||
test_binder_br_transaction_complete(fd);
|
||||
g_assert(gbinder_client_transact_sync_oneway(client, 0, NULL) ==
|
||||
GBINDER_STATUS_OK);
|
||||
|
||||
gbinder_client_unref(client);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* sync_reply
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_sync_reply_tx(
|
||||
GBinderClient* client,
|
||||
GBinderLocalRequest* req)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_client_ipc(client)->driver;
|
||||
int fd = gbinder_driver_fd(driver);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderRemoteReply* tx_reply;
|
||||
GBinderOutputData* data;
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
const char* result_in = "foo";
|
||||
char* result_out;
|
||||
int status = INT_MAX;
|
||||
|
||||
g_assert(gbinder_local_reply_append_string16(reply, result_in));
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_transaction_complete(fd));
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_reply(fd, handle, code, data->bytes));
|
||||
|
||||
tx_reply = gbinder_client_transact_sync_reply(client, 0, req, &status);
|
||||
g_assert(tx_reply);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
|
||||
result_out = gbinder_remote_reply_read_string16(tx_reply);
|
||||
g_assert(!g_strcmp0(result_out, result_in));
|
||||
g_free(result_out);
|
||||
|
||||
gbinder_remote_reply_unref(tx_reply);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_sync_reply(
|
||||
void)
|
||||
{
|
||||
GBinderClient* client = test_client_new(0, "foo");
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
test_sync_reply_tx(client, req);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
/* Same but using the internal (empty) request */
|
||||
test_sync_reply_tx(client, NULL);
|
||||
|
||||
gbinder_client_unref(client);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* reply
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_INTERFACE "foo"
|
||||
#define TEST_REQ_PARAM_STR "bar"
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_destroy(
|
||||
void* user_data)
|
||||
{
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_ok_reply(
|
||||
GBinderClient* client,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
char* result;
|
||||
|
||||
GVERBOSE_("%d", status);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
g_assert(reply);
|
||||
result = gbinder_remote_reply_read_string16(reply);
|
||||
g_assert(!g_strcmp0(result, TEST_REQ_PARAM_STR));
|
||||
g_free(result);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_ok_quit(
|
||||
GBinderClient* client,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
test_reply_ok_reply(client, reply, status, user_data);
|
||||
test_reply_destroy(user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_tx(
|
||||
GBinderClient* client,
|
||||
GBinderLocalRequest* req,
|
||||
GBinderClientReplyFunc done,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_client_ipc(client)->driver;
|
||||
int fd = gbinder_driver_fd(driver);
|
||||
const GBinderIo* io = gbinder_driver_io(driver);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderOutputData* data;
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
g_assert(gbinder_local_reply_append_string16(reply, TEST_REQ_PARAM_STR));
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_transaction_complete(fd));
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_reply(fd, handle, code, data->bytes));
|
||||
|
||||
id = gbinder_client_transact(client, 0, 0, req, done, destroy, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_local_reply_unref(reply);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply(
|
||||
GBinderClientReplyFunc done,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
GBinderClient* client = test_client_new(0, TEST_INTERFACE);
|
||||
GBinderLocalRequest* req = gbinder_client_new_request(client);
|
||||
|
||||
test_reply_tx(client, req, done, destroy);
|
||||
gbinder_local_request_unref(req);
|
||||
|
||||
/* Same but using the internal (empty) request */
|
||||
test_reply_tx(client, NULL, done, destroy);
|
||||
|
||||
gbinder_client_unref(client);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_ok1(
|
||||
void)
|
||||
{
|
||||
test_reply(test_reply_ok_reply, test_reply_destroy);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_ok2(
|
||||
void)
|
||||
{
|
||||
test_reply(NULL, test_reply_destroy);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_ok3(
|
||||
void)
|
||||
{
|
||||
test_reply(test_reply_ok_quit, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/client/"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "basic", test_basic);
|
||||
g_test_add_func(TEST_PREFIX "sync_oneway", test_sync_oneway);
|
||||
g_test_add_func(TEST_PREFIX "sync_reply", test_sync_reply);
|
||||
g_test_add_func(TEST_PREFIX "reply/ok1", test_reply_ok1);
|
||||
g_test_add_func(TEST_PREFIX "reply/ok2", test_reply_ok2);
|
||||
g_test_add_func(TEST_PREFIX "reply/ok3", test_reply_ok3);
|
||||
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_driver/Makefile
Normal file
5
unit/unit_driver/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_driver
|
||||
|
||||
include ../common/Makefile
|
||||
151
unit/unit_driver/unit_driver.c
Normal file
151
unit/unit_driver/unit_driver.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_driver.h"
|
||||
#include "gbinder_handler.h"
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
|
||||
#define BINDER_RPC_FLAGS (STRICT_MODE_PENALTY_GATHER)
|
||||
|
||||
/*==========================================================================*
|
||||
* basic
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderDriver* driver;
|
||||
const char* dev = GBINDER_DEFAULT_BINDER;
|
||||
|
||||
g_assert(!gbinder_driver_new(""));
|
||||
driver = gbinder_driver_new(dev);
|
||||
g_assert(driver);
|
||||
g_assert(!g_strcmp0(dev, gbinder_driver_dev(driver)));
|
||||
g_assert(gbinder_driver_ref(driver) == driver);
|
||||
gbinder_driver_unref(driver);
|
||||
gbinder_driver_free_buffer(driver, NULL);
|
||||
g_assert(gbinder_driver_io(driver));
|
||||
g_assert(gbinder_driver_increfs(driver, 0));
|
||||
g_assert(gbinder_driver_decrefs(driver, 0));
|
||||
g_assert(gbinder_driver_acquire(driver, 0));
|
||||
g_assert(gbinder_driver_release(driver, 0));
|
||||
g_assert(gbinder_driver_enter_looper(driver));
|
||||
g_assert(gbinder_driver_exit_looper(driver));
|
||||
g_assert(!gbinder_driver_request_death_notification(driver, NULL));
|
||||
g_assert(!gbinder_driver_clear_death_notification(driver, NULL));
|
||||
gbinder_driver_unref(driver);
|
||||
|
||||
g_assert(!gbinder_handler_transact(NULL, NULL, NULL, 0, 0, NULL));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* noop
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_noop(
|
||||
void)
|
||||
{
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
const int fd = gbinder_driver_fd(driver);
|
||||
|
||||
g_assert(driver);
|
||||
g_assert(fd >= 0);
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(gbinder_driver_poll(driver, NULL) == POLLIN);
|
||||
g_assert(gbinder_driver_read(driver, NULL, NULL) == 0);
|
||||
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* local_request
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_local_request(
|
||||
void)
|
||||
{
|
||||
static const char iface[] = "test";
|
||||
static const guint8 rpc_header [] = {
|
||||
TEST_INT32_BYTES(BINDER_RPC_FLAGS),
|
||||
TEST_INT32_BYTES(4),
|
||||
TEST_INT16_BYTES('t'), TEST_INT16_BYTES('e'),
|
||||
TEST_INT16_BYTES('s'), TEST_INT16_BYTES('t'),
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderLocalRequest* req = gbinder_driver_local_request_new(driver, iface);
|
||||
GBinderOutputData* data = gbinder_local_request_data(req);
|
||||
|
||||
g_assert(data->bytes->len == sizeof(rpc_header));
|
||||
g_assert(!memcmp(data->bytes->data, rpc_header, sizeof(rpc_header)));
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_driver_unref(driver);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/driver/"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "basic", test_basic);
|
||||
g_test_add_func(TEST_PREFIX "noop", test_noop);
|
||||
g_test_add_func(TEST_PREFIX "local_request", test_local_request);
|
||||
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_ipc/Makefile
Normal file
5
unit/unit_ipc/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_ipc
|
||||
|
||||
include ../common/Makefile
|
||||
755
unit/unit_ipc/unit_ipc.c
Normal file
755
unit/unit_ipc/unit_ipc.c
Normal file
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_ipc.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_local_object.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_local_request_p.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_remote_reply.h"
|
||||
#include "gbinder_remote_request.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
#include "gbinder_writer.h"
|
||||
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* null = NULL;
|
||||
int status = INT_MAX;
|
||||
|
||||
g_assert(!gbinder_ipc_ref(null));
|
||||
gbinder_ipc_unref(null);
|
||||
g_assert(!gbinder_ipc_transact_sync_reply(null, 0, 0, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_transact_sync_reply(null, 0, 0, NULL, &status));
|
||||
g_assert(status == (-EINVAL));
|
||||
g_assert(gbinder_ipc_transact_sync_oneway(null, 0, 0, NULL) == (-EINVAL));
|
||||
g_assert(!gbinder_ipc_transact(null, 0, 0, 0, NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_transact_custom(null, NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_ipc_object_registry(null));
|
||||
gbinder_ipc_looper_check(null);
|
||||
gbinder_ipc_cancel(null, 0);
|
||||
|
||||
g_assert(!gbinder_object_registry_ref(NULL));
|
||||
gbinder_object_registry_unref(NULL);
|
||||
g_assert(!gbinder_object_registry_get_local(NULL, NULL));
|
||||
g_assert(!gbinder_object_registry_get_remote(NULL, 0));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* basic
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderIpc* ipc2 = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER);
|
||||
|
||||
g_assert(ipc);
|
||||
g_assert(ipc2);
|
||||
g_assert(ipc != ipc2);
|
||||
gbinder_ipc_cancel(ipc2, 0); /* not a valid transaction */
|
||||
gbinder_ipc_unref(ipc2);
|
||||
|
||||
/* Second gbinder_ipc_new returns the same (default) object */
|
||||
g_assert(gbinder_ipc_new(NULL) == ipc);
|
||||
g_assert(gbinder_ipc_new("") == ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
/* Invalid path */
|
||||
g_assert(!gbinder_ipc_new("invalid path"));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* sync_oneway
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_sync_oneway(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
|
||||
g_assert(test_binder_br_transaction_complete(fd));
|
||||
g_assert(gbinder_ipc_transact_sync_oneway(ipc, 0, 1, req) ==
|
||||
GBINDER_STATUS_OK);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* sync_reply_ok
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_sync_reply_ok_status(
|
||||
int* status)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderRemoteReply* tx_reply;
|
||||
GBinderOutputData* data;
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
const char* result_in = "foo";
|
||||
char* result_out;
|
||||
|
||||
g_assert(gbinder_local_reply_append_string16(reply, result_in));
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_transaction_complete(fd));
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_reply(fd, handle, code, data->bytes));
|
||||
|
||||
tx_reply = gbinder_ipc_transact_sync_reply(ipc, handle, code, req, status);
|
||||
g_assert(tx_reply);
|
||||
|
||||
result_out = gbinder_remote_reply_read_string16(tx_reply);
|
||||
g_assert(!g_strcmp0(result_out, result_in));
|
||||
g_free(result_out);
|
||||
|
||||
gbinder_remote_reply_unref(tx_reply);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_sync_reply_ok(
|
||||
void)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
test_sync_reply_ok_status(NULL);
|
||||
test_sync_reply_ok_status(&status);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* sync_reply_error
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_sync_reply_error(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
const gint expected_status = GBINDER_STATUS_FAILED;
|
||||
int status = INT_MAX;
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_transaction_complete(fd));
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_reply_status(fd, expected_status));
|
||||
|
||||
g_assert(!gbinder_ipc_transact_sync_reply(ipc, handle, code, req, &status));
|
||||
g_assert(status == expected_status);
|
||||
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_ok
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_REQ_PARAM_STR "foo"
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_ok_destroy(
|
||||
void* user_data)
|
||||
{
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_ok_done(
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
char* result;
|
||||
|
||||
GVERBOSE_("");
|
||||
result = gbinder_remote_reply_read_string16(reply);
|
||||
g_assert(!g_strcmp0(result, TEST_REQ_PARAM_STR));
|
||||
g_free(result);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_ok(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(io);
|
||||
GBinderOutputData* data;
|
||||
const guint32 handle = 0;
|
||||
const guint32 code = 1;
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
g_assert(gbinder_local_reply_append_string16(reply, TEST_REQ_PARAM_STR));
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(data);
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_transaction_complete(fd));
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_reply(fd, handle, code, data->bytes));
|
||||
|
||||
id = gbinder_ipc_transact(ipc, handle, code, 0, req,
|
||||
test_transact_ok_done, test_transact_ok_destroy, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Transaction id is not valid anymore: */
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_dead
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_dead_done(
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("%d", status);
|
||||
g_assert(!reply);
|
||||
g_assert(status == GBINDER_STATUS_DEAD_OBJECT);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_dead(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_dead_reply(fd));
|
||||
|
||||
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_dead_done,
|
||||
NULL, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Transaction id is not valid anymore: */
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_failed
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_failed_done(
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("%d", status);
|
||||
g_assert(!reply);
|
||||
g_assert(status == GBINDER_STATUS_FAILED);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_failed(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_failed_reply(fd));
|
||||
|
||||
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_failed_done,
|
||||
NULL, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Transaction id is not valid anymore: */
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_status
|
||||
*==========================================================================*/
|
||||
|
||||
#define EXPECTED_STATUS (0x42424242)
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_status_done(
|
||||
GBinderIpc* ipc,
|
||||
GBinderRemoteReply* reply,
|
||||
int status,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("%d", status);
|
||||
g_assert(!reply);
|
||||
g_assert(status == EXPECTED_STATUS);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_status(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id;
|
||||
|
||||
g_assert(test_binder_br_noop(fd));
|
||||
g_assert(test_binder_br_reply_status(fd, EXPECTED_STATUS));
|
||||
|
||||
id = gbinder_ipc_transact(ipc, 1, 2, 0, req, test_transact_status_done,
|
||||
NULL, loop);
|
||||
g_assert(id);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Transaction id is not valid anymore: */
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
gbinder_local_request_unref(req);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_custom
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_custom_done(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GVERBOSE_("");
|
||||
test_quit_later((GMainLoop*)tx->user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_custom(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, NULL,
|
||||
test_transact_custom_done, NULL, loop);
|
||||
|
||||
g_assert(id);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_custom2
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_custom_destroy(
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("");
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_custom2(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, NULL, NULL,
|
||||
test_transact_custom_destroy, loop);
|
||||
|
||||
g_assert(id);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_cancel
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_cancel_destroy(
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("");
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_cancel_exec(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GVERBOSE_("");
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_cancel_done(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GVERBOSE_("");
|
||||
g_assert(tx->cancelled);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_cancel(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel_exec,
|
||||
test_transact_cancel_done, test_transact_cancel_destroy, loop);
|
||||
|
||||
g_assert(id);
|
||||
gbinder_ipc_cancel(ipc, id);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_cancel2
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_transact_cancel2_cancel(
|
||||
gpointer data)
|
||||
{
|
||||
const GBinderIpcTx* tx = data;
|
||||
|
||||
GVERBOSE_("");
|
||||
gbinder_ipc_cancel(tx->ipc, tx->id);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_cancel2_exec(
|
||||
const GBinderIpcTx* tx)
|
||||
{
|
||||
GVERBOSE_("");
|
||||
g_assert(!tx->cancelled);
|
||||
g_main_context_invoke(NULL, test_transact_cancel2_cancel, (void*)tx);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_cancel2(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
/* Reusing test_transact_cancel_done and test_transact_cancel_destroy */
|
||||
gulong id = gbinder_ipc_transact_custom(ipc, test_transact_cancel2_exec,
|
||||
test_transact_cancel_done, test_transact_cancel_destroy, loop);
|
||||
|
||||
g_assert(id);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_incoming
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
test_transact_incoming_proc(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("\"%s\" %u", gbinder_remote_request_interface(req), code);
|
||||
g_assert(!flags);
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), "test"));
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_read_string8(req), "message"));
|
||||
g_assert(code == 1);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
|
||||
*status = GBINDER_STATUS_OK;
|
||||
return gbinder_local_object_new_reply(obj);
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
test_transact_unref_ipc(
|
||||
gpointer ipc)
|
||||
{
|
||||
gbinder_ipc_unref(ipc);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_done(
|
||||
gpointer loop,
|
||||
GObject* ipc)
|
||||
{
|
||||
test_quit_later((GMainLoop*)loop);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_incoming(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object
|
||||
(ipc, "test", test_transact_incoming_proc, loop);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
gbinder_local_request_init_writer(req, &writer);
|
||||
prot->write_rpc_header(&writer, "test");
|
||||
gbinder_writer_append_string8(&writer, "message");
|
||||
data = gbinder_local_request_data(req);
|
||||
|
||||
test_binder_br_transaction(fd, obj, 1, data->bytes);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Now we need to wait until GBinderIpc is destroyed */
|
||||
GDEBUG("waiting for GBinderIpc to get destroyed");
|
||||
g_object_weak_ref(G_OBJECT(ipc), test_transact_done, loop);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_request_unref(req);
|
||||
g_idle_add(test_transact_unref_ipc, ipc);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* transact_incoming_status
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
test_transact_status_reply_proc(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("\"%s\" %u", gbinder_remote_request_interface(req), code);
|
||||
g_assert(!flags);
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), "test"));
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_read_string8(req), "message"));
|
||||
g_assert(code == 1);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
|
||||
*status = EXPECTED_STATUS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_transact_status_reply(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
const GBinderIo* io = gbinder_driver_io(ipc->driver);
|
||||
const int fd = gbinder_driver_fd(ipc->driver);
|
||||
const char* dev = gbinder_driver_dev(ipc->driver);
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object
|
||||
(ipc, "test", test_transact_status_reply_proc, loop);
|
||||
GBinderLocalRequest* req = gbinder_local_request_new(io, NULL);
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
gbinder_local_request_init_writer(req, &writer);
|
||||
prot->write_rpc_header(&writer, "test");
|
||||
gbinder_writer_append_string8(&writer, "message");
|
||||
data = gbinder_local_request_data(req);
|
||||
|
||||
test_binder_br_transaction(fd, obj, 1, data->bytes);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
/* Now we need to wait until GBinderIpc is destroyed */
|
||||
GDEBUG("waiting for GBinderIpc to get destroyed");
|
||||
g_object_weak_ref(G_OBJECT(ipc), test_transact_done, loop);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_request_unref(req);
|
||||
g_idle_add(test_transact_unref_ipc, ipc);
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/ipc/"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "basic", test_basic);
|
||||
g_test_add_func(TEST_PREFIX "sync_oneway", test_sync_oneway);
|
||||
g_test_add_func(TEST_PREFIX "sync_reply_ok", test_sync_reply_ok);
|
||||
g_test_add_func(TEST_PREFIX "sync_reply_error", test_sync_reply_error);
|
||||
g_test_add_func(TEST_PREFIX "transact_ok", test_transact_ok);
|
||||
g_test_add_func(TEST_PREFIX "transact_dead", test_transact_dead);
|
||||
g_test_add_func(TEST_PREFIX "transact_failed", test_transact_failed);
|
||||
g_test_add_func(TEST_PREFIX "transact_status", test_transact_status);
|
||||
g_test_add_func(TEST_PREFIX "transact_custom", test_transact_custom);
|
||||
g_test_add_func(TEST_PREFIX "transact_custom2", test_transact_custom2);
|
||||
g_test_add_func(TEST_PREFIX "transact_cancel", test_transact_cancel);
|
||||
g_test_add_func(TEST_PREFIX "transact_cancel2", test_transact_cancel2);
|
||||
g_test_add_func(TEST_PREFIX "transact_incoming", test_transact_incoming);
|
||||
g_test_add_func(TEST_PREFIX "transact_status_reply",
|
||||
test_transact_status_reply);
|
||||
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_local_object/Makefile
Normal file
5
unit/unit_local_object/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_local_object
|
||||
|
||||
include ../common/Makefile
|
||||
648
unit/unit_local_object/unit_local_object.c
Normal file
648
unit/unit_local_object/unit_local_object.c
Normal file
@@ -0,0 +1,648 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_buffer_p.h"
|
||||
#include "gbinder_driver.h"
|
||||
#include "gbinder_ipc.h"
|
||||
#include "gbinder_local_object_p.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_object_registry.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_reader_p.h"
|
||||
#include "gbinder_remote_request_p.h"
|
||||
#include "gbinder_rpc_protocol.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_log.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
/* android.hidl.base@1.0::IBase */
|
||||
#define TEST_BASE_INTERFACE_BYTES \
|
||||
'a', 'n', 'd', 'r', 'o', 'i', 'd', '.', \
|
||||
'h', 'i', 'd', 'l', '.', 'b', 'a', 's', \
|
||||
'e', '@', '1', '.', '0', ':', ':', 'I', \
|
||||
'B', 'a', 's', 'e'
|
||||
#define TEST_BASE_INTERFACE_HEADER_BYTES \
|
||||
TEST_BASE_INTERFACE_BYTES, 0x00, 0x00, 0x00, 0x00
|
||||
static const char base_interface[] = { TEST_BASE_INTERFACE_BYTES, 0x00 };
|
||||
|
||||
static
|
||||
void
|
||||
test_reader_data_init_for_reply(
|
||||
GBinderReaderData* data,
|
||||
GBinderLocalObject* obj,
|
||||
GBinderLocalReply* reply)
|
||||
{
|
||||
GBinderIpc* ipc = obj->ipc;
|
||||
GBinderOutputData* out = gbinder_local_reply_data(reply);
|
||||
GUtilIntArray* offsets = gbinder_output_data_offsets(out);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(out->bytes->data, out->bytes->len), out->bytes->len);
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->buffer = buf;
|
||||
data->reg = gbinder_object_registry_ref(reg);
|
||||
g_assert(!gbinder_object_registry_get_local(reg, NULL));
|
||||
g_assert(gbinder_object_registry_get_local(reg, obj) == obj);
|
||||
gbinder_local_object_unref(obj); /* ref added by the above call */
|
||||
if (offsets && offsets->count > 0) {
|
||||
guint i;
|
||||
|
||||
data->objects = g_new(void*, offsets->count + 1);
|
||||
for (i = 0; i < offsets->count; i++) {
|
||||
data->objects[i] = (guint8*)buf->data + offsets->data[i];
|
||||
}
|
||||
data->objects[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reader_data_cleanup(
|
||||
GBinderReaderData* data)
|
||||
{
|
||||
gbinder_object_registry_unref(data->reg);
|
||||
gbinder_buffer_free(data->buffer);
|
||||
g_free(data->objects);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
g_assert(!gbinder_local_object_new(NULL, NULL, NULL, NULL));
|
||||
g_assert(!gbinder_local_object_ref(NULL));
|
||||
gbinder_local_object_unref(NULL);
|
||||
gbinder_local_object_drop(NULL);
|
||||
g_assert(!gbinder_local_object_new_reply(NULL));
|
||||
g_assert(!gbinder_local_object_add_weak_refs_changed_handler(NULL,
|
||||
NULL, NULL));
|
||||
g_assert(!gbinder_local_object_add_strong_refs_changed_handler(NULL,
|
||||
NULL, NULL));
|
||||
gbinder_local_object_remove_handler(NULL, 0);
|
||||
g_assert(gbinder_local_object_can_handle_transaction(NULL, NULL, 0) ==
|
||||
GBINDER_LOCAL_TRANSACTION_NOT_SUPPORTED);
|
||||
g_assert(!gbinder_local_object_handle_transaction(NULL, NULL, 0, 0, NULL));
|
||||
g_assert(!gbinder_local_object_handle_transaction(NULL, NULL, 0, 0,
|
||||
&status));
|
||||
g_assert(!gbinder_local_object_handle_looper_transaction(NULL, NULL, 0, 0,
|
||||
NULL));
|
||||
g_assert(!gbinder_local_object_handle_looper_transaction(NULL, NULL, 0, 0,
|
||||
&status));
|
||||
g_assert(status == (-EBADMSG));
|
||||
g_assert(!gbinder_ipc_transact_custom(NULL, NULL, NULL, NULL, NULL));
|
||||
gbinder_local_object_handle_increfs(NULL);
|
||||
gbinder_local_object_handle_decrefs(NULL);
|
||||
gbinder_local_object_handle_acquire(NULL);
|
||||
gbinder_local_object_handle_release(NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* basic
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_basic(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderLocalObject* foo;
|
||||
GBinderLocalObject* bar;
|
||||
|
||||
/* ipc is not a local object */
|
||||
g_assert(!gbinder_object_registry_get_local(reg, ipc));
|
||||
|
||||
/* Create a new local objects */
|
||||
foo = gbinder_ipc_new_local_object(ipc, "foo", NULL, NULL);
|
||||
bar = gbinder_ipc_new_local_object(ipc, "bar", NULL, NULL);
|
||||
|
||||
/* But ipc is still not a local object! */
|
||||
g_assert(!gbinder_object_registry_get_local(reg, ipc));
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
|
||||
g_assert(foo);
|
||||
g_assert(!gbinder_local_object_add_weak_refs_changed_handler(foo,
|
||||
NULL, NULL));
|
||||
g_assert(!gbinder_local_object_add_strong_refs_changed_handler(foo,
|
||||
NULL, NULL));
|
||||
gbinder_local_object_remove_handler(foo, 0);
|
||||
g_assert(gbinder_local_object_can_handle_transaction(foo,
|
||||
base_interface, -1) == GBINDER_LOCAL_TRANSACTION_NOT_SUPPORTED);
|
||||
gbinder_local_object_handle_increfs(foo);
|
||||
gbinder_local_object_handle_decrefs(foo);
|
||||
gbinder_local_object_handle_acquire(foo);
|
||||
gbinder_local_object_handle_release(foo);
|
||||
gbinder_local_object_unref(foo);
|
||||
|
||||
g_assert(bar);
|
||||
g_assert(gbinder_local_object_ref(bar) == bar);
|
||||
gbinder_local_object_drop(bar);
|
||||
gbinder_local_object_unref(bar);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* get_descriptor
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_get_descriptor(
|
||||
void)
|
||||
{
|
||||
static const guint8 req_data [] = {
|
||||
TEST_BASE_INTERFACE_HEADER_BYTES
|
||||
};
|
||||
int status = INT_MAX;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new
|
||||
(gbinder_ipc_object_registry(ipc), prot);
|
||||
GBinderLocalObject* obj =
|
||||
gbinder_ipc_new_local_object(ipc, NULL, NULL, NULL);
|
||||
GBinderLocalReply* reply;
|
||||
|
||||
gbinder_remote_request_set_data(req, gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(req_data, sizeof(req_data)), sizeof(req_data)), NULL);
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), base_interface));
|
||||
g_assert(gbinder_local_object_can_handle_transaction(obj, base_interface,
|
||||
HIDL_GET_DESCRIPTOR_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_LOOPER);
|
||||
|
||||
/* If can_handle_transaction() returns TRANSACTION_LOOPER then it must be
|
||||
* handled by handle_looper_transaction() */
|
||||
g_assert(!gbinder_local_object_handle_transaction(obj, req,
|
||||
HIDL_GET_DESCRIPTOR_TRANSACTION, 0, &status));
|
||||
g_assert(status == (-EBADMSG));
|
||||
reply = gbinder_local_object_handle_looper_transaction(obj, req,
|
||||
HIDL_GET_DESCRIPTOR_TRANSACTION, 0, &status);
|
||||
g_assert(reply);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
|
||||
/* Unsupported transaction */
|
||||
g_assert(!gbinder_local_object_handle_looper_transaction
|
||||
(obj, req, -1, 0, NULL));
|
||||
g_assert(!gbinder_local_object_handle_looper_transaction
|
||||
(obj, req, -1, 0, &status));
|
||||
g_assert(status == (-EBADMSG));
|
||||
g_assert(!gbinder_local_object_handle_transaction(obj, req, -1, 0, NULL));
|
||||
g_assert(!gbinder_local_object_handle_transaction(obj, req, -1, 0,
|
||||
&status));
|
||||
g_assert(status == (-EBADMSG));
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* descriptor_chain
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_descriptor_chain(
|
||||
void)
|
||||
{
|
||||
static const guint8 req_data [] = {
|
||||
TEST_BASE_INTERFACE_HEADER_BYTES
|
||||
};
|
||||
int status = INT_MAX;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new
|
||||
(gbinder_ipc_object_registry(ipc), prot);
|
||||
GBinderLocalObject* obj =
|
||||
gbinder_ipc_new_local_object(ipc, NULL, NULL, NULL);
|
||||
GBinderLocalReply* reply;
|
||||
|
||||
gbinder_remote_request_set_data(req, gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(req_data, sizeof(req_data)), sizeof(req_data)), NULL);
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), base_interface));
|
||||
g_assert(gbinder_local_object_can_handle_transaction(obj, base_interface,
|
||||
HIDL_DESCRIPTOR_CHAIN_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_LOOPER);
|
||||
|
||||
/* If can_handle_transaction() returns TRANSACTION_LOOPER then it must be
|
||||
* handled by handle_looper_transaction() */
|
||||
g_assert(!gbinder_local_object_handle_transaction(obj, req,
|
||||
HIDL_DESCRIPTOR_CHAIN_TRANSACTION, 0, &status));
|
||||
g_assert(status == (-EBADMSG));
|
||||
reply = gbinder_local_object_handle_looper_transaction(obj, req,
|
||||
HIDL_DESCRIPTOR_CHAIN_TRANSACTION, 0, &status);
|
||||
g_assert(reply);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* custom_call
|
||||
*==========================================================================*/
|
||||
|
||||
#define CUSTOM_TRANSACTION (GBINDER_FIRST_CALL_TRANSACTION + 1)
|
||||
#define CUSTOM_INTERFACE_BYTES 'f', 'o', 'o'
|
||||
#define CUSTOM_INTERFACE_HEADER_BYTES CUSTOM_INTERFACE_BYTES, 0x00
|
||||
static const char custom_iface[] = { CUSTOM_INTERFACE_BYTES, 0x00 };
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
test_custom_iface_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
int* count = user_data;
|
||||
|
||||
g_assert(!flags);
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), custom_iface));
|
||||
g_assert(code == CUSTOM_TRANSACTION);
|
||||
*status = GBINDER_STATUS_OK;
|
||||
(*count)++;
|
||||
return gbinder_local_object_new_reply(obj);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_custom_iface(
|
||||
void)
|
||||
{
|
||||
static const guint8 req_data [] = { CUSTOM_INTERFACE_HEADER_BYTES };
|
||||
int count = 0, status = INT_MAX;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new
|
||||
(gbinder_ipc_object_registry(ipc), prot);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object(ipc, custom_iface,
|
||||
test_custom_iface_handler, &count);
|
||||
GBinderLocalReply* reply;
|
||||
GBinderReaderData reader_data;
|
||||
GBinderReader reader;
|
||||
char** strv;
|
||||
char* str;
|
||||
|
||||
gbinder_remote_request_set_data(req, gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(req_data, sizeof(req_data)), sizeof(req_data)), NULL);
|
||||
g_assert(gbinder_local_object_can_handle_transaction(obj, base_interface,
|
||||
HIDL_DESCRIPTOR_CHAIN_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_LOOPER);
|
||||
g_assert(gbinder_local_object_can_handle_transaction(obj, custom_iface,
|
||||
HIDL_DESCRIPTOR_CHAIN_TRANSACTION) ==
|
||||
GBINDER_LOCAL_TRANSACTION_SUPPORTED);
|
||||
g_assert(gbinder_local_object_can_handle_transaction(obj, custom_iface,
|
||||
CUSTOM_TRANSACTION) == GBINDER_LOCAL_TRANSACTION_SUPPORTED);
|
||||
|
||||
/* This returns the custom interface */
|
||||
reply = gbinder_local_object_handle_looper_transaction(obj, req,
|
||||
HIDL_GET_DESCRIPTOR_TRANSACTION, 0, &status);
|
||||
g_assert(reply);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
|
||||
/* Parse the reply and check the interface */
|
||||
test_reader_data_init_for_reply(&reader_data, obj, reply);
|
||||
gbinder_reader_init(&reader, &reader_data, 0, reader_data.buffer->size);
|
||||
g_assert(gbinder_reader_read_int32(&reader, &status));
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
str = gbinder_reader_read_hidl_string(&reader);
|
||||
g_assert(!g_strcmp0(str, custom_iface));
|
||||
g_free(str);
|
||||
test_reader_data_cleanup(&reader_data);
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* And this returns two interfaces */
|
||||
reply = gbinder_local_object_handle_looper_transaction(obj, req,
|
||||
HIDL_DESCRIPTOR_CHAIN_TRANSACTION, 0, &status);
|
||||
g_assert(reply);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
|
||||
/* Parse the reply and check the interface */
|
||||
test_reader_data_init_for_reply(&reader_data, obj, reply);
|
||||
gbinder_reader_init(&reader, &reader_data, 0, reader_data.buffer->size);
|
||||
g_assert(gbinder_reader_read_int32(&reader, &status));
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
strv = gbinder_reader_read_hidl_string_vec(&reader);
|
||||
g_assert(gutil_strv_length(strv) == 2);
|
||||
g_assert(!g_strcmp0(strv[0], custom_iface));
|
||||
g_assert(!g_strcmp0(strv[1], base_interface));
|
||||
g_strfreev(strv);
|
||||
test_reader_data_cleanup(&reader_data);
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* Execute the custom transaction */
|
||||
reply = gbinder_local_object_handle_transaction(obj, req,
|
||||
CUSTOM_TRANSACTION, 0, &status);
|
||||
g_assert(reply);
|
||||
g_assert(status == GBINDER_STATUS_OK);
|
||||
g_assert(count == 1);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_remote_request_unref(req);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* reply_status
|
||||
*==========================================================================*/
|
||||
|
||||
#define EXPECTED_STATUS (424242)
|
||||
|
||||
static
|
||||
GBinderLocalReply*
|
||||
test_reply_status_handler(
|
||||
GBinderLocalObject* obj,
|
||||
GBinderRemoteRequest* req,
|
||||
guint code,
|
||||
guint flags,
|
||||
int* status,
|
||||
void* user_data)
|
||||
{
|
||||
int* count = user_data;
|
||||
|
||||
g_assert(!flags);
|
||||
g_assert(!g_strcmp0(gbinder_remote_request_interface(req), custom_iface));
|
||||
g_assert(code == CUSTOM_TRANSACTION);
|
||||
*status = EXPECTED_STATUS;
|
||||
(*count)++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_reply_status(
|
||||
void)
|
||||
{
|
||||
static const guint8 req_data [] = { CUSTOM_INTERFACE_HEADER_BYTES };
|
||||
int count = 0, status = 0;
|
||||
const char* dev = GBINDER_DEFAULT_HWBINDER;
|
||||
const GBinderRpcProtocol* prot = gbinder_rpc_protocol_for_device(dev);
|
||||
GBinderIpc* ipc = gbinder_ipc_new(dev);
|
||||
GBinderObjectRegistry* reg = gbinder_ipc_object_registry(ipc);
|
||||
GBinderRemoteRequest* req = gbinder_remote_request_new(reg, prot);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object(ipc, custom_iface,
|
||||
test_reply_status_handler, &count);
|
||||
|
||||
gbinder_remote_request_set_data(req, gbinder_buffer_new(ipc->driver,
|
||||
g_memdup(req_data, sizeof(req_data)), sizeof(req_data)), NULL);
|
||||
|
||||
/* Execute the custom transaction */
|
||||
g_assert(!gbinder_local_object_handle_transaction(obj, req,
|
||||
CUSTOM_TRANSACTION, 0, &status));
|
||||
g_assert(status == EXPECTED_STATUS);
|
||||
g_assert(count == 1);
|
||||
|
||||
gbinder_ipc_unref(ipc);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_remote_request_unref(req);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* increfs
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_increfs_cb(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("%d", obj->weak_refs);
|
||||
g_assert(obj->weak_refs == 1);
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_increfs(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object
|
||||
(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_weak_refs_changed_handler(obj,
|
||||
test_increfs_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_increfs(fd, ipc);
|
||||
test_binder_br_increfs(fd, obj);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->weak_refs == 1);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* decrefs
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_decrefs_cb(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("%d", obj->weak_refs);
|
||||
if (!obj->weak_refs) {
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_decrefs(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object
|
||||
(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_weak_refs_changed_handler(obj,
|
||||
test_decrefs_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_decrefs(fd, ipc);
|
||||
test_binder_br_increfs(fd, obj);
|
||||
test_binder_br_decrefs(fd, obj);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->weak_refs == 0);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* acquire
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_acquire_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_acquire(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object
|
||||
(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_acquire_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_acquire(fd, ipc);
|
||||
test_binder_br_acquire(fd, obj);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->strong_refs == 1);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* release
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_release_cb(
|
||||
GBinderLocalObject* obj,
|
||||
void* user_data)
|
||||
{
|
||||
GVERBOSE_("%d", obj->strong_refs);
|
||||
if (!obj->strong_refs) {
|
||||
test_quit_later((GMainLoop*)user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_release(
|
||||
void)
|
||||
{
|
||||
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER);
|
||||
GBinderLocalObject* obj = gbinder_ipc_new_local_object
|
||||
(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_release_cb, loop);
|
||||
|
||||
/* ipc is not an object, will be ignored */
|
||||
test_binder_br_release(fd, ipc);
|
||||
test_binder_br_acquire(fd, obj);
|
||||
test_binder_br_release(fd, obj);
|
||||
|
||||
test_run(&test_opt, loop);
|
||||
|
||||
g_assert(obj->strong_refs == 0);
|
||||
gbinder_local_object_remove_handler(obj, id);
|
||||
gbinder_local_object_unref(obj);
|
||||
gbinder_ipc_unref(ipc);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/local_object/"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "basic", test_basic);
|
||||
g_test_add_func(TEST_PREFIX "get_descriptor", test_get_descriptor);
|
||||
g_test_add_func(TEST_PREFIX "descriptor_chain", test_descriptor_chain);
|
||||
g_test_add_func(TEST_PREFIX "custom_iface", test_custom_iface);
|
||||
g_test_add_func(TEST_PREFIX "reply_status", test_reply_status);
|
||||
g_test_add_func(TEST_PREFIX "increfs", test_increfs);
|
||||
g_test_add_func(TEST_PREFIX "decrefs", test_decrefs);
|
||||
g_test_add_func(TEST_PREFIX "acquire", test_acquire);
|
||||
g_test_add_func(TEST_PREFIX "release", test_release);
|
||||
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_local_reply/Makefile
Normal file
5
unit/unit_local_reply/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- Mode: makefile-gmake -*-
|
||||
|
||||
EXE = unit_local_reply
|
||||
|
||||
include ../common/Makefile
|
||||
382
unit/unit_local_reply/unit_local_reply.c
Normal file
382
unit/unit_local_reply/unit_local_reply.c
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Jolla Ltd.
|
||||
* Contact: 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 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.
|
||||
*
|
||||
* 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_local_object.h"
|
||||
#include "gbinder_local_reply_p.h"
|
||||
#include "gbinder_output_data.h"
|
||||
#include "gbinder_writer.h"
|
||||
#include "gbinder_io.h"
|
||||
#include "gbinder_ipc.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
|
||||
static TestOpt test_opt;
|
||||
|
||||
#define BUFFER_OBJECT_SIZE_32 (24)
|
||||
#define BUFFER_OBJECT_SIZE_64 (GBINDER_MAX_BUFFER_OBJECT_SIZE)
|
||||
#define BINDER_OBJECT_SIZE_32 (16)
|
||||
#define BINDER_OBJECT_SIZE_64 (GBINDER_MAX_BINDER_OBJECT_SIZE)
|
||||
|
||||
static
|
||||
void
|
||||
test_int_inc(
|
||||
void* data)
|
||||
{
|
||||
(*((int*)data))++;
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* null
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_null(
|
||||
void)
|
||||
{
|
||||
GBinderWriter writer;
|
||||
int count = 0;
|
||||
|
||||
g_assert(!gbinder_local_reply_new(NULL));
|
||||
g_assert(!gbinder_local_reply_ref(NULL));
|
||||
gbinder_local_reply_unref(NULL);
|
||||
gbinder_local_reply_init_writer(NULL, NULL);
|
||||
gbinder_local_reply_init_writer(NULL, &writer);
|
||||
g_assert(!gbinder_local_reply_data(NULL));
|
||||
|
||||
gbinder_local_reply_cleanup(NULL, NULL, &count);
|
||||
gbinder_local_reply_cleanup(NULL, test_int_inc, &count);
|
||||
g_assert(count == 1);
|
||||
|
||||
g_assert(!gbinder_local_reply_append_int32(NULL, 0));
|
||||
g_assert(!gbinder_local_reply_append_int64(NULL, 0));
|
||||
g_assert(!gbinder_local_reply_append_string8(NULL, NULL));
|
||||
g_assert(!gbinder_local_reply_append_string16(NULL, NULL));
|
||||
g_assert(!gbinder_local_reply_append_hidl_string(NULL, NULL));
|
||||
g_assert(!gbinder_local_reply_append_hidl_string_vec(NULL, NULL, 0));
|
||||
g_assert(!gbinder_local_reply_append_local_object(NULL, NULL));
|
||||
g_assert(!gbinder_local_reply_append_remote_object(NULL, NULL));
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* cleanup
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_cleanup(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
int count = 0;
|
||||
|
||||
gbinder_local_reply_cleanup(reply, NULL, &count);
|
||||
gbinder_local_reply_cleanup(reply, test_int_inc, &count);
|
||||
gbinder_local_reply_cleanup(reply, test_int_inc, &count);
|
||||
g_assert(!count);
|
||||
|
||||
gbinder_local_reply_unref(reply);
|
||||
g_assert(count == 2);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* int32
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_int32(
|
||||
void)
|
||||
{
|
||||
const guint32 value = 1234567;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderOutputData* data;
|
||||
GBinderWriter writer;
|
||||
|
||||
gbinder_local_reply_append_int32(reply, value);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == sizeof(value));
|
||||
g_assert(!memcmp(data->bytes->data, &value, data->bytes->len));
|
||||
g_assert(gbinder_local_reply_ref(reply) == reply);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* Same with writer */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
gbinder_local_reply_init_writer(reply, &writer);
|
||||
gbinder_writer_append_int32(&writer, value);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == sizeof(value));
|
||||
g_assert(!memcmp(data->bytes->data, &value, data->bytes->len));
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* int64
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_int64(
|
||||
void)
|
||||
{
|
||||
const guint64 value = 123456789;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_int64(reply, value);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == sizeof(value));
|
||||
g_assert(!memcmp(data->bytes->data, &value, data->bytes->len));
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* string8
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_string8(
|
||||
void)
|
||||
{
|
||||
/* The size of the string gets aligned at 4-byte boundary */
|
||||
static const char input[] = "test";
|
||||
static const guint8 output[] = { 't', 'e', 's', 't', 0, 0, 0, 0 };
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_string8(reply, input);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == sizeof(output));
|
||||
g_assert(!memcmp(data->bytes->data, output, data->bytes->len));
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* NULL string doesn't get encoded at all (should it be?) */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
gbinder_local_reply_append_string8(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(!data->bytes->len);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* string16
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_string16(
|
||||
void)
|
||||
{
|
||||
static const const char input[] = "x";
|
||||
static const guint8 output[] = {
|
||||
TEST_INT32_BYTES(1),
|
||||
TEST_INT16_BYTES('x'), 0x00, 0x00
|
||||
};
|
||||
const gint32 null_output = -1;
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderOutputData* data;
|
||||
|
||||
gbinder_local_reply_append_string16(reply, input);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == sizeof(output));
|
||||
g_assert(!memcmp(data->bytes->data, output, data->bytes->len));
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* NULL string gets encoded as -1 */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
gbinder_local_reply_append_string16(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
g_assert(!gbinder_output_data_offsets(data));
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == sizeof(null_output));
|
||||
g_assert(!memcmp(data->bytes->data, &null_output, data->bytes->len));
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* hidl_string
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_hidl_string(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
gbinder_local_reply_append_hidl_string(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(HidlString));
|
||||
g_assert(data->bytes->len == BUFFER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* hidl_string_vec
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_hidl_string_vec(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
gbinder_local_reply_append_hidl_string_vec(reply, NULL, 0);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(gbinder_output_data_buffers_size(data) == sizeof(HidlVec));
|
||||
g_assert(data->bytes->len == BUFFER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* local_object
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_local_object(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply;
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
GBinderIpc* ipc = gbinder_ipc_new(NULL);
|
||||
GBinderLocalObject* obj =
|
||||
gbinder_ipc_new_local_object(ipc, "foo", NULL, NULL);
|
||||
|
||||
/* Append a real object (64-bit I/O is used by test_binder.c) */
|
||||
reply = gbinder_local_object_new_reply(obj);
|
||||
gbinder_local_reply_append_local_object(reply, obj);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_64);
|
||||
gbinder_local_reply_unref(reply);
|
||||
|
||||
/* Append NULL object (with 32-bit I/O module) */
|
||||
reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
gbinder_local_reply_append_local_object(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
gbinder_ipc_unref(ipc);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* remote_object
|
||||
*==========================================================================*/
|
||||
|
||||
static
|
||||
void
|
||||
test_remote_object(
|
||||
void)
|
||||
{
|
||||
GBinderLocalReply* reply = gbinder_local_reply_new(&gbinder_io_32);
|
||||
GBinderOutputData* data;
|
||||
GUtilIntArray* offsets;
|
||||
|
||||
gbinder_local_reply_append_remote_object(reply, NULL);
|
||||
data = gbinder_local_reply_data(reply);
|
||||
offsets = gbinder_output_data_offsets(data);
|
||||
g_assert(offsets);
|
||||
g_assert(offsets->count == 1);
|
||||
g_assert(offsets->data[0] == 0);
|
||||
g_assert(!gbinder_output_data_buffers_size(data));
|
||||
g_assert(data->bytes->len == BINDER_OBJECT_SIZE_32);
|
||||
gbinder_local_reply_unref(reply);
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* Common
|
||||
*==========================================================================*/
|
||||
|
||||
#define TEST_PREFIX "/local_reply/"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func(TEST_PREFIX "null", test_null);
|
||||
g_test_add_func(TEST_PREFIX "cleanup", test_cleanup);
|
||||
g_test_add_func(TEST_PREFIX "int32", test_int32);
|
||||
g_test_add_func(TEST_PREFIX "int64", test_int64);
|
||||
g_test_add_func(TEST_PREFIX "string8", test_string8);
|
||||
g_test_add_func(TEST_PREFIX "string16", test_string16);
|
||||
g_test_add_func(TEST_PREFIX "hidl_string", test_hidl_string);
|
||||
g_test_add_func(TEST_PREFIX "hidl_string_vec", test_hidl_string_vec);
|
||||
g_test_add_func(TEST_PREFIX "local_object", test_local_object);
|
||||
g_test_add_func(TEST_PREFIX "remote_object", test_remote_object);
|
||||
test_init(&test_opt, argc, argv);
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user