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>
35 #include "service_common.h"
36 #include "service_main.h"
37 #include "service_plugin.h"
38 #include "service_ipc_dbus.h"
39 #include "service_config.h"
41 static CServiceMain* g_service_main = nullptr;
43 void CPackageUpdateEventObserver::OnUpdateStarted()
46 g_service_main->deinitialize_service_plugin();
48 MAS_LOGE("service_main is NULL");
52 void CPackageUpdateEventObserver::OnUpdateFinished()
56 void CPackageUpdateEventObserver::OnRestartRequired()
61 bool CServiceMain::check_preprocessing_assistant_exists()
65 boost::optional<std::string> preprocessing_appid =
66 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
67 if (preprocessing_appid) {
68 ClientInfoItems *items = mClientInfo.getItems();
69 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
70 if (items[loop].used &&
71 strncmp((*preprocessing_appid).c_str(), items[loop].appid, MAX_APPID_LEN) == 0) {
72 if (mClientManager.check_client_validity_by_appid(*preprocessing_appid)) {
79 MAS_LOGD("result : %d", ret);
84 bool CServiceMain::is_current_assistant(pid_t pid)
87 const char *current_maclient_appid = NULL;
88 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
89 ClientInfoItems *items = mClientInfo.getItems();
90 current_maclient_appid = items[mCurrentClientInfo].appid;
91 pid_t pid_by_appid = mClientManager.find_client_pid_by_appid(
92 std::string{current_maclient_appid});
93 if (pid == pid_by_appid) {
96 MAS_LOGE("[ERROR] Current client: [%d], active client : [%d %s]",
97 pid, pid_by_appid, current_maclient_appid);
103 bool CServiceMain::is_current_preprocessing_assistant(const char* appid)
105 if (NULL == appid) return false;
109 boost::optional<std::string> preprocessing_appid =
110 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
111 if (preprocessing_appid) {
112 if (strncmp((*preprocessing_appid).c_str(), appid, MAX_APPID_LEN) == 0) {
120 int CServiceMain::client_get_audio_format(pid_t pid, int* rate, int* channel, int* audio_type)
122 MAS_LOGI("[Enter] pid(%d)", pid);
124 int ret = mServicePlugin.get_recording_audio_format(rate, channel, audio_type);
126 MAS_LOGE("[ERROR] Fail to get recording audio format, ret(%d)", ret);
132 #define MAX_LOCAL_VARIABLE_STRING_LEN 256
133 int CServiceMain::client_get_audio_source_type(pid_t pid, char** type)
135 MAS_LOGI("[Enter] pid(%d)", pid);
137 if (NULL == type) return -1;
139 static char cached[MAX_LOCAL_VARIABLE_STRING_LEN] = {'\0'};
140 int ret = mServicePlugin.get_recording_audio_source_type(type);
142 MAS_LOGE("[ERROR] Fail to get recording audio source type, ret(%d)", ret);
145 strncpy(cached, *type, MAX_LOCAL_VARIABLE_STRING_LEN - 1);
146 cached[MAX_LOCAL_VARIABLE_STRING_LEN - 1] = '\0';
152 int CServiceMain::client_send_preprocessing_information(pid_t pid)
155 MAS_LOGI("[Enter] pid(%d)", pid);
157 boost::optional<std::string> preprocessing_appid =
158 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
159 if (preprocessing_appid) {
160 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_appid).c_str());
161 ret = mServiceIpc.send_preprocessing_information(pid, (*preprocessing_appid).c_str());
167 int CServiceMain::client_send_voice_key_status_change(pid_t pid, ma_voice_key_status_e status)
170 MAS_LOGI("[Enter] pid(%d)", pid);
172 ret = mServiceIpc.change_voice_key_status(pid, status);
174 MAS_LOGE("[ERROR] Fail to send voice key status changed information, ret(%d)", ret);
176 mLastVoiceKeyStatus = status;
181 int CServiceMain::client_send_asr_result(pid_t pid, int event, const char* asr_result)
183 MAS_LOGI("[Enter] pid(%d), event(%d), asr_result(%s)", pid, event, asr_result);
184 if (!is_current_assistant(pid)) return -1;
186 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
188 if (ui_panel_enabled) {
189 ret = mServiceIpc.masc_ui_dbus_send_asr_result(pid, event, asr_result);
191 MAS_LOGE("[ERROR] Fail to send asr result, ret(%d)", ret);
195 // if final event is , launch assistant app which is invoked with wakeup word.
200 int CServiceMain::client_send_result(pid_t pid, const char* display_text,
201 const char* utterance_text, const char* result_json)
203 MAS_LOGI("[Enter] pid(%d), display_text(%s), utterance_text(%s), result_json(%s)", pid, display_text, utterance_text, result_json);
204 if (!is_current_assistant(pid)) return -1;
206 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
208 if (ui_panel_enabled) {
209 ret = mServiceIpc.masc_ui_dbus_send_result(pid, display_text, utterance_text, result_json);
211 MAS_LOGE("[ERROR] Fail to send result, ret(%d)", ret);
215 std::string pid_appid;
216 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
218 pid_appid = *appid_by_pid;
220 mServicePlugin.update_recognition_result(pid_appid.c_str(), MA_RECOGNITION_RESULT_EVENT_SUCCESS);
225 int CServiceMain::client_send_recognition_result(pid_t pid, int result)
227 MAS_LOGE("[Enter] pid(%d), result(%d)", pid, result);
228 if (!is_current_assistant(pid)) return -1;
230 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
232 if (ui_panel_enabled) {
233 ret = mServiceIpc.masc_ui_dbus_send_recognition_result(pid, result);
235 MAS_LOGE("[ERROR] Fail to send recognition result, ret(%d)", ret);
239 std::string pid_appid;
240 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
242 pid_appid = *appid_by_pid;
244 mServicePlugin.update_recognition_result(pid_appid.c_str(), result);
249 int CServiceMain::client_start_streaming_audio_data(pid_t pid, int type)
251 MAS_LOGE("[ENTER] %d", type);
254 if (!is_current_assistant(pid)) {
255 MAS_LOGE("Start streaming request from inactive assistant : %d", pid);
260 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
261 ret = mServicePlugin.start_streaming_utterance_data();
262 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED);
264 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
265 ret = mServicePlugin.start_streaming_previous_utterance_data();
266 /* Preprocessing is not required for previous utterance streaming */
268 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
269 ret = mServicePlugin.start_streaming_follow_up_data();
270 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED);
276 int CServiceMain::client_stop_streaming_audio_data(pid_t pid, int type)
278 MAS_LOGE("[ENTER] %d", type);
281 if (!is_current_assistant(pid)) {
282 MAS_LOGE("Start streaming request from inactive assistant : %d", pid);
287 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
288 ret = mServicePlugin.stop_streaming_utterance_data();
290 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
291 ret = mServicePlugin.stop_streaming_previous_utterance_data();
293 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
294 ret = mServicePlugin.stop_streaming_follow_up_data();
300 int CServiceMain::client_update_voice_feedback_state(pid_t pid, int state)
302 std::string pid_appid;
303 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
305 pid_appid = *appid_by_pid;
307 mServicePlugin.update_voice_feedback_state(pid_appid.c_str(), state);
311 int CServiceMain::client_set_assistant_specific_command(pid_t pid, const char *command)
313 std::string pid_appid;
314 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
316 pid_appid = *appid_by_pid;
318 mServicePlugin.set_assistant_specific_command(pid_appid.c_str(), command);
322 int CServiceMain::client_set_background_volume(pid_t pid, double ratio)
324 bool valid = is_current_assistant(pid);
326 std::string pid_appid;
327 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
329 pid_appid = *appid_by_pid;
332 /* Better extracting this into a new Ducking Management class */
333 const int max_history_size = 5;
334 static std::list<std::tuple<pid_t, std::string, double, std::time_t, bool>> history;
335 history.push_front(std::make_tuple(pid, pid_appid, ratio,
336 std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()), valid));
337 if (history.size() > max_history_size) history.pop_back();
339 std::stringstream ss;
340 for (auto item : history) {
341 std::time_t time_info = std::get<3>(item);
342 char time_string[32];
344 localtime_r(&time_info, &tm);
345 std::strftime(time_string, sizeof(time_string), "%H%M%S", &tm);
347 ss << std::get<0>(item);
349 ss << std::get<1>(item);
351 ss << std::get<2>(item);
355 ss << std::get<4>(item);
358 MAS_LOGW("History : %s", ss.str().c_str());
360 if (!valid) return -1;
363 mLastDuckingRequester = pid;
365 mLastDuckingRequester = -1;
368 mServicePlugin.set_background_volume(pid_appid.c_str(), ratio);
372 int CServiceMain::client_set_preprocessing_allow_mode(pid_t pid, ma_preprocessing_allow_mode_e mode, const char* appid)
374 std::string pid_appid;
375 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
377 pid_appid = *appid_by_pid;
380 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
381 ClientInfoItems *items = mClientInfo.getItems();
382 if (items[loop].used) {
383 if (0 == pid_appid.compare(items[loop].appid)) {
384 items[loop].preprocessing_allow_mode = mode;
386 strncpy(items[loop].preprocessing_allow_appid, appid, MAX_APPID_LEN);
387 items[loop].preprocessing_allow_appid[MAX_APPID_LEN - 1] = '\0';
389 items[loop].preprocessing_allow_appid[0] = '\0';
395 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED);
400 int CServiceMain::client_send_preprocessing_result(pid_t pid, bool result)
402 std::string pid_appid;
403 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
405 pid_appid = *appid_by_pid;
407 if (!is_current_preprocessing_assistant(pid_appid.c_str())) return -1;
409 const char *current_maclient_appid = NULL;
410 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
411 ClientInfoItems *items = mClientInfo.getItems();
412 current_maclient_appid = items[mCurrentClientInfo].appid;
416 MAS_LOGD("Preprocessing succeeded, bring (%s) to foreground", pid_appid.c_str());
417 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED);
419 MAS_LOGD("Preprocessing failed, bring (%s) to foreground", current_maclient_appid);
420 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED);
423 if (current_maclient_appid) {
424 pid_t pid_by_appid = mClientManager.find_client_pid_by_appid(
425 std::string{current_maclient_appid});
426 mServiceIpc.send_preprocessing_result(pid_by_appid, result);
432 int CServiceMain::client_set_wake_word_audio_require_flag(pid_t pid, bool require)
434 std::string pid_appid;
435 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
437 pid_appid = *appid_by_pid;
440 mServicePlugin.set_wake_word_audio_require_flag(pid_appid.c_str(), require);
444 int CServiceMain::client_set_assistant_language(pid_t pid, const char* language)
446 std::string pid_appid;
447 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
449 pid_appid = *appid_by_pid;
452 mServicePlugin.set_assistant_language(pid_appid.c_str(), language);
456 int CServiceMain::client_add_wake_word(pid_t pid, const char* wake_word, const char* language)
458 std::string pid_appid;
459 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
461 pid_appid = *appid_by_pid;
464 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
465 ClientInfoItems *items = mClientInfo.getItems();
466 if (items[loop].used &&
467 0 == pid_appid.compare(items[loop].appid)) {
468 int ret = mServiceConfig.add_custom_wake_word(wake_word, language,
469 items[loop].wakeup_word,
470 items[loop].wakeup_language);
472 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
473 items[loop].wakeup_word,
474 items[loop].wakeup_language);
476 LOGE("add new wake word failed!");
482 mServicePlugin.add_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
486 int CServiceMain::client_remove_wake_word(pid_t pid, const char* wake_word, const char* language)
488 std::string pid_appid;
489 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
491 pid_appid = *appid_by_pid;
494 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
495 ClientInfoItems *items = mClientInfo.getItems();
496 if (items[loop].used &&
497 0 == pid_appid.compare(items[loop].appid)) {
498 int ret = mServiceConfig.remove_custom_wake_word(wake_word, language,
499 items[loop].wakeup_word,
500 items[loop].wakeup_language);
502 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
503 items[loop].wakeup_word,
504 items[loop].wakeup_language);
509 mServicePlugin.remove_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
513 int CServiceMain::ui_client_initialize(pid_t pid)
515 MAS_LOGD("[Enter] pid(%d)", pid);
520 int CServiceMain::ui_client_deinitialize(pid_t pid)
522 MAS_LOGD("[Enter] pid(%d)", pid);
527 int CServiceMain::ui_client_change_assistant(const char* appid)
532 MAS_LOGE("NULL parameter");
536 bool use_custom_ui = get_client_custom_ui_option_by_appid(appid);
537 bool ui_panel_enabled = mServicePlugin.is_ui_panel_enabled();
538 if (ui_panel_enabled) {
539 mServiceIpc.masc_ui_dbus_enable_common_ui(!use_custom_ui);
542 set_current_client_by_appid(appid);
543 pid_t pid = get_client_pid_by_appid(appid);
545 bring_client_to_foreground(appid);
546 client_send_preprocessing_information(pid);
547 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
548 client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
551 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_ACTIVE, nullptr, nullptr, 0, nullptr);
552 MAS_LOGD("MA Client with appid %s exists, requesting speech data", (appid ? appid : "NULL"));
554 int ret = mServicePlugin.start_streaming_utterance_data();
556 MAS_LOGE("[ERROR] Fail to start streaming utterance data(%d)", ret);
560 // Appropriate MA Client not available, trying to launch new one
561 MAS_LOGD("MA Client with appid %s does not exist, launching client", (appid ? appid : "NULL"));
563 /* The appid parameter might not exist after this function call, so we use appid string in our mClientInfo */
564 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
565 ClientInfoItems *items = mClientInfo.getItems();
566 if (items[loop].used &&
567 0 < strlen(items[loop].appid) &&
568 0 < strlen(items[loop].wakeup_word[0])) {
569 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
570 launch_client_by_appid(items[loop].appid, nullptr,
571 nullptr, 0, nullptr, CLIENT_LAUNCH_MODE_ACTIVATION);
580 static int assistant_info_cb(ma_assistant_info_s* info, void* user_data) {
582 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
584 ret = service_main->add_assistant_info(info);
589 int CServiceMain::add_assistant_info(ma_assistant_info_s* info) {
590 MAS_LOGD("__assistant_info_cb called");
593 MAS_LOGE("info NULL, returning");
596 if (NULL == info->app_id) {
597 MAS_LOGE("app_id NULL, returning");
603 ClientInfoItems *items = mClientInfo.getItems();
604 while(-1 == index && loop < MAX_MACLIENT_INFO_NUM) {
605 if (false == items[loop].used) {
611 items[index].used = true;
612 items[index].preprocessing_allow_mode = MA_PREPROCESSING_ALLOW_NONE;
613 items[index].preprocessing_allow_appid[0] = '\0';
614 MAS_LOGD("app_id(%s)", info->app_id);
615 strncpy(items[index].appid, info->app_id, MAX_APPID_LEN);
616 items[index].appid[MAX_APPID_LEN - 1] = '\0';
618 if (is_current_preprocessing_assistant(items[index].appid)) {
619 mCurrentPreprocessingClientInfo = index;
622 for (loop = 0;loop < MAX_WAKEUP_WORDS_NUM;loop++) {
623 if (loop < info->cnt_wakeup && info->wakeup_list[loop]) {
624 MAS_LOGD("wakeup_list(%d)(%s)(%s)", loop, info->wakeup_list[loop], info->wakeup_language[loop]);
625 strncpy(items[index].wakeup_word[loop], info->wakeup_list[loop], MAX_WAKEUP_WORD_LEN);
626 items[index].wakeup_word[loop][MAX_WAKEUP_WORD_LEN - 1] = '\0';
627 if (info->wakeup_language[loop]) {
628 strncpy(items[index].wakeup_language[loop], info->wakeup_language[loop], MAX_SUPPORTED_LANGUAGE_LEN);
629 items[index].wakeup_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
631 strncpy(items[index].wakeup_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
634 strncpy(items[index].wakeup_word[loop], "", MAX_WAKEUP_WORD_LEN);
638 for (loop = 0;loop < MAX_SUPPORTED_LANGUAGES_NUM;loop++) {
639 if (loop < info->cnt_lang && info->supported_lang[loop]) {
640 MAS_LOGD("supported_lang(%d)(%s)", loop, info->supported_lang[loop]);
641 strncpy(items[index].supported_language[loop], info->supported_lang[loop], MAX_SUPPORTED_LANGUAGE_LEN);
642 items[index].supported_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
644 strncpy(items[index].supported_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
648 for (loop = 0;loop < MAX_WAKEUP_ENGINES_NUM;loop++) {
649 if (loop < info->cnt_wakeup_engine && info->wakeup_engine[loop]) {
650 MAS_LOGD("wakeup_engine(%s)", info->wakeup_engine[loop]);
651 strncpy(items[index].wakeup_engine[loop], info->wakeup_engine[loop], MAX_APPID_LEN);
652 items[index].wakeup_engine[loop][MAX_APPID_LEN - 1] = '\0';
654 items[index].wakeup_engine[loop][0] = '\0';
655 MAS_LOGW("Wakeup engine information not provided for : %s", info->app_id);
658 items[index].custom_ui_option = info->custom_ui_option;
660 MAS_LOGD("voice_key_support_mode(%d)", info->voice_key_support_mode);
661 items[index].voice_key_support_mode = info->voice_key_support_mode;
662 MAS_LOGD("voice_key_tap_duration(%f)", info->voice_key_tap_duration);
663 items[index].voice_key_tap_duration = info->voice_key_tap_duration;
664 MAS_LOGD("audio_processing_appid(%s)",
665 (info->audio_data_processing_appid ? (info->audio_data_processing_appid)->c_str() : "[NONE]"));
666 items[index].audio_processing_appid = info->audio_data_processing_appid;
668 MAS_LOGD("Couldn't find an empty slot for storing assistant info");
671 MAS_LOGD("__assistant_info_cb end");
676 static void active_state_changed_cb(std::string key, void* user_data)
678 IPreferenceManager* manager = static_cast<IPreferenceManager*>(user_data);
679 if (nullptr == manager) return;
681 boost::optional<bool> activated =
682 manager->get_bool(MULTI_ASSISTANT_SETTINGS_ACTIVATED);
684 MAS_LOGE("multi-assistant active state : %d\n", *activated);
686 CServicePlugin *plugin = nullptr;
687 if (g_service_main) {
688 plugin = g_service_main->get_service_plugin();
694 plugin->deactivate();
697 MAS_LOGE("Could not change plugin state : %p %p", g_service_main, plugin);
700 MAS_LOGE("Get value failed for : %s", MULTI_ASSISTANT_SETTINGS_ACTIVATED);
704 int CServiceMain::initialize_service_plugin(void)
707 if (0 != mServicePlugin.initialize()) {
708 MAS_LOGE("Fail to ws intialize");
712 if (0 != mServicePlugin.set_language(mCurrentLanguage.c_str())) {
713 MAS_LOGE("Fail to ws set language");
717 mClientInfo.resetItems();
718 mCurrentClientInfo = -1;
719 MAS_LOGI("mCurrentClientInfo : %d", mCurrentClientInfo);
720 mCurrentPreprocessingClientInfo = -1;
721 mLastWakeupInfo.wakeupAppId.clear();
722 mLastWakeupInfo.wakeupWord.clear();
723 mLastWakeupInfo.extraData.clear();
724 mLastWakeupInfo.extraDataDesc.clear();
726 if (0 == mServiceConfig.get_assistant_info(assistant_info_cb, this)) {
727 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
729 ClientInfoItems *items = mClientInfo.getItems();
730 if (0 < strlen(items[loop].appid)) {
731 mServiceConfig.load_custom_wake_words(items[loop].appid,
732 items[loop].wakeup_word, items[loop].wakeup_language);
733 for (inner_loop = 0; inner_loop < MAX_WAKEUP_ENGINES_NUM; inner_loop++) {
734 if (0 < strlen(items[loop].wakeup_engine[inner_loop])) {
735 mServicePlugin.add_assistant_wakeup_engine(
737 items[loop].wakeup_engine[inner_loop]);
740 for (inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
741 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
742 MAS_LOGD("Registering wakeup word %s for app %s",
743 items[loop].wakeup_word[inner_loop], items[loop].appid);
744 if (0 != mServicePlugin.add_assistant_wakeup_word(
746 items[loop].wakeup_word[inner_loop],
747 items[loop].wakeup_language[inner_loop])) {
748 MAS_LOGE("Fail to add assistant's wakeup word");
752 for (inner_loop = 0; inner_loop < MAX_SUPPORTED_LANGUAGES_NUM; inner_loop++) {
753 if (0 < strlen(items[loop].supported_language[inner_loop])) {
754 MAS_LOGD("Adding language %s for app %s",
755 items[loop].supported_language[inner_loop], items[loop].appid);
756 if (0 != mServicePlugin.add_assistant_language(
758 items[loop].supported_language[inner_loop])) {
759 MAS_LOGE("Fail to add assistant's language");
766 MAS_LOGE("Fail to load assistant info");
769 if (0 != mServicePlugin.set_callbacks()) {
770 MAS_LOGE("Fail to set callbacks");
777 int CServiceMain::deinitialize_service_plugin(void)
780 if (0 != mServicePlugin.deactivate()) {
781 MAS_LOGE("Fail to deactivate");
783 if (0 != mServicePlugin.deinitialize()) {
784 MAS_LOGE("Fail to deinitialize");
787 std::vector<pid_t> clients;
788 int client_num = mClientManager.get_client_num();
789 for (int loop = 0;loop < client_num;loop++) {
790 clients.push_back(mClientManager.find_client_pid_by_index(loop));
793 for (auto pid : clients) {
794 on_deinitialize(pid, mClientManager.find_sender_info_by_pid(pid));
800 int CServiceMain::process_activated_setting()
802 if (mPreferenceManager.register_changed_callback(
803 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb, &mPreferenceManager)) {
804 /* Activate / deactivate according to the vconf key setting */
805 active_state_changed_cb(std::string{}, &mPreferenceManager);
807 #ifdef ENABLE_MULTI_ASSISTANT_BY_DEFAULT
808 /* Multi-assistant needs to be enabled by default, unless disabled explicitly */
809 mServicePlugin.activate();
810 const char *default_assistant = NULL;
811 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
812 if (NULL == default_assistant) {
813 ClientInfoItems *items = mClientInfo.getItems();
815 default_assistant = items[0].appid;
816 MAS_LOGW("No default assistant, setting %s as default", default_assistant);
817 mServicePlugin.set_default_assistant(default_assistant);
819 MAS_LOGE("No default assistant, and no assistant installed");
828 int CServiceMain::get_current_client_pid()
831 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
832 ClientInfoItems *items = mClientInfo.getItems();
833 const char *appid = items[mCurrentClientInfo].appid;
835 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
841 pid_t CServiceMain::get_current_preprocessing_client_pid()
844 if (mCurrentPreprocessingClientInfo >= 0 && mCurrentPreprocessingClientInfo < MAX_MACLIENT_INFO_NUM) {
845 ClientInfoItems *items = mClientInfo.getItems();
846 const char *appid = items[mCurrentPreprocessingClientInfo].appid;
848 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
854 pid_t CServiceMain::get_current_audio_processing_pid()
857 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
858 ClientInfoItems *items = mClientInfo.getItems();
859 boost::optional<std::string> audio_processing_appid =
860 items[mCurrentClientInfo].audio_processing_appid;
861 if (audio_processing_appid) {
862 boost::optional<pid_t> audio_processing_pid;
863 audio_processing_pid = mApplicationManager.get_pid_by_appid((*audio_processing_appid).c_str());
864 if (audio_processing_pid) {
865 ret = *audio_processing_pid;
872 pid_t CServiceMain::get_client_pid_by_appid(const char *appid)
874 MAS_LOGI("Checking PID of appid : %s", appid);
878 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
881 if (-1 != ret && !mApplicationManager.is_application_running(appid)) {
882 MAS_LOGE("The PID for %s was %d, but it seems to be terminated", appid, ret);
883 on_deinitialize(ret, mClientManager.find_sender_info_by_pid(ret));
890 bool CServiceMain::get_client_custom_ui_option_by_appid(const char *appid)
893 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
894 ClientInfoItems *items = mClientInfo.getItems();
895 if (items[loop].used &&
896 0 < strlen(items[loop].appid) &&
897 0 < strlen(items[loop].wakeup_word[0])) {
898 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
899 ret = items[loop].custom_ui_option;
906 int CServiceMain::get_client_pid_by_wakeup_word(const char *wakeup_word)
908 const char *appid = get_client_appid_by_wakeup_word(wakeup_word);
909 return get_client_pid_by_appid(appid);
912 const char* CServiceMain::get_client_appid_by_wakeup_word(const char *wakeup_word)
915 const char *appid = NULL;
917 if (NULL == wakeup_word) return NULL;
919 ClientInfoItems *items = mClientInfo.getItems();
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 if (0 == strncmp(wakeup_word, items[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
926 appid = items[loop].appid;
933 /* Perform extended search, by eliminating blank characters */
935 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
936 if (items[loop].used &&
937 0 < strlen(items[loop].appid)) {
938 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
939 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
940 char comparand[MAX_WAKEUP_WORD_LEN];
941 int comparand_index = 0;
942 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
943 if (' ' != items[loop].wakeup_word[inner_loop][index]) {
944 comparand[comparand_index++] = items[loop].wakeup_word[inner_loop][index];
947 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
948 appid = items[loop].appid;
959 int CServiceMain::set_current_client_by_wakeup_word(const char *wakeup_word)
961 LOGI("[ENTER] %s", wakeup_word);
965 int prev_selection = mCurrentClientInfo;
967 ClientInfoItems *items = mClientInfo.getItems();
968 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
969 if (items[loop].used &&
970 0 < strlen(items[loop].appid)) {
971 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
972 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
973 if (0 == strncmp(wakeup_word, items[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
974 mCurrentClientInfo = loop;
975 MAS_LOGE("mCurrentClientInfo : %d %s", mCurrentClientInfo, wakeup_word);
982 /* Perform extended search, by eliminating blank characters */
984 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
985 if (items[loop].used &&
986 0 < strlen(items[loop].appid)) {
987 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
988 if (0 < strlen(items[loop].wakeup_word[inner_loop])) {
989 char comparand[MAX_WAKEUP_WORD_LEN];
990 int comparand_index = 0;
991 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
992 if (' ' != items[loop].wakeup_word[inner_loop][index]) {
993 comparand[comparand_index++] = items[loop].wakeup_word[inner_loop][index];
996 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
997 mCurrentClientInfo = loop;
998 MAS_LOGE("mCurrentClientInfo : %d %s", mCurrentClientInfo, wakeup_word);
1007 if (mCurrentClientInfo != prev_selection) {
1008 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
1009 pid_t pid = get_client_pid_by_appid(items[prev_selection].appid);
1010 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_INACTIVE, nullptr, nullptr, 0, nullptr);
1011 if (mLastDuckingRequester == pid) {
1012 MAS_LOGE("Last ducking requester is deactivated, resetting background volume");
1013 mServicePlugin.set_background_volume(items[prev_selection].appid, 1.0f);
1014 mLastDuckingRequester = -1;
1022 int CServiceMain::set_current_client_by_appid(const char *appid)
1024 LOGI("[ENTER] %s", appid);
1027 int prev_selection = mCurrentClientInfo;
1029 ClientInfoItems *items = mClientInfo.getItems();
1030 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1031 if (items[loop].used &&
1032 0 < strlen(items[loop].appid) &&
1033 0 < strlen(items[loop].wakeup_word[0])) {
1034 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
1035 MAS_LOGE("mCurrentClientInfo : %d %s", mCurrentClientInfo, appid);
1036 mCurrentClientInfo = loop;
1042 if (mCurrentClientInfo != prev_selection) {
1043 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
1044 pid_t pid = get_client_pid_by_appid(items[prev_selection].appid);
1045 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_INACTIVE, nullptr, nullptr, 0, nullptr);
1046 if (mLastDuckingRequester == pid) {
1047 MAS_LOGE("Last ducking requester is deactivated, resetting background volume");
1048 mServicePlugin.set_background_volume(items[prev_selection].appid, 1.0f);
1049 mLastDuckingRequester = -1;
1057 int CServiceMain::launch_client_by_appid(const char *appid, const char *word,
1058 const unsigned char* extra_data, size_t extra_data_length, const char *extra_data_desc,
1059 CLIENT_LAUNCH_MODE launch_mode)
1061 LOGI("[ENTER] %s %s", appid, word);
1064 if (NULL == appid || 0 == strlen(appid)) {
1065 MAS_LOGE("appid invalid, failed launching MA Client");
1069 if (CLIENT_LAUNCH_MODE_PRELAUNCH == launch_mode) {
1070 if (mApplicationManager.is_application_running(appid)) {
1071 MAS_LOGE("appid %s is already running, no need for a prelaunch", appid);
1075 result = mApplicationManager.launch_app_async(appid, true);
1077 result = mApplicationManager.launch_app_async(appid, false);
1080 if (CLIENT_LAUNCH_MODE_ACTIVATION == launch_mode) {
1082 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1083 ClientInfoItems *items = mClientInfo.getItems();
1084 if (items[loop].used &&
1085 0 < strlen(items[loop].appid)) {
1086 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
1087 mLastWakeupInfo.wakeupAppId = items[loop].appid;
1088 mLastWakeupInfo.wakeupWord = (word ? word : "");
1089 if (extra_data && extra_data_length > 0) {
1090 mLastWakeupInfo.extraData.assign(extra_data, extra_data + extra_data_length);
1092 mLastWakeupInfo.extraData.clear();
1094 mLastWakeupInfo.extraDataDesc = (extra_data_desc ? extra_data_desc : "");
1099 MAS_LOGE("mLastWakeupInfo.wakeupAppId : %s %s %p %zu %s, %d",
1100 mLastWakeupInfo.wakeupAppId.c_str(), mLastWakeupInfo.wakeupWord.c_str(),
1101 mLastWakeupInfo.extraData.data(), mLastWakeupInfo.extraData.size(),
1102 mLastWakeupInfo.extraDataDesc.c_str(), found);
1108 int CServiceMain::bring_client_to_foreground(const char* appid)
1113 if (NULL == appid || 0 == strlen(appid)) {
1114 MAS_LOGE("appid invalid, failed launching MA Client");
1118 if (!mApplicationManager.bring_app_to_foreground(appid)) {
1125 int CServiceMain::launch_client_by_wakeup_word(const char *wakeup_word,
1126 const unsigned char* extra_data, size_t extra_data_length, const char *extra_data_desc)
1128 const char *appid = get_client_appid_by_wakeup_word(wakeup_word);
1129 return launch_client_by_appid(appid, wakeup_word,
1130 extra_data, extra_data_length, extra_data_desc, CLIENT_LAUNCH_MODE_ACTIVATION);
1133 int CServiceMain::prelaunch_default_assistant()
1136 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
1137 boost::optional<bool> prelaunch_mode =
1138 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PRELAUNCH_MODE);
1139 if (prelaunch_mode && *prelaunch_mode) {
1140 const char *default_assistant = NULL;
1141 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
1142 if (default_assistant &&
1143 !(mApplicationManager.is_application_running(default_assistant))) {
1144 MAS_LOGD("prelaunching default_assistant_appid : %s", default_assistant);
1145 launch_client_by_appid(default_assistant, nullptr, nullptr, 0, nullptr, CLIENT_LAUNCH_MODE_PRELAUNCH);
1152 int CServiceMain::update_voice_key_support_mode()
1155 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
1156 bool successful = false;
1157 const char *default_assistant = NULL;
1158 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
1159 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1160 ClientInfoItems *items = mClientInfo.getItems();
1161 if (items[loop].used) {
1162 LOGI("APPID : %s", items[loop].appid);
1163 if (default_assistant &&
1164 strncmp(default_assistant, items[loop].appid, MAX_APPID_LEN) == 0) {
1165 float duration = items[loop].voice_key_tap_duration;
1166 if (0.0f < duration) {
1167 mServicePlugin.set_voice_key_tap_duration(duration);
1169 mServicePlugin.unset_voice_key_tap_duration();
1171 mServicePlugin.set_voice_key_support_mode(
1172 items[loop].voice_key_support_mode);
1180 LOGE("VOICE KEY SUPPORT MODE update not successful!!!");
1181 mServicePlugin.unset_voice_key_tap_duration();
1182 mServicePlugin.set_voice_key_support_mode(VOICE_KEY_SUPPORT_MODE_NONE);
1187 ma_preprocessing_allow_mode_e CServiceMain::get_preprocessing_allow_mode(const char* appid)
1189 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1190 ClientInfoItems *items = mClientInfo.getItems();
1191 if (appid && items[loop].used) {
1192 if (strncmp(appid, items[loop].appid, MAX_APPID_LEN) == 0) {
1193 return items[loop].preprocessing_allow_mode;
1197 return MA_PREPROCESSING_ALLOW_NONE;
1200 /* This might need to be read from settings in the future, but using macro for now */
1201 //#define BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1203 int CServiceMain::process_preprocessing_state_event(PREPROCESSING_STATE_EVENT event)
1205 const char* current_maclient_appid = NULL;
1206 const char* preprocessing_allow_appid = NULL;
1207 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1208 ClientInfoItems *items = mClientInfo.getItems();
1209 current_maclient_appid = items[mCurrentClientInfo].appid;
1210 preprocessing_allow_appid = items[mCurrentClientInfo].preprocessing_allow_appid;
1212 ma_preprocessing_allow_mode_e mode = get_preprocessing_allow_mode(current_maclient_appid);
1215 case PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED:
1217 #ifndef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1218 /* If there is no need to bring preprocessing assistant to front,
1219 current_maclient should always be brought to front */
1220 bring_client_to_foreground(current_maclient_appid);
1222 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1223 if (check_preprocessing_assistant_exists()) {
1224 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1225 MA_PREPROCESSING_ALLOW_ALL == mode) {
1226 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1227 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1231 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1232 /* If preprocessing assistant does not exist, there is no way to enable
1233 preprocessing assistant, so bring current maclient to front right away */
1234 bring_client_to_foreground(current_maclient_appid);
1239 case PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED:
1241 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1242 /* Enable preprocessing mode only if the preprocessing assistant exists */
1243 if (check_preprocessing_assistant_exists()) {
1244 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1245 MA_PREPROCESSING_ALLOW_ALL == mode) {
1246 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1247 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1253 case PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED:
1255 if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED == mCurrentPreprocessingState) {
1256 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_UTTERANCE;
1257 } else if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED == mCurrentPreprocessingState) {
1258 /* If preprocessing assistant does not exist, the current_maclient
1259 would have been brought to front already on wakeup event */
1260 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1261 if (check_preprocessing_assistant_exists()) {
1262 bring_client_to_foreground(current_maclient_appid);
1265 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1269 case PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED:
1271 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1272 if (check_preprocessing_assistant_exists()) {
1273 if (MA_PREPROCESSING_ALLOW_FOLLOW_UP == mode ||
1274 MA_PREPROCESSING_ALLOW_ALL == mode) {
1275 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_FOLLOW_UP;
1280 case PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED:
1282 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1283 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1284 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1285 boost::optional<std::string> preprocessing_assistant =
1286 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1287 if (preprocessing_assistant) {
1288 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1289 bring_client_to_foreground((*preprocessing_assistant).c_str());
1293 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1296 case PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED:
1298 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1299 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1300 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1301 bring_client_to_foreground(current_maclient_appid);
1304 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1311 int CServiceMain::set_current_service_state(ma_service_state_e state)
1313 mCurrentServiceState = state;
1315 int count = mClientManager.get_client_num();
1318 for (i = 0; i < count; i++) {
1319 pid_t pid = mClientManager.find_client_pid_by_index(i);
1322 int ret = mServiceIpc.change_service_state(pid, state);
1324 MAS_LOGE("[ERROR] Fail to set service state change to %d, ret(%d)", pid, ret);
1331 ma_service_state_e CServiceMain::get_current_service_state()
1333 return mCurrentServiceState;
1336 bool CServiceMain::is_valid_wakeup_engine(const char* appid)
1338 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM;loop++) {
1339 ClientInfoItems *items = mClientInfo.getItems();
1340 if (items[loop].used) {
1341 for (int inner_loop = 0;inner_loop < MAX_WAKEUP_ENGINES_NUM;inner_loop++) {
1342 LOGD("comparing appid : %s %s", items[loop].wakeup_engine[inner_loop], appid);
1343 if (0 == strncmp(items[loop].wakeup_engine[inner_loop], appid, MAX_APPID_LEN)) {
1352 bool CServiceMain::app_create(void *data)
1354 // Todo: add your code here.
1355 MAS_LOGE("[ENTER] Service app create");
1357 g_service_main = this;
1359 mClientManager.set_application_manager(&mApplicationManager);
1361 mServiceIpc.set_client_manager(&mClientManager);
1362 mServiceIpc.set_application_manager(&mApplicationManager);
1363 mServiceIpc.set_service_ipc_observer(this);
1365 mServicePlugin.set_service_ipc(&mServiceIpc);
1366 mServicePlugin.set_service_main(this);
1368 const int retry_interval = 5;
1369 const int max_retry_count = 5;
1370 int retry_count = 0;
1373 ret = mServiceIpc.open_connection();
1375 sleep(retry_interval);
1376 MAS_LOGE("[ERROR] Fail to open connection, Retrying : %d", retry_count);
1378 } while (0 != ret && retry_count++ < max_retry_count);
1380 if (retry_count >= max_retry_count) {
1381 MAS_LOGE("[ERROR] Maximum retry count reached, restarting...");
1386 initialize_service_plugin();
1388 process_activated_setting();
1390 prelaunch_default_assistant();
1391 update_voice_key_support_mode();
1393 /* For the case of preprocessing assistant, it always have to be launched beforehand */
1394 boost::optional<std::string> preprocessing_assistant =
1395 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1396 if (preprocessing_assistant) {
1397 MAS_LOGD("prelaunching preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1398 launch_client_by_appid((*preprocessing_assistant).c_str(), nullptr,
1399 nullptr, 0, nullptr, CLIENT_LAUNCH_MODE_PRELAUNCH);
1402 mPackageUpdateMonitor.initialize();
1404 MAS_LOGE("[END] Service app create");
1408 void CServiceMain::app_terminate(void *data)
1410 MAS_LOGE("[ENTER]");
1412 mPackageUpdateMonitor.deinitialize();
1414 deinitialize_service_plugin();
1416 mPreferenceManager.unregister_changed_callback(
1417 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb);
1419 int ret = mServiceIpc.close_connection();
1421 MAS_LOGE("[ERROR] Fail to close connection");
1424 g_service_main = nullptr;
1430 void CServiceMain::app_restart()
1435 int CServiceMain::on_initialize(pid_t pid, std::string sender_info) {
1436 MAS_LOGD("[Enter] pid(%d)", pid);
1438 std::string pid_appid;
1439 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
1441 pid_appid = *appid_by_pid;
1442 MAS_LOGD("appid for pid %d is : %s (%s)", pid, pid_appid.c_str(), sender_info.c_str());
1444 /* Remove existing client that has same appid, if there's any */
1445 mClientManager.destroy_client_by_appid(pid_appid.c_str());
1447 /* And remove a client that has same pid also */
1448 mClientManager.destroy_client_by_pid(pid);
1450 mClientManager.create_client(pid, pid_appid, sender_info);
1452 const char *current_maclient_appid = NULL;
1453 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1454 ClientInfoItems *items = mClientInfo.getItems();
1455 current_maclient_appid = items[mCurrentClientInfo].appid;
1458 client_send_preprocessing_information(pid);
1459 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
1460 client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
1462 if (current_maclient_appid && 0 == pid_appid.compare(current_maclient_appid)) {
1463 MAS_LOGD("MA client with current maclient appid connected!");
1465 if (0 == mLastWakeupInfo.wakeupAppId.compare(pid_appid)) {
1466 mServiceIpc.change_active_state(pid, MA_ACTIVE_STATE_ACTIVE,
1467 mLastWakeupInfo.wakeupWord.c_str(),
1468 mLastWakeupInfo.extraData.data(),
1469 mLastWakeupInfo.extraData.size(),
1470 mLastWakeupInfo.extraDataDesc.c_str());
1471 process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED);
1472 mLastWakeupInfo.wakeupAppId.clear();
1473 mLastWakeupInfo.wakeupWord.clear();
1474 mLastWakeupInfo.extraData.clear();
1475 mLastWakeupInfo.extraDataDesc.clear();
1477 MAS_LOGE("[ERROR] mLastWakeupInfo.wakeupAppId and appid differ : %s %s",
1478 mLastWakeupInfo.wakeupAppId.c_str(), pid_appid.c_str());
1481 MAS_LOGD("MA client connected, but its appid does not match with current maclient");
1484 mServiceIpc.change_service_state(pid, get_current_service_state());
1486 MAS_LOGE("[ERROR] Fail to retrieve appid");
1492 int CServiceMain::on_deinitialize(pid_t pid, std::string sender_info) {
1493 MAS_LOGD("[Enter] pid(%d)", pid);
1494 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1497 if (mLastDuckingRequester == pid) {
1498 MAS_LOGE("Last ducking requester has disconnected, resetting background volume");
1499 std::string pid_appid = mClientManager.find_client_appid_by_pid( pid);
1500 mServicePlugin.set_background_volume(pid_appid.c_str(), 1.0f);
1501 mLastDuckingRequester = -1;
1504 mClientManager.destroy_client_by_pid(pid);
1509 int CServiceMain::on_get_audio_format(pid_t pid, int& rate, int& channel, int& audio_type, std::string sender_info) {
1510 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1513 int main_rate, main_channel, main_audio_type;
1514 int ret = client_get_audio_format(pid,
1515 &main_rate, &main_channel, &main_audio_type);
1517 channel = main_channel;
1518 audio_type = main_audio_type;
1522 int CServiceMain::on_get_audio_source_type(pid_t pid, std::string& type, std::string sender_info) {
1523 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1526 char *main_type = nullptr;
1527 int ret = client_get_audio_source_type(pid, &main_type);
1528 if (0 == ret && main_type) {
1529 type = std::string{main_type};
1534 int CServiceMain::on_send_asr_result(pid_t pid, int event, std::string asr_result, std::string sender_info) {
1535 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1538 return client_send_asr_result(pid, event, asr_result.c_str());
1541 int CServiceMain::on_send_result(pid_t pid, std::string display_text,
1542 std::string utterance_text, std::string result_json, std::string sender_info) {
1543 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1546 return client_send_result(pid,
1547 display_text.c_str(), utterance_text.c_str(), result_json.c_str());
1550 int CServiceMain::on_send_recognition_result(pid_t pid, int result, std::string sender_info) {
1551 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1554 return client_send_recognition_result(pid, result);
1557 int CServiceMain::on_start_streaming_audio_data(pid_t pid, int type, std::string sender_info) {
1558 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1561 return client_start_streaming_audio_data(pid, type);
1564 int CServiceMain::on_stop_streaming_audio_data(pid_t pid, int type, std::string sender_info) {
1565 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1568 return client_stop_streaming_audio_data(pid, type);
1571 int CServiceMain::on_update_voice_feedback_state(pid_t pid, int state, std::string sender_info) {
1572 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1575 return client_update_voice_feedback_state(pid, state);
1578 int CServiceMain::on_send_assistant_specific_command(pid_t pid, std::string command, std::string sender_info) {
1579 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1582 return client_set_assistant_specific_command(pid, command.c_str());
1585 int CServiceMain::on_set_background_volume(pid_t pid, double ratio, std::string sender_info) {
1586 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1589 return client_set_background_volume(pid, ratio);
1592 int CServiceMain::on_set_preprocessing_allow_mode(pid_t pid, int mode, std::string app_id, std::string sender_info) {
1593 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1596 return client_set_preprocessing_allow_mode(pid,
1597 static_cast<ma_preprocessing_allow_mode_e>(mode), app_id.c_str());
1600 int CServiceMain::on_send_preprocessing_result(pid_t pid, int result, std::string sender_info) {
1601 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1604 return client_send_preprocessing_result(pid, result);
1607 int CServiceMain::on_set_wake_word_audio_require_flag(pid_t pid, int require, std::string sender_info) {
1608 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1611 return client_set_wake_word_audio_require_flag(pid, require);
1614 int CServiceMain::on_set_assistant_language(pid_t pid, std::string language, std::string sender_info) {
1615 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1618 return client_set_assistant_language(pid, language.c_str());
1621 int CServiceMain::on_add_wake_word(pid_t pid, std::string wake_word, std::string language, std::string sender_info) {
1622 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1625 return client_add_wake_word(pid, wake_word.c_str(), language.c_str());
1628 int CServiceMain::on_remove_wake_word(pid_t pid, std::string wake_word, std::string language, std::string sender_info) {
1629 if (!mClientManager.check_sender_info_by_pid(pid, sender_info)) {
1632 return client_remove_wake_word(pid, wake_word.c_str(), language.c_str());
1635 int CServiceMain::on_ui_initialize(pid_t pid)
1637 return ui_client_initialize(pid);
1640 int CServiceMain::on_ui_deinitialize(pid_t pid)
1642 return ui_client_deinitialize(pid);
1645 int CServiceMain::on_ui_change_assistant(std::string app_id)
1647 return ui_client_change_assistant(app_id.c_str());