Set service state by engine launching status 79/288379/5
authorSuyeon Hwang <stom.hwang@samsung.com>
Tue, 7 Feb 2023 08:21:58 +0000 (17:21 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Mon, 6 Mar 2023 05:02:58 +0000 (14:02 +0900)
- Issue:
If the client is out of service by service reset, client can not get
proper service state.

- Solution:
By the on-demand reprepare logic, the clients subscribing service state
changed event can not get service state until that the client invokes
the API. However, if the client invokes the API depending on service
state, the client may not call the API, so it can be out of service
permanently.
To solve this problem, this patch adds logic for checking engine
launching status. Through this patch, the client library can check
whether the engine is launched or not. When the engine is launched, the
client library notifies the service state changed event to the client
app can run the code which depends on the service state.

Change-Id: If4e3310054143732f5705ed4acfae42762fa21b1
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
client/tts_core.c

index 9098e4c6e1ea96a61588970d4a4f702cb889bafd..fd4b4d6c0449bbecbaaea1a20461f596f35fa0e2 100644 (file)
@@ -36,6 +36,7 @@ static int g_engine_update_status = 0;
 static atomic_bool g_is_engine_name_changed = false;
 
 static Ecore_Thread* g_reprepare_thread = NULL;
+static Ecore_Idler *g_unset_app_context_cb_idler = NULL;
 
 static char* g_pkgmgr_status = NULL;
 static pkgmgr_client* g_pkgmgr = NULL;
@@ -61,7 +62,7 @@ static const char* __convert_state(tts_state_e state)
        return "Invalid state";
 }
 
-static char* __get_engine_appid() {
+static char* get_engine_appid() {
        if (NULL == g_engine_name) {
                return NULL;
        }
@@ -156,7 +157,7 @@ static bool __is_engine_installed(const char* appid)
 
 static bool __is_engine_launched()
 {
-       char* appid = __get_engine_appid();
+       char* appid = get_engine_appid();
        if (NULL == appid) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get engine app ID");
                return false;
@@ -702,6 +703,11 @@ int tts_core_deinitialize()
                ecore_thread_wait(g_reprepare_thread, 0.5);             // wait g_reprepare_thread is terminated.
        }
 
+       if (NULL != g_unset_app_context_cb_idler) {
+               ecore_idler_del(g_unset_app_context_cb_idler);
+               g_unset_app_context_cb_idler = NULL;
+       }
+
        if (NULL != g_pkgmgr_thread) {
                SLOG(LOG_INFO, TAG_TTSC, "[INFO] Cancel pkgmgr thread");
                g_is_thread_canceled = true;
@@ -1230,6 +1236,54 @@ static void set_service_out_for_each_client(gpointer data, gpointer user_data)
        tts_core_notify_service_state_changed(client, before_state, TTS_SERVICE_STATE_BLOCKED);
 }
 
+static void notify_engine_launch_for_each_client(gpointer data, gpointer user_data)
+{
+       tts_client_s *client = (tts_client_s *)data;
+       RETM_IF(false == tts_client_is_valid_client(client), "[ERROR] Client is not valid");
+
+       const tts_service_state_e before_state = tts_client_get_current_service_state(client);
+       if (TTS_SERVICE_STATE_BLOCKED == before_state) {
+               tts_core_notify_service_state_changed(client, before_state, TTS_SERVICE_STATE_READY);
+       }
+}
+
+static Eina_Bool unset_app_context_cb_by_idler(void *user_data)
+{
+       app_manager_unset_app_context_event_cb();
+       g_unset_app_context_cb_idler = NULL;
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] Unset callback for checking engine launching status");
+       return EINA_FALSE;
+}
+
+static void check_engine_launching_status(app_context_h app_context, app_context_event_e event, void *user_data)
+{
+       RET_IF(event != APP_CONTEXT_EVENT_LAUNCHED);
+
+       char *app_id = NULL;
+       int ret = app_context_get_app_id(app_context, &app_id);
+
+       RET_IF(ret != APP_MANAGER_ERROR_NONE || NULL == app_id);
+
+       char *engine_id = get_engine_appid();
+       bool is_engine = (0 == strncmp(app_id, engine_id, TTS_ENGINE_APPID_LEN));
+       free(app_id);
+       free(engine_id);
+
+       RET_IF(false == is_engine);
+
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] Engine is launched now");
+       GList* client_list = tts_client_get_client_list();
+       if (NULL != client_list) {
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] Set service out to all clients");
+               g_list_foreach(client_list, notify_engine_launch_for_each_client, NULL);
+               g_list_free(client_list);
+       }
+
+       if (NULL == g_unset_app_context_cb_idler) {
+               g_unset_app_context_cb_idler = ecore_idler_add(unset_app_context_cb_by_idler, NULL);
+       }
+}
+
 int tts_core_handle_service_reset()
 {
        SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Service Reset");
@@ -1247,6 +1301,12 @@ int tts_core_handle_service_reset()
        g_list_foreach(client_list, set_service_out_for_each_client, &instant_reprepare_uid);
        g_list_free(client_list);
 
+       ret = app_manager_set_app_context_event_cb(check_engine_launching_status, NULL);
+       if (APP_MANAGER_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set engine launching status callback. ret(%d/%s)", ret, get_error_message(ret));
+               return TTS_ERROR_OPERATION_FAILED;
+       }
+
        return TTS_ERROR_NONE;
 }