lib/media-util-register.c \
lib/media-util-cynara.c \
lib/media-util-user.c
+if USE_ON_DEMAND
+libmedia_utils_la_SOURCES += lib/media-util-socket-activation.c
+endif
libmedia_utils_la_CFLAGS = -I${srcdir}/lib/include \
-D_FILE_OFFSET_BITS=64 \
src/server/media-server-db-manage.c
endif
+if USE_ON_DEMAND
+media_server_SOURCES += src/server/media-server-on-demand.c
+endif
+
media_server_CFLAGS = -I${srcdir}/src/server/include \
$(SQLITE3_CFLAGS) \
$(COMMON_CFLAGS) \
lib/include/media-util-cynara.h \
lib/include/media-util.h \
lib/include/media-util-user.h
+
+if USE_ON_DEMAND
+includeheaders_HEADERS += lib/include/media-util-socket-activation.h
+endif
fi
AM_CONDITIONAL(USE_PRODUCT_TV, test "x$USE_PRODUCT_TV" = "xyes")
+# for on-demand
+AC_ARG_ENABLE(on_demand, AC_HELP_STRING([--enable-on-demand], [on-demand server]),
+ [
+ case "${enableval}" in
+ yes) USE_ON_DEMAND=yes ;;
+ no) USE_ON_DEMAND=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-on-demand) ;;
+ esac
+ ],
+[USE_ON_DEMAND=no])
+AM_CONDITIONAL(USE_ON_DEMAND, test "x$USE_ON_DEMAND" = "xyes")
+
# for gtests
AC_ARG_ENABLE(tests, AC_HELP_STRING([--enable-tests], [unittest build]),
[
LOGD(FONT_COLOR_RESET); \
} while (0)
+#define MSAPI_DBG_FENTER() do { \
+ LOGD(FONT_COLOR_YELLOW"<ENTER>"FONT_COLOR_RESET); \
+ } while (0)
+
+#define MSAPI_DBG_FLEAVE() do { \
+ LOGD(FONT_COLOR_YELLOW"<LEAVE>"FONT_COLOR_RESET); \
+ } while (0)
+
#define MSAPI_RETV_IF(expr, val) do { \
if (expr) { \
LOGE(FONT_COLOR_RED""FONT_COLOR_RESET); \
MS_MSG_RECURSIVE_START,
MS_MSG_MEDIA_DB_RESET, /**< media DB is reset*/
MS_MSG_MEDIA_DB_MALFORMED,
+#ifdef _USE_ON_DEMAND
+ MS_MSG_MEDIA_SERVER_READY,
+#endif
MS_MSG_MAX /**< Invalid msg type */
} ms_msg_type_e;
--- /dev/null
+/*
+ * Media Utility
+ *
+ * Copyright (c) 2024 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.
+ *
+ */
+
+#ifndef _MEDIA_UTIL_SOCKET_ACTIVATION_H_
+#define _MEDIA_UTIL_SOCKET_ACTIVATION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ms_ipc_activate_media_server(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_MEDIA_UTIL_SOCKET_ACTIVATION_H_*/
#include <media-util-ipc.h>
#include <media-util-cynara.h>
#include <media-util-user.h>
+#ifdef _USE_ON_DEMAND
+#include <media-util-socket-activation.h>
+#endif
#endif /*_MEDIA_UTIL_H_*/
#include "media-util-db.h"
#include "media-util-err.h"
#include "media-util-user.h"
+#ifdef _USE_ON_DEMAND
+#include "media-util-socket-activation.h"
+#endif
static int __media_db_busy_handler(void *pData, int count)
{
MSAPI_RETVM_IF(!query_str || strlen(query_str) == 0, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query");
+#ifdef _USE_ON_DEMAND
+ ret = ms_ipc_activate_media_server();
+ if (ret != MS_MEDIA_ERR_NONE) {
+ MSAPI_DBG_ERR("ms_ipc_activate_media_server failed : %d", ret);
+ return ret;
+ }
+#endif
ret = ms_ipc_request_update_tcp(MS_MSG_DB_UPDATE, query_str, uid);
+
if (ret != MS_MEDIA_ERR_NONE)
MSAPI_DBG_ERR("ms_ipc_request_update_tcp failed : %d", ret);
#include "media-util-err.h"
#include "media-util-user.h"
#include "media-util-ipc.h"
+#ifdef _USE_ON_DEMAND
+#include "media-util-socket-activation.h"
+#endif
static GMutex scan_req_mutex;
MSAPI_RETVM_IF(!path || strlen(path) == 0, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
+#ifdef _USE_ON_DEMAND
+ ret = ms_ipc_activate_media_server();
+ if (ret != MS_MEDIA_ERR_NONE) {
+ MSAPI_DBG_ERR("ms_ipc_activate_media_server failed : %d", ret);
+ return ret;
+ }
+#endif
+
request_path = g_canonicalize_filename(path, NULL);
MSAPI_DBG_SLOG("trimmed path[%s]", request_path);
__attach_callback(request_path, &sockfd, user_callback, user_data);
- return ret;
+ return MS_MEDIA_ERR_NONE;
}
static int __media_db_request_update_cancel(ms_msg_type_e msg_type, const char *path)
--- /dev/null
+/*
+ * Media Utility
+ *
+ * Copyright (c) 2024 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 <glib.h>
+#include <unistd.h>
+#include <tzplatform_config.h>
+
+#include "media-util.h"
+#include "media-util-dbg.h"
+#include "media-util-err.h"
+#include "media-util-ipc.h"
+
+#define MS_SOCKET_ACTIVATION_PATH tzplatform_mkpath(TZ_SYS_RUN, ".media-server.sock")
+#define MS_SOCKET_ACTIVATION_MSG "MS_MSG_MEDIA_SERVER_READY"
+#define MAX_RECIEVE_RETRY_COUNT 3
+#define MAX_WAIT_DAEMON_COUNT 100
+
+static int __check_media_server()
+{
+ int ret = MS_MEDIA_ERR_NONE;
+ int sockfd = -1;
+ ms_comm_msg_s send_msg;
+ ms_comm_msg_s recv_msg;
+ int recv_msg_size = -1;
+ int retry_count = 0;
+
+ MSAPI_DBG_FENTER();
+
+ memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
+ memset((void *)&recv_msg, 0, sizeof(ms_comm_msg_s));
+
+ send_msg.msg_type = MS_MSG_MEDIA_SERVER_READY;
+ g_strlcpy(send_msg.msg, MS_SOCKET_ACTIVATION_MSG, sizeof(send_msg.msg));
+
+ /*Create Socket*/
+ ret = ms_ipc_create_client_socket(0, &sockfd);
+ if (ret != MS_MEDIA_ERR_NONE) {
+ MSAPI_DBG_ERR("ms_ipc_create_client_socket failed : %d", ret);
+ return ret;
+ }
+
+ ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
+ if (ret != MS_MEDIA_ERR_NONE) {
+ MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret);
+ close(sockfd);
+ return ret;
+ }
+
+ while ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
+ if (errno == EINTR) {
+ MSAPI_DBG_STRERROR("catch interrupt");
+ continue;
+ } else if (errno == EWOULDBLOCK) {
+ if (retry_count++ < MAX_RECIEVE_RETRY_COUNT) {
+ MSAPI_DBG_ERR("[No-Error] Time Out. retry_count [%d]", retry_count);
+ continue;
+ }
+ MSAPI_DBG_ERR("Timeout. Can't try any more");
+
+ } else {
+ MSAPI_DBG_STRERROR("recv failed");
+ }
+ ret = MS_MEDIA_ERR_IPC;
+ }
+
+ if (ret == MS_MEDIA_ERR_NONE)
+ MSAPI_DBG("media_server return %d", recv_msg.result);
+
+ close(sockfd);
+ MSAPI_DBG_FLEAVE();
+ return ret;
+}
+
+static int __launch_media_server()
+{
+ int ret = MS_MEDIA_ERR_NONE;
+ int sockfd = -1;
+ struct sockaddr_un addr;
+
+ MSAPI_DBG_FENTER();
+
+ /*Create Socket*/
+ ret = ms_ipc_create_client_socket(0, &sockfd);
+ if (ret != MS_MEDIA_ERR_NONE) {
+ MSAPI_DBG_ERR("ms_ipc_create_client_socket failed : %d", ret);
+ return ret;
+ }
+
+ /* Set server Address */
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ g_strlcpy(addr.sun_path, MS_SOCKET_ACTIVATION_PATH, sizeof(addr.sun_path));
+
+ MSAPI_DBG_ERR("addr.sun_path. [%s]", addr.sun_path);
+
+ /* Connecting to the media db server */
+ if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ MSAPI_DBG_STRERROR("connect error");
+ if (errno == EACCES || errno == EPERM)
+ ret = MS_MEDIA_ERR_PERMISSION_DENIED;
+ else
+ ret = MS_MEDIA_ERR_IPC;
+ }
+
+ close(sockfd);
+ MSAPI_DBG_FLEAVE();
+ return ret;
+}
+
+int ms_ipc_activate_media_server()
+{
+ int ret = MS_MEDIA_ERR_NONE;
+ int retry_count = 0;
+
+ MSAPI_DBG_FENTER();
+
+ /* check media-server is already executed */
+ if (__check_media_server() == MS_MEDIA_ERR_NONE)
+ return MS_MEDIA_ERR_NONE;
+
+ /* send activation to socket */
+ ret = __launch_media_server();
+ if (ret != MS_MEDIA_ERR_NONE) {
+ MSAPI_DBG_ERR("__launch_media_server failed : %d", ret);
+ return ret;
+ }
+
+ /* wait & verify that media-server has been executed successfully */
+ while (retry_count++ < MAX_WAIT_DAEMON_COUNT) {
+ MSAPI_DBG_ERR("[No-Error] retry_count [%d]", retry_count);
+ if (__check_media_server() == MS_MEDIA_ERR_NONE)
+ break;
+ usleep(10000);
+ }
+
+ MSAPI_DBG_FLEAVE();
+ return ret;
+}
--- /dev/null
+SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ENV{ID_BUS}=="usb", RUN+="/usr/bin/systemctl start media-server"
--- /dev/null
+[Unit]
+Description=media-server-user path activation
+
+[Path]
+PathExists=/tmp/media_server_boot
--- /dev/null
+[Unit]
+Description=Media Server socket activation
+
+[Socket]
+SocketUser=multimedia_fw
+SocketGroup=multimedia_fw
+ListenStream=/run/.media-server.sock
+Service=media-server.service
+SocketMode=0777
+
+[Install]
+WantedBy=sockets.target
Source1: media-server.service
Source2: media-server-user.service
Source3: media-server-user.path
+Source4: media-server.socket
+Source5: 99-media-server.rules
+Source6: media-server-user-ondemand.path
Source1001: %{name}.manifest
Source1002: libmedia-utils.manifest
Source1003: libmedia-utils-devel.manifest
%define product_tv 0
%endif
+%if ("%{sec_buildconf_optimized_memory}" == "1")
+%define on_demand 1
+%else
+%define on_demand 0
+%endif
+
%define upgrade_script_path /usr/share/upgrade/scripts
%description
%if "%{asan}" == "1"
%restore_fcommon
%endif
-%if 0%{?product_tv}
-export CFLAGS="$CFLAGS -D_USE_TVPD_MODE"
-%else
-export CFLAGS="$CFLAGS"
-%endif
export CFLAGS="$CFLAGS -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 -DTIZEN_DEBUG_ENABLE -DSYSCONFDIR=\\\"%{_sysconfdir}\\\""
export CFLAGS+=" -DPATH_LIBDIR=\\\"%{_libdir}\\\""
+%if 0%{?on_demand}
+export CFLAGS+=" -D_USE_ON_DEMAND"
+%endif
+%if 0%{?product_tv}
+export CFLAGS+=" -D_USE_TVPD_MODE"
+%endif
rm -rf autom4te.cache
rm -f aclocal.m4 ltmain.sh
mkdir -p m4
%if 0%{?gtests:1}
--enable-tests \
%endif
+%if 0%{?on_demand}
+ --enable-on-demand \
+%endif
%if 0%{?product_tv}
--enable-product-tv \
%else
mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
install -m 644 %{SOURCE1} %{buildroot}%{_unitdir}/media-server.service
+%if 0%{?on_demand}
+mkdir -p %{buildroot}%{_unitdir}/sockets.target.wants
+mkdir -p %{buildroot}%{_sysconfdir}/udev/rules.d
+install -m 644 %{SOURCE4} %{buildroot}%{_unitdir}/media-server.socket
+ln -s ../media-server.socket %{buildroot}%{_unitdir}/sockets.target.wants/media-server.socket
+install -m 644 %{SOURCE5} %{buildroot}%{_sysconfdir}/udev/rules.d/99-media-server.rules
+%endif
%if !0%{?product_tv}
mkdir -p %{buildroot}%{_unitdir_user}
install -m 644 %{SOURCE2} %{buildroot}%{_unitdir_user}/media-server-user.service
+%if 0%{?on_demand}
+install -m 644 %{SOURCE6} %{buildroot}%{_unitdir_user}/media-server-user.path
+%else
install -m 644 %{SOURCE3} %{buildroot}%{_unitdir_user}/media-server-user.path
%endif
+%endif
ln -s ../media-server.service %{buildroot}%{_unitdir}/multi-user.target.wants/media-server.service
%endif
%{_unitdir}/media-server.service
%{_unitdir}/multi-user.target.wants/media-server.service
+%if 0%{?on_demand}
+%{_unitdir}/media-server.socket
+%{_unitdir}/sockets.target.wants/media-server.socket
+%{_sysconfdir}/udev/rules.d/99-media-server.rules
+%endif
%if !0%{?product_tv}
%{_unitdir_user}/media-server-user.service
%{_unitdir_user}/media-server-user.path
--- /dev/null
+/*
+ * Media Server
+ *
+ * Copyright (c) 2024 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.
+ *
+ */
+
+#ifndef _MEDIA_SERVER_ON_DEMAND_H_
+#define _MEDIA_SERVER_ON_DEMAND_H_
+
+#include <glib.h>
+
+#include "media-common-system.h"
+
+typedef enum {
+ MS_START_TYPE_BOOT,
+ MS_START_TYPE_SOCKET,
+ MS_START_TYPE_UDEV,
+} ms_start_type_e;
+
+void ms_on_demand_start_timer(ms_start_type_e start_type);
+ms_start_type_e ms_on_demand_get_start_type(void);
+void ms_on_demand_initialize(void);
+void ms_on_demand_finalize(void);
+void ms_on_demand_insert_storage(gpointer data, gpointer user_data);
+void ms_on_demand_remove_storage(gpointer data, gpointer user_data);
+void ms_on_demand_update_storage_list(GSList *storage_list);
+
+#endif /* _MEDIA_SERVER_ON_DEMAND_H_ */
#define PROD_CUSTOM_MIME_ADDED "1"
#define PROD_CUSTOM_MIME_REMOVED "0"
#endif
+#ifdef _USE_ON_DEMAND
+#include "media-server-on-demand.h"
+#endif
int ms_storage_insert_handler(const char *mount_path, const char *mount_uuid)
{
if (block_info->mount_path != NULL && block_info->mount_uuid != NULL) {
MS_DBG("uuid[%s] path[%s]", block_info->mount_uuid, block_info->mount_path);
+#ifdef _USE_ON_DEMAND
+ if (block_info->state == MS_STG_INSERTED)
+ ms_on_demand_insert_storage((gpointer)block_info, NULL);
+ else if (block_info->state == MS_STG_REMOVED)
+ ms_on_demand_remove_storage((gpointer)block_info, NULL);
+#else
if (block_info->state == MS_STG_INSERTED)
ms_storage_insert_handler(block_info->mount_path, block_info->mount_uuid);
else if (block_info->state == MS_STG_REMOVED)
ms_storage_remove_handler(block_info->mount_path, block_info->mount_uuid);
+#endif
} else {
MS_DBG_ERR("mount_path or mount_uuid is NULL");
}
#include "media-server-scanner.h"
#include "media-server-device-block.h"
+#ifdef _USE_ON_DEMAND
+#include "media-server-on-demand.h"
+#endif
+
#ifdef _USE_TVPD_MODE
#include "media-common-external-storage.h"
#include "media-server-db-manage.h"
#ifdef _USE_TVPD_MODE
int ret = 0;
#endif
+#ifdef _USE_ON_DEMAND
+ ms_start_type_e start_type = ms_on_demand_get_start_type();
+#endif
resource_pid_t stResource = {};
stResource.pid = getpid();
__ms_deal_reset_status();
#endif
-
+#ifdef _USE_ON_DEMAND
+ ms_on_demand_initialize();
+#endif
/*Init main loop*/
mainloop = g_main_loop_new(NULL, FALSE);
__ms_add_event_receiver();
__ms_add_signal_handler();
+#ifdef _USE_ON_DEMAND
+ switch (start_type) {
+ case MS_START_TYPE_SOCKET:
+ /* do nothing */
+ break;
+ case MS_START_TYPE_UDEV:
+ /* improve mount/unmount performance */
+ MS_DBG("ms_scanner_start [%s]", (ms_scanner_start() == MS_MEDIA_ERR_NONE) ? "success" : "fail");
+ /* fall through */
+ case MS_START_TYPE_BOOT:
+ __ms_check_mediadb();
+ break;
+ default:
+ MS_DBG_ERR("invalid start_type(%d)", start_type);
+ break;
+ }
+#else
__ms_check_mediadb();
+#endif
/*Active flush */
malloc_trim(0);
#endif
resource_clear_cpu_boosting(stResource);
+#ifdef _USE_ON_DEMAND
+ ms_on_demand_start_timer(start_type);
+#endif
+
g_main_loop_run(mainloop);
ms_db_update_thread_join();
ms_scanner_dispatcher_thread_join();
+#ifdef _USE_ON_DEMAND
+ ms_on_demand_finalize();
+#endif
ms_cynara_finish();
#ifdef _USE_TVPD_MODE
ms_unload_functions();
g_free(_data);
}
+#ifndef _USE_ON_DEMAND
static void __ms_insert_storage(gpointer data, gpointer user_data)
{
ms_block_info_s *block_info = (ms_block_info_s *)data;
ms_storage_insert_handler(block_info->mount_path, block_info->mount_uuid);
}
+#endif
static void __ms_update_storage_status(void)
{
return;
}
+#ifdef _USE_ON_DEMAND
+ ms_on_demand_update_storage_list(dev_list);
+#else
if (!dev_list) {
MS_DBG_ERR("External storage not found");
ms_storage_remove_handler(STORAGE_REMOVED, NULL);
}
g_slist_foreach(dev_list, __ms_insert_storage, NULL);
+#endif
g_slist_free_full(dev_list, __ms_dev_free);
}
--- /dev/null
+/*
+ * Media Server
+ *
+ * Copyright (c) 2024 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 <stdbool.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <systemd/sd-daemon.h>
+#include <gio/gio.h>
+#include <tzplatform_config.h>
+#include <sqlite3.h>
+
+#include "media-common-db-svc.h"
+#include "media-util.h"
+
+#include "media-server-dbg.h"
+#include "media-server-db.h"
+#include "media-server-scanner.h"
+#include "media-server-device-block.h"
+#include "media-server-on-demand.h"
+
+#define MS_MAIN_TIMEOUT_SEC 300
+#define BOOT_CHECK_FILE tzplatform_mkpath(TZ_SYS_TMP, "media_server_boot")
+#define SELECT_VALID_STORAGES "SELECT storage_id, storage_path FROM storage WHERE validity=1"
+
+extern GMainLoop *mainloop;
+
+static int g_ms_on_demand_timer_id = 0;
+static GSList *g_ms_on_demand_storage_list = NULL;
+
+static void __ms_on_demand_create_timer(void);
+
+static gboolean __ms_on_demand_check_active(gpointer user_data)
+{
+ int scanner_pid = ms_get_scanner_pid();
+
+ /* check if scanner & dcm are running */
+ if (scanner_pid > 0) {
+ MS_DBG_ERR("[No-error] Timer is Called but there is active media-scanner, scanner_pid = %d", scanner_pid);
+
+ return G_SOURCE_CONTINUE;
+ }
+
+ MS_DBG_ERR("[No-error] Timer is Called. Now Killing media-server process");
+ g_ms_on_demand_timer_id = 0;
+
+ /* stop media-server */
+ ms_scanner_dispatcher_thread_stop();
+ ms_db_update_thread_stop();
+ g_main_loop_quit(mainloop);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void __ms_on_demand_destroy_timer(void)
+{
+ if (g_source_remove(g_ms_on_demand_timer_id))
+ g_ms_on_demand_timer_id = 0;
+ MS_DBG_ERR("[No-error] __ms_on_demand_destroy_timer");
+}
+
+static void __ms_on_demand_create_timer(void)
+{
+ __ms_on_demand_destroy_timer();
+
+ MS_DBG_ERR("[No-error] __ms_on_demand_create_timer");
+
+ g_ms_on_demand_timer_id = g_timeout_add_seconds(MS_MAIN_TIMEOUT_SEC,
+ __ms_on_demand_check_active, NULL);
+}
+
+static bool __ms_on_demand_is_boot()
+{
+ g_autoptr (GFile) tmpfile = NULL;
+
+ tmpfile = g_file_new_for_path(BOOT_CHECK_FILE);
+
+ if (g_file_query_exists(tmpfile, NULL))
+ return false;
+
+ return true;
+}
+
+static void __ms_on_demand_write_boot_status(void)
+{
+ GError *error = NULL;
+
+ if (!g_file_set_contents(BOOT_CHECK_FILE, (const gchar *)"1", (gssize)1, &error)) {
+ MS_DBG_ERR("g_file_set_contents error(%s: %s)",
+ BOOT_CHECK_FILE, (error ? error->message : "none"));
+ if (error)
+ g_error_free(error);
+ }
+}
+
+static bool __ms_on_demand_acquire_socket_activation(void)
+{
+ int ret = 0;
+ int client_fd = -1;
+ struct sockaddr_in client_addr;
+ socklen_t client_addr_size = sizeof(client_addr);
+ fd_set readfds;
+ struct timeval timeout = { 0, 10000 }; // 10 msec
+
+ MS_DBG("SD_LISTEN_FDS_START: %d", SD_LISTEN_FDS_START);
+
+ /* If the media-server is executed by udev, the block occur in accept() function.
+ So select() function is used to prevent block. */
+ FD_ZERO(&readfds);
+ FD_SET(SD_LISTEN_FDS_START, &readfds);
+ ret = select(SD_LISTEN_FDS_START + 1, &readfds, NULL, NULL, &timeout);
+ MS_DBG("select: %d", ret);
+ MS_DBG_RETVM_IF(ret < 1, false, "[No-error] not socket activation.");
+
+ /* It is necessary to accept fd so that no more socket activation occur from the systemd. */
+ client_fd = accept(SD_LISTEN_FDS_START, (struct sockaddr *)&client_addr, &client_addr_size);
+ if (client_fd == -1) {
+ MS_DBG_STRERROR("accept failed");
+ return false;
+ }
+ close(client_fd);
+ return true;
+}
+
+void ms_on_demand_start_timer(ms_start_type_e start_type)
+{
+ /* start kill timer */
+ __ms_on_demand_create_timer();
+ if (start_type == MS_START_TYPE_BOOT)
+ __ms_on_demand_write_boot_status();
+}
+
+ms_start_type_e ms_on_demand_get_start_type(void)
+{
+ /* Media-server is initially executed without temp file at boot time. */
+ bool is_boot = __ms_on_demand_is_boot();
+ MS_DBG_RETVM_IF(is_boot, MS_START_TYPE_BOOT, "[No-error] Media Server was started by boot.");
+
+ /* Media-server is executed with socket by socket activation. */
+ MS_DBG_RETVM_IF(__ms_on_demand_acquire_socket_activation(), MS_START_TYPE_SOCKET,
+ "[No-error] Media Server was started by socket activation.");
+
+ /* Media-server can be executed by udev except boot and socket activation */
+ MS_DBG_ERR("[No-error] Media Server was started by udev.");
+ return MS_START_TYPE_UDEV;
+}
+
+static void __ms_read_storage_list_from_db(void)
+{
+ int ret = MS_MEDIA_ERR_NONE;
+ sqlite3 *db_handle = NULL;
+ sqlite3_stmt *sql_stmt = NULL;
+ ms_block_info_s *block_info = NULL;
+
+ ret = ms_connect_db(&db_handle, ms_sys_get_uid());
+ if (ret != MS_MEDIA_ERR_NONE) {
+ MS_DBG_ERR("ms_connect_db failed [%d]", ret);
+ return;
+ }
+
+ ret = sqlite3_prepare_v2(db_handle, SELECT_VALID_STORAGES, strlen(SELECT_VALID_STORAGES), &sql_stmt, NULL);
+ if (SQLITE_OK != ret) {
+ MS_DBG_ERR("prepare error [%s]", sqlite3_errmsg(db_handle));
+ ms_disconnect_db(db_handle);
+ return;
+ }
+
+ while (sqlite3_step(sql_stmt) == SQLITE_ROW) {
+ block_info = g_new0(ms_block_info_s, 1);
+ block_info->mount_uuid = g_strdup((const char *)sqlite3_column_text(sql_stmt, 0));
+ block_info->mount_path = g_strdup((const char *)sqlite3_column_text(sql_stmt, 1));
+
+ g_ms_on_demand_storage_list = g_slist_append(g_ms_on_demand_storage_list, block_info);
+ }
+
+ sqlite3_finalize(sql_stmt);
+ ms_disconnect_db(db_handle);
+}
+
+static gint __ms_compare_storage(gconstpointer a, gconstpointer b)
+{
+ ms_block_info_s *_a = (ms_block_info_s *)a;
+ ms_block_info_s *_b = (ms_block_info_s *)b;
+
+ return g_strcmp0(_a->mount_path, _b->mount_path);
+}
+
+static void __ms_free_storage(gpointer data)
+{
+ ms_block_info_s *block_info = (ms_block_info_s *)data;
+
+ if (!block_info)
+ return;
+
+ g_free(block_info->mount_path);
+ g_free(block_info->mount_uuid);
+ g_free(block_info);
+}
+
+static void __ms_print_storage(gpointer data, gpointer user_data)
+{
+ ms_block_info_s *_data = (ms_block_info_s *)data;
+ const char *message = (const char *)user_data;
+
+ if (!data)
+ return;
+
+ MS_DBG_SINFO("[%s] Storage uuid[%s] path[%s]",
+ message ? message : "None", _data->mount_uuid, _data->mount_path);
+}
+
+/* diff = a - b, the diff exist in a, but it does not exist in b */
+static GSList *__ms_get_diff_list(GSList *a, GSList *b)
+{
+ GSList *diff = NULL;
+ GSList *iter = NULL;
+
+ for (iter = a; iter != NULL; iter = g_slist_next(iter)) {
+ if (!g_slist_find_custom(b, iter->data, (GCompareFunc)__ms_compare_storage))
+ diff = g_slist_append(diff, iter->data);
+ }
+
+ return diff;
+}
+
+void ms_on_demand_initialize(void)
+{
+ MS_DBG_FENTER();
+
+ __ms_read_storage_list_from_db();
+ g_slist_foreach(g_ms_on_demand_storage_list, (GFunc)__ms_print_storage, "Initial");
+
+ MS_DBG_FLEAVE();
+}
+
+void ms_on_demand_finalize(void)
+{
+ g_slist_free_full(g_ms_on_demand_storage_list, (GDestroyNotify)__ms_free_storage);
+}
+
+void ms_on_demand_insert_storage(gpointer data, gpointer user_data)
+{
+ ms_block_info_s *block_info = (ms_block_info_s *)data;
+ ms_block_info_s *new_storage = NULL;
+
+ if (!block_info)
+ return;
+
+ if (g_slist_find_custom(g_ms_on_demand_storage_list, block_info,
+ (GCompareFunc)__ms_compare_storage))
+ return;
+
+ __ms_print_storage(block_info, "Insert");
+
+ new_storage = g_new0(ms_block_info_s, 1);
+ new_storage->mount_path = g_strdup(block_info->mount_path);
+ new_storage->mount_uuid = g_strdup(block_info->mount_uuid);
+
+ g_ms_on_demand_storage_list = g_slist_append(g_ms_on_demand_storage_list, new_storage);
+
+ /* request database insertion to scanner */
+ ms_storage_insert_handler(block_info->mount_path, block_info->mount_uuid);
+}
+
+void ms_on_demand_remove_storage(gpointer data, gpointer user_data)
+{
+ ms_block_info_s *block_info = (ms_block_info_s *)data;
+ GSList *found = NULL;
+
+ if (!block_info)
+ return;
+
+ found = g_slist_find_custom(g_ms_on_demand_storage_list, block_info,
+ (GCompareFunc)__ms_compare_storage);
+ if (!found)
+ return;
+
+ __ms_print_storage(block_info, "Remove");
+
+ /* request database removal to scanner */
+ ms_storage_remove_handler(block_info->mount_path, block_info->mount_uuid);
+
+ g_ms_on_demand_storage_list = g_slist_remove_link(g_ms_on_demand_storage_list, found);
+ g_slist_free_full(found, (GDestroyNotify)__ms_free_storage);
+}
+
+void ms_on_demand_update_storage_list(GSList *storage_list)
+{
+ GSList *insert_storages = NULL;
+ GSList *remove_storages = NULL;
+
+ MS_DBG_FENTER();
+
+ /* Insert the storages that don't exist in previous list(g_ms_on_demand_storage_list) */
+ insert_storages = __ms_get_diff_list(storage_list, g_ms_on_demand_storage_list);
+ if (insert_storages) {
+ g_slist_foreach(insert_storages, (GFunc)ms_on_demand_insert_storage, NULL);
+ g_slist_free(insert_storages);
+ }
+
+ /* Remove the storages that don't exist in new list(storage_list) */
+ remove_storages = __ms_get_diff_list(g_ms_on_demand_storage_list, storage_list);
+ if (remove_storages) {
+ g_slist_foreach(remove_storages, (GFunc)ms_on_demand_remove_storage, NULL);
+ g_slist_free(remove_storages);
+ }
+
+ MS_DBG_FLEAVE();
+}
/*media DB is corrupted, recovery media DB*/
__ms_recovery_media_db(recv_msg.uid);
goto ERROR;
+#ifdef _USE_ON_DEMAND
+ case MS_MSG_MEDIA_SERVER_READY:
+ ret = MS_MEDIA_ERR_NONE;
+ MS_DBG_INFO("%s", recv_msg.msg);
+ goto ERROR;
+#endif
default:
close(client_sock);
break;
case MS_MSG_MEDIA_DB_MALFORMED:
res_msg.msg_type = MS_MSG_MEDIA_DB_MALFORMED;
break;
+#ifdef _USE_ON_DEMAND
+ case MS_MSG_MEDIA_SERVER_READY:
+ res_msg.msg_type = MS_MSG_MEDIA_SERVER_READY;
+ res_msg.result = MS_MEDIA_ERR_NONE;
+ break;
+#endif
default:
break;
}