[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