hal-backend-service: Change to create socket, service and header dynamically using... 38/320938/11
authorSangYoun Kwak <sy.kwak@samsung.com>
Mon, 10 Mar 2025 07:58:47 +0000 (16:58 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Wed, 19 Mar 2025 02:12:01 +0000 (02:12 +0000)
Services/sockets, stub proc names can be vary, so they should be changed
easily. To accomplish this, script and template file(ends with .in) are
added to create socket, service and header file dynamically, by the
information in the json config file.

hal-backend-service-config.json file contains service informations,
thread informations. Service information contains service_name(which
will be service name and stub proc name), thread informations. Thread
information contains hal module names to be used.
Below is an example of json config file:
{
    "process": [
        {
            "type": "systemd",
            "property": {
                "name": "hal-backend-service-1"
            },
            "thread": [
                { "hal_module_name": [ "device_display", "device_led" ] },
                { "hal_module_name": [ "abc" ] }
            ]
        },
        {
            "type": "systemd",
            "property": {
                "name": "hal-backend-service-2"
            },
            "thread": [
                { "hal_module_name": [ "codec" ] }
            ]
        }
    ]
}

Based on the parsed information from the json file, service and socket
files are created. Also, a header file which maps hal module(enum) to
the stub proc name. To get the stub proc name form the proxy, a function
is added to get them.

Please be notified that name in the property section does not have to be
same with stub_proc_name. name is used to define stub_proc_name since it
is unique. stub_proc_name can be other value if it is unique.

Change-Id: I13b03196f3cd64b3404cd2946d540e67fd6afeec
Signed-off-by: SangYoun Kwak <sy.kwak@samsung.com>
15 files changed:
CMakeLists.txt
hal-backend-service/CMakeLists.txt
hal-backend-service/config/hal-backend-service-config.json [new file with mode: 0644]
hal-backend-service/config_types.py [new file with mode: 0644]
hal-backend-service/hal-api-backend-service-list.h.in [new file with mode: 0644]
hal-backend-service/hal-backend-service-generator.py [new file with mode: 0755]
hal-backend-service/hal-backend-service.service.in [new file with mode: 0644]
hal-backend-service/hal-backend-service.socket.in [new file with mode: 0644]
include/hal-common.h
packaging/hal-api-common.spec
packaging/hal-backend-service.service [deleted file]
packaging/hal-backend-service.socket [deleted file]
src/hal-api-backend-service.c [new file with mode: 0644]
src/hal-api-backend-service.h [new file with mode: 0644]
src/hal-api-common.c

index 77f8cae416dcfe6df3360d4ff8359f967221dd14..0553a4a617b8a516c9f571329dbea261e8d6f8aa 100644 (file)
@@ -53,7 +53,8 @@ SET(SRCS
        src/hal-api-conf.c
        src/hal-api-compatibility-checker.c
        src/hal-api-compatibility-checker-object.c
-       src/hal-api-compatibility-checker-parser.c)
+       src/hal-api-compatibility-checker-parser.c
+       src/hal-api-backend-service.c)
 
 ADD_LIBRARY( ${PROJECT_NAME} SHARED ${SRCS})
 TARGET_LINK_LIBRARIES( ${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl -Wl,-z,nodelete,--no-undefined)
@@ -70,13 +71,6 @@ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/${PROJECT_NAME}.pc
        DESTINATION ${LIBDIR}/pkgconfig)
 
-if (${ENABLE_HAL_BACKEND_SERVICE})
-INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/packaging/ DESTINATION lib/systemd/system
-       FILES_MATCHING
-       PATTERN "hal-backend-service.*"
-       )
-endif()
-
 ADD_SUBDIRECTORY(tests)
 
 ADD_SUBDIRECTORY(tools/lshal)
