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>
36 #include "service_common.h"
37 #include "service_main.h"
38 #include "service_plugin.h"
39 #include "service_ipc_dbus.h"
40 #include "service_config.h"
42 static CServiceMain* g_service_main = nullptr;
44 void CPackageUpdateEventObserver::OnUpdateStarted()
47 g_service_main->deinitialize_service_plugin();
49 MAS_LOGE("service_main is NULL");
53 void CPackageUpdateEventObserver::OnUpdateFinished()
57 void CPackageUpdateEventObserver::OnRestartRequired()
62 bool CServiceMain::check_preprocessing_assistant_exists()
66 boost::optional<std::string> preprocessing_appid =
67 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
68 if (preprocessing_appid) {
69 ClientInfoItems *items = mClientInfo.getItems();
70 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
71 if (items[loop].used &&
72 strncmp((*preprocessing_appid).c_str(), items[loop].appid, MAX_APPID_LEN) == 0) {
73 if (mClientManager.check_client_validity_by_appid(*preprocessing_appid)) {
80 MAS_LOGD("result : %d", ret);
85 bool CServiceMain::is_current_assistant(pid_t pid)
88 const char *current_maclient_appid = NULL;
89 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
90 ClientInfoItems *items = mClientInfo.getItems();
91 current_maclient_appid = items[mCurrentClientInfo].appid;
92 pid_t pid_by_appid = mClientManager.find_client_pid_by_appid(
93 std::string{current_maclient_appid});
94 if (pid == pid_by_appid) {
97 MAS_LOGE("[ERROR] Current client: [%d], active client : [%d %s]",
98 pid, pid_by_appid, current_maclient_appid);
104 bool CServiceMain::is_current_preprocessing_assistant(const char* appid)
106 if (NULL == appid) return false;
110 boost::optional<std::string> preprocessing_appid =
111 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
112 if (preprocessing_appid) {
113 if (strncmp((*preprocessing_appid).c_str(), appid, MAX_APPID_LEN) == 0) {
121 int CServiceMain::client_get_audio_format(pid_t pid, int* rate, int* channel, int* audio_type)
123 MAS_LOGI("[Enter] pid(%d)", pid);
125 int ret = mServicePlugin.get_recording_audio_format(rate, channel, audio_type);
127 MAS_LOGE("[ERROR] Fail to get recording audio format, ret(%d)", ret);
133 #define MAX_LOCAL_VARIABLE_STRING_LEN 256
134 int CServiceMain::client_get_audio_source_type(pid_t pid, char** type)
136 MAS_LOGI("[Enter] pid(%d)", pid);
138 if (NULL == type) return -1;
140 static char cached[MAX_LOCAL_VARIABLE_STRING_LEN] = {'\0'};
141 int ret = mServicePlugin.get_recording_audio_source_type(type);
143 MAS_LOGE("[ERROR] Fail to get recording audio source type, ret(%d)", ret);
146 strncpy(cached, *type, MAX_LOCAL_VARIABLE_STRING_LEN - 1);
147 cached[MAX_LOCAL_VARIABLE_STRING_LEN - 1] = '\0';
153 int CServiceMain::client_send_preprocessing_information(pid_t pid)
156 MAS_LOGI("[Enter] pid(%d)", pid);
158 boost::optional<std::string> preprocessing_appid =
159 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
160 if (preprocessing_appid) {
161 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_appid).c_str());
162 ret = mServiceIpc.send_preprocessing_information(pid, (*preprocessing_appid).c_str());
168 int CServiceMain::client_send_voice_key_status_change(pid_t pid, ma_voice_key_status_e status)
171 MAS_LOGI("[Enter] pid(%d)", pid);
173 ret = mServiceIpc.change_voice_key_status(pid, status);
175 MAS_LOGE("[ERROR] Fail to send voice key status changed information, ret(%d)", ret);
177 mLastVoiceKeyStatus = status;
182 int CServiceMain::client_send_asr_result(pid_t pid, int event, const char* asr_result)
184 MAS_LOGI("[Enter] pid(%d), event(%d), asr_result(%s)", pid, event, asr_result);
185 if (!is_current_assistant(pid)) return -1;
187 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
189 if (ui_panel_enabled) {
190 ret = mServiceIpc.masc_ui_dbus_send_asr_result(pid, event, asr_result);
192 MAS_LOGE("[ERROR] Fail to send asr result, ret(%d)", ret);
196 // if final event is , launch assistant app which is invoked with wakeup word.
201 int CServiceMain::client_send_result(pid_t pid, const char* display_text,
202 const char* utterance_text, const char* result_json)
204 MAS_LOGI("[Enter] pid(%d), display_text(%s), utterance_text(%s), result_json(%s)", pid, display_text, utterance_text, result_json);
205 if (!is_current_assistant(pid)) return -1;
207 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
209 if (ui_panel_enabled) {
210 ret = mServiceIpc.masc_ui_dbus_send_result(pid, display_text, utterance_text, result_json);
212 MAS_LOGE("[ERROR] Fail to send result, ret(%d)", ret);
216 std::string pid_appid;
217 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
219 pid_appid = *appid_by_pid;
221 mServicePlugin.update_recognition_result(pid_appid.c_str(), MA_RECOGNITION_RESULT_EVENT_SUCCESS);
226 int CServiceMain::client_send_recognition_result(pid_t pid, int result)
228 MAS_LOGE("[Enter] pid(%d), result(%d)", pid, result);
229 if (!is_current_assistant(pid)) return -1;
231 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
233 if (ui_panel_enabled) {
234 ret = mServiceIpc.masc_ui_dbus_send_recognition_result(pid, result);
236 MAS_LOGE("[ERROR] Fail to send recognition result, ret(%d)", ret);
240 std::string pid_appid;
241 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
243 pid_appid = *appid_by_pid;
245 mServicePlugin.update_recognition_result(pid_appid.c_str(), result);
250 int CServiceMain::client_start_streaming_audio_data(pid_t pid, int type)
252 MAS_LOGE("[ENTER] %d", type);
255 if (!is_current_assistant(pid)) {
256 MAS_LOGE("Start streaming request from inactive assistant : %d", pid);
261 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
262 ret = mServicePlugin.start_streaming_utterance_data();
263 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED);
265 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
266 ret = mServicePlugin.start_streaming_previous_utterance_data();
267 /* Preprocessing is not required for previous utterance streaming */
269 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
270 ret = mServicePlugin.start_streaming_follow_up_data();
271 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED);
277 int CServiceMain::client_stop_streaming_audio_data(pid_t pid, int type)
279 MAS_LOGE("[ENTER] %d", type);
282 if (!is_current_assistant(pid)) {
283 MAS_LOGE("Start streaming request from inactive assistant : %d", pid);
288 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
289 ret = mServicePlugin.stop_streaming_utterance_data();
291 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
292 ret = mServicePlugin.stop_streaming_previous_utterance_data();
294 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
295 ret = mServicePlugin.stop_streaming_follow_up_data();
301 int CServiceMain::client_update_voice_feedback_state(pid_t pid, int state)
303 std::string pid_appid;
304 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
306 pid_appid = *appid_by_pid;
308 mServicePlugin.update_voice_feedback_state(pid_appid.c_str(), state);
312 int CServiceMain::client_set_assistant_specific_command(pid_t pid, const char *command)
314 std::string pid_appid;
315 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
317 pid_appid = *appid_by_pid;
319 mServicePlugin.set_assistant_specific_command(pid_appid.c_str(), command);
323 int CServiceMain::client_set_background_volume(pid_t pid, double ratio)
325 bool valid = is_current_assistant(pid);
327 std::string pid_appid;
328 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
330 pid_appid = *appid_by_pid;
333 /* Better extracting this into a new Ducking Management class */
334 const int max_history_size = 5;
335 static std::list<std::tuple<pid_t, std::string, double, std::time_t, bool>> history;
336 history.push_front(std::make_tuple(pid, pid_appid, ratio,
337 std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()), valid));
338 if (history.size() > max_history_size) history.pop_back();
340 std::stringstream ss;
341 for (auto item : history) {
342 std::time_t time_info = std::get<3>(item);
343 char time_string[32];
344 std::strftime(time_string, sizeof(time_string), "%H%M%S", std::localtime(&time_info));
346 ss << std::get<0>(item);
348 ss << std::get<1>(item);
350 ss << std::get<2>(item);
354 ss << std::get<4>(item);
357 MAS_LOGW("History : %s", ss.str().c_str());
359 if (!valid) return -1;
362 mLastDuckingRequester = pid;
364 mLastDuckingRequester = -1;
367 mServicePlugin.set_background_volume(pid_appid.c_str(), ratio);
371 int CServiceMain::client_set_preprocessing_allow_mode(pid_t pid, ma_preprocessing_allow_mode_e mode, const char* appid)
373 std::string pid_appid;
374 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
376 pid_appid = *appid_by_pid;
379 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
380 ClientInfoItems *items = mClientInfo.getItems();
381 if (items[loop].used) {
382 if (0 == pid_appid.compare(items[loop].appid)) {
383 items[loop].preprocessing_allow_mode = mode;
385 strncpy(items[loop].preprocessing_allow_appid, appid, MAX_APPID_LEN);
386 items[loop].preprocessing_allow_appid[MAX_APPID_LEN - 1] = '\0';
388 items[loop].preprocessing_allow_appid[0] = '\0';
394 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED);
399 int CServiceMain::client_send_preprocessing_result(pid_t pid, bool result)
401 std::string pid_appid;
402 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
404 pid_appid = *appid_by_pid;
406 if (!is_current_preprocessing_assistant(pid_appid.c_str())) return -1;
408 const char *current_maclient_appid = NULL;
409 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
410 ClientInfoItems *items = mClientInfo.getItems();
411 current_maclient_appid = items[mCurrentClientInfo].appid;
415 MAS_LOGD("Preprocessing succeeded, bring (%s) to foreground", pid_appid.c_str());
416 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED);
418 MAS_LOGD("Preprocessing failed, bring (%s) to foreground", current_maclient_appid);
419 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED);
422 if (current_maclient_appid) {
423 pid_t pid_by_appid = mClientManager.find_client_pid_by_appid(
424 std::string{current_maclient_appid});
425 mServiceIpc.send_preprocessing_result(pid_by_appid, result);
431 int CServiceMain::client_set_wake_word_audio_require_flag(pid_t pid, bool require)
433 std::string pid_appid;
434 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
436 pid_appid = *appid_by_pid;
439 mServicePlugin.set_wake_word_audio_require_flag(pid_appid.c_str(), require);
443 int CServiceMain::client_set_assistant_language(pid_t pid, const char* language)
445 std::string pid_appid;
446 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
448 pid_appid = *appid_by_pid;
451 mServicePlugin.set_assistant_language(pid_appid.c_str(), language);
455 int CServiceMain::client_add_wake_word(pid_t pid, const char* wake_word, const char* language)
457 std::string pid_appid;
458 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
460 pid_appid = *appid_by_pid;
463 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
464 ClientInfoItems *items = mClientInfo.getItems();
465 if (items[loop].used &&
466 0 == pid_appid.compare(items[loop].appid)) {
467 int ret = mServiceConfig.add_custom_wake_word(wake_word, language,
468 items[loop].wakeup_word,
469 items[loop].wakeup_language);
471 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
472 items[loop].wakeup_word,
473 items[loop].wakeup_language);
475 LOGE("add new wake word failed!");
481 mServicePlugin.add_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
485 int CServiceMain::client_remove_wake_word(pid_t pid, const char* wake_word, const char* language)
487 std::string pid_appid;
488 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
490 pid_appid = *appid_by_pid;
493 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
494 ClientInfoItems *items = mClientInfo.getItems();
495 if (items[loop].used &&
496 0 == pid_appid.compare(items[loop].appid)) {
497 int ret = mServiceConfig.remove_custom_wake_word(wake_word, language,
498 items[loop].wakeup_word,
499 items[loop].wakeup_language);
501 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
502 items[loop].wakeup_word,
503 items[loop].wakeup_language);
508 mServicePlugin.remove_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
512 int CServiceMain::ui_client_initialize(pid_t pid)
514 MAS_LOGD("[Enter] pid(%d)", pid);
519 int CServiceMain::ui_client_deinitialize(pid_t pid)
521 MAS_LOGD("[Enter] pid(%d)", pid);
526 int CServiceMain::ui_client_change_assistant(const char* appid)
531 MAS_LOGE("NULL parameter");
535 bool use_custom_ui = get_client_custom_ui_option_by_appid(appid);
536 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
537 if (ui_panel_enabled) {
538 mServiceIpc.masc_ui_dbus_enable_common_ui(!use_custom_ui);
541 set_current_client_by_appid(appid);
542 pid_t pid = get_client_pid_by_appid(appid);
544 bring_client_to_foreground(appid);
545 client_send_preprocessing_information(pid);
546 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
547 client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
550 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_ACTIVE);
551 MAS_LOGD("MA Client with appid %s exists, requesting speech data", (appid ? appid : "NULL"));
553 int ret = mServicePlugin.start_streaming_utterance_data();
555 MAS_LOGE("[ERROR] Fail to start streaming utterance data(%d)", ret);
559 // Appropriate MA Client not available, trying to launch new one
560 MAS_LOGD("MA Client with appid %s does not exist, launching client", (appid ? appid : "NULL"));
562 /* The appid parameter might not exist after this function call, so we use appid string in our mClientInfo */
563 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
564 ClientInfoItems *items = mClientInfo.getItems();
565 if (items[loop].used &&
566 0 < strlen(items[loop].appid) &&
567 0 < strlen(items[loop].wakeup_word[0])) {
568 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
569 launch_client_by_appid(items[loop].appid, CLIENT_LAUNCH_MODE_ACTIVATION);
578 static int assistant_info_cb(ma_assistant_info_s* info, void* user_data) {
580 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
582 ret = service_main->add_assistant_info(info);
587 int CServiceMain::add_assistant_info(ma_assistant_info_s* info) {
588 MAS_LOGD("__assistant_info_cb called");
591 MAS_LOGE("info NULL, returning");
594 if (NULL == info->app_id) {
595 MAS_LOGE("app_id NULL, returning");
601 ClientInfoItems *items = mClientInfo.getItems();
602 while(-1 == index && loop < MAX_MACLIENT_INFO_NUM) {
603 if (false == items[loop].used) {
609 items[index].used = true;
610 items[index].preprocessing_allow_mode = MA_PREPROCESSING_ALLOW_NONE;
611 items[index].preprocessing_allow_appid[0] = '\0';
612 MAS_LOGD("app_id(%s)", info->app_id);
613 strncpy(items[index].appid, info->app_id, MAX_APPID_LEN);
614 items[index].appid[MAX_APPID_LEN - 1] = '\0';
616 if (is_current_preprocessing_assistant(items[index].appid)) {
617 mCurrentPreprocessingClientInfo = index;
620 for (loop = 0;loop < MAX_WAKEUP_WORDS_NUM;loop++) {
621 if (loop < info->cnt_wakeup && info->wakeup_list[loop]) {
622 MAS_LOGD("wakeup_list(%d)(%s)(%s)", loop, info->wakeup_list[loop], info->wakeup_language[loop]);
623 strncpy(items[index].wakeup_word[loop], info->wakeup_list[loop], MAX_WAKEUP_WORD_LEN);
624 items[index].wakeup_word[loop][MAX_WAKEUP_WORD_LEN - 1] = '\0';
625 if (info->wakeup_language[loop]) {
626 strncpy(items[index].wakeup_language[loop], info->wakeup_language[loop], MAX_SUPPORTED_LANGUAGE_LEN);
627 items[index].wakeup_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
629 strncpy(items[index].wakeup_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
632 strncpy(items[index].wakeup_word[loop], "", MAX_WAKEUP_WORD_LEN);
636 for (loop = 0;loop < MAX_SUPPORTED_LANGUAGES_NUM;loop++) {
637 if (loop < info->cnt_lang && info->supported_lang[loop]) {
638 MAS_LOGD("supported_lang(%d)(%s)", loop, info->supported_lang[loop]);
639 strncpy(items[index].supported_language[loop], info->supported_lang[loop], MAX_SUPPORTED_LANGUAGE_LEN);
640 items[index].supported_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
642 strncpy(items[index].supported_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
646 for (loop = 0;loop < MAX_WAKEUP_ENGINES_NUM;loop++) {
647 if (loop < info->cnt_wakeup_engine && info->wakeup_engine[loop]) {
648 MAS_LOGD("wakeup_engine(%s)", info->wakeup_engine[loop]);
649 strncpy(items[index].wakeup_engine[loop], info->wakeup_engine[loop], MAX_APPID_LEN);
650 items[index].wakeup_engine[loop][MAX_APPID_LEN - 1] = '\0';
652 items[index].wakeup_engine[loop][0] = '\0';
653 MAS_LOGW("Wakeup engine information not provided for : %s", info->app_id);
656 items[index].custom_ui_option = info->custom_ui_option;
658 MAS_LOGD("voice_key_support_mode(%d)", info->voice_key_support_mode);
659 items[index].voice_key_support_mode = info->voice_key_support_mode;
660 MAS_LOGD("voice_key_tap_duration(%f)", info->voice_key_tap_duration);
661 items[index].voice_key_tap_duration = info->voice_key_tap_duration;
662 MAS_LOGD("audio_processing_appid(%s)",
663 (info->audio_data_processing_appid ? (info->audio_data_processing_appid)->c_str() : "[NONE]"));
664 items[index].audio_processing_appid = info->audio_data_processing_appid;
666 MAS_LOGD("Couldn't find an empty slot for storing assistant info");
669 MAS_LOGD("__assistant_info_cb end");
674 static void active_state_changed_cb(std::string key, void* user_data)
676 IPreferenceManager* manager = static_cast<IPreferenceManager*>(user_data);
677 if (nullptr == manager) return;
679 boost::optional<bool> activated =
680 manager->get_bool(MULTI_ASSISTANT_SETTINGS_ACTIVATED);
682 MAS_LOGE("multi-assistant active state : %d\n", *activated);
684 CServicePlugin *plugin = nullptr;
685 if (g_service_main) {
686 plugin = g_service_main->get_service_plugin();
692 plugin->deactivate();
695 MAS_LOGE("Could not change plugin state : %p %p", g_service_main, plugin);
698 MAS_LOGE("Get value failed for : %s", MULTI_ASSISTANT_SETTINGS_ACTIVATED);
702 int CServiceMain::initialize_service_plugin(void)
705 if (0 != mServicePlugin.initialize()) {
706 MAS_LOGE("Fail to ws intialize");
710 if (0 != mServicePlugin.set_language(mCurrentLanguage.c_str())) {
711 MAS_LOGE("Fail to ws set language");
715 mClientInfo.resetItems();
716 mCurrentClientInfo = -1;
717 MAS_LOGI("mCurrentClientInfo : %d", mCurrentClientInfo);
718 mCurrentPreprocessingClientInfo = -1;
719 mWakeupClientAppId.clear();
721 if (0 == mServiceConfig.get_assistant_info(assistant_info_cb, this)) {
722 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
724 ClientInfoItems *items = mClientInfo.getItems();
725 if (0 < strlen(items[loop].appid)) {
726 mServiceConfig.load_custom_wake_words(items[loop].appid,
727 items[loop].wakeup_word, items[loop].wakeup_language);
728 for (inner_loop = 0; inner_loop < MAX_WAKEUP_ENGINES_NUM; inner_loop++) {
729 if (0 < strlen(items[loop].wakeup_engine[inner_loop])) {
730 mServicePlugin.add_assistant_wakeup_engine(
732 items[loop].wakeup_engine[inner_loop]);
735 for (inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
736 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
737 MAS_LOGD("Registering wakeup word %s for app %s",
738 items[loop].wakeup_word[inner_loop], items[loop].appid);
739 if (0 != mServicePlugin.add_assistant_wakeup_word(
741 items[loop].wakeup_word[inner_loop],
742 items[loop].wakeup_language[inner_loop])) {
743 MAS_LOGE("Fail to add assistant's wakeup word");
747 for (inner_loop = 0; inner_loop < MAX_SUPPORTED_LANGUAGES_NUM; inner_loop++) {
748 if (0 < strlen(items[loop].supported_language[inner_loop])) {
749 MAS_LOGD("Adding language %s for app %s",
750 items[loop].supported_language[inner_loop], items[loop].appid);
751 if (0 != mServicePlugin.add_assistant_language(
753 items[loop].supported_language[inner_loop])) {
754 MAS_LOGE("Fail to add assistant's language");
761 MAS_LOGE("Fail to load assistant info");
764 if (0 != mServicePlugin.set_callbacks()) {
765 MAS_LOGE("Fail to set callbacks");
772 int CServiceMain::deinitialize_service_plugin(void)
775 if (0 != mServicePlugin.deactivate()) {
776 MAS_LOGE("Fail to deactivate");
778 if (0 != mServicePlugin.deinitialize()) {
779 MAS_LOGE("Fail to deinitialize");
785 int CServiceMain::process_activated_setting()
787 if (mPreferenceManager.register_changed_callback(
788 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb, &mPreferenceManager)) {
789 /* Activate / deactivate according to the vconf key setting */
790 active_state_changed_cb(std::string{}, &mPreferenceManager);
792 #ifdef ENABLE_MULTI_ASSISTANT_BY_DEFAULT
793 /* Multi-assistant needs to be enabled by default, unless disabled explicitly */
794 mServicePlugin.activate();
795 const char *default_assistant = NULL;
796 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
797 if (NULL == default_assistant) {
798 ClientInfoItems *items = mClientInfo.getItems();
800 default_assistant = items[0].appid;
801 MAS_LOGW("No default assistant, setting %s as default", default_assistant);
802 mServicePlugin.set_default_assistant(default_assistant);
804 MAS_LOGE("No default assistant, and no assistant installed");
813 int CServiceMain::get_current_client_pid()
816 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
817 ClientInfoItems *items = mClientInfo.getItems();
818 const char *appid = items[mCurrentClientInfo].appid;
820 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
826 pid_t CServiceMain::get_current_preprocessing_client_pid()
829 if (mCurrentPreprocessingClientInfo >= 0 && mCurrentPreprocessingClientInfo < MAX_MACLIENT_INFO_NUM) {
830 ClientInfoItems *items = mClientInfo.getItems();
831 const char *appid = items[mCurrentPreprocessingClientInfo].appid;
833 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
839 pid_t CServiceMain::get_current_audio_processing_pid()
842 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
843 ClientInfoItems *items = mClientInfo.getItems();
844 boost::optional<std::string> audio_processing_appid =
845 items[mCurrentClientInfo].audio_processing_appid;
846 if (audio_processing_appid) {
847 boost::optional<pid_t> audio_processing_pid;
848 audio_processing_pid = mApplicationManager.get_pid_by_appid((*audio_processing_appid).c_str());
849 if (audio_processing_pid) {
850 ret = *audio_processing_pid;
857 pid_t CServiceMain::get_client_pid_by_appid(const char *appid)
859 MAS_LOGI("Checking PID of appid : %s", appid);
863 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
866 if (-1 != ret && !mApplicationManager.is_application_running(appid)) {
867 MAS_LOGE("The PID for %s was %d, but it seems to be terminated", appid, ret);
868 on_deinitialize(ret);
875 bool CServiceMain::get_client_custom_ui_option_by_appid(const char *appid)
878 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
879 ClientInfoItems *items = mClientInfo.getItems();
880 if (items[loop].used &&
881 0 < strlen(items[loop].appid) &&
882 0 < strlen(items[loop].wakeup_word[0])) {
883 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
884 ret = items[loop].custom_ui_option;
891 int CServiceMain::get_client_pid_by_wakeup_word(const char *wakeup_word)
893 const char *appid = get_client_appid_by_wakeup_word(wakeup_word);
894 return get_client_pid_by_appid(appid);
897 const char* CServiceMain::get_client_appid_by_wakeup_word(const char *wakeup_word)
900 const char *appid = NULL;
902 if (NULL == wakeup_word) return NULL;
904 ClientInfoItems *items = mClientInfo.getItems();
905 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
906 if (items[loop].used &&
907 0 < strlen(items[loop].appid)) {
908 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
909 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
910 if (0 == strncmp(wakeup_word, items[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
911 appid = items[loop].appid;
918 /* Perform extended search, by eliminating blank characters */
920 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
921 if (items[loop].used &&
922 0 < strlen(items[loop].appid)) {
923 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
924 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
925 char comparand[MAX_WAKEUP_WORD_LEN];
926 int comparand_index = 0;
927 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
928 if (' ' != items[loop].wakeup_word[inner_loop][index]) {
929 comparand[comparand_index++] = items[loop].wakeup_word[inner_loop][index];
932 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
933 appid = items[loop].appid;
944 int CServiceMain::set_current_client_by_wakeup_word(const char *wakeup_word)
948 int prev_selection = mCurrentClientInfo;
950 ClientInfoItems *items = mClientInfo.getItems();
951 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
952 if (items[loop].used &&
953 0 < strlen(items[loop].appid)) {
954 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
955 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
956 if (0 == strncmp(wakeup_word, items[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
957 mCurrentClientInfo = loop;
958 MAS_LOGE("mCurrentClientInfo : %d %s", mCurrentClientInfo, wakeup_word);
965 /* Perform extended search, by eliminating blank characters */
967 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
968 if (items[loop].used &&
969 0 < strlen(items[loop].appid)) {
970 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
971 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
972 char comparand[MAX_WAKEUP_WORD_LEN];
973 int comparand_index = 0;
974 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
975 if (' ' != items[loop].wakeup_word[inner_loop][index]) {
976 comparand[comparand_index++] = items[loop].wakeup_word[inner_loop][index];
979 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
980 mCurrentClientInfo = loop;
981 MAS_LOGE("mCurrentClientInfo : %d %s", mCurrentClientInfo, wakeup_word);
990 if (mCurrentClientInfo != prev_selection) {
991 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
992 pid_t pid = get_client_pid_by_appid(items[prev_selection].appid);
993 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_INACTIVE);
994 if (mLastDuckingRequester == pid) {
995 MAS_LOGE("Last ducking requester is deactivated, resetting background volume");
996 mServicePlugin.set_background_volume(items[prev_selection].appid, 1.0f);
997 mLastDuckingRequester = -1;
1005 int CServiceMain::set_current_client_by_appid(const char *appid)
1008 int prev_selection = mCurrentClientInfo;
1010 ClientInfoItems *items = mClientInfo.getItems();
1011 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1012 if (items[loop].used &&
1013 0 < strlen(items[loop].appid) &&
1014 0 < strlen(items[loop].wakeup_word[0])) {
1015 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
1016 MAS_LOGE("mCurrentClientInfo : %d %s", mCurrentClientInfo, appid);
1017 mCurrentClientInfo = loop;
1023 if (mCurrentClientInfo != prev_selection) {
1024 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
1025 pid_t pid = get_client_pid_by_appid(items[prev_selection].appid);
1026 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_INACTIVE);
1027 if (mLastDuckingRequester == pid) {
1028 MAS_LOGE("Last ducking requester is deactivated, resetting background volume");
1029 mServicePlugin.set_background_volume(items[prev_selection].appid, 1.0f);
1030 mLastDuckingRequester = -1;
1038 int CServiceMain::launch_client_by_appid(const char *appid, CLIENT_LAUNCH_MODE launch_mode)
1042 if (NULL == appid || 0 == strlen(appid)) {
1043 MAS_LOGE("appid invalid, failed launching MA Client");
1047 if (CLIENT_LAUNCH_MODE_PRELAUNCH == launch_mode) {
1048 if (mApplicationManager.is_application_running(appid)) {
1049 MAS_LOGE("appid %s is already running, no need for a prelaunch", appid);
1053 result = mApplicationManager.launch_app_async(appid, true);
1055 result = mApplicationManager.launch_app_async(appid, false);
1058 if (CLIENT_LAUNCH_MODE_ACTIVATION == launch_mode) {
1060 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1061 ClientInfoItems *items = mClientInfo.getItems();
1062 if (items[loop].used &&
1063 0 < strlen(items[loop].appid)) {
1064 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
1065 mWakeupClientAppId = items[loop].appid;
1070 MAS_LOGD("mWakeupClientAppId : %s, %d", mWakeupClientAppId.c_str(), found);
1076 int CServiceMain::bring_client_to_foreground(const char* appid)
1080 if (NULL == appid || 0 == strlen(appid)) {
1081 MAS_LOGE("appid invalid, failed launching MA Client");
1085 if (!mApplicationManager.bring_app_to_foreground(appid)) {
1092 int CServiceMain::launch_client_by_wakeup_word(const char *wakeup_word)
1094 const char *appid = get_client_appid_by_wakeup_word(wakeup_word);
1095 return launch_client_by_appid(appid, CLIENT_LAUNCH_MODE_ACTIVATION);
1098 int CServiceMain::prelaunch_default_assistant()
1100 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
1101 boost::optional<bool> prelaunch_mode =
1102 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PRELAUNCH_MODE);
1103 if (prelaunch_mode && *prelaunch_mode) {
1104 const char *default_assistant = NULL;
1105 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
1106 if (default_assistant &&
1107 !(mApplicationManager.is_application_running(default_assistant))) {
1108 MAS_LOGD("prelaunching default_assistant_appid : %s", default_assistant);
1109 launch_client_by_appid(default_assistant, CLIENT_LAUNCH_MODE_PRELAUNCH);
1116 int CServiceMain::update_voice_key_support_mode()
1118 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
1119 bool successful = false;
1120 const char *default_assistant = NULL;
1121 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
1122 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1123 ClientInfoItems *items = mClientInfo.getItems();
1124 if (items[loop].used) {
1125 if (default_assistant &&
1126 strncmp(default_assistant, items[loop].appid, MAX_APPID_LEN) == 0) {
1127 float duration = items[loop].voice_key_tap_duration;
1128 if (0.0f < duration) {
1129 mServicePlugin.set_voice_key_tap_duration(duration);
1131 mServicePlugin.unset_voice_key_tap_duration();
1133 mServicePlugin.set_voice_key_support_mode(
1134 items[loop].voice_key_support_mode);
1142 mServicePlugin.unset_voice_key_tap_duration();
1143 mServicePlugin.set_voice_key_support_mode(VOICE_KEY_SUPPORT_MODE_NONE);
1148 ma_preprocessing_allow_mode_e CServiceMain::get_preprocessing_allow_mode(const char* appid)
1150 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1151 ClientInfoItems *items = mClientInfo.getItems();
1152 if (appid && items[loop].used) {
1153 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
1154 return items[loop].preprocessing_allow_mode;
1158 return MA_PREPROCESSING_ALLOW_NONE;
1161 /* This might need to be read from settings in the future, but using macro for now */
1162 //#define BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1164 int CServiceMain::process_preprocessing_state_event(PREPROCESSING_STATE_EVENT event)
1166 const char* current_maclient_appid = NULL;
1167 const char* preprocessing_allow_appid = NULL;
1168 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1169 ClientInfoItems *items = mClientInfo.getItems();
1170 current_maclient_appid = items[mCurrentClientInfo].appid;
1171 preprocessing_allow_appid = items[mCurrentClientInfo].preprocessing_allow_appid;
1173 ma_preprocessing_allow_mode_e mode = get_preprocessing_allow_mode(current_maclient_appid);
1176 case PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED:
1178 #ifndef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1179 /* If there is no need to bring preprocessing assistant to front,
1180 current_maclient should always be brought to front */
1181 bring_client_to_foreground(current_maclient_appid);
1183 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1184 if (check_preprocessing_assistant_exists()) {
1185 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1186 MA_PREPROCESSING_ALLOW_ALL == mode) {
1187 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1188 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1192 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1193 /* If preprocessing assistant does not exist, there is no way to enable
1194 preprocessing assistant, so bring current maclient to front right away */
1195 bring_client_to_foreground(current_maclient_appid);
1200 case PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED:
1202 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1203 /* Enable preprocessing mode only if the preprocessing assistant exists */
1204 if (check_preprocessing_assistant_exists()) {
1205 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1206 MA_PREPROCESSING_ALLOW_ALL == mode) {
1207 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1208 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1214 case PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED:
1216 if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED == mCurrentPreprocessingState) {
1217 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_UTTERANCE;
1218 } else if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED == mCurrentPreprocessingState) {
1219 /* If preprocessing assistant does not exist, the current_maclient
1220 would have been brought to front already on wakeup event */
1221 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1222 if (check_preprocessing_assistant_exists()) {
1223 bring_client_to_foreground(current_maclient_appid);
1226 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1230 case PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED:
1232 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1233 if (check_preprocessing_assistant_exists()) {
1234 if (MA_PREPROCESSING_ALLOW_FOLLOW_UP == mode ||
1235 MA_PREPROCESSING_ALLOW_ALL == mode) {
1236 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_FOLLOW_UP;
1241 case PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED:
1243 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1244 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1245 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1246 boost::optional<std::string> preprocessing_assistant =
1247 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1248 if (preprocessing_assistant) {
1249 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1250 bring_client_to_foreground((*preprocessing_assistant).c_str());
1254 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1257 case PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED:
1259 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1260 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1261 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1262 bring_client_to_foreground(current_maclient_appid);
1265 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1272 int CServiceMain::set_current_service_state(ma_service_state_e state)
1274 mCurrentServiceState = state;
1276 int count = mClientManager.get_client_num();
1279 for (i = 0; i < count; i++) {
1280 pid_t pid = mClientManager.find_client_pid_by_index(i);
1283 int ret = mServiceIpc.change_service_state(pid, state);
1285 MAS_LOGE("[ERROR] Fail to set service state change to %d, ret(%d)", pid, ret);
1292 ma_service_state_e CServiceMain::get_current_service_state()
1294 return mCurrentServiceState;
1297 bool CServiceMain::is_valid_wakeup_engine(const char* appid)
1299 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM;loop++) {
1300 ClientInfoItems *items = mClientInfo.getItems();
1301 if (items[loop].used) {
1302 for (int inner_loop = 0;inner_loop < MAX_WAKEUP_ENGINES_NUM;inner_loop++) {
1303 LOGD("comparing appid : %s %s", items[loop].wakeup_engine[inner_loop], appid);
1304 if (0 == strncmp(items[loop].wakeup_engine[inner_loop], appid, MAX_APPID_LEN)) {
1313 bool CServiceMain::app_create(void *data)
1315 // Todo: add your code here.
1316 MAS_LOGE("[ENTER] Service app create");
1318 g_service_main = this;
1320 mClientManager.set_application_manager(&mApplicationManager);
1322 mServiceIpc.set_client_manager(&mClientManager);
1323 mServiceIpc.set_application_manager(&mApplicationManager);
1324 mServiceIpc.set_service_ipc_observer(this);
1326 mServicePlugin.set_service_ipc(&mServiceIpc);
1327 mServicePlugin.set_service_main(this);
1329 const int retry_interval = 5;
1330 const int max_retry_count = 5;
1331 int retry_count = 0;
1334 ret = mServiceIpc.open_connection();
1336 sleep(retry_interval);
1337 MAS_LOGE("[ERROR] Fail to open connection, Retrying : %d", retry_count);
1339 } while (0 != ret && retry_count++ < max_retry_count);
1341 if (retry_count >= max_retry_count) {
1342 MAS_LOGE("[ERROR] Maximum retry count reached, restarting...");
1347 initialize_service_plugin();
1349 process_activated_setting();
1351 prelaunch_default_assistant();
1352 update_voice_key_support_mode();
1354 /* For the case of preprocessing assistant, it always have to be launched beforehand */
1355 boost::optional<std::string> preprocessing_assistant =
1356 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1357 if (preprocessing_assistant) {
1358 MAS_LOGD("prelaunching preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1359 launch_client_by_appid((*preprocessing_assistant).c_str(), CLIENT_LAUNCH_MODE_PRELAUNCH);
1362 mPackageUpdateMonitor.initialize();
1364 MAS_LOGE("[END] Service app create");
1368 void CServiceMain::app_terminate(void *data)
1370 MAS_LOGE("[ENTER]");
1372 mPackageUpdateMonitor.deinitialize();
1374 deinitialize_service_plugin();
1376 mPreferenceManager.unregister_changed_callback(
1377 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb);
1379 int ret = mServiceIpc.close_connection();
1381 MAS_LOGE("[ERROR] Fail to close connection");
1384 g_service_main = nullptr;
1390 int CServiceMain::on_initialize(pid_t pid) {
1391 MAS_LOGD("[Enter] pid(%d)", pid);
1393 std::string pid_appid;
1394 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
1396 pid_appid = *appid_by_pid;
1397 MAS_LOGD("appid for pid %d is : %s", pid, pid_appid.c_str());
1399 /* Remove existing client that has same appid, if there's any */
1400 mClientManager.destroy_client_by_appid(pid_appid.c_str());
1402 /* And remove a client that has same pid also */
1403 mClientManager.destroy_client_by_pid(pid);
1405 mClientManager.create_client(pid, pid_appid.c_str());
1407 const char *current_maclient_appid = NULL;
1408 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1409 ClientInfoItems *items = mClientInfo.getItems();
1410 current_maclient_appid = items[mCurrentClientInfo].appid;
1413 client_send_preprocessing_information(pid);
1414 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
1415 client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
1417 if (current_maclient_appid && 0 == pid_appid.compare(current_maclient_appid)) {
1418 MAS_LOGD("MA client with current maclient appid connected!");
1420 if (0 == mWakeupClientAppId.compare(pid_appid)) {
1421 mWakeupClientAppId.clear();
1422 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_ACTIVE);
1423 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED);
1425 MAS_LOGE("[ERROR] mWakeupClientAppId and appid differ : %s %s",
1426 mWakeupClientAppId.c_str(), pid_appid.c_str());
1429 MAS_LOGD("MA client connected, but its appid does not match with current maclient");
1432 mServiceIpc.change_service_state(pid, get_current_service_state());
1434 MAS_LOGE("[ERROR] Fail to retrieve appid");
1440 int CServiceMain::on_deinitialize(pid_t pid) {
1441 MAS_LOGD("[Enter] pid(%d)", pid);
1442 if (mLastDuckingRequester == pid) {
1443 MAS_LOGE("Last ducking requester has disconnected, resetting background volume");
1444 std::string pid_appid = mClientManager.find_client_appid_by_pid( pid);
1445 mServicePlugin.set_background_volume(pid_appid.c_str(), 1.0f);
1446 mLastDuckingRequester = -1;
1449 mClientManager.destroy_client_by_pid(pid);
1454 int CServiceMain::on_get_audio_format(pid_t pid, int& rate, int& channel, int& audio_type) {
1455 int main_rate, main_channel, main_audio_type;
1456 int ret = client_get_audio_format(pid,
1457 &main_rate, &main_channel, &main_audio_type);
1459 channel = main_channel;
1460 audio_type = main_audio_type;
1464 int CServiceMain::on_get_audio_source_type(pid_t pid, std::string& type) {
1465 char *main_type = nullptr;
1466 int ret = client_get_audio_source_type(pid, &main_type);
1467 if (0 == ret && main_type) {
1468 type = std::string{main_type};
1473 int CServiceMain::on_send_asr_result(pid_t pid, int event, std::string asr_result) {
1474 return client_send_asr_result(pid, event, asr_result.c_str());
1477 int CServiceMain::on_send_result(pid_t pid, std::string display_text,
1478 std::string utterance_text, std::string result_json) {
1479 return client_send_result(pid,
1480 display_text.c_str(), utterance_text.c_str(), result_json.c_str());
1483 int CServiceMain::on_send_recognition_result(pid_t pid, int result) {
1484 return client_send_recognition_result(pid, result);
1487 int CServiceMain::on_start_streaming_audio_data(pid_t pid, int type) {
1488 return client_start_streaming_audio_data(pid, type);
1491 int CServiceMain::on_stop_streaming_audio_data(pid_t pid, int type) {
1492 return client_stop_streaming_audio_data(pid, type);
1495 int CServiceMain::on_update_voice_feedback_state(pid_t pid, int state) {
1496 return client_update_voice_feedback_state(pid, state);
1499 int CServiceMain::on_send_assistant_specific_command(pid_t pid, std::string command) {
1500 return client_set_assistant_specific_command(pid, command.c_str());
1503 int CServiceMain::on_set_background_volume(pid_t pid, double ratio) {
1504 return client_set_background_volume(pid, ratio);
1507 int CServiceMain::on_set_preprocessing_allow_mode(pid_t pid, int mode, std::string app_id) {
1508 return client_set_preprocessing_allow_mode(pid,
1509 static_cast<ma_preprocessing_allow_mode_e>(mode), app_id.c_str());
1512 int CServiceMain::on_send_preprocessing_result(pid_t pid, int result) {
1513 return client_send_preprocessing_result(pid, result);
1516 int CServiceMain::on_set_wake_word_audio_require_flag(pid_t pid, int require) {
1517 return client_set_wake_word_audio_require_flag(pid, require);
1520 int CServiceMain::on_set_assistant_language(pid_t pid, std::string language) {
1521 return client_set_assistant_language(pid, language.c_str());
1524 int CServiceMain::on_add_wake_word(pid_t pid, std::string wake_word, std::string language) {
1525 return client_add_wake_word(pid, wake_word.c_str(), language.c_str());
1528 int CServiceMain::on_remove_wake_word(pid_t pid, std::string wake_word, std::string language) {
1529 return client_remove_wake_word(pid, wake_word.c_str(), language.c_str());
1532 int CServiceMain::on_ui_initialize(pid_t pid)
1534 return ui_client_initialize(pid);
1537 int CServiceMain::on_ui_deinitialize(pid_t pid)
1539 return ui_client_deinitialize(pid);
1542 int CServiceMain::on_ui_change_assistant(std::string app_id)
1544 return ui_client_change_assistant(app_id.c_str());