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)
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)
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")
--- /dev/null
+{
+ "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" ] }
+ ]
+ }
+ ]
+}
--- /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
+[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
--- /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
*/
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);
+
/**
* @}
*/
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)
%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} \
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
%{_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}
+++ /dev/null
-[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
+++ /dev/null
-[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
--- /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.
+ */
+
+#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;
+}
--- /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
+
+#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
#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;
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);
+}