index 35868d39291959cabb4d34299fdc2efe8ca67033..dfeeb64de7ce4f52975d94f32b137f616e9e9e06 100644 (file)
@@ -33,3 +33,8 @@ 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/)
+
+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")
diff --git a/hal-backend-service/config/hal-backend-service-config.json b/hal-backend-service/config/hal-backend-service-config.json
new file mode 100644 (file)
index 0000000..ee4bdf2
--- /dev/null
@@ -0,0 +1,15 @@
+{
+       "process": [
+               {
+                       "type": "systemd",
+                       "property": {
+                               "name": "hal-backend-service-device"
+                       },
+                       "thread": [
+                               { "hal_module_name": [ "device_display" ] },
+                               { "hal_module_name": [ "device_led" ] },
+                               { "hal_module_name": [ "device_battery" ] }
+                       ]
+               }
+       ]
+}
diff --git a/hal-backend-service/config_types.py b/hal-backend-service/config_types.py
new file mode 100644 (file)
index 0000000..d93f99e
--- /dev/null
@@ -0,0 +1,167 @@
+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
diff --git a/hal-backend-service/hal-api-backend-service-list.h.in b/hal-backend-service/hal-api-backend-service-list.h.in
new file mode 100644 (file)
index 0000000..7023fe2
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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,
+};
diff --git a/hal-backend-service/hal-backend-service-generator.py b/hal-backend-service/hal-backend-service-generator.py
new file mode 100755 (executable)
index 0000000..b1d9c72
--- /dev/null
@@ -0,0 +1,232 @@
+#!/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())
diff --git a/hal-backend-service/hal-backend-service.service.in b/hal-backend-service/hal-backend-service.service.in
new file mode 100644 (file)
index 0000000..1272ee8
--- /dev/null
@@ -0,0 +1,16 @@
+[Unit]
+Description=HAL Backend Service
+DefaultDependencies=no
+Requires=local-fs.target @SERVICE_NAME@.socket
+Before=basic.target
+After=local-fs.target @SERVICE_NAME@.socket
+
+[Service]
+Type=simple
+SmackProcessLabel=System
+ExecStart=/usr/bin/hal-backend-service --stub-proc-name '@PROC_NAME@' @THREADS@
+KillSignal=SIGUSR1
+MemoryMax=20M
+
+[Install]
+WantedBy=basic.target
diff --git a/hal-backend-service/hal-backend-service.socket.in b/hal-backend-service/hal-backend-service.socket.in
new file mode 100644 (file)
index 0000000..fd6d7ef
--- /dev/null
@@ -0,0 +1,15 @@
+[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
index 035889a19e08a1a5653d0a9aa14d9122edbdd5ac..8ef64c07c97900b3ba9bcf3a02bd23b9709e0f72 100644 (file)
@@ -373,6 +373,19 @@ int hal_common_get_supported_interface_versions(enum hal_module module,
  */
 int hal_common_get_transport(enum hal_module module, enum hal_common_transport *transport);
 
+/**
+ * @brief Get the stub proc name to identify the stub of RPC
+ * @details Get the stub_proc_name which should be used by the proxy. It is necessary to the proxy
+ *          to identify stub to be connected through the RPC.
+ * @param[in] module HAL id among enum hal_module
+ * @param[out] stub_proc_name The proc_name for identifying the stub
+ * @code
+ * const char *stub_proc_name = NULL;
+ * int ret = hal_common_get_stub_proc_name(HAL_MODULE_DEVICE_DISPLAY, &stub_proc_name);
+ * @endcode
+ */
+int hal_common_get_stub_proc_name(enum hal_module module, const char **stub_proc_name);
+
 /**
  * @}
  */
index 98c448820648f660885c9972efb8d1be464e763d..dd2aab8cedb09973ad0ec1e1ade6e0a3dd0737ea 100644 (file)
@@ -27,12 +27,11 @@ Source7:    reboot-haltest
 Source8:    reboot-normal
 Source9:    500.%{name}.sh
 Source10:   hal-compatibility-checker.conf
-Source11:   hal-backend-service.socket
-Source12:   hal-backend-service.service
 
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
 BuildRequires: cmake
+BuildRequires: python3
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(gio-2.0)
 BuildRequires: pkgconfig(glib-2.0)
@@ -68,6 +67,14 @@ Haltests for hal-api-common
 %prep
 %setup -q
 
+%if %{enable_hal_backend_service}
+hal-backend-service/hal-backend-service-generator.py \
+               --enable \
+               --config=hal-backend-service-config.json
+%else
+hal-backend-service/hal-backend-service-generator.py --disable
+%endif
+
 cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
        -DCMAKE_LIBDIR_PREFIX=%{_libdir} \
        -DENABLE_HALCC=%{enable_halcc} \
@@ -101,8 +108,17 @@ install -D -m 0755 %{SOURCE8} %{buildroot}%{_bindir}/reboot-normal
 install -D -m 0755 %{SOURCE9} %{buildroot}%{_datadir}/upgrade/scripts/500.%{name}.sh
 
 %if %{enable_hal_backend_service}
-%install_service sockets.target.wants hal-backend-service.socket
-%install_service basic.target.wants hal-backend-service.service
+
+for HAL_BACKEND_SERVICE_SERVICE in $(ls hal-backend-service/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}
+done
+
 %endif
 
 %clean
@@ -135,10 +151,10 @@ rm -f %{_unitdir}/sysinit.target.wants/hal-compatibility-checker.service
 %{_datadir}/upgrade/scripts/500.%{name}.sh
 %if %{enable_hal_backend_service}
 %{_bindir}/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
+%{_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
 %endif
 
 %files -n %{devel_name}
diff --git a/packaging/hal-backend-service.service b/packaging/hal-backend-service.service
deleted file mode 100644 (file)
index 170f853..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-[Unit]
-Description=HAL Backend Service
-DefaultDependencies=no
-Requires=local-fs.target hal-backend-service.socket
-Before=basic.target
-After=local-fs.target hal-backend-service.socket
-
-[Service]
-Type=simple
-SmackProcessLabel=System
-ExecStart=/usr/bin/hal-backend-service --stub-proc-name 'd::HalBackendService' device-display device-led device-battery
-KillSignal=SIGUSR1
-MemoryMax=20M
-
-[Install]
-WantedBy=basic.target
diff --git a/packaging/hal-backend-service.socket b/packaging/hal-backend-service.socket
deleted file mode 100644 (file)
index d3e64e4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-[Unit]
-Description=HAL Backend Service Socket
-DefaultDependencies=no
-Before=sockets.target
-
-[Socket]
-ListenStream=/run/aul/rpcport/.d::HalBackendService::device_display
-ListenStream=/run/aul/rpcport/.d::HalBackendService::device_led
-SocketMode=0777
-DirectoryMode=0777
-SmackLabelIPIn=*
-SmackLabelIPOut=@
-Service=hal-backend-service.service
-
-[Install]
-WantedBy=sockets.target
diff --git a/src/hal-api-backend-service.c b/src/hal-api-backend-service.c
new file mode 100644 (file)
index 0000000..0669832
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#include "common.h"
+#include "hal-api-backend-service-list.h"
+
+int hal_api_backend_service_get_stub_proc_name(enum hal_module module,
+                                               const char **stub_proc_name)
+{
+       const char *stub_proc_name_temp = NULL;
+
+       if (stub_proc_name == NULL) {
+               _E("Invalid parameter: stub_proc_name(NULL)");
+               return -EINVAL;
+       }
+
+       if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
+               _E("Invalid parameter: module(%d)", module);
+               return -EINVAL;
+       }
+
+       stub_proc_name_temp = g_hal_module_stub_proc_name[module];
+       if (stub_proc_name_temp == NULL) {
+               _E("Failed to get stub proc name: " \
+                       "stub proc name is not defined for hal module %d",
+                       module);
+               return -ENOENT;
+       }
+
+       *stub_proc_name = stub_proc_name_temp;
+
+       return 0;
+}
diff --git a/src/hal-api-backend-service.h b/src/hal-api-backend-service.h
new file mode 100644 (file)
index 0000000..19151a5
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int hal_api_backend_service_get_stub_proc_name(enum hal_module module,
+                                               const char **stub_proc_name);
+
+#ifdef __cplusplus
+}
+#endif
index dc4a1022bb47c215a6f0fddb14c9ce1e52760c9f..4a5e3c625e7c9c78a2c5166e1a942a72afda39d7 100644 (file)
@@ -31,6 +31,7 @@
 #include "common.h"
 #include "hal-api-conf.h"
 #include "hal-api-compatibility-checker.h"
+#include "hal-api-backend-service.h"
 
 extern char *program_invocation_name;
 
@@ -802,3 +803,9 @@ int hal_common_get_transport(enum hal_module module, enum hal_common_transport *
 
        return hal_api_cc_get_transport(module, transport);
 }
+
+EXPORT
+int hal_common_get_stub_proc_name(enum hal_module module, const char **stub_proc_name)
+{
+       return hal_api_backend_service_get_stub_proc_name(module, stub_proc_name);
+}