2 * Copyright 2020 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <service_app.h>
19 #include <app_manager.h>
30 #include "service_common.h"
31 #include "service_main.h"
32 #include "service_plugin.h"
33 #include "service_ipc_dbus.h"
34 #include "service_config.h"
36 static CServiceMain* g_service_main = nullptr;
38 bool CServiceMain::check_preprocessing_assistant_exists()
42 boost::optional<std::string> preprocessing_appid =
43 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
44 if (preprocessing_appid) {
45 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
46 if (mClientInfo[loop].used &&
47 strncmp((*preprocessing_appid).c_str(), mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
48 if (mClientManager.check_client_validity_by_appid(*preprocessing_appid)) {
55 MAS_LOGD("result : %d", ret);
60 bool CServiceMain::is_current_preprocessing_assistant(const char* appid)
62 if (NULL == appid) return false;
66 boost::optional<std::string> preprocessing_appid =
67 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
68 if (preprocessing_appid) {
69 if (strncmp((*preprocessing_appid).c_str(), appid, MAX_APPID_LEN) == 0) {
77 int CServiceMain::client_get_audio_format(pid_t pid, int* rate, int* channel, int* audio_type)
79 MAS_LOGD("[Enter] pid(%d)", pid);
81 int ret = mServicePlugin.get_recording_audio_format(rate, channel, audio_type);
83 MAS_LOGE("[ERROR] Fail to get recording audio format, ret(%d)", ret);
89 #define MAX_LOCAL_VARIABLE_STRING_LEN 256
90 int CServiceMain::client_get_audio_source_type(pid_t pid, char** type)
92 MAS_LOGD("[Enter] pid(%d)", pid);
94 if (NULL == type) return -1;
96 static char cached[MAX_LOCAL_VARIABLE_STRING_LEN] = {'\0'};
97 int ret = mServicePlugin.get_recording_audio_source_type(type);
99 MAS_LOGE("[ERROR] Fail to get recording audio source type, ret(%d)", ret);
102 strncpy(cached, *type, MAX_LOCAL_VARIABLE_STRING_LEN - 1);
103 cached[MAX_LOCAL_VARIABLE_STRING_LEN - 1] = '\0';
109 int CServiceMain::client_send_preprocessing_information(pid_t pid)
112 MAS_LOGD("[Enter] pid(%d)", pid);
114 boost::optional<std::string> preprocessing_appid =
115 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
116 if (preprocessing_appid) {
117 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_appid).c_str());
118 ret = mServiceIpc.send_preprocessing_information(pid, (*preprocessing_appid).c_str());
124 int CServiceMain::client_send_voice_key_status_change(pid_t pid, ma_voice_key_status_e status)
127 MAS_LOGD("[Enter] pid(%d)", pid);
129 ret = mServiceIpc.change_voice_key_status(pid, status);
131 MAS_LOGE("[ERROR] Fail to send voice key status changed information, ret(%d)", ret);
133 mLastVoiceKeyStatus = status;
138 int CServiceMain::client_send_asr_result(pid_t pid, int event, const char* asr_result)
140 MAS_LOGD("[Enter] pid(%d), event(%d), asr_result(%s)", pid, event, asr_result);
141 int ret = mServiceIpc.masc_ui_dbus_send_asr_result(pid, event, asr_result);
143 MAS_LOGE("[ERROR] Fail to send asr result, ret(%d)", ret);
146 // if final event is , launch assistant app which is invoked with wakeup word.
151 int CServiceMain::client_send_result(pid_t pid, const char* display_text,
152 const char* utterance_text, const char* result_json)
154 MAS_LOGD("[Enter] pid(%d), display_text(%s), utterance_text(%s), result_json(%s)", pid, display_text, utterance_text, result_json);
155 int ret = mServiceIpc.masc_ui_dbus_send_result(pid, display_text, utterance_text, result_json);
157 MAS_LOGE("[ERROR] Fail to send result, ret(%d)", ret);
160 std::string pid_appid;
161 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
163 pid_appid = *appid_by_pid;
165 mServicePlugin.update_recognition_result(pid_appid.c_str(), MA_RECOGNITION_RESULT_EVENT_SUCCESS);
170 int CServiceMain::client_send_recognition_result(pid_t pid, int result)
172 MAS_LOGD("[Enter] pid(%d), result(%d)", pid, result);
173 int ret = mServiceIpc.masc_ui_dbus_send_recognition_result(pid, result);
175 MAS_LOGE("[ERROR] Fail to send recognition result, ret(%d)", ret);
178 std::string pid_appid;
179 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
181 pid_appid = *appid_by_pid;
183 mServicePlugin.update_recognition_result(pid_appid.c_str(), result);
188 int CServiceMain::client_start_streaming_audio_data(pid_t pid, int type)
192 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
193 ret = mServicePlugin.start_streaming_utterance_data();
194 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED);
196 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
197 ret = mServicePlugin.start_streaming_previous_utterance_data();
198 /* Preprocessing is not required for previous utterance streaming */
200 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
201 ret = mServicePlugin.start_streaming_follow_up_data();
202 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED);
208 int CServiceMain::client_stop_streaming_audio_data(pid_t pid, int type)
212 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
213 ret = mServicePlugin.stop_streaming_utterance_data();
215 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
216 ret = mServicePlugin.stop_streaming_previous_utterance_data();
218 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
219 ret = mServicePlugin.stop_streaming_follow_up_data();
225 int CServiceMain::client_update_voice_feedback_state(pid_t pid, int state)
227 std::string pid_appid;
228 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
230 pid_appid = *appid_by_pid;
232 mServicePlugin.update_voice_feedback_state(pid_appid.c_str(), state);
236 int CServiceMain::client_set_assistant_specific_command(pid_t pid, const char *command)
238 std::string pid_appid;
239 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
241 pid_appid = *appid_by_pid;
243 mServicePlugin.set_assistant_specific_command(pid_appid.c_str(), command);
247 int CServiceMain::client_set_background_volume(pid_t pid, double ratio)
249 std::string pid_appid;
250 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
252 pid_appid = *appid_by_pid;
254 mServicePlugin.set_background_volume(pid_appid.c_str(), ratio);
258 int CServiceMain::client_set_preprocessing_allow_mode(pid_t pid, ma_preprocessing_allow_mode_e mode, const char* appid)
260 std::string pid_appid;
261 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
263 pid_appid = *appid_by_pid;
266 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
267 if (mClientInfo[loop].used) {
268 if (0 == pid_appid.compare(mClientInfo[loop].appid)) {
269 mClientInfo[loop].preprocessing_allow_mode = mode;
271 strncpy(mClientInfo[loop].preprocessing_allow_appid, appid, MAX_APPID_LEN);
272 mClientInfo[loop].preprocessing_allow_appid[MAX_APPID_LEN - 1] = '\0';
274 mClientInfo[loop].preprocessing_allow_appid[0] = '\0';
280 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED);
285 int CServiceMain::client_send_preprocessing_result(pid_t pid, bool result)
287 std::string pid_appid;
288 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
290 pid_appid = *appid_by_pid;
292 if (!is_current_preprocessing_assistant(pid_appid.c_str())) return -1;
294 const char *current_maclient_appid = NULL;
295 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
296 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
300 MAS_LOGD("Preprocessing succeeded, bring (%s) to foreground", pid_appid.c_str());
301 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED);
303 MAS_LOGD("Preprocessing failed, bring (%s) to foreground", current_maclient_appid);
304 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED);
307 if (current_maclient_appid) {
308 pid_t pid_by_appid = mClientManager.find_client_pid_by_appid(
309 std::string{current_maclient_appid});
310 mServiceIpc.send_preprocessing_result(pid_by_appid, result);
316 int CServiceMain::client_set_wake_word_audio_require_flag(pid_t pid, bool require)
318 std::string pid_appid;
319 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
321 pid_appid = *appid_by_pid;
324 mServicePlugin.set_wake_word_audio_require_flag(pid_appid.c_str(), require);
328 int CServiceMain::client_set_assistant_language(pid_t pid, const char* language)
330 std::string pid_appid;
331 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
333 pid_appid = *appid_by_pid;
336 mServicePlugin.set_assistant_language(pid_appid.c_str(), language);
340 int CServiceMain::client_add_wake_word(pid_t pid, const char* wake_word, const char* language)
342 std::string pid_appid;
343 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
345 pid_appid = *appid_by_pid;
348 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
349 if (mClientInfo[loop].used &&
350 0 == pid_appid.compare(mClientInfo[loop].appid)) {
351 int ret = mServiceConfig.add_custom_wake_word(wake_word, language,
352 mClientInfo[loop].wakeup_word,
353 mClientInfo[loop].wakeup_language);
355 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
356 mClientInfo[loop].wakeup_word,
357 mClientInfo[loop].wakeup_language);
359 LOGE("add new wake word failed!");
365 mServicePlugin.add_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
369 int CServiceMain::client_remove_wake_word(pid_t pid, const char* wake_word, const char* language)
371 std::string pid_appid;
372 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
374 pid_appid = *appid_by_pid;
377 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
378 if (mClientInfo[loop].used &&
379 0 == pid_appid.compare(mClientInfo[loop].appid)) {
380 int ret = mServiceConfig.remove_custom_wake_word(wake_word, language,
381 mClientInfo[loop].wakeup_word,
382 mClientInfo[loop].wakeup_language);
384 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
385 mClientInfo[loop].wakeup_word,
386 mClientInfo[loop].wakeup_language);
391 mServicePlugin.remove_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
395 int CServiceMain::ui_client_initialize(pid_t pid)
397 MAS_LOGD("[Enter] pid(%d)", pid);
402 int CServiceMain::ui_client_deinitialize(pid_t pid)
404 MAS_LOGD("[Enter] pid(%d)", pid);
409 int CServiceMain::ui_client_change_assistant(const char* appid)
414 MAS_LOGE("NULL parameter");
418 bool use_custom_ui = get_client_custom_ui_option_by_appid(appid);
419 mServiceIpc.masc_ui_dbus_enable_common_ui(!use_custom_ui);
421 set_current_client_by_appid(appid);
422 pid_t pid = get_client_pid_by_appid(appid);
424 bring_client_to_foreground(appid);
425 client_send_preprocessing_information(pid);
426 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
427 client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
430 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_ACTIVE);
431 MAS_LOGD("MA Client with appid %s exists, requesting speech data", (appid ? appid : "NULL"));
433 int ret = mServicePlugin.start_streaming_utterance_data();
435 MAS_LOGE("[ERROR] Fail to start streaming utterance data(%d)", ret);
439 // Appropriate MA Client not available, trying to launch new one
440 MAS_LOGD("MA Client with appid %s does not exist, launching client", (appid ? appid : "NULL"));
442 /* The appid parameter might not exist after this function call, so we use appid string in our mClientInfo */
443 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
444 if (mClientInfo[loop].used &&
445 0 < strlen(mClientInfo[loop].appid) &&
446 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
447 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
448 launch_client_by_appid(mClientInfo[loop].appid, CLIENT_LAUNCH_MODE_ACTIVATION);
457 static int assistant_info_cb(ma_assistant_info_s* info, void* user_data) {
459 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
461 ret = service_main->add_assistant_info(info);
466 int CServiceMain::add_assistant_info(ma_assistant_info_s* info) {
467 MAS_LOGD("__assistant_info_cb called");
470 MAS_LOGE("info NULL, returning");
473 if (NULL == info->app_id) {
474 MAS_LOGE("app_id NULL, returning");
480 while(-1 == index && loop < MAX_MACLIENT_INFO_NUM) {
481 if (false == mClientInfo[loop].used) {
487 mClientInfo[index].used = true;
488 mClientInfo[index].preprocessing_allow_mode = MA_PREPROCESSING_ALLOW_NONE;
489 mClientInfo[index].preprocessing_allow_appid[0] = '\0';
490 MAS_LOGD("app_id(%s)", info->app_id);
491 strncpy(mClientInfo[index].appid, info->app_id, MAX_APPID_LEN);
492 mClientInfo[index].appid[MAX_APPID_LEN - 1] = '\0';
494 if (is_current_preprocessing_assistant(mClientInfo[index].appid)) {
495 mCurrentPreprocessingClientInfo = index;
498 for (loop = 0;loop < MAX_WAKEUP_WORDS_NUM;loop++) {
499 if (loop < info->cnt_wakeup && info->wakeup_list[loop]) {
500 MAS_LOGD("wakeup_list(%d)(%s)(%s)", loop, info->wakeup_list[loop], info->wakeup_language[loop]);
501 strncpy(mClientInfo[index].wakeup_word[loop], info->wakeup_list[loop], MAX_WAKEUP_WORD_LEN);
502 mClientInfo[index].wakeup_word[loop][MAX_WAKEUP_WORD_LEN - 1] = '\0';
503 if (info->wakeup_language[loop]) {
504 strncpy(mClientInfo[index].wakeup_language[loop], info->wakeup_language[loop], MAX_SUPPORTED_LANGUAGE_LEN);
505 mClientInfo[index].wakeup_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
507 strncpy(mClientInfo[index].wakeup_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
510 strncpy(mClientInfo[index].wakeup_word[loop], "", MAX_WAKEUP_WORD_LEN);
514 for (loop = 0;loop < MAX_SUPPORTED_LANGUAGES_NUM;loop++) {
515 if (loop < info->cnt_lang && info->supported_lang[loop]) {
516 MAS_LOGD("supported_lang(%d)(%s)", loop, info->supported_lang[loop]);
517 strncpy(mClientInfo[index].supported_language[loop], info->supported_lang[loop], MAX_SUPPORTED_LANGUAGE_LEN);
518 mClientInfo[index].supported_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
520 strncpy(mClientInfo[index].supported_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
524 MAS_LOGD("wakeup_engine(%s)", info->wakeup_engine);
525 if (info->wakeup_engine) {
526 strncpy(mClientInfo[index].wakeup_engine, info->wakeup_engine, MAX_APPID_LEN);
527 mClientInfo[index].wakeup_engine[MAX_APPID_LEN - 1] = '\0';
529 mClientInfo[index].wakeup_engine[0] = '\0';
530 MAS_LOGW("Wakeup engine information not provided for : %s", info->app_id);
532 mClientInfo[index].custom_ui_option = info->custom_ui_option;
534 MAS_LOGD("voice_key_support_mode(%d)", info->voice_key_support_mode);
535 mClientInfo[index].voice_key_support_mode = info->voice_key_support_mode;
536 MAS_LOGD("voice_key_tap_duration(%f)", info->voice_key_tap_duration);
537 mClientInfo[index].voice_key_tap_duration = info->voice_key_tap_duration;
538 MAS_LOGD("audio_processing_appid(%s)",
539 (info->audio_data_processing_appid ? (info->audio_data_processing_appid)->c_str() : "[NONE]"));
540 mClientInfo[index].audio_processing_appid = info->audio_data_processing_appid;
542 MAS_LOGD("Couldn't find an empty slot for storing assistant info");
545 MAS_LOGD("__assistant_info_cb end");
550 static void active_state_changed_cb(std::string key, void* user_data)
552 IPreferenceManager* manager = static_cast<IPreferenceManager*>(user_data);
553 if (nullptr == manager) return;
555 boost::optional<bool> activated =
556 manager->get_bool(MULTI_ASSISTANT_SETTINGS_ACTIVATED);
558 MAS_LOGD("multi-assistant active state : %d\n", *activated);
560 CServicePlugin *plugin = nullptr;
561 if (g_service_main) {
562 plugin = g_service_main->get_service_plugin();
568 plugin->deactivate();
571 MAS_LOGE("Could not change plugin state : %p %p", g_service_main, plugin);
576 int CServiceMain::initialize_service_plugin(void)
579 if (0 != mServicePlugin.initialize()) {
580 MAS_LOGE("Fail to ws intialize");
584 if (0 != mServicePlugin.set_language(mCurrentLanguage.c_str())) {
585 MAS_LOGE("Fail to ws set language");
589 memset(&mClientInfo, 0x00, sizeof(mClientInfo));
590 mCurrentClientInfo = -1;
591 mCurrentPreprocessingClientInfo = -1;
592 mWakeupClientAppId.clear();
594 if (0 == mServiceConfig.get_assistant_info(assistant_info_cb, this)) {
595 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
597 if (0 < strlen(mClientInfo[loop].appid)) {
598 mServiceConfig.load_custom_wake_words(mClientInfo[loop].appid,
599 mClientInfo[loop].wakeup_word, mClientInfo[loop].wakeup_language);
600 if (0 < strlen(mClientInfo[loop].wakeup_engine)) {
601 mServicePlugin.set_assistant_wakeup_engine(
602 mClientInfo[loop].appid,
603 mClientInfo[loop].wakeup_engine);
605 for (inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
606 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
607 MAS_LOGD("Registering wakeup word %s for app %s",
608 mClientInfo[loop].wakeup_word[inner_loop], mClientInfo[loop].appid);
609 if (0 != mServicePlugin.add_assistant_wakeup_word(
610 mClientInfo[loop].appid,
611 mClientInfo[loop].wakeup_word[inner_loop],
612 mClientInfo[loop].wakeup_language[inner_loop])) {
613 MAS_LOGE("Fail to add assistant's wakeup word");
617 for (inner_loop = 0; inner_loop < MAX_SUPPORTED_LANGUAGES_NUM; inner_loop++) {
618 if (0 < strlen(mClientInfo[loop].supported_language[inner_loop])) {
619 MAS_LOGD("Adding language %s for app %s",
620 mClientInfo[loop].supported_language[inner_loop], mClientInfo[loop].appid);
621 if (0 != mServicePlugin.add_assistant_language(
622 mClientInfo[loop].appid,
623 mClientInfo[loop].supported_language[inner_loop])) {
624 MAS_LOGE("Fail to add assistant's language");
631 MAS_LOGE("Fail to load assistant info");
634 if (0 != mServicePlugin.set_callbacks()) {
635 MAS_LOGE("Fail to set callbacks");
642 int CServiceMain::deinitialize_service_plugin(void)
645 if (0 != mServicePlugin.deactivate()) {
646 MAS_LOGE("Fail to deactivate");
648 if (0 != mServicePlugin.deinitialize()) {
649 MAS_LOGE("Fail to deinitialize");
655 int CServiceMain::process_activated_setting()
657 if (mPreferenceManager.register_changed_callback(
658 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb, &mPreferenceManager)) {
659 /* Activate / deactivate according to the vconf key setting */
660 active_state_changed_cb(std::string{}, &mPreferenceManager);
662 #ifdef ENABLE_MULTI_ASSISTANT_BY_DEFAULT
663 /* Multi-assistant needs to be enabled by default, unless disabled explicitly */
664 mServicePlugin.activate();
665 const char *default_assistant = NULL;
666 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
667 if (NULL == default_assistant) {
668 if (mClientInfo[0].used) {
669 default_assistant = mClientInfo[0].appid;
670 MAS_LOGW("No default assistant, setting %s as default", default_assistant);
671 mServicePlugin.set_default_assistant(default_assistant);
673 MAS_LOGE("No default assistant, and no assistant installed");
682 int CServiceMain::get_current_client_pid()
685 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
686 const char *appid = mClientInfo[mCurrentClientInfo].appid;
688 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
694 pid_t CServiceMain::get_current_preprocessing_client_pid()
697 if (mCurrentPreprocessingClientInfo >= 0 && mCurrentPreprocessingClientInfo < MAX_MACLIENT_INFO_NUM) {
698 const char *appid = mClientInfo[mCurrentPreprocessingClientInfo].appid;
700 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
706 pid_t CServiceMain::get_current_audio_processing_pid()
709 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
710 boost::optional<std::string> audio_processing_appid =
711 mClientInfo[mCurrentClientInfo].audio_processing_appid;
712 if (audio_processing_appid) {
713 boost::optional<pid_t> audio_processing_pid;
714 audio_processing_pid = mApplicationManager.get_pid_by_appid((*audio_processing_appid).c_str());
715 if (audio_processing_pid) {
716 ret = *audio_processing_pid;
723 pid_t CServiceMain::get_client_pid_by_appid(const char *appid)
728 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
731 if (-1 != ret && !mApplicationManager.is_application_running(appid)) {
732 MAS_LOGE("The PID for %s was %d, but it seems to be terminated", appid, ret);
733 on_deinitialize(ret);
740 bool CServiceMain::get_client_custom_ui_option_by_appid(const char *appid)
743 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
744 if (mClientInfo[loop].used &&
745 0 < strlen(mClientInfo[loop].appid) &&
746 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
747 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
748 ret = mClientInfo[loop].custom_ui_option;
755 int CServiceMain::get_client_pid_by_wakeup_word(const char *wakeup_word)
757 const char *appid = get_client_appid_by_wakeup_word(wakeup_word);
758 return get_client_pid_by_appid(appid);
761 const char* CServiceMain::get_client_appid_by_wakeup_word(const char *wakeup_word)
764 const char *appid = NULL;
766 if (NULL == wakeup_word) return NULL;
768 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
769 if (mClientInfo[loop].used &&
770 0 < strlen(mClientInfo[loop].appid)) {
771 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
772 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
773 if (0 == strncmp(wakeup_word, mClientInfo[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
774 appid = mClientInfo[loop].appid;
781 /* Perform extended search, by eliminating blank characters */
783 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
784 if (mClientInfo[loop].used &&
785 0 < strlen(mClientInfo[loop].appid)) {
786 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
787 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
788 char comparand[MAX_WAKEUP_WORD_LEN];
789 int comparand_index = 0;
790 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
791 if (' ' != mClientInfo[loop].wakeup_word[inner_loop][index]) {
792 comparand[comparand_index++] = mClientInfo[loop].wakeup_word[inner_loop][index];
795 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
796 appid = mClientInfo[loop].appid;
807 int CServiceMain::set_current_client_by_wakeup_word(const char *wakeup_word)
811 int prev_selection = mCurrentClientInfo;
813 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
814 if (mClientInfo[loop].used &&
815 0 < strlen(mClientInfo[loop].appid)) {
816 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
817 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
818 if (0 == strncmp(wakeup_word, mClientInfo[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
819 mCurrentClientInfo = loop;
826 /* Perform extended search, by eliminating blank characters */
828 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
829 if (mClientInfo[loop].used &&
830 0 < strlen(mClientInfo[loop].appid)) {
831 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
832 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
833 char comparand[MAX_WAKEUP_WORD_LEN];
834 int comparand_index = 0;
835 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
836 if (' ' != mClientInfo[loop].wakeup_word[inner_loop][index]) {
837 comparand[comparand_index++] = mClientInfo[loop].wakeup_word[inner_loop][index];
840 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
841 mCurrentClientInfo = loop;
850 if (mCurrentClientInfo != prev_selection) {
851 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
852 pid_t pid = get_client_pid_by_appid(mClientInfo[prev_selection].appid);
853 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_INACTIVE);
860 int CServiceMain::set_current_client_by_appid(const char *appid)
863 int prev_selection = mCurrentClientInfo;
865 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
866 if (mClientInfo[loop].used &&
867 0 < strlen(mClientInfo[loop].appid) &&
868 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
869 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
870 mCurrentClientInfo = loop;
876 if (mCurrentClientInfo != prev_selection) {
877 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
878 pid_t pid = get_client_pid_by_appid(mClientInfo[prev_selection].appid);
879 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_INACTIVE);
886 int CServiceMain::launch_client_by_appid(const char *appid, CLIENT_LAUNCH_MODE launch_mode)
890 if (NULL == appid || 0 == strlen(appid)) {
891 MAS_LOGE("appid invalid, failed launching MA Client");
895 if (CLIENT_LAUNCH_MODE_PRELAUNCH == launch_mode) {
896 if (mApplicationManager.is_application_running(appid)) {
897 MAS_LOGE("appid %s is already running, no need for a prelaunch", appid);
901 result = mApplicationManager.launch_app_async(appid, true);
903 result = mApplicationManager.launch_app_async(appid, false);
906 if (CLIENT_LAUNCH_MODE_ACTIVATION == launch_mode) {
908 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
909 if (mClientInfo[loop].used &&
910 0 < strlen(mClientInfo[loop].appid)) {
911 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
912 mWakeupClientAppId = mClientInfo[loop].appid;
917 MAS_LOGD("mWakeupClientAppId : %s, %d", mWakeupClientAppId.c_str(), found);
923 int CServiceMain::bring_client_to_foreground(const char* appid)
927 if (NULL == appid || 0 == strlen(appid)) {
928 MAS_LOGE("appid invalid, failed launching MA Client");
932 if (!mApplicationManager.bring_app_to_foreground(appid)) {
939 int CServiceMain::launch_client_by_wakeup_word(const char *wakeup_word)
941 const char *appid = get_client_appid_by_wakeup_word(wakeup_word);
942 return launch_client_by_appid(appid, CLIENT_LAUNCH_MODE_ACTIVATION);
945 int CServiceMain::prelaunch_default_assistant()
947 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
948 boost::optional<bool> prelaunch_mode =
949 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PRELAUNCH_MODE);
950 if (prelaunch_mode && *prelaunch_mode) {
951 const char *default_assistant = NULL;
952 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
953 if (default_assistant &&
954 !(mApplicationManager.is_application_running(default_assistant))) {
955 MAS_LOGD("prelaunching default_assistant_appid : %s", default_assistant);
956 launch_client_by_appid(default_assistant, CLIENT_LAUNCH_MODE_PRELAUNCH);
963 int CServiceMain::update_voice_key_support_mode()
965 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
966 bool successful = false;
967 const char *default_assistant = NULL;
968 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
969 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
970 if (mClientInfo[loop].used) {
971 if (default_assistant &&
972 strncmp(default_assistant, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
973 float duration = mClientInfo[loop].voice_key_tap_duration;
974 if (0.0f < duration) {
975 mServicePlugin.set_voice_key_tap_duration(duration);
977 mServicePlugin.unset_voice_key_tap_duration();
979 mServicePlugin.set_voice_key_support_mode(
980 mClientInfo[loop].voice_key_support_mode);
988 mServicePlugin.unset_voice_key_tap_duration();
989 mServicePlugin.set_voice_key_support_mode(VOICE_KEY_SUPPORT_MODE_NONE);
994 ma_preprocessing_allow_mode_e CServiceMain::get_preprocessing_allow_mode(const char* appid)
996 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
997 if (appid && mClientInfo[loop].used) {
998 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
999 return mClientInfo[loop].preprocessing_allow_mode;
1003 return MA_PREPROCESSING_ALLOW_NONE;
1006 /* This might need to be read from settings in the future, but using macro for now */
1007 //#define BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1009 int CServiceMain::process_preprocessing_state_event(PREPROCESSING_STATE_EVENT event)
1011 const char* current_maclient_appid = NULL;
1012 const char* preprocessing_allow_appid = NULL;
1013 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1014 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
1015 preprocessing_allow_appid = mClientInfo[mCurrentClientInfo].preprocessing_allow_appid;
1017 ma_preprocessing_allow_mode_e mode = get_preprocessing_allow_mode(current_maclient_appid);
1020 case PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED:
1022 #ifndef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1023 /* If there is no need to bring preprocessing assistant to front,
1024 current_maclient should always be brought to front */
1025 bring_client_to_foreground(current_maclient_appid);
1027 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1028 if (check_preprocessing_assistant_exists()) {
1029 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1030 MA_PREPROCESSING_ALLOW_ALL == mode) {
1031 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1032 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1036 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1037 /* If preprocessing assistant does not exist, there is no way to enable
1038 preprocessing assistant, so bring current maclient to front right away */
1039 bring_client_to_foreground(current_maclient_appid);
1044 case PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED:
1046 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1047 /* Enable preprocessing mode only if the preprocessing assistant exists */
1048 if (check_preprocessing_assistant_exists()) {
1049 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1050 MA_PREPROCESSING_ALLOW_ALL == mode) {
1051 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1052 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1058 case PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED:
1060 if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED == mCurrentPreprocessingState) {
1061 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_UTTERANCE;
1062 } else if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED == mCurrentPreprocessingState) {
1063 /* If preprocessing assistant does not exist, the current_maclient
1064 would have been brought to front already on wakeup event */
1065 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1066 if (check_preprocessing_assistant_exists()) {
1067 bring_client_to_foreground(current_maclient_appid);
1070 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1074 case PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED:
1076 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1077 if (check_preprocessing_assistant_exists()) {
1078 if (MA_PREPROCESSING_ALLOW_FOLLOW_UP == mode ||
1079 MA_PREPROCESSING_ALLOW_ALL == mode) {
1080 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_FOLLOW_UP;
1085 case PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED:
1087 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1088 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1089 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1090 boost::optional<std::string> preprocessing_assistant =
1091 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1092 if (preprocessing_assistant) {
1093 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1094 bring_client_to_foreground((*preprocessing_assistant).c_str());
1098 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1101 case PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED:
1103 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1104 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1105 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1106 bring_client_to_foreground(current_maclient_appid);
1109 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1116 int CServiceMain::set_current_service_state(ma_service_state_e state)
1118 mCurrentServiceState = state;
1120 int count = mClientManager.get_client_num();
1123 for (i = 0; i < count; i++) {
1124 pid_t pid = mClientManager.find_client_pid_by_index(i);
1127 int ret = mServiceIpc.change_service_state(pid, state);
1129 MAS_LOGE("[ERROR] Fail to set service state change to %d, ret(%d)", pid, ret);
1136 ma_service_state_e CServiceMain::get_current_service_state()
1138 return mCurrentServiceState;
1141 bool CServiceMain::is_valid_wakeup_engine(const char* appid)
1143 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM;loop++) {
1144 if (mClientInfo[loop].used) {
1145 LOGD("comparing appid : %s %s", mClientInfo[loop].wakeup_engine, appid);
1146 if (0 == strncmp(mClientInfo[loop].wakeup_engine, appid, MAX_APPID_LEN)) {
1154 bool CServiceMain::is_wakeup_engine(const pkgmgrinfo_appinfo_h handle)
1156 if (nullptr == g_service_main) return false;
1157 bool is_wakeup_engine = false;
1161 int ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
1162 if (PMINFO_R_OK == ret && NULL != appid) {
1163 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM;loop++) {
1164 if (mClientInfo[loop].used) {
1165 LOGD("comparing appid : %s %s", mClientInfo[loop].wakeup_engine, appid);
1166 if (0 == strncmp(mClientInfo[loop].wakeup_engine, appid, MAX_APPID_LEN)) {
1167 is_wakeup_engine = true;
1172 LOGE("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1175 return is_wakeup_engine;
1178 bool CServiceMain::is_voice_assistant(const pkgmgrinfo_appinfo_h handle)
1180 bool is_voice_assistant = false;
1181 char* metadata_value = NULL;
1182 const char* voice_assistant_metadata = "http://tizen.org/metadata/multi-assistant/name";
1183 int ret = pkgmgrinfo_appinfo_get_metadata_value(handle, voice_assistant_metadata, &metadata_value);
1184 if (PMINFO_R_OK == ret && NULL != metadata_value) {
1185 is_voice_assistant = true;
1187 LOGE("pkgmgrinfo_appinfo_get_metadata_value failed! error code=%d", ret);
1189 return is_voice_assistant;
1192 static int pkg_app_list_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
1194 if (!g_service_main) return 0;
1196 int *result = (int*)user_data;
1198 if (g_service_main->is_voice_assistant(handle)) {
1200 } else if (g_service_main->is_wakeup_engine(handle)) {
1208 INFO: Package install/update/uninstall scenario
1209 Install and Uninstall are obviously simple.
1210 Install: just INSTALL
1211 Uninstall: just UNINSTALL
1212 Update package (change the source codes and Run As again), there are four scenarios:
1215 2. UNINSTALL -> INSTALL
1216 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1217 and change Application ID in tizen-manifest.xml file and Run As.
1218 3. UPDATE -> INSTALL
1219 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1220 and change Application ID in tizen-manifest.xml file and Run As.
1221 At UPDATE event, pkgid (package parameter) is invalid...
1223 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1224 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1226 static void _package_manager_event_cb(const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data)
1228 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
1231 uid_t uid = getuid();
1232 pkgmgrinfo_pkginfo_h handle = NULL;
1233 static bool in_progress = false;
1234 bool should_exit = false;
1235 bool pkginfo_found = true;
1237 if (!package || !type)
1240 if (PACKAGE_MANAGER_EVENT_TYPE_UPDATE != event_type &&
1241 PACKAGE_MANAGER_EVENT_TYPE_INSTALL != event_type &&
1242 PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL != event_type)
1245 if (PACKAGE_MANAGER_EVENT_STATE_STARTED != event_state &&
1246 PACKAGE_MANAGER_EVENT_STATE_COMPLETED != event_state &&
1247 PACKAGE_MANAGER_EVENT_STATE_FAILED != event_state)
1251 MAS_LOGD("type=%s package=%s event_type=%d event_state=%d progress=%d error=%d",
1252 type, package, event_type, event_state, progress, error);
1253 ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
1254 if (ret != PMINFO_R_OK || NULL == handle) {
1255 MAS_LOGW("Failed to call pkgmgrinfo_pkginfo_get_pkginfo(\"%s\",~) returned %d", package, ret);
1256 /* Try to get in user packages */
1258 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(package, uid, &handle);
1259 if (ret != PMINFO_R_OK || NULL == handle) {
1260 MAS_LOGW("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", package, ret, getuid ());
1261 pkginfo_found = false;
1265 if (pkginfo_found) {
1267 /* Try to get in user packages */
1268 pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, pkg_app_list_cb, (void *)&ret, uid);
1270 /* Try to get in global packages */
1271 pkgmgrinfo_appinfo_get_list(handle, PMINFO_ALL_APP, pkg_app_list_cb, (void *)&ret);
1274 /* Even if we failed acquiring the pkginfo, proceed if we're uninstalling
1275 since at the time of uninstall completion, pkginfo would not exist */
1277 if (PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL == event_type &&
1278 (PACKAGE_MANAGER_EVENT_STATE_COMPLETED == event_state ||
1279 PACKAGE_MANAGER_EVENT_STATE_FAILED == event_state)) {
1285 if (PACKAGE_MANAGER_EVENT_STATE_STARTED == event_state) {
1286 MAS_LOGI("processing PACKAGE_MANAGER_EVENT_STATE_STARTED event : %d", event_type);
1287 if (false == in_progress) {
1290 service_main->deinitialize_service_plugin();
1292 MAS_LOGE("service_main is NULL");
1295 } else if (PACKAGE_MANAGER_EVENT_STATE_COMPLETED == event_state ||
1296 PACKAGE_MANAGER_EVENT_STATE_FAILED == event_state) {
1297 MAS_LOGI("processing PACKAGE_MANAGER_EVENT_STATE_COMPLETED/FAILED event : %d %d",
1298 event_state, event_type);
1299 if (false == in_progress) {
1301 service_main->deinitialize_service_plugin();
1303 MAS_LOGE("service_main is NULL");
1308 service_main->initialize_service_plugin();
1309 service_main->process_activated_setting();
1311 MAS_LOGE("service_main is NULL");
1315 in_progress = false;
1319 if (handle) pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1322 LOGI("Now restarting multi-assistant-service for reloading updated modules");
1329 bool CServiceMain::app_create(void *data)
1331 // Todo: add your code here.
1332 MAS_LOGI("[ENTER] Service app create");
1334 g_service_main = this;
1336 mClientManager.set_application_manager(&mApplicationManager);
1338 mServiceIpc.set_client_manager(&mClientManager);
1339 mServiceIpc.set_application_manager(&mApplicationManager);
1340 mServiceIpc.set_service_ipc_observer(this);
1342 mServicePlugin.set_service_ipc(&mServiceIpc);
1343 mServicePlugin.set_service_main(this);
1345 int ret = mServiceIpc.open_connection();
1347 MAS_LOGE("[ERROR] Fail to open connection");
1350 initialize_service_plugin();
1352 process_activated_setting();
1354 prelaunch_default_assistant();
1355 update_voice_key_support_mode();
1357 /* For the case of preprocessing assistant, it always have to be launched beforehand */
1358 boost::optional<std::string> preprocessing_assistant =
1359 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1360 if (preprocessing_assistant) {
1361 MAS_LOGD("prelaunching preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1362 launch_client_by_appid((*preprocessing_assistant).c_str(), CLIENT_LAUNCH_MODE_PRELAUNCH);
1365 if (!mPackageManagerHandle) {
1366 int ret = package_manager_create(&mPackageManagerHandle);
1367 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
1368 ret = package_manager_set_event_cb(mPackageManagerHandle, _package_manager_event_cb, this);
1369 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
1370 LOGD("package_manager_set_event_cb succeeded.");
1372 LOGE("package_manager_set_event_cb failed(%d)", ret);
1375 LOGE("package_manager_create failed(%d)", ret);
1379 MAS_LOGI("[END] Service app create");
1383 void CServiceMain::app_terminate(void *data)
1385 MAS_LOGI("[ENTER]");
1386 if (mPackageManagerHandle) {
1387 package_manager_unset_event_cb(mPackageManagerHandle);
1388 package_manager_destroy(mPackageManagerHandle);
1389 mPackageManagerHandle = NULL;
1392 deinitialize_service_plugin();
1394 mPreferenceManager.unregister_changed_callback(
1395 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb);
1397 int ret = mServiceIpc.close_connection();
1399 MAS_LOGE("[ERROR] Fail to close connection");
1402 g_service_main = nullptr;
1408 int CServiceMain::on_initialize(pid_t pid) {
1409 MAS_LOGD("[Enter] pid(%d)", pid);
1411 std::string pid_appid;
1412 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
1414 pid_appid = *appid_by_pid;
1415 MAS_LOGD("appid for pid %d is : %s", pid, pid_appid.c_str());
1417 /* Remove existing client that has same appid, if there's any */
1418 mClientManager.destroy_client_by_appid(pid_appid.c_str());
1420 /* And remove a client that has same pid also */
1421 mClientManager.destroy_client_by_pid(pid);
1423 mClientManager.create_client(pid, pid_appid.c_str());
1425 const char *current_maclient_appid = NULL;
1426 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1427 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
1430 client_send_preprocessing_information(pid);
1431 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
1432 client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
1434 if (current_maclient_appid && 0 == pid_appid.compare(current_maclient_appid)) {
1435 MAS_LOGD("MA client with current maclient appid connected!");
1437 if (0 == mWakeupClientAppId.compare(pid_appid)) {
1438 mWakeupClientAppId.clear();
1439 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_ACTIVE);
1440 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED);
1442 MAS_LOGE("[ERROR] mWakeupClientAppId and appid differ : %s %s",
1443 mWakeupClientAppId.c_str(), pid_appid.c_str());
1446 MAS_LOGD("MA client connected, but its appid does not match with current maclient");
1449 mServiceIpc.change_service_state(pid, get_current_service_state());
1451 MAS_LOGE("[ERROR] Fail to retrieve appid");
1457 int CServiceMain::on_deinitialize(pid_t pid) {
1458 MAS_LOGD("[Enter] pid(%d)", pid);
1459 mClientManager.destroy_client_by_pid(pid);
1463 int CServiceMain::on_get_audio_format(pid_t pid, int& rate, int& channel, int& audio_type) {
1464 int main_rate, main_channel, main_audio_type;
1465 int ret = client_get_audio_format(pid,
1466 &main_rate, &main_channel, &main_audio_type);
1468 channel = main_channel;
1469 audio_type = main_audio_type;
1473 int CServiceMain::on_get_audio_source_type(pid_t pid, std::string& type) {
1474 char *main_type = nullptr;
1475 int ret = client_get_audio_source_type(pid, &main_type);
1476 if (0 == ret && main_type) {
1477 type = std::string{main_type};
1482 int CServiceMain::on_send_asr_result(pid_t pid, int event, std::string asr_result) {
1483 return client_send_asr_result(pid, event, asr_result.c_str());
1486 int CServiceMain::on_send_result(pid_t pid, std::string display_text,
1487 std::string utterance_text, std::string result_json) {
1488 return client_send_result(pid,
1489 display_text.c_str(), utterance_text.c_str(), result_json.c_str());
1492 int CServiceMain::on_send_recognition_result(pid_t pid, int result) {
1493 return client_send_recognition_result(pid, result);
1496 int CServiceMain::on_start_streaming_audio_data(pid_t pid, int type) {
1497 return client_start_streaming_audio_data(pid, type);
1500 int CServiceMain::on_stop_streaming_audio_data(pid_t pid, int type) {
1501 return client_stop_streaming_audio_data(pid, type);
1504 int CServiceMain::on_update_voice_feedback_state(pid_t pid, int state) {
1505 return client_update_voice_feedback_state(pid, state);
1508 int CServiceMain::on_send_assistant_specific_command(pid_t pid, std::string command) {
1509 return client_set_assistant_specific_command(pid, command.c_str());
1512 int CServiceMain::on_set_background_volume(pid_t pid, double ratio) {
1513 return client_set_background_volume(pid, ratio);
1516 int CServiceMain::on_set_preprocessing_allow_mode(pid_t pid, int mode, std::string app_id) {
1517 return client_set_preprocessing_allow_mode(pid,
1518 static_cast<ma_preprocessing_allow_mode_e>(mode), app_id.c_str());
1521 int CServiceMain::on_send_preprocessing_result(pid_t pid, int result) {
1522 return client_send_preprocessing_result(pid, result);
1525 int CServiceMain::on_set_wake_word_audio_require_flag(pid_t pid, int require) {
1526 return client_set_wake_word_audio_require_flag(pid, require);
1529 int CServiceMain::on_set_assistant_language(pid_t pid, std::string language) {
1530 return client_set_assistant_language(pid, language.c_str());
1533 int CServiceMain::on_add_wake_word(pid_t pid, std::string wake_word, std::string language) {
1534 return client_add_wake_word(pid, wake_word.c_str(), language.c_str());
1537 int CServiceMain::on_remove_wake_word(pid_t pid, std::string wake_word, std::string language) {
1538 return client_remove_wake_word(pid, wake_word.c_str(), language.c_str());
1541 int CServiceMain::on_ui_initialize(pid_t pid)
1543 return ui_client_initialize(pid);
1546 int CServiceMain::on_ui_deinitialize(pid_t pid)
1548 return ui_client_deinitialize(pid);
1551 int CServiceMain::on_ui_change_assistant(std::string app_id)
1553 return ui_client_change_assistant(app_id.c_str());