endif()
if (${ENABLE_HAL_BACKEND_SERVICE})
-ADD_SUBDIRECTORY(hal-backend-service)
+ADD_SUBDIRECTORY(hal-backend-service-with-dbus)
+ADD_SUBDIRECTORY(hal-backend-service-without-dbus)
endif()
--- /dev/null
+PROJECT(hal-backend-service C)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(gtest_pkgs REQUIRED dbus-1)
+
+FOREACH(flag ${gtest_pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -fPIC")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 -Wl,-z,relro")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt")
+SET(CMAKE_EXE_LINKER_FLAGS "-pie")
+
+SET(EXEC_NAME "${PROJECT_NAME}-with-dbus")
+SET(src ${CMAKE_SOURCE_DIR}/hal-backend-service-with-dbus/hal-backend-service.c)
+ADD_EXECUTABLE(${EXEC_NAME} ${src})
+TARGET_LINK_LIBRARIES(${EXEC_NAME} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal)
+INSTALL(TARGETS ${EXEC_NAME} DESTINATION /usr/bin/hal)
+
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION lib/systemd/system
+ FILES_MATCHING PATTERN "hal-backend-service-with-dbus.service")
--- /dev/null
+{
+ "process": [
+ {
+ "type": "systemd",
+ "property": {
+ "name": "hal-backend-service"
+ },
+ "thread": [
+ { "hal_module_name": [ "device_display" ] },
+ { "hal_module_name": [ "device_led" ] },
+ { "hal_module_name": [ "device_battery" ] },
+ { "hal_module_name": [ "device_bezel" ] },
+ { "hal_module_name": [ "device_external_connection" ] }
+ ]
+ },
+ {
+ "type": "systemd",
+ "property": {
+ "name": "hal-backend-service-codec"
+ },
+ "thread": [
+ { "hal_module_name": [ "codec" ] }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "process": [
+ {
+ "type": "systemd",
+ "property": {
+ "name": "hal-backend-service-with-dbus"
+ },
+ "thread": [
+ { "hal_module_name": [ "device_display" ] },
+ { "hal_module_name": [ "device_led" ] },
+ { "hal_module_name": [ "device_battery" ] },
+ { "hal_module_name": [ "device_bezel" ] },
+ { "hal_module_name": [ "device_external_connection" ] }
+ ]
+ }
+ ]
+}
--- /dev/null
+import errno
+
+class InvalidJsonStructException(Exception):
+ errno = errno.EINVAL
+
+class InvalidJsonValueException(Exception):
+ errno = errno.EINVAL
+
+class JsonConfigEntity:
+ def get_name(self):
+ return None
+ def get_hal_module_names(self):
+ return None
+ def map_json_obj(self, json_obj):
+ return None
+
+class ThreadConfig(JsonConfigEntity):
+ hal_module_names: list
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"\t\tThread:\n"
+ result += f"\t\t\thal module names: " + ", ".join(self.hal_module_names) + "\n"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != dict:
+ raise InvalidJsonStructException("Invalid json struct: thread should be a json object")
+ if "hal_module_name" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: thread should have \"hal_module_name\"")
+
+ hal_module_name_obj = json_obj["hal_module_name"]
+ if type(hal_module_name_obj) != list:
+ raise InvalidJsonStructException("Invalid json struct: hal_module_name should be a list")
+
+ if any(filter(lambda x: type(x) != str, hal_module_name_obj)):
+ raise InvalidJsonStructException("Invalid json struct: hal_module_name should be a list of strings")
+
+ self.hal_module_names = [ str(obj) for obj in hal_module_name_obj ]
+
+class ThreadsConfig(JsonConfigEntity):
+ threads: list
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"\tThreads:\n"
+ for thread in self.threads:
+ result += f"{str(thread)}"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != list:
+ raise InvalidJsonStructException("Invalid json struct: thread should be a list")
+
+ threads = list()
+
+ for obj in json_obj:
+ threads.append(ThreadConfig(obj))
+
+ self.threads = threads
+
+ def get_hal_module_names(self):
+ hal_module_names = list()
+
+ for thread in self.threads:
+ hal_module_names += thread.hal_module_names
+
+ return hal_module_names
+
+class HalBackendServiceSystemdPropertyConfig(JsonConfigEntity):
+ name: str
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"\tProperties:\n"
+ result += f"\t\tname: {self.name}\n"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != dict:
+ raise InvalidJsonStructException("Invalid json struct: systemd property should be a json object")
+ if "name" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: systemd property should have \"name\"")
+
+ name_obj = json_obj["name"]
+ if type(name_obj) != str:
+ raise InvalidJsonStructException("Invalid json struct: systemd name should be a string")
+
+ service_name_prefix = "hal-backend-service"
+ if not name_obj.startswith(service_name_prefix):
+ raise InvalidJsonValueException(f"Invalid json value: systemd name should start with {service_name_prefix}")
+
+ self.name = name_obj
+
+class HalBackendServiceSystemdConfig(JsonConfigEntity):
+ properties: HalBackendServiceSystemdPropertyConfig
+ thread_config: ThreadsConfig
+
+ def __init__(self, json_obj):
+ self.type = "systemd"
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"Service:\n"
+ result += f"{str(self.properties)}"
+ result += f"{str(self.thread_config)}"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != dict:
+ raise InvalidJsonStructException("Invalid json struct: systemd process should be a json object")
+ if "property" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: systemd process should have \"properties\"")
+ if "thread" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: systemd process should have \"thread\"")
+
+ property_obj = json_obj["property"]
+ self.properties = HalBackendServiceSystemdPropertyConfig(property_obj)
+
+ thread_obj = json_obj["thread"]
+ self.thread_config = ThreadsConfig(thread_obj)
+
+ def get_name(self):
+ return self.properties.name
+
+ def get_hal_module_names(self):
+ return self.thread_config.get_hal_module_names()
+
+class HalBackendServiceConfig(JsonConfigEntity):
+ processes: list
+ type_classes = { "systemd": HalBackendServiceSystemdConfig }
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ return '\n'.join([ str(process) for process in self.processes ])
+
+ def map_json_obj(self, json_obj):
+ if "process" not in json_obj:
+ raise InvalidJsonStructException("No process element")
+
+ process_obj = json_obj["process"]
+ if type(process_obj) != list:
+ raise InvalidJsonStructException(f"Invalid json struct: \"process\" should be a list, not {type(process_obj)}")
+
+ processes = list()
+
+ for obj in process_obj:
+ if "type" not in obj:
+ raise InvalidJsonStructException(f"Invalid json struct: process should have \"type\"")
+ process_type = obj["type"]
+ if process_type not in self.type_classes:
+ raise InvalidJsonValueException(f"Invalid json value: unknown type({process_type})")
+ processes.append(self.type_classes[process_type](obj))
+
+ self.processes = processes
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+static const char *g_hal_module_stub_proc_name[] = {
+ [HAL_MODULE_UNKNOWN] = NULL,
+@HAL_MODULE_STUB_PROC_NAME_MAP@
+ [HAL_MODULE_END] = NULL,
+};
--- /dev/null
+#!/usr/bin/python3
+
+import errno
+import json
+
+from getopt import getopt, GetoptError
+from sys import exit, argv
+
+from config_types import *
+
+def log(message):
+ message_lines = message.split('\n')
+ for line in message_lines:
+ print(f"[hal-backend-service-generator] {line}")
+
+def parse_hal_backend_service_configs(config_file_path):
+ with open(config_file_path, "r") as f:
+ json_object = json.load(f)
+ return HalBackendServiceConfig(json_object)
+
+def check_hal_backend_service_configs_duplications(configs):
+ names_set = set()
+ hal_module_names_set = set()
+
+ for config in configs.processes:
+ name = config.get_name()
+ if name not in names_set:
+ names_set.add(name)
+ continue
+ raise InvalidJsonValueException(f"Invalid json value: duplicated name({name})")
+
+ for config in configs.processes:
+ for hal_module_name in config.get_hal_module_names():
+ if hal_module_name not in hal_module_names_set:
+ hal_module_names_set.add(hal_module_name)
+ continue
+ raise InvalidJsonValueException(f"Invalid json value: duplicated hal module name({hal_module_name})")
+
+def create_empty_hal_backend_service_list_header(prototype_path, header_file_path):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ module_name_map = prototype.replace("@HAL_MODULE_STUB_PROC_NAME_MAP@", "")
+
+ with open(header_file_path, "w") as f:
+ f.write(module_name_map)
+
+def create_hal_backend_service_list_header(prototype_path, configs, header_file_path):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ module_name_map_list = list()
+ for config in configs.processes:
+ name = config.get_name()
+ for hal_module_name in config.get_hal_module_names():
+ hal_module_enum = f"HAL_MODULE_{hal_module_name.upper()}"
+ stub_proc_name = f"d::{name}"
+ module_name_map_list.append(f"\t[{hal_module_enum}] = \"{stub_proc_name}\",")
+ module_name_map = prototype.replace("@HAL_MODULE_STUB_PROC_NAME_MAP@", '\n'.join(module_name_map_list))
+
+ with open(header_file_path, "w") as f:
+ f.write(module_name_map)
+
+def create_hal_backend_service_service(prototype_path, configs, install_dir):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ for config in configs.processes:
+ if config.type != "systemd":
+ continue
+ service_name = config.get_name()
+ service_file_name = f"{service_name}.service"
+ stub_proc_name = f"d::{service_name}"
+ threads = ' '.join(map(lambda thread: ','.join(thread.hal_module_names), config.thread_config.threads))
+ threads = threads.replace('_', '-')
+
+ service_content = prototype.replace("@SERVICE_NAME@", service_name)\
+ .replace("@PROC_NAME@", stub_proc_name)\
+ .replace("@THREADS@", threads)
+
+ with open(f"{install_dir}/{service_file_name}", "w") as f:
+ f.write(service_content)
+
+def create_hal_backend_service_socket(prototype_path, configs, install_dir):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ for config in configs.processes:
+ if config.type != "systemd":
+ continue
+ service_name = config.get_name()
+ socket_file_name = f"{service_name}.socket"
+ stub_proc_name = f"d::{service_name}"
+ listen_streams = list()
+
+ for thread_config in config.thread_config.threads:
+ for hal_module_name in thread_config.hal_module_names:
+ listen_streams.append(f"ListenStream=/run/aul/rpcport/.{stub_proc_name}::{hal_module_name}")
+
+ socket_content = prototype.replace("@SERVICE_NAME@", service_name)\
+ .replace("@LISTEN_STREAMS@", '\n'.join(listen_streams))
+
+ with open(f"{install_dir}/{socket_file_name}", "w") as f:
+ f.write(socket_content)
+
+def print_usage(exec_name):
+ print(f"usage: {exec_name} <option> [ --config=<config file name> ]")
+ print("option:")
+ print(" --enable:")
+ print(" enable hal-backend-service, --config is mandatory.")
+ print(" exclusive with --disable.")
+ print("")
+ print(" --disable:")
+ print(" disable hal-backend-service, --config will be ignored.")
+ print(" exclusive with --enable.")
+ print("")
+ print(" --config=<config file name>:")
+ print(" should be provided if --enable is set.")
+ print(" will be ignored if --disable is set.")
+ print(" config file should be located under \"hal-backend-service/config/\".")
+
+def parse_commandline_argument(argv):
+ short_options = ""
+ long_options = ( "help", "enable", "disable", "config=" )
+
+ is_help = False
+ is_enable = False
+ is_disable = False
+ config_file = ""
+
+ try:
+ parsed_options, args = getopt(argv, short_options, long_options)
+ except GetoptError as e:
+ log(f"Invalid option: {str(e)}")
+ return None
+
+ for option, arg in parsed_options:
+ if option == "--help":
+ is_help = True
+ continue
+
+ if option == "--enable":
+ if is_disable:
+ log("Invalid option: enable and disable are exclusive")
+ return None
+ is_enable = True
+ continue
+
+ if option == "--disable":
+ if is_enable:
+ log("Invalid option: enable and disable are exclusive")
+ return None
+ is_disable = True
+ continue
+
+ if option == "--config":
+ if config_file != "":
+ log("Invalid option: config provided twice")
+ return None
+ config_file = arg
+ continue
+
+ if is_help:
+ return ( is_help, is_enable, config_file )
+
+ if not is_enable and not is_disable:
+ log("Invalid option: either enable or disable must be set")
+ return None
+
+ if is_enable and not config_file:
+ log("Invalid option: config_file should be set if enabled")
+ return None
+
+ return ( is_help, is_enable, config_file )
+
+def main():
+ hal_backend_service_list_header_prototype_path = "hal-backend-service-with-dbus/hal-api-backend-service-list.h.in"
+ hal_backend_service_service_prototype_path = "hal-backend-service-with-dbus/hal-backend-service.service.in"
+ hal_backend_service_socket_prototype_path = "hal-backend-service-with-dbus/hal-backend-service.socket.in"
+
+ hal_backend_service_list_header_install_path = "src/hal-api-backend-service-list.h"
+ hal_backend_service_service_install_path = "hal-backend-service-with-dbus"
+ hal_backend_service_socket_install_path = "hal-backend-service-with-dbus"
+
+ parsed_result = parse_commandline_argument(argv[1:])
+ if not parsed_result:
+ log("Failed to parse commandline argument")
+ return errno.EINVAL
+
+ is_help, is_enabled, config_file = parsed_result
+
+ if is_help:
+ print_usage(argv[0])
+ return 0
+
+ if not is_enabled:
+ log(f"hal-backend-service is disabled, create empty header file: {hal_backend_service_list_header_install_path}")
+ create_empty_hal_backend_service_list_header(hal_backend_service_list_header_prototype_path, hal_backend_service_list_header_install_path)
+ return 0
+
+ try:
+ config_file_path = f"hal-backend-service-with-dbus/config/{config_file}"
+
+ log(f"Using config file: {config_file_path}")
+ configs = parse_hal_backend_service_configs(config_file_path)
+ check_hal_backend_service_configs_duplications(configs)
+
+ log("Following process files will be generated:")
+ log(f"{str(configs)}")
+
+ create_hal_backend_service_list_header(hal_backend_service_list_header_prototype_path, configs, hal_backend_service_list_header_install_path)
+ create_hal_backend_service_service(hal_backend_service_service_prototype_path, configs, hal_backend_service_service_install_path)
+ create_hal_backend_service_socket(hal_backend_service_socket_prototype_path, configs, hal_backend_service_socket_install_path)
+
+ except json.JSONDecodeError as e:
+ log("Invalid json file, " + str(e))
+ return errno.EINVAL
+
+ except (InvalidJsonStructException, InvalidJsonValueException) as e:
+ log(str(e))
+ return e.errno
+
+ except Exception as e:
+ log(str(e))
+ return errno.EINVAL
+
+ log("done.")
+
+ return 0
+
+if __name__ == "__main__":
+ exit(main())
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <dbus/dbus.h>
+
+int main(void)
+{
+ DBusConnection *connection = NULL;
+ DBusBusType type = DBUS_BUS_SYSTEM;
+ DBusError error = { NULL };
+
+ connection = dbus_bus_get(type, &error);
+ if (connection == NULL)
+ return 1;
+
+ printf("Initialized\n");
+
+ while (1);
+
+ return 0;
+}
--- /dev/null
+[Unit]
+Description=HAL Backend Service
+DefaultDependencies=no
+Requires=local-fs.target tizen-system-env.service systemd-tmpfiles-setup.service
+After=local-fs.target tizen-system-env.service systemd-tmpfiles-setup.service
+
+[Service]
+Type=simple
+SmackProcessLabel=System
+ExecStart=/usr/bin/hal/hal-backend-service-with-dbus --stub-proc-name '@PROC_NAME@' @THREADS@
+EnvironmentFile=/run/xdg-root-env
+Restart=on-failure
+RestartSec=0
+KillSignal=SIGUSR1
+MemoryMax=20M
+
+[Install]
+WantedBy=basic.target
--- /dev/null
+[Unit]
+Description=HAL Backend Service Socket
+DefaultDependencies=no
+Before=sockets.target
+
+[Socket]
+@LISTEN_STREAMS@
+SocketMode=0777
+DirectoryMode=0777
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+Service=@SERVICE_NAME@.service
+
+[Install]
+WantedBy=sockets.target
--- /dev/null
+PROJECT(hal-backend-service C)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -fPIC")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 -Wl,-z,relro")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt")
+SET(CMAKE_EXE_LINKER_FLAGS "-pie")
+
+SET(EXEC_NAME "${PROJECT_NAME}-without-dbus")
+SET(src ${CMAKE_SOURCE_DIR}/hal-backend-service-without-dbus/hal-backend-service.c)
+ADD_EXECUTABLE(${EXEC_NAME} ${src})
+TARGET_LINK_LIBRARIES(${EXEC_NAME} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal)
+INSTALL(TARGETS ${EXEC_NAME} DESTINATION /usr/bin/hal)
+
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION lib/systemd/system
+ FILES_MATCHING PATTERN "hal-backend-service-without-dbus.service")
--- /dev/null
+{
+ "process": [
+ {
+ "type": "systemd",
+ "property": {
+ "name": "hal-backend-service"
+ },
+ "thread": [
+ { "hal_module_name": [ "device_display" ] },
+ { "hal_module_name": [ "device_led" ] },
+ { "hal_module_name": [ "device_battery" ] },
+ { "hal_module_name": [ "device_bezel" ] },
+ { "hal_module_name": [ "device_external_connection" ] }
+ ]
+ },
+ {
+ "type": "systemd",
+ "property": {
+ "name": "hal-backend-service-codec"
+ },
+ "thread": [
+ { "hal_module_name": [ "codec" ] }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "process": [
+ {
+ "type": "systemd",
+ "property": {
+ "name": "hal-backend-service-without-dbus"
+ },
+ "thread": [
+ { "hal_module_name": [ "device_display" ] },
+ { "hal_module_name": [ "device_led" ] },
+ { "hal_module_name": [ "device_battery" ] },
+ { "hal_module_name": [ "device_bezel" ] },
+ { "hal_module_name": [ "device_external_connection" ] }
+ ]
+ }
+ ]
+}
--- /dev/null
+import errno
+
+class InvalidJsonStructException(Exception):
+ errno = errno.EINVAL
+
+class InvalidJsonValueException(Exception):
+ errno = errno.EINVAL
+
+class JsonConfigEntity:
+ def get_name(self):
+ return None
+ def get_hal_module_names(self):
+ return None
+ def map_json_obj(self, json_obj):
+ return None
+
+class ThreadConfig(JsonConfigEntity):
+ hal_module_names: list
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"\t\tThread:\n"
+ result += f"\t\t\thal module names: " + ", ".join(self.hal_module_names) + "\n"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != dict:
+ raise InvalidJsonStructException("Invalid json struct: thread should be a json object")
+ if "hal_module_name" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: thread should have \"hal_module_name\"")
+
+ hal_module_name_obj = json_obj["hal_module_name"]
+ if type(hal_module_name_obj) != list:
+ raise InvalidJsonStructException("Invalid json struct: hal_module_name should be a list")
+
+ if any(filter(lambda x: type(x) != str, hal_module_name_obj)):
+ raise InvalidJsonStructException("Invalid json struct: hal_module_name should be a list of strings")
+
+ self.hal_module_names = [ str(obj) for obj in hal_module_name_obj ]
+
+class ThreadsConfig(JsonConfigEntity):
+ threads: list
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"\tThreads:\n"
+ for thread in self.threads:
+ result += f"{str(thread)}"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != list:
+ raise InvalidJsonStructException("Invalid json struct: thread should be a list")
+
+ threads = list()
+
+ for obj in json_obj:
+ threads.append(ThreadConfig(obj))
+
+ self.threads = threads
+
+ def get_hal_module_names(self):
+ hal_module_names = list()
+
+ for thread in self.threads:
+ hal_module_names += thread.hal_module_names
+
+ return hal_module_names
+
+class HalBackendServiceSystemdPropertyConfig(JsonConfigEntity):
+ name: str
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"\tProperties:\n"
+ result += f"\t\tname: {self.name}\n"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != dict:
+ raise InvalidJsonStructException("Invalid json struct: systemd property should be a json object")
+ if "name" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: systemd property should have \"name\"")
+
+ name_obj = json_obj["name"]
+ if type(name_obj) != str:
+ raise InvalidJsonStructException("Invalid json struct: systemd name should be a string")
+
+ service_name_prefix = "hal-backend-service"
+ if not name_obj.startswith(service_name_prefix):
+ raise InvalidJsonValueException(f"Invalid json value: systemd name should start with {service_name_prefix}")
+
+ self.name = name_obj
+
+class HalBackendServiceSystemdConfig(JsonConfigEntity):
+ properties: HalBackendServiceSystemdPropertyConfig
+ thread_config: ThreadsConfig
+
+ def __init__(self, json_obj):
+ self.type = "systemd"
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ result = ""
+ result += f"Service:\n"
+ result += f"{str(self.properties)}"
+ result += f"{str(self.thread_config)}"
+ return result
+
+ def map_json_obj(self, json_obj):
+ if type(json_obj) != dict:
+ raise InvalidJsonStructException("Invalid json struct: systemd process should be a json object")
+ if "property" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: systemd process should have \"properties\"")
+ if "thread" not in json_obj:
+ raise InvalidJsonStructException("Invalid json struct: systemd process should have \"thread\"")
+
+ property_obj = json_obj["property"]
+ self.properties = HalBackendServiceSystemdPropertyConfig(property_obj)
+
+ thread_obj = json_obj["thread"]
+ self.thread_config = ThreadsConfig(thread_obj)
+
+ def get_name(self):
+ return self.properties.name
+
+ def get_hal_module_names(self):
+ return self.thread_config.get_hal_module_names()
+
+class HalBackendServiceConfig(JsonConfigEntity):
+ processes: list
+ type_classes = { "systemd": HalBackendServiceSystemdConfig }
+
+ def __init__(self, json_obj):
+ self.map_json_obj(json_obj)
+
+ def __str__(self):
+ return '\n'.join([ str(process) for process in self.processes ])
+
+ def map_json_obj(self, json_obj):
+ if "process" not in json_obj:
+ raise InvalidJsonStructException("No process element")
+
+ process_obj = json_obj["process"]
+ if type(process_obj) != list:
+ raise InvalidJsonStructException(f"Invalid json struct: \"process\" should be a list, not {type(process_obj)}")
+
+ processes = list()
+
+ for obj in process_obj:
+ if "type" not in obj:
+ raise InvalidJsonStructException(f"Invalid json struct: process should have \"type\"")
+ process_type = obj["type"]
+ if process_type not in self.type_classes:
+ raise InvalidJsonValueException(f"Invalid json value: unknown type({process_type})")
+ processes.append(self.type_classes[process_type](obj))
+
+ self.processes = processes
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+static const char *g_hal_module_stub_proc_name[] = {
+ [HAL_MODULE_UNKNOWN] = NULL,
+@HAL_MODULE_STUB_PROC_NAME_MAP@
+ [HAL_MODULE_END] = NULL,
+};
--- /dev/null
+#!/usr/bin/python3
+
+import errno
+import json
+
+from getopt import getopt, GetoptError
+from sys import exit, argv
+
+from config_types import *
+
+def log(message):
+ message_lines = message.split('\n')
+ for line in message_lines:
+ print(f"[hal-backend-service-generator] {line}")
+
+def parse_hal_backend_service_configs(config_file_path):
+ with open(config_file_path, "r") as f:
+ json_object = json.load(f)
+ return HalBackendServiceConfig(json_object)
+
+def check_hal_backend_service_configs_duplications(configs):
+ names_set = set()
+ hal_module_names_set = set()
+
+ for config in configs.processes:
+ name = config.get_name()
+ if name not in names_set:
+ names_set.add(name)
+ continue
+ raise InvalidJsonValueException(f"Invalid json value: duplicated name({name})")
+
+ for config in configs.processes:
+ for hal_module_name in config.get_hal_module_names():
+ if hal_module_name not in hal_module_names_set:
+ hal_module_names_set.add(hal_module_name)
+ continue
+ raise InvalidJsonValueException(f"Invalid json value: duplicated hal module name({hal_module_name})")
+
+def create_empty_hal_backend_service_list_header(prototype_path, header_file_path):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ module_name_map = prototype.replace("@HAL_MODULE_STUB_PROC_NAME_MAP@", "")
+
+ with open(header_file_path, "w") as f:
+ f.write(module_name_map)
+
+def create_hal_backend_service_list_header(prototype_path, configs, header_file_path):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ module_name_map_list = list()
+ for config in configs.processes:
+ name = config.get_name()
+ for hal_module_name in config.get_hal_module_names():
+ hal_module_enum = f"HAL_MODULE_{hal_module_name.upper()}"
+ stub_proc_name = f"d::{name}"
+ module_name_map_list.append(f"\t[{hal_module_enum}] = \"{stub_proc_name}\",")
+ module_name_map = prototype.replace("@HAL_MODULE_STUB_PROC_NAME_MAP@", '\n'.join(module_name_map_list))
+
+ with open(header_file_path, "w") as f:
+ f.write(module_name_map)
+
+def create_hal_backend_service_service(prototype_path, configs, install_dir):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ for config in configs.processes:
+ if config.type != "systemd":
+ continue
+ service_name = config.get_name()
+ service_file_name = f"{service_name}.service"
+ stub_proc_name = f"d::{service_name}"
+ threads = ' '.join(map(lambda thread: ','.join(thread.hal_module_names), config.thread_config.threads))
+ threads = threads.replace('_', '-')
+
+ service_content = prototype.replace("@SERVICE_NAME@", service_name)\
+ .replace("@PROC_NAME@", stub_proc_name)\
+ .replace("@THREADS@", threads)
+
+ with open(f"{install_dir}/{service_file_name}", "w") as f:
+ f.write(service_content)
+
+def create_hal_backend_service_socket(prototype_path, configs, install_dir):
+ with open(prototype_path, "r") as f:
+ prototype = f.read()
+
+ for config in configs.processes:
+ if config.type != "systemd":
+ continue
+ service_name = config.get_name()
+ socket_file_name = f"{service_name}.socket"
+ stub_proc_name = f"d::{service_name}"
+ listen_streams = list()
+
+ for thread_config in config.thread_config.threads:
+ for hal_module_name in thread_config.hal_module_names:
+ listen_streams.append(f"ListenStream=/run/aul/rpcport/.{stub_proc_name}::{hal_module_name}")
+
+ socket_content = prototype.replace("@SERVICE_NAME@", service_name)\
+ .replace("@LISTEN_STREAMS@", '\n'.join(listen_streams))
+
+ with open(f"{install_dir}/{socket_file_name}", "w") as f:
+ f.write(socket_content)
+
+def print_usage(exec_name):
+ print(f"usage: {exec_name} <option> [ --config=<config file name> ]")
+ print("option:")
+ print(" --enable:")
+ print(" enable hal-backend-service, --config is mandatory.")
+ print(" exclusive with --disable.")
+ print("")
+ print(" --disable:")
+ print(" disable hal-backend-service, --config will be ignored.")
+ print(" exclusive with --enable.")
+ print("")
+ print(" --config=<config file name>:")
+ print(" should be provided if --enable is set.")
+ print(" will be ignored if --disable is set.")
+ print(" config file should be located under \"hal-backend-service/config/\".")
+
+def parse_commandline_argument(argv):
+ short_options = ""
+ long_options = ( "help", "enable", "disable", "config=" )
+
+ is_help = False
+ is_enable = False
+ is_disable = False
+ config_file = ""
+
+ try:
+ parsed_options, args = getopt(argv, short_options, long_options)
+ except GetoptError as e:
+ log(f"Invalid option: {str(e)}")
+ return None
+
+ for option, arg in parsed_options:
+ if option == "--help":
+ is_help = True
+ continue
+
+ if option == "--enable":
+ if is_disable:
+ log("Invalid option: enable and disable are exclusive")
+ return None
+ is_enable = True
+ continue
+
+ if option == "--disable":
+ if is_enable:
+ log("Invalid option: enable and disable are exclusive")
+ return None
+ is_disable = True
+ continue
+
+ if option == "--config":
+ if config_file != "":
+ log("Invalid option: config provided twice")
+ return None
+ config_file = arg
+ continue
+
+ if is_help:
+ return ( is_help, is_enable, config_file )
+
+ if not is_enable and not is_disable:
+ log("Invalid option: either enable or disable must be set")
+ return None
+
+ if is_enable and not config_file:
+ log("Invalid option: config_file should be set if enabled")
+ return None
+
+ return ( is_help, is_enable, config_file )
+
+def main():
+ hal_backend_service_list_header_prototype_path = "hal-backend-service-without-dbus/hal-api-backend-service-list.h.in"
+ hal_backend_service_service_prototype_path = "hal-backend-service-without-dbus/hal-backend-service.service.in"
+ hal_backend_service_socket_prototype_path = "hal-backend-service-without-dbus/hal-backend-service.socket.in"
+
+ hal_backend_service_list_header_install_path = "src/hal-api-backend-service-list.h"
+ hal_backend_service_service_install_path = "hal-backend-service-without-dbus"
+ hal_backend_service_socket_install_path = "hal-backend-service-without-dbus"
+
+ parsed_result = parse_commandline_argument(argv[1:])
+ if not parsed_result:
+ log("Failed to parse commandline argument")
+ return errno.EINVAL
+
+ is_help, is_enabled, config_file = parsed_result
+
+ if is_help:
+ print_usage(argv[0])
+ return 0
+
+ if not is_enabled:
+ log(f"hal-backend-service-without-dbus is disabled, create empty header file: {hal_backend_service_list_header_install_path}")
+ create_empty_hal_backend_service_list_header(hal_backend_service_list_header_prototype_path, hal_backend_service_list_header_install_path)
+ return 0
+
+ try:
+ config_file_path = f"hal-backend-service-without-dbus/config/{config_file}"
+
+ log(f"Using config file: {config_file_path}")
+ configs = parse_hal_backend_service_configs(config_file_path)
+ check_hal_backend_service_configs_duplications(configs)
+
+ log("Following process files will be generated:")
+ log(f"{str(configs)}")
+
+ create_hal_backend_service_list_header(hal_backend_service_list_header_prototype_path, configs, hal_backend_service_list_header_install_path)
+ create_hal_backend_service_service(hal_backend_service_service_prototype_path, configs, hal_backend_service_service_install_path)
+ create_hal_backend_service_socket(hal_backend_service_socket_prototype_path, configs, hal_backend_service_socket_install_path)
+
+ except json.JSONDecodeError as e:
+ log("Invalid json file, " + str(e))
+ return errno.EINVAL
+
+ except (InvalidJsonStructException, InvalidJsonValueException) as e:
+ log(str(e))
+ return e.errno
+
+ except Exception as e:
+ log(str(e))
+ return errno.EINVAL
+
+ log("done.")
+
+ return 0
+
+if __name__ == "__main__":
+ exit(main())
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+int main(void)
+{
+ printf("Initialized\n");
+
+ while (1);
+
+ return 0;
+}
--- /dev/null
+[Unit]
+Description=HAL Backend Service
+DefaultDependencies=no
+Requires=local-fs.target tizen-system-env.service systemd-tmpfiles-setup.service
+After=local-fs.target tizen-system-env.service systemd-tmpfiles-setup.service
+
+[Service]
+Type=simple
+SmackProcessLabel=System
+ExecStart=/usr/bin/hal/hal-backend-service-without-dbus --stub-proc-name '@PROC_NAME@' @THREADS@
+EnvironmentFile=/run/xdg-root-env
+Restart=on-failure
+RestartSec=0
+KillSignal=SIGUSR1
+MemoryMax=20M
+
+[Install]
+WantedBy=basic.target
--- /dev/null
+[Unit]
+Description=HAL Backend Service Socket
+DefaultDependencies=no
+Before=sockets.target
+
+[Socket]
+@LISTEN_STREAMS@
+SocketMode=0777
+DirectoryMode=0777
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+Service=@SERVICE_NAME@.service
+
+[Install]
+WantedBy=sockets.target
+++ /dev/null
-PROJECT(hal-backend-service C CXX)
-
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src)
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
-
-ADD_DEFINITIONS("-DLOG_TAG=\"HAL_BACKEND_SERVICE\"")
-
-INCLUDE(FindPkgConfig)
-pkg_check_modules(gtest_pkgs REQUIRED
- dlog
- glib-2.0
- rpc-port
- bundle
- tizen-core
-)
-
-FOREACH(flag ${gtest_pkgs_CFLAGS})
- SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
-ENDFOREACH(flag)
-
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -fPIC")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 -Wl,-z,relro")
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt")
-SET(CMAKE_EXE_LINKER_FLAGS "-pie")
-
-SET(src
- ${CMAKE_SOURCE_DIR}/src/hal-api-conf.c
- ${CMAKE_SOURCE_DIR}/hal-backend-service/hal-backend-service.c
-)
-MESSAGE("${PROJECT_NAME}")
-ADD_EXECUTABLE(${PROJECT_NAME} ${src})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal)
-INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/hal)
-
-INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION lib/systemd/system
- FILES_MATCHING PATTERN "hal-backend-service*.service")
-INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION lib/systemd/system
- FILES_MATCHING PATTERN "hal-backend-service*.socket")
+++ /dev/null
-{
- "process": [
- {
- "type": "systemd",
- "property": {
- "name": "hal-backend-service"
- },
- "thread": [
- { "hal_module_name": [ "device_display" ] },
- { "hal_module_name": [ "device_led" ] },
- { "hal_module_name": [ "device_battery" ] },
- { "hal_module_name": [ "device_bezel" ] },
- { "hal_module_name": [ "device_external_connection" ] }
- ]
- },
- {
- "type": "systemd",
- "property": {
- "name": "hal-backend-service-codec"
- },
- "thread": [
- { "hal_module_name": [ "codec" ] }
- ]
- }
- ]
-}
+++ /dev/null
-{
- "process": [
- {
- "type": "systemd",
- "property": {
- "name": "hal-backend-service"
- },
- "thread": [
- { "hal_module_name": [ "device_display" ] },
- { "hal_module_name": [ "device_led" ] },
- { "hal_module_name": [ "device_battery" ] },
- { "hal_module_name": [ "device_bezel" ] },
- { "hal_module_name": [ "device_external_connection" ] }
- ]
- }
- ]
-}
+++ /dev/null
-import errno
-
-class InvalidJsonStructException(Exception):
- errno = errno.EINVAL
-
-class InvalidJsonValueException(Exception):
- errno = errno.EINVAL
-
-class JsonConfigEntity:
- def get_name(self):
- return None
- def get_hal_module_names(self):
- return None
- def map_json_obj(self, json_obj):
- return None
-
-class ThreadConfig(JsonConfigEntity):
- hal_module_names: list
-
- def __init__(self, json_obj):
- self.map_json_obj(json_obj)
-
- def __str__(self):
- result = ""
- result += f"\t\tThread:\n"
- result += f"\t\t\thal module names: " + ", ".join(self.hal_module_names) + "\n"
- return result
-
- def map_json_obj(self, json_obj):
- if type(json_obj) != dict:
- raise InvalidJsonStructException("Invalid json struct: thread should be a json object")
- if "hal_module_name" not in json_obj:
- raise InvalidJsonStructException("Invalid json struct: thread should have \"hal_module_name\"")
-
- hal_module_name_obj = json_obj["hal_module_name"]
- if type(hal_module_name_obj) != list:
- raise InvalidJsonStructException("Invalid json struct: hal_module_name should be a list")
-
- if any(filter(lambda x: type(x) != str, hal_module_name_obj)):
- raise InvalidJsonStructException("Invalid json struct: hal_module_name should be a list of strings")
-
- self.hal_module_names = [ str(obj) for obj in hal_module_name_obj ]
-
-class ThreadsConfig(JsonConfigEntity):
- threads: list
-
- def __init__(self, json_obj):
- self.map_json_obj(json_obj)
-
- def __str__(self):
- result = ""
- result += f"\tThreads:\n"
- for thread in self.threads:
- result += f"{str(thread)}"
- return result
-
- def map_json_obj(self, json_obj):
- if type(json_obj) != list:
- raise InvalidJsonStructException("Invalid json struct: thread should be a list")
-
- threads = list()
-
- for obj in json_obj:
- threads.append(ThreadConfig(obj))
-
- self.threads = threads
-
- def get_hal_module_names(self):
- hal_module_names = list()
-
- for thread in self.threads:
- hal_module_names += thread.hal_module_names
-
- return hal_module_names
-
-class HalBackendServiceSystemdPropertyConfig(JsonConfigEntity):
- name: str
-
- def __init__(self, json_obj):
- self.map_json_obj(json_obj)
-
- def __str__(self):
- result = ""
- result += f"\tProperties:\n"
- result += f"\t\tname: {self.name}\n"
- return result
-
- def map_json_obj(self, json_obj):
- if type(json_obj) != dict:
- raise InvalidJsonStructException("Invalid json struct: systemd property should be a json object")
- if "name" not in json_obj:
- raise InvalidJsonStructException("Invalid json struct: systemd property should have \"name\"")
-
- name_obj = json_obj["name"]
- if type(name_obj) != str:
- raise InvalidJsonStructException("Invalid json struct: systemd name should be a string")
-
- service_name_prefix = "hal-backend-service"
- if not name_obj.startswith(service_name_prefix):
- raise InvalidJsonValueException(f"Invalid json value: systemd name should start with {service_name_prefix}")
-
- self.name = name_obj
-
-class HalBackendServiceSystemdConfig(JsonConfigEntity):
- properties: HalBackendServiceSystemdPropertyConfig
- thread_config: ThreadsConfig
-
- def __init__(self, json_obj):
- self.type = "systemd"
- self.map_json_obj(json_obj)
-
- def __str__(self):
- result = ""
- result += f"Service:\n"
- result += f"{str(self.properties)}"
- result += f"{str(self.thread_config)}"
- return result
-
- def map_json_obj(self, json_obj):
- if type(json_obj) != dict:
- raise InvalidJsonStructException("Invalid json struct: systemd process should be a json object")
- if "property" not in json_obj:
- raise InvalidJsonStructException("Invalid json struct: systemd process should have \"properties\"")
- if "thread" not in json_obj:
- raise InvalidJsonStructException("Invalid json struct: systemd process should have \"thread\"")
-
- property_obj = json_obj["property"]
- self.properties = HalBackendServiceSystemdPropertyConfig(property_obj)
-
- thread_obj = json_obj["thread"]
- self.thread_config = ThreadsConfig(thread_obj)
-
- def get_name(self):
- return self.properties.name
-
- def get_hal_module_names(self):
- return self.thread_config.get_hal_module_names()
-
-class HalBackendServiceConfig(JsonConfigEntity):
- processes: list
- type_classes = { "systemd": HalBackendServiceSystemdConfig }
-
- def __init__(self, json_obj):
- self.map_json_obj(json_obj)
-
- def __str__(self):
- return '\n'.join([ str(process) for process in self.processes ])
-
- def map_json_obj(self, json_obj):
- if "process" not in json_obj:
- raise InvalidJsonStructException("No process element")
-
- process_obj = json_obj["process"]
- if type(process_obj) != list:
- raise InvalidJsonStructException(f"Invalid json struct: \"process\" should be a list, not {type(process_obj)}")
-
- processes = list()
-
- for obj in process_obj:
- if "type" not in obj:
- raise InvalidJsonStructException(f"Invalid json struct: process should have \"type\"")
- process_type = obj["type"]
- if process_type not in self.type_classes:
- raise InvalidJsonValueException(f"Invalid json value: unknown type({process_type})")
- processes.append(self.type_classes[process_type](obj))
-
- self.processes = processes
+++ /dev/null
-/*
- * Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-static const char *g_hal_module_stub_proc_name[] = {
- [HAL_MODULE_UNKNOWN] = NULL,
-@HAL_MODULE_STUB_PROC_NAME_MAP@
- [HAL_MODULE_END] = NULL,
-};
+++ /dev/null
-#!/usr/bin/python3
-
-import errno
-import json
-
-from getopt import getopt, GetoptError
-from sys import exit, argv
-
-from config_types import *
-
-def log(message):
- message_lines = message.split('\n')
- for line in message_lines:
- print(f"[hal-backend-service-generator] {line}")
-
-def parse_hal_backend_service_configs(config_file_path):
- with open(config_file_path, "r") as f:
- json_object = json.load(f)
- return HalBackendServiceConfig(json_object)
-
-def check_hal_backend_service_configs_duplications(configs):
- names_set = set()
- hal_module_names_set = set()
-
- for config in configs.processes:
- name = config.get_name()
- if name not in names_set:
- names_set.add(name)
- continue
- raise InvalidJsonValueException(f"Invalid json value: duplicated name({name})")
-
- for config in configs.processes:
- for hal_module_name in config.get_hal_module_names():
- if hal_module_name not in hal_module_names_set:
- hal_module_names_set.add(hal_module_name)
- continue
- raise InvalidJsonValueException(f"Invalid json value: duplicated hal module name({hal_module_name})")
-
-def create_empty_hal_backend_service_list_header(prototype_path, header_file_path):
- with open(prototype_path, "r") as f:
- prototype = f.read()
-
- module_name_map = prototype.replace("@HAL_MODULE_STUB_PROC_NAME_MAP@", "")
-
- with open(header_file_path, "w") as f:
- f.write(module_name_map)
-
-def create_hal_backend_service_list_header(prototype_path, configs, header_file_path):
- with open(prototype_path, "r") as f:
- prototype = f.read()
-
- module_name_map_list = list()
- for config in configs.processes:
- name = config.get_name()
- for hal_module_name in config.get_hal_module_names():
- hal_module_enum = f"HAL_MODULE_{hal_module_name.upper()}"
- stub_proc_name = f"d::{name}"
- module_name_map_list.append(f"\t[{hal_module_enum}] = \"{stub_proc_name}\",")
- module_name_map = prototype.replace("@HAL_MODULE_STUB_PROC_NAME_MAP@", '\n'.join(module_name_map_list))
-
- with open(header_file_path, "w") as f:
- f.write(module_name_map)
-
-def create_hal_backend_service_service(prototype_path, configs, install_dir):
- with open(prototype_path, "r") as f:
- prototype = f.read()
-
- for config in configs.processes:
- if config.type != "systemd":
- continue
- service_name = config.get_name()
- service_file_name = f"{service_name}.service"
- stub_proc_name = f"d::{service_name}"
- threads = ' '.join(map(lambda thread: ','.join(thread.hal_module_names), config.thread_config.threads))
- threads = threads.replace('_', '-')
-
- service_content = prototype.replace("@SERVICE_NAME@", service_name)\
- .replace("@PROC_NAME@", stub_proc_name)\
- .replace("@THREADS@", threads)
-
- with open(f"{install_dir}/{service_file_name}", "w") as f:
- f.write(service_content)
-
-def create_hal_backend_service_socket(prototype_path, configs, install_dir):
- with open(prototype_path, "r") as f:
- prototype = f.read()
-
- for config in configs.processes:
- if config.type != "systemd":
- continue
- service_name = config.get_name()
- socket_file_name = f"{service_name}.socket"
- stub_proc_name = f"d::{service_name}"
- listen_streams = list()
-
- for thread_config in config.thread_config.threads:
- for hal_module_name in thread_config.hal_module_names:
- listen_streams.append(f"ListenStream=/run/aul/rpcport/.{stub_proc_name}::{hal_module_name}")
-
- socket_content = prototype.replace("@SERVICE_NAME@", service_name)\
- .replace("@LISTEN_STREAMS@", '\n'.join(listen_streams))
-
- with open(f"{install_dir}/{socket_file_name}", "w") as f:
- f.write(socket_content)
-
-def print_usage(exec_name):
- print(f"usage: {exec_name} <option> [ --config=<config file name> ]")
- print("option:")
- print(" --enable:")
- print(" enable hal-backend-service, --config is mandatory.")
- print(" exclusive with --disable.")
- print("")
- print(" --disable:")
- print(" disable hal-backend-service, --config will be ignored.")
- print(" exclusive with --enable.")
- print("")
- print(" --config=<config file name>:")
- print(" should be provided if --enable is set.")
- print(" will be ignored if --disable is set.")
- print(" config file should be located under \"hal-backend-service/config/\".")
-
-def parse_commandline_argument(argv):
- short_options = ""
- long_options = ( "help", "enable", "disable", "config=" )
-
- is_help = False
- is_enable = False
- is_disable = False
- config_file = ""
-
- try:
- parsed_options, args = getopt(argv, short_options, long_options)
- except GetoptError as e:
- log(f"Invalid option: {str(e)}")
- return None
-
- for option, arg in parsed_options:
- if option == "--help":
- is_help = True
- continue
-
- if option == "--enable":
- if is_disable:
- log("Invalid option: enable and disable are exclusive")
- return None
- is_enable = True
- continue
-
- if option == "--disable":
- if is_enable:
- log("Invalid option: enable and disable are exclusive")
- return None
- is_disable = True
- continue
-
- if option == "--config":
- if config_file != "":
- log("Invalid option: config provided twice")
- return None
- config_file = arg
- continue
-
- if is_help:
- return ( is_help, is_enable, config_file )
-
- if not is_enable and not is_disable:
- log("Invalid option: either enable or disable must be set")
- return None
-
- if is_enable and not config_file:
- log("Invalid option: config_file should be set if enabled")
- return None
-
- return ( is_help, is_enable, config_file )
-
-def main():
- hal_backend_service_list_header_prototype_path = "hal-backend-service/hal-api-backend-service-list.h.in"
- hal_backend_service_service_prototype_path = "hal-backend-service/hal-backend-service.service.in"
- hal_backend_service_socket_prototype_path = "hal-backend-service/hal-backend-service.socket.in"
-
- hal_backend_service_list_header_install_path = "src/hal-api-backend-service-list.h"
- hal_backend_service_service_install_path = "hal-backend-service"
- hal_backend_service_socket_install_path = "hal-backend-service"
-
- parsed_result = parse_commandline_argument(argv[1:])
- if not parsed_result:
- log("Failed to parse commandline argument")
- return errno.EINVAL
-
- is_help, is_enabled, config_file = parsed_result
-
- if is_help:
- print_usage(argv[0])
- return 0
-
- if not is_enabled:
- log(f"hal-backend-service is disabled, create empty header file: {hal_backend_service_list_header_install_path}")
- create_empty_hal_backend_service_list_header(hal_backend_service_list_header_prototype_path, hal_backend_service_list_header_install_path)
- return 0
-
- try:
- config_file_path = f"hal-backend-service/config/{config_file}"
-
- log(f"Using config file: {config_file_path}")
- configs = parse_hal_backend_service_configs(config_file_path)
- check_hal_backend_service_configs_duplications(configs)
-
- log("Following process files will be generated:")
- log(f"{str(configs)}")
-
- create_hal_backend_service_list_header(hal_backend_service_list_header_prototype_path, configs, hal_backend_service_list_header_install_path)
- create_hal_backend_service_service(hal_backend_service_service_prototype_path, configs, hal_backend_service_service_install_path)
- create_hal_backend_service_socket(hal_backend_service_socket_prototype_path, configs, hal_backend_service_socket_install_path)
-
- except json.JSONDecodeError as e:
- log("Invalid json file, " + str(e))
- return errno.EINVAL
-
- except (InvalidJsonStructException, InvalidJsonValueException) as e:
- log(str(e))
- return e.errno
-
- except Exception as e:
- log(str(e))
- return errno.EINVAL
-
- log("done.")
-
- return 0
-
-if __name__ == "__main__":
- exit(main())
+++ /dev/null
-/*
- * Copyright (c) 2025 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdbool.h>
-#include <dlfcn.h>
-#include <dirent.h>
-#include <getopt.h>
-#include <errno.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <glib-unix.h>
-#include <rpc-port-internal.h>
-#include <bundle_internal.h>
-#include <tizen_core.h>
-
-#include "hal-common.h"
-#include "hal-api-conf.h"
-#include "hal-api-list.h"
-#include "common.h"
-
-#define COMMANDLINE_OPTION_STUB_PROC_NAME "stub-proc-name"
-
-struct hal_backend_service_data {
- enum hal_module *modules;
- size_t modules_len;
- tizen_core_task_h task;
- bool is_initialized;
-};
-
-enum hal_backend_service_func {
- HAL_BACKEND_SERVICE_FUNC_UNKNOWN = 0,
- HAL_BACKEND_SERVICE_FUNC_GET_NAME,
- HAL_BACKEND_SERVICE_FUNC_INIT,
- HAL_BACKEND_SERVICE_FUNC_EXIT,
-};
-
-extern char *program_invocation_name;
-
-static tizen_core_task_h g_main_task = NULL;
-
-static GSList *g_hal_backend_service_data_list = NULL;
-G_LOCK_DEFINE_STATIC(hal_backend_service_lock);
-
-static inline const char* get_backend_service_library_name(struct __hal_module_info *info)
-{
- if (!info)
- return NULL;
-
-#if defined(__aarch64__) || defined(__x86_64__) || defined (__riscv)
- return info->backend_service_library_name_64bit;
-#else
- return info->backend_service_library_name;
-#endif
-}
-
-static int __open_backend_service(struct __hal_module_info *info)
-{
- const char *backend_service_library_name = NULL;
- int ret;
-
- if (info->backend_service && info->backend_service_handle)
- return 0;
-
- backend_service_library_name = get_backend_service_library_name(info);
- if (!backend_service_library_name) {
- _E("%s: Failed to get backend service library name\n",
- info->module_name);
- ret = -EINVAL;
- goto err;
- } else if (access(backend_service_library_name, F_OK) == -1) {
- _I("%s: There is no backend service library\n",
- info->module_name);
- ret = -ENOENT;
- goto err;
- }
-
- _I("%s: Prepare to open HAL backend Plugin: library(%s)/count(%d) by %s\n",
- info->module_name, get_backend_service_library_name(info), info->backend_service_usage_count,
- program_invocation_name);
-
- if (!info->backend_service_symbol_name) {
- _E("%s: Failed to get backend symbol name\n",
- info->module_name);
- ret = -EINVAL;
- goto err;
- }
-
- info->backend_service_handle = dlopen(backend_service_library_name, RTLD_LAZY);
- if (!info->backend_service_handle) {
- _E("%s: Failed to load backend service library (%s)\n",
- info->module_name, dlerror());
- ret = -EINVAL;
- goto err;
- }
-
- info->backend_service = dlsym(info->backend_service_handle,
- info->backend_service_symbol_name);
- if (!info->backend_service) {
- _E("%s: Failed to find backend service data (%s)\n",
- info->module_name, dlerror());
- ret = -EINVAL;
- goto err_dlclose;
- }
-
- return 0;
-
-err_dlclose:
- dlclose(info->backend_service_handle);
-err:
- info->backend_service = NULL;
- info->backend_service_handle = NULL;
-
- return ret;
-}
-
-static void __close_backend_service(struct __hal_module_info *info)
-{
- if (!info->backend_service || !info->backend_service_handle)
- return;
-
- if (info->backend_service_handle)
- dlclose(info->backend_service_handle);
-
- info->backend_service = NULL;
- info->backend_service_handle = NULL;
-}
-
-static int __do_backend_service_func(enum hal_module module,
- enum hal_backend_service_func func,
- void *user_data,
- char *name, int name_size)
-{
- struct __hal_module_info *info = NULL;
- int ret = 0, ret_error = 0, len;
-
- if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
- _E("Invalid parameter of HAL module (%d)\n", module);
- return 0;
- }
-
- G_LOCK(hal_backend_service_lock);
-
- if (_hal_api_conf_init()) {
- ret = -ENODATA;
- goto err_unlock;
- }
-
- info = _hal_api_conf_get_module_info(module, NULL);
- if (info == NULL) {
- _E("Failed to get HAL module(%d) information\n", module);
- ret = -ENODATA;
- goto err_conf_exit;
- }
-
- if (!info->hal_api) {
- ret = -ENOENT;
- goto err_conf_exit;
- }
-
- if (!info->backend_service_handle || !info->backend_service) {
- _E("%s hal-backend-servicd doesn't be opended\n", info->module_name);
- ret = -EINVAL;
- goto err_conf_exit;
- }
-
- /* Return name of hal_backend_service structure */
- switch (func) {
- case HAL_BACKEND_SERVICE_FUNC_GET_NAME:
- if (info->backend_service->name== 0 || !name || name_size == 0) {
- _E("%s: Invalid size of name[] array\n", info->module_name);
- ret = -EINVAL;
- goto err_conf_exit;
- }
-
- len = strlen(info->backend_service->name);
- if (!info->backend_service->name || (len + 1 > name_size)) {
- _E("%s: Invalid size of name[] array\n", info->module_name);
- ret = -EINVAL;
- goto err_conf_exit;
- }
- strncpy(name, info->backend_service->name, name_size);
- break;
- case HAL_BACKEND_SERVICE_FUNC_INIT:
- if (info->backend_service->early_init) {
- ret = info->backend_service->early_init(user_data);
- if (ret != 0) {
- _E("Failed to early initialize %s: ret(%d)",
- info->backend_service->name, ret);
- goto err_conf_exit;
- }
- }
-
- if (info->backend_service->init) {
- ret = info->backend_service->init(user_data);
- if (ret != 0) {
- _E("Failed to initialize %s: ret(%d)",
- info->backend_service->name, ret);
- goto err_conf_exit;
- }
- }
- break;
- case HAL_BACKEND_SERVICE_FUNC_EXIT:
- if (info->backend_service->exit) {
- ret = info->backend_service->exit(user_data);
- if (ret != 0) {
- _W("Cannot exit %s: ret(%d)",
- info->backend_service->name, ret);
- ret_error = ret;
- }
- }
-
- if (info->backend_service->late_exit) {
- ret = info->backend_service->late_exit(user_data);
- if (ret != 0) {
- _W("Cannot late exit %s: ret(%d)",
- info->backend_service->name, ret);
- ret_error = ret;
- }
- }
- break;
- default:
- _E("%s: Failed to get backend data\n", info->module_name);
- ret = -EINVAL;
- goto err_conf_exit;
- }
-
- if (ret_error != 0)
- ret = ret_error;
- else
- ret = 0;
-
-err_conf_exit:
- _hal_api_conf_exit();
-err_unlock:
- G_UNLOCK(hal_backend_service_lock);
- return ret;
-}
-
-static int __get_backend_service(enum hal_module module,
- void **data, void *user_data,
- const char *library_name)
-{
- struct __hal_module_info *info = NULL;
- int ret;
-
- if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
- _E("Invalid parameter of HAL module (%d)\n", module);
- return -EINVAL;
- }
-
- G_LOCK(hal_backend_service_lock);
- if (_hal_api_conf_init()) {
- ret = -EINVAL;
- goto err;
- }
-
- info = _hal_api_conf_get_module_info(module, library_name);
- if (info == NULL) {
- if (!library_name)
- _E("Failed to get HAL module(%d) information\n", module);
- else
- _E("Failed to get HAL module(%d) information (%s)\n",
- module, library_name);
- ret = -EINVAL;
- goto err_conf_exit;
- }
-
- if (!info->hal_api) {
- ret = -ENOENT;
- goto err_conf_exit;
- }
-
- ret = __open_backend_service(info);
- if (ret < 0)
- goto err_conf_exit;
-
- info->backend_service_usage_count++;
-
- _I("%s: Get HAL backend Plugin: name(%s)/library(%s)/count(%d) by %s\n",
- info->module_name, info->backend_service->name,
- get_backend_service_library_name(info), info->backend_service_usage_count,
- program_invocation_name);
-
- G_UNLOCK(hal_backend_service_lock);
- return 0;
-
-err_conf_exit:
- _hal_api_conf_exit();
-err:
- G_UNLOCK(hal_backend_service_lock);
- return ret;
-}
-
-static int __put_backend_service(enum hal_module module,
- void *data, void *user_data,
- const char *library_name)
-{
- struct __hal_module_info *info = NULL;
- int ret;
-
- /* Check parameter whether is valid or not */
- if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
- _E("Invalid parameter of HAL module (%d)\n", module);
- return -EINVAL;
- }
-
- G_LOCK(hal_backend_service_lock);
-
- info = _hal_api_conf_get_module_info(module, library_name);
- if (info == NULL) {
- _E("Failed to get HAL module(%d) information\n", module);
- ret = -EINVAL;
- goto out;
- }
-
- if (!info->hal_api) {
- ret = 0;
- goto out;
- }
-
- if (!info->handle || !info->backend) {
- _I("%s: Has not yet dlopend backend\n", info->module_name);
- ret = 0;
- goto out;
- }
-
- if (!info->backend_service_usage_count) {
- _I("%s: Already fully put for HAL module\n", info->module_name);
- ret = 0;
- goto out;
- }
-
- _I("%s: Prepare to exit HAL backend plugin: name(%s)/library(%s)/count(%d) by %s\n",
- info->module_name, info->backend_service->name,
- get_backend_service_library_name(info), info->backend_service_usage_count,
- program_invocation_name);
-
- info->backend_service_usage_count--;
-
- _I("%s: Exit and Prepare to put HAL backend: name(%s)/library(%s)/count(%d) by %s\n",
- info->module_name, info->backend_service->name,
- get_backend_service_library_name(info), info->backend_service_usage_count,
- program_invocation_name);
-
- if (info->backend_service_usage_count > 0) {
- ret = 0;
- goto out;
- }
-
- __close_backend_service(info);
-
- _I("%s: Put HAL backend: library(%s)/count(%d) by %s\n",
- info->module_name, get_backend_service_library_name(info), info->backend_service_usage_count,
- program_invocation_name);
-
- _hal_api_conf_exit();
-
- ret = 0;
-
-out:
- G_UNLOCK(hal_backend_service_lock);
-
- return ret;
-}
-
-EXPORT
-int hal_common_get_backend_service(enum hal_module module, void *data)
-{
- return __get_backend_service(module, data, NULL, NULL);
-}
-
-EXPORT
-int hal_common_put_backend_service(enum hal_module module, void *data)
-{
- return __put_backend_service(module, data, NULL, NULL);
-}
-
-EXPORT
-int hal_common_init_backend_service(enum hal_module module, void *user_data)
-{
- return __do_backend_service_func(module, HAL_BACKEND_SERVICE_FUNC_INIT,
- user_data, NULL, 0);
-}
-
-EXPORT
-int hal_common_exit_backend_service(enum hal_module module, void *user_data)
-{
- return __do_backend_service_func(module, HAL_BACKEND_SERVICE_FUNC_EXIT,
- user_data, NULL, 0);
-}
-
-static int add_hal_backend_service(enum hal_module *modules, size_t modules_len)
-{
- struct hal_backend_service_data *hal_backend_service_data = NULL;
-
- if (modules_len == 0) {
- _E("Invalid modules len: 0");
- return -EINVAL;
- }
-
- for (size_t i = 0; i < modules_len; ++i) {
- if (modules[i] <= HAL_MODULE_UNKNOWN || modules[i] >= HAL_MODULE_END) {
- _E("Invalid parameter of HAL module (%d)\n", modules[i]);
- return -EINVAL;
- }
- }
-
- hal_backend_service_data = calloc(1, sizeof(*hal_backend_service_data));
- if (hal_backend_service_data == NULL) {
- _E("Failed to allocate memory for hal_backend_service");
- return -EINVAL;
- }
-
- hal_backend_service_data->modules = modules;
- hal_backend_service_data->modules_len = modules_len;
- hal_backend_service_data->task = NULL;
- hal_backend_service_data->is_initialized = false;
-
- g_hal_backend_service_data_list = g_slist_prepend(g_hal_backend_service_data_list,
- (gpointer)hal_backend_service_data);
-
- return 0;
-}
-
-static int find_module_by_backend_module_name(const char *module_name, enum hal_module *module_found)
-{
- enum hal_module module;
- struct __hal_module_info* module_info = NULL;
- size_t module_name_len = 0;
-
- if (!module_name) {
- _E("Invalid parameter of HAL module: module_name(NULL)");
- return -EINVAL;
- }
-
- if (!module_found) {
- _E("Invalid parameter of HAL module: module_found(NULL)");
- return -EINVAL;
- }
-
- module_name_len = strlen(module_name);
-
- for (module = HAL_MODULE_UNKNOWN + 1 ; module < HAL_MODULE_END; module++) {
- module_info = &g_hal_module_info[module];
-
- if (module_info->backend_module_name == NULL)
- continue;
-
- if (strncmp(module_name, module_info->backend_module_name, module_name_len + 1) == 0) {
- *module_found = module;
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-static int hal_backend_service_open_and_add_plugin(char **module_names)
-{
- enum hal_module module;
- char *module_name = NULL;
- int ret = 0;
-
- size_t module_names_len = 0;
-
- enum hal_module *modules = NULL;
- size_t modules_len = 0;
-
- for (size_t i = 0; module_names[i]; ++i)
- ++module_names_len;
-
- modules = calloc(module_names_len, sizeof(*modules));
- if (!modules) {
- _E("Failed to allocate memory for %zu modules", module_names_len);
- return -ENOMEM;
- }
-
- for (size_t i = 0; i < module_names_len; ++i) {
- module_name = module_names[i];
-
- ret = find_module_by_backend_module_name(module_name, &module);
- if (ret != 0) {
- _W("Cannot get module by backend_module_name: ret(%d)", ret);
- continue;
- }
-
- ret = hal_common_get_backend_service(module, NULL);
- if (ret == -ENOENT)
- continue;
- else if (ret < 0) {
- _W("Cannot get hal-backend-service: ret(%d)\n", ret);
- continue;
- }
-
- modules[modules_len] = module;
- ++modules_len;
- }
-
- ret = add_hal_backend_service(modules, modules_len);
- if (ret < 0) {
- _E("Failed to add hal-backend-service: ret(%d)\n", ret);
-
- for (size_t i = 0; i < modules_len; ++i)
- hal_common_put_backend_service(modules[i], NULL);
- free(modules);
-
- return ret;
- }
-
- return 0;
-}
-
-static int delete_hal_backend_service(
- struct hal_backend_service_data *hal_backend_service_data,
- size_t *failed_count)
-{
- int ret = 0;
-
- for (size_t i = 0; i < hal_backend_service_data->modules_len; ++i) {
- ret = hal_common_put_backend_service(
- hal_backend_service_data->modules[i],
- NULL);
- if (ret < 0) {
- _W("Cannot put hal-backend-service: ret(%d), module(%d)\n",
- ret, hal_backend_service_data->modules[i]);
- ++(*failed_count);
- continue;
- }
- }
-
- free(hal_backend_service_data->modules);
- free(hal_backend_service_data);
-
- return 0;
-}
-
-static int hal_backend_service_delete_and_close_plugin(void)
-{
- enum hal_module module;
- size_t failed_count = 0;
- int ret;
-
- g_slist_foreach(g_hal_backend_service_data_list,
- (GFunc)delete_hal_backend_service, &failed_count);
-
- g_slist_free(g_hal_backend_service_data_list);
- g_hal_backend_service_data_list = NULL;
-
- return 0;
-}
-
-static bool hal_backend_service_initialize_cb(tizen_core_source_h source, int *timeout, void *data)
-{
- struct hal_backend_service_data *service_data = NULL;
- int ret = 0;
-
- /* FIXME: This is error situation, task should be terminated? */
- if (data == NULL) {
- _E("Invalid hal_backend_service(NULL)");
- return false;
- }
- service_data = (struct hal_backend_service_data *)data;
-
- if (service_data->is_initialized)
- return false;
-
- for (size_t i = 0; i < service_data->modules_len; ++i) {
- if (service_data->modules[i] <= HAL_MODULE_UNKNOWN || service_data->modules[i] >= HAL_MODULE_END) {
- _E("Invalid parameter of HAL module (%d)\n", service_data->modules[i]);
- return false;
- }
- }
-
- for (size_t i = 0; i < service_data->modules_len; ++i) {
- ret = hal_common_init_backend_service(service_data->modules[i], NULL);
- if (ret < 0) {
- _W("Cannot initialize hal backend service: ret(%d), module(%d)",
- ret, service_data->modules[i]);
- continue;
- }
- }
-
- service_data->is_initialized = true;
-
- return false;
-}
-
-static void hal_backend_service_finalize_cb(tizen_core_source_h source, void *data)
-{
- struct hal_backend_service_data *service_data = NULL;
- int ret = 0;
-
- if (data == NULL) {
- _E("Invalid hal_backend_service(NULL)");
- return;
- }
- service_data = (struct hal_backend_service_data *)data;
-
- for (size_t i = 0; i < service_data->modules_len; ++i) {
- if (service_data->modules[i] <= HAL_MODULE_UNKNOWN || service_data->modules[i] >= HAL_MODULE_END) {
- _E("Invalid parameter of HAL module (%d)\n", service_data->modules[i]);
- return;
- }
- }
-
- bool is_all_exit = true;
- for (size_t i = 0; i < service_data->modules_len; ++i) {
- ret = hal_common_exit_backend_service(service_data->modules[i], NULL);
- if (ret < 0) {
- _W("Cannot exit hal backend service: ret(%d), module(%d)",
- ret, service_data->modules[i]);
- is_all_exit = false;
- continue;
- }
- }
-
- service_data->is_initialized = !is_all_exit;
-
- _D("Exit done.");
-}
-
-static int create_task_name(struct hal_backend_service_data *service_data, char **task_name)
-{
- char *task_name_temp = NULL;
- struct __hal_module_info *module_info = NULL;
-
- if (service_data == NULL) {
- _E("Invalid parameter: service_data(NULL)");
- return -EINVAL;
- }
-
- module_info = _hal_api_conf_get_module_info(service_data->modules[0], NULL);
- if (module_info == NULL) {
- _E("Failed to get module info for module(%d)", service_data->modules[0]);
- return -EINVAL;
- }
-
- task_name_temp = strdup(module_info->backend_module_name);
- if (task_name_temp == NULL) {
- _E("Failed to duplicate task name");
- return -ENOMEM;
- }
-
- *task_name = task_name_temp;
-
- return 0;
-}
-
-static void create_hal_backend_service_task(gpointer data, gpointer user_data)
-{
- tizen_core_task_h task = NULL;
- tizen_core_h core = NULL;
- tizen_core_source_h source = NULL;
-
- char *task_name = NULL;
- struct hal_backend_service_data *service_data = NULL;
- size_t *failed_count = NULL;
- int ret = 0;
-
- if (data == NULL || user_data == NULL) {
- _E("Invalid parameter: data(%p), user_data(%p)", data, user_data);
- return;
- }
-
- service_data = (struct hal_backend_service_data *)data;
- failed_count = (size_t *)user_data;
-
- ret = create_task_name(service_data, &task_name);
- if (ret != 0) {
- _E("Failed to create task name: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_task_create(task_name, true, &task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to create tizen_core task: ret(%d)", ret);
- goto error;
- }
- free(task_name);
- task_name = NULL;
-
- ret = tizen_core_source_create(&source);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to create tizen_core source: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_task_get_tizen_core(task, &core);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to get tizen_core core from task: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_source_set_prepare_cb(source, hal_backend_service_initialize_cb, service_data);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to set prepare callback: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_source_set_finalize_cb(source, hal_backend_service_finalize_cb, service_data);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to set finalize callback: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_add_source(core, source);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to add tizen_core source to core: ret(%d)", ret);
- goto error;
- }
-
- service_data->task = task;
-
- _D("Task created for %zu task(s)", service_data->modules_len);
-
- ret = tizen_core_task_run(task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to run tizen_core task: ret(%d)", ret);
- goto error;
- }
-
- return;
-
-error:
- if (source != NULL)
- tizen_core_source_destroy(source);
-
- if (task != NULL)
- tizen_core_task_destroy(task);
-
- free(task_name);
- task_name = NULL;
-
- (*failed_count)++;
-
- return;
-}
-
-static void delete_hal_backend_service_task(gpointer data, gpointer user_data)
-{
- struct hal_backend_service_data *service_data = NULL;
- int ret = 0;
-
- if (data == NULL) {
- _E("Invalid parameter: data(NULL)");
- return;
- }
- service_data = (struct hal_backend_service_data *)data;
-
- /* FIXME: Improve debugging message for more informatino about modules */
- if (service_data->task == NULL) {
- _D("No task for %zu hal_modules", service_data->modules_len);
- return;
- }
-
- ret = tizen_core_task_quit(service_data->task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to quit task for %zu hal_modules", service_data->modules_len);
- return;
- }
-
- ret = tizen_core_task_destroy(service_data->task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to destroy task for %zu hal_modules", service_data->modules_len);
- return;
- }
-
- service_data->task = NULL;
-
- _D("Task destroyed for %zu hal_modules", service_data->modules_len);
-}
-
-static int hal_backend_service_start(void)
-{
- size_t failed_count = 0;
- size_t hal_backend_service_len = g_slist_length(g_hal_backend_service_data_list);
-
- /* Create tasks for hal-backend-service and then tie them */
- g_slist_foreach(g_hal_backend_service_data_list,
- (GFunc)create_hal_backend_service_task,
- &failed_count);
-
- if (failed_count > 0) {
- _W("Cannot register %zu/%zu service(s)",
- failed_count, hal_backend_service_len);
- }
-
- if (failed_count == hal_backend_service_len) {
- _E("Failed to start hal backend service, no task is created");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void hal_backend_service_stop(void)
-{
- g_slist_foreach(g_hal_backend_service_data_list,
- delete_hal_backend_service_task, NULL);
-}
-
-/**
- * Signal Handler
- */
-static gboolean handle_signal_glib(gpointer data)
-{
- int signal_number = GPOINTER_TO_INT(data);
-
- _D("Received signal(%d)", signal_number);
- if (g_main_task != NULL)
- tizen_core_task_quit(g_main_task);
-
- return G_SOURCE_REMOVE;
-}
-
-static void handle_signal_std(int signal_number)
-{
- _W("Received signal(%d)", signal_number);
- raise(SIGTERM);
-}
-
-static void attach_signal_handlers(void)
-{
- g_unix_signal_add(SIGINT, handle_signal_glib, GINT_TO_POINTER(SIGINT));
- g_unix_signal_add(SIGHUP, handle_signal_glib, GINT_TO_POINTER(SIGHUP));
- g_unix_signal_add(SIGTERM, handle_signal_glib, GINT_TO_POINTER(SIGTERM));
-
- signal(SIGQUIT, handle_signal_std);
- signal(SIGABRT, handle_signal_std);
-}
-
-static void print_usage(char *exec_name)
-{
- _E("Usage: %s --%s <proc_name> <modules> [ <modules> ... ]\n",
- exec_name, COMMANDLINE_OPTION_STUB_PROC_NAME);
-}
-
-static int parse_arguments(int argc, char **argv, char **proc_name, int *modules_arg_start_index)
-{
- int opt_flag = 0;
- char *parsed_proc_name = NULL;
-
- struct option options[] = {
- {
- .name = COMMANDLINE_OPTION_STUB_PROC_NAME,
- .has_arg = required_argument,
- .flag = &opt_flag,
- .val = 1
- }, {
- .name = NULL,
- .has_arg = 0,
- .flag = NULL,
- .val = 0
- },
- };
-
- if (proc_name == NULL || modules_arg_start_index == NULL) {
- _E("Invalid argument: proc_name and modules_arg_start_index should not be NULL");
- return -EINVAL;
- }
-
- opt_flag = 0;
- opterr = 0;
- while (getopt_long(argc, argv, "", options, NULL) != -1) {
- switch (opt_flag) {
- case 1:
- if (parsed_proc_name != NULL) {
- _E("Invalid commandline argument: <proc_name> provided twice\n");
- return -EINVAL;
- }
- parsed_proc_name = optarg;
- break;
- default:
- _E("Invalid commandline argument: %s", argv[optind - 1]);
- return -EINVAL;
- }
-
- opt_flag = 0;
- }
-
- if (parsed_proc_name == NULL) {
- _E("Invalid commandline argument: <proc_name> is not provided\n");
- return -EINVAL;
- }
-
- if (optind >= argc) {
- _E("No module name provided.");
- return -EINVAL;
- }
-
- *proc_name = parsed_proc_name;
- *modules_arg_start_index = optind;
-
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- int ret = 0;
- char *proc_name = NULL;
- int modules_arg_start_index = 0;
-
- ret = parse_arguments(argc, argv, &proc_name, &modules_arg_start_index);
- if (ret != 0) {
- print_usage(argv[0]);
- return ret;
- }
-
- _D("Initialize hal-backend-service");
-
- tizen_core_init();
-
- ret = tizen_core_task_create("main", false, &g_main_task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to create tizen_core main task: ret(%d)", ret);
- tizen_core_shutdown();
- return 1;
- }
-
- ret = rpc_port_register_proc_info(proc_name, NULL);
- if (ret != RPC_PORT_ERROR_NONE) {
- _E("Failed to register rpc port proc info: proc_name(%s), ret(%d)",
- proc_name, ret);
- return false;
- }
-
- for (int i = modules_arg_start_index; i < argc; ++i) {
- char *module_names_str = argv[i];
- gchar **module_names = g_strsplit(module_names_str, ",", 0);
-
- hal_backend_service_open_and_add_plugin(module_names);
-
- g_strfreev(module_names);
- }
-
- if (g_slist_length(g_hal_backend_service_data_list) == 0) {
- _W("No available modules, exit");
-
- tizen_core_task_destroy(g_main_task);
- tizen_core_shutdown();
-
- return 0;
- }
-
- ret = hal_backend_service_start();
- if (ret != 0) {
- _E("Failed to start hal-backend-service: ret(%d)", ret);
-
- tizen_core_task_destroy(g_main_task);
- tizen_core_shutdown();
-
- return 1;
- }
-
- attach_signal_handlers();
-
- tizen_core_task_run(g_main_task);
-
- /* Un-load hal-backend-service plugin */
- hal_backend_service_stop();
- hal_backend_service_delete_and_close_plugin();
-
- tizen_core_task_destroy(g_main_task);
-
- tizen_core_shutdown();
-
- _D("Exit hal-backend-service");
-
- return 0;
-}
+++ /dev/null
-[Unit]
-Description=HAL Backend Service
-DefaultDependencies=no
-Requires=local-fs.target tizen-system-env.service systemd-tmpfiles-setup.service @SERVICE_NAME@.socket
-After=local-fs.target tizen-system-env.service systemd-tmpfiles-setup.service @SERVICE_NAME@.socket
-
-[Service]
-Type=simple
-SmackProcessLabel=System
-ExecStart=/usr/bin/hal/hal-backend-service --stub-proc-name '@PROC_NAME@' @THREADS@
-EnvironmentFile=/run/xdg-root-env
-Restart=on-failure
-RestartSec=0
-KillSignal=SIGUSR1
-MemoryMax=20M
-
-[Install]
-WantedBy=basic.target
+++ /dev/null
-[Unit]
-Description=HAL Backend Service Socket
-DefaultDependencies=no
-Before=sockets.target
-
-[Socket]
-@LISTEN_STREAMS@
-SocketMode=0777
-DirectoryMode=0777
-SmackLabelIPIn=*
-SmackLabelIPOut=@
-Service=@SERVICE_NAME@.service
-
-[Install]
-WantedBy=sockets.target
BuildRequires: pkgconfig(rpc-port)
BuildRequires: pkgconfig(bundle)
BuildRequires: pkgconfig(tizen-core)
+BuildRequires: pkgconfig(dbus-1)
%description
%{name} interface
%description -n %{test_name}
Haltests for hal-api-common
+%package -n hal-backend-service-with-dbus
+Summary: with dbus test
+
+%description -n hal-backend-service-with-dbus
+with dbus test
+
+%package -n hal-backend-service-without-dbus
+Summary: without dbus test
+
+%description -n hal-backend-service-without-dbus
+without dbus test
+
### build and install #########
%prep
%setup -q
%define hal_backend_service_config "hal-backend-service-config-vd.json"
%endif
- hal-backend-service/hal-backend-service-generator.py \
+ hal-backend-service-with-dbus/hal-backend-service-generator.py \
+ --enable \
+ --config=%{hal_backend_service_config}
+
+ hal-backend-service-without-dbus/hal-backend-service-generator.py \
--enable \
--config=%{hal_backend_service_config}
%else
- hal-backend-service/hal-backend-service-generator.py --disable
+ hal-backend-service-with-dbus/hal-backend-service-generator.py --disable
+ hal-backend-service-without-dbus/hal-backend-service-generator.py --disable
%endif
cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
%if %{enable_hal_backend_service}
-for HAL_BACKEND_SERVICE_SERVICE in $(ls hal-backend-service/hal-backend-service*.service); do
+for HAL_BACKEND_SERVICE_SERVICE in $(ls hal-backend-service-with-dbus/hal-backend-service*.service); do
HAL_BACKEND_SERVICE_SERVICE=$(basename ${HAL_BACKEND_SERVICE_SERVICE})
%install_service basic.target.wants ${HAL_BACKEND_SERVICE_SERVICE}
done
-for HAL_BACKEND_SERVICE_SOCKET in $(ls hal-backend-service/hal-backend-service*.socket); do
-HAL_BACKEND_SERVICE_SOCKET=$(basename ${HAL_BACKEND_SERVICE_SOCKET})
-%install_service sockets.target.wants ${HAL_BACKEND_SERVICE_SOCKET}
+for HAL_BACKEND_SERVICE_SERVICE in $(ls hal-backend-service-without-dbus/hal-backend-service*.service); do
+HAL_BACKEND_SERVICE_SERVICE=$(basename ${HAL_BACKEND_SERVICE_SERVICE})
+%install_service basic.target.wants ${HAL_BACKEND_SERVICE_SERVICE}
done
%endif
%{_tmpfilesdir}/hal-compatibility-checker.conf
%endif
%{_datadir}/upgrade/scripts/500.%{name}.sh
+
+%files -n hal-backend-service-with-dbus
+%if %{enable_hal_backend_service}
+%{_bindir}/hal/hal-backend-service-with-dbus
+%{_unitdir}/basic.target.wants/hal-backend-service-with-dbus.service
+%{_unitdir}/hal-backend-service-with-dbus.service
+%endif
+
+%files -n hal-backend-service-without-dbus
%if %{enable_hal_backend_service}
-%{_bindir}/hal/hal-backend-service
-%{_unitdir}/sockets.target.wants/hal-backend-service*.socket
-%{_unitdir}/basic.target.wants/hal-backend-service*.service
-%{_unitdir}/hal-backend-service*.socket
-%{_unitdir}/hal-backend-service*.service
+%{_bindir}/hal/hal-backend-service-without-dbus
+%{_unitdir}/basic.target.wants/hal-backend-service-without-dbus.service
+%{_unitdir}/hal-backend-service-without-dbus.service
%endif
%files -n %{devel_name}