2 * Copyright 2018-2019 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>
24 #include <pkgmgr-info.h>
31 #include "service_common.h"
32 #include "service_main.h"
33 #include "service_plugin.h"
34 #include "service_ipc_dbus.h"
35 #include "service_config.h"
37 static CServiceMain* g_service_main = nullptr;
39 bool CServiceMain::check_preprocessing_assistant_exists()
43 boost::optional<std::string> preprocessing_appid =
44 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
45 if (preprocessing_appid) {
46 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
47 if (mClientInfo[loop].used &&
48 strncmp((*preprocessing_appid).c_str(), mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
49 if (mClientManager.check_client_validity_by_appid(*preprocessing_appid)) {
56 MAS_LOGD("result : %d", ret);
61 bool CServiceMain::is_current_preprocessing_assistant(const char* appid)
63 if (NULL == appid) return false;
67 boost::optional<std::string> preprocessing_appid =
68 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
69 if (preprocessing_appid) {
70 if (strncmp((*preprocessing_appid).c_str(), appid, MAX_APPID_LEN) == 0) {
78 int CServiceMain::mas_client_get_audio_format(int pid, int* rate, int* channel, int* audio_type)
80 MAS_LOGD("[Enter] pid(%d)", pid);
82 int ret = mServicePlugin.get_recording_audio_format(rate, channel, audio_type);
84 MAS_LOGE("[ERROR] Fail to get recording audio format, ret(%d)", ret);
90 #define MAX_LOCAL_VARIABLE_STRING_LEN 256
91 int CServiceMain::mas_client_get_audio_source_type(int pid, char** type)
93 MAS_LOGD("[Enter] pid(%d)", pid);
95 if (NULL == type) return -1;
97 static char cached[MAX_LOCAL_VARIABLE_STRING_LEN] = {'\0'};
98 int ret = mServicePlugin.get_recording_audio_source_type(type);
100 MAS_LOGE("[ERROR] Fail to get recording audio source type, ret(%d)", ret);
103 strncpy(cached, *type, MAX_LOCAL_VARIABLE_STRING_LEN - 1);
104 cached[MAX_LOCAL_VARIABLE_STRING_LEN - 1] = '\0';
110 int CServiceMain::mas_client_send_preprocessing_information(int pid)
113 MAS_LOGD("[Enter] pid(%d)", pid);
115 boost::optional<std::string> preprocessing_appid =
116 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
117 if (preprocessing_appid) {
118 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_appid).c_str());
119 ret = mServiceIpc.send_preprocessing_information(pid, (*preprocessing_appid).c_str());
125 int CServiceMain::mas_client_send_voice_key_status_change(int pid, ma_voice_key_status_e status)
128 MAS_LOGD("[Enter] pid(%d)", pid);
130 ret = mServiceIpc.voice_key_status_change(pid, status);
132 MAS_LOGE("[ERROR] Fail to send voice key status changed information, ret(%d)", ret);
134 mLastVoiceKeyStatus = status;
139 int CServiceMain::mas_client_send_asr_result(int pid, int event, const char* asr_result)
141 MAS_LOGD("[Enter] pid(%d), event(%d), asr_result(%s)", pid, event, asr_result);
142 int ret = mServiceIpc.masc_ui_dbus_send_asr_result(pid, event, asr_result);
144 MAS_LOGE("[ERROR] Fail to send asr result, ret(%d)", ret);
147 // if final event is , launch assistant app which is invoked with wakeup word.
152 int CServiceMain::mas_client_send_result(int pid, const char* display_text,
153 const char* utterance_text, const char* result_json)
155 MAS_LOGD("[Enter] pid(%d), display_text(%s), utterance_text(%s), result_json(%s)", pid, display_text, utterance_text, result_json);
156 int ret = mServiceIpc.masc_ui_dbus_send_result(pid, display_text, utterance_text, result_json);
158 MAS_LOGE("[ERROR] Fail to send result, ret(%d)", ret);
161 std::string pid_appid;
162 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
164 pid_appid = *appid_by_pid;
166 mServicePlugin.update_recognition_result(pid_appid.c_str(), MA_RECOGNITION_RESULT_EVENT_SUCCESS);
171 int CServiceMain::mas_client_send_recognition_result(int pid, int result)
173 MAS_LOGD("[Enter] pid(%d), result(%d)", pid, result);
174 int ret = mServiceIpc.masc_ui_dbus_send_recognition_result(pid, result);
176 MAS_LOGE("[ERROR] Fail to send recognition result, ret(%d)", ret);
179 std::string pid_appid;
180 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
182 pid_appid = *appid_by_pid;
184 mServicePlugin.update_recognition_result(pid_appid.c_str(), result);
189 int CServiceMain::mas_client_start_streaming_audio_data(int pid, int type)
193 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
194 ret = mServicePlugin.start_streaming_utterance_data();
195 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED);
197 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
198 ret = mServicePlugin.start_streaming_previous_utterance_data();
199 /* Preprocessing is not required for previous utterance streaming */
201 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
202 ret = mServicePlugin.start_streaming_follow_up_data();
203 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED);
209 int CServiceMain::mas_client_stop_streaming_audio_data(int pid, int type)
213 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
214 ret = mServicePlugin.stop_streaming_utterance_data();
216 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
217 ret = mServicePlugin.stop_streaming_previous_utterance_data();
219 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
220 ret = mServicePlugin.stop_streaming_follow_up_data();
226 int CServiceMain::mas_client_update_voice_feedback_state(int pid, int state)
228 std::string pid_appid;
229 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
231 pid_appid = *appid_by_pid;
233 mServicePlugin.update_voice_feedback_state(pid_appid.c_str(), state);
237 int CServiceMain::mas_client_set_assistant_specific_command(int pid, const char *command)
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.set_assistant_specific_command(pid_appid.c_str(), command);
248 int CServiceMain::mas_client_set_background_volume(int pid, double ratio)
250 std::string pid_appid;
251 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
253 pid_appid = *appid_by_pid;
255 mServicePlugin.set_background_volume(pid_appid.c_str(), ratio);
259 int CServiceMain::mas_client_set_preprocessing_allow_mode(int pid, ma_preprocessing_allow_mode_e mode, const char* appid)
261 std::string pid_appid;
262 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
264 pid_appid = *appid_by_pid;
267 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
268 if (mClientInfo[loop].used) {
269 if (0 == pid_appid.compare(mClientInfo[loop].appid)) {
270 mClientInfo[loop].preprocessing_allow_mode = mode;
272 strncpy(mClientInfo[loop].preprocessing_allow_appid, appid, MAX_APPID_LEN);
273 mClientInfo[loop].preprocessing_allow_appid[MAX_APPID_LEN - 1] = '\0';
275 mClientInfo[loop].preprocessing_allow_appid[0] = '\0';
281 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED);
286 int CServiceMain::mas_client_send_preprocessing_result(int pid, bool result)
288 std::string pid_appid;
289 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
291 pid_appid = *appid_by_pid;
293 if (!is_current_preprocessing_assistant(pid_appid.c_str())) return -1;
295 const char *current_maclient_appid = NULL;
296 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
297 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
301 MAS_LOGD("Preprocessing succeeded, bring (%s) to foreground", pid_appid.c_str());
302 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED);
304 MAS_LOGD("Preprocessing failed, bring (%s) to foreground", current_maclient_appid);
305 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED);
308 if (current_maclient_appid) {
309 int pid = mClientManager.find_client_pid_by_appid(
310 std::string{current_maclient_appid});
311 mServiceIpc.send_preprocessing_result(pid, result);
317 int CServiceMain::mas_client_set_wake_word_audio_require_flag(int pid, bool require)
319 std::string pid_appid;
320 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
322 pid_appid = *appid_by_pid;
325 mServicePlugin.set_wake_word_audio_require_flag(pid_appid.c_str(), require);
329 int CServiceMain::mas_client_set_assistant_language(int pid, const char* language)
331 std::string pid_appid;
332 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
334 pid_appid = *appid_by_pid;
337 mServicePlugin.set_assistant_language(pid_appid.c_str(), language);
341 int CServiceMain::mas_client_add_wake_word(int pid, const char* wake_word, const char* language)
343 std::string pid_appid;
344 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
346 pid_appid = *appid_by_pid;
349 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
350 if (mClientInfo[loop].used &&
351 0 == pid_appid.compare(mClientInfo[loop].appid)) {
352 int ret = mServiceConfig.add_custom_wake_word(wake_word, language,
353 mClientInfo[loop].wakeup_word,
354 mClientInfo[loop].wakeup_language);
356 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
357 mClientInfo[loop].wakeup_word,
358 mClientInfo[loop].wakeup_language);
360 LOGE("add new wake word failed!");
366 mServicePlugin.add_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
370 int CServiceMain::mas_client_remove_wake_word(int pid, const char* wake_word, const char* language)
372 std::string pid_appid;
373 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
375 pid_appid = *appid_by_pid;
378 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
379 if (mClientInfo[loop].used &&
380 0 == pid_appid.compare(mClientInfo[loop].appid)) {
381 int ret = mServiceConfig.remove_custom_wake_word(wake_word, language,
382 mClientInfo[loop].wakeup_word,
383 mClientInfo[loop].wakeup_language);
385 mServiceConfig.save_custom_wake_words(pid_appid.c_str(),
386 mClientInfo[loop].wakeup_word,
387 mClientInfo[loop].wakeup_language);
392 mServicePlugin.remove_assistant_wakeup_word(pid_appid.c_str(), wake_word, language);
396 int CServiceMain::mas_ui_client_initialize(int pid)
398 MAS_LOGD("[Enter] pid(%d)", pid);
403 int CServiceMain::mas_ui_client_deinitialize(int pid)
405 MAS_LOGD("[Enter] pid(%d)", pid);
410 int CServiceMain::mas_ui_client_change_assistant(const char* appid)
415 MAS_LOGE("NULL parameter");
419 bool use_custom_ui = mas_get_client_custom_ui_option_by_appid(appid);
420 mServiceIpc.masc_ui_dbus_enable_common_ui(!use_custom_ui);
422 mas_set_current_client_by_appid(appid);
423 int pid = mas_get_client_pid_by_appid(appid);
425 mas_bring_client_to_foreground(appid);
426 mas_client_send_preprocessing_information(pid);
427 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
428 mas_client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
431 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_ACTIVE);
432 MAS_LOGD("MA Client with appid %s exists, requesting speech data", (appid ? appid : "NULL"));
434 int ret = mServicePlugin.start_streaming_utterance_data();
436 MAS_LOGE("[ERROR] Fail to start streaming utterance data(%d)", ret);
440 // Appropriate MA Client not available, trying to launch new one
441 MAS_LOGD("MA Client with appid %s does not exist, launching client", (appid ? appid : "NULL"));
443 /* The appid parameter might not exist after this function call, so we use appid string in our mClientInfo */
444 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
445 if (mClientInfo[loop].used &&
446 0 < strlen(mClientInfo[loop].appid) &&
447 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
448 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
449 mas_launch_client_by_appid(mClientInfo[loop].appid, CLIENT_LAUNCH_MODE_ACTIVATION);
458 static int mas_assistant_info_cb(ma_assistant_info_s* info, void* user_data) {
460 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
462 ret = service_main->add_assistant_info(info);
467 int CServiceMain::add_assistant_info(ma_assistant_info_s* info) {
468 MAS_LOGD("__mas_assistant_info_cb called");
471 MAS_LOGE("info NULL, returning");
474 if (NULL == info->app_id) {
475 MAS_LOGE("app_id NULL, returning");
481 while(-1 == index && loop < MAX_MACLIENT_INFO_NUM) {
482 if (false == mClientInfo[loop].used) {
488 mClientInfo[index].used = true;
489 mClientInfo[index].preprocessing_allow_mode = MA_PREPROCESSING_ALLOW_NONE;
490 mClientInfo[index].preprocessing_allow_appid[0] = '\0';
491 MAS_LOGD("app_id(%s)", info->app_id);
492 strncpy(mClientInfo[index].appid, info->app_id, MAX_APPID_LEN);
493 mClientInfo[index].appid[MAX_APPID_LEN - 1] = '\0';
495 if (is_current_preprocessing_assistant(mClientInfo[index].appid)) {
496 mCurrentPreprocessingClientInfo = index;
499 for (loop = 0;loop < MAX_WAKEUP_WORDS_NUM;loop++) {
500 if (loop < info->cnt_wakeup && info->wakeup_list[loop]) {
501 MAS_LOGD("wakeup_list(%d)(%s)(%s)", loop, info->wakeup_list[loop], info->wakeup_language[loop]);
502 strncpy(mClientInfo[index].wakeup_word[loop], info->wakeup_list[loop], MAX_WAKEUP_WORD_LEN);
503 mClientInfo[index].wakeup_word[loop][MAX_WAKEUP_WORD_LEN - 1] = '\0';
504 if (info->wakeup_language[loop]) {
505 strncpy(mClientInfo[index].wakeup_language[loop], info->wakeup_language[loop], MAX_SUPPORTED_LANGUAGE_LEN);
506 mClientInfo[index].wakeup_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
508 strncpy(mClientInfo[index].wakeup_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
511 strncpy(mClientInfo[index].wakeup_word[loop], "", MAX_WAKEUP_WORD_LEN);
515 for (loop = 0;loop < MAX_SUPPORTED_LANGUAGES_NUM;loop++) {
516 if (loop < info->cnt_lang && info->supported_lang[loop]) {
517 MAS_LOGD("supported_lang(%d)(%s)", loop, info->supported_lang[loop]);
518 strncpy(mClientInfo[index].supported_language[loop], info->supported_lang[loop], MAX_SUPPORTED_LANGUAGE_LEN);
519 mClientInfo[index].supported_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
521 strncpy(mClientInfo[index].supported_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
525 MAS_LOGD("wakeup_engine(%s)", info->wakeup_engine);
526 if (info->wakeup_engine) {
527 strncpy(mClientInfo[index].wakeup_engine, info->wakeup_engine, MAX_APPID_LEN);
528 mClientInfo[index].wakeup_engine[MAX_APPID_LEN - 1] = '\0';
530 mClientInfo[index].wakeup_engine[0] = '\0';
531 MAS_LOGW("Wakeup engine information not provided for : %s", info->app_id);
533 mClientInfo[index].custom_ui_option = info->custom_ui_option;
535 MAS_LOGD("voice_key_support_mode(%d)", info->voice_key_support_mode);
536 mClientInfo[index].voice_key_support_mode = info->voice_key_support_mode;
537 MAS_LOGD("voice_key_tap_duration(%f)", info->voice_key_tap_duration);
538 mClientInfo[index].voice_key_tap_duration = info->voice_key_tap_duration;
540 MAS_LOGD("Couldn't find an empty slot for storing assistant info");
543 MAS_LOGD("__mas_assistant_info_cb end");
548 static void active_state_changed_cb(std::string key, void* user_data)
550 IPreferenceManager* manager = static_cast<IPreferenceManager*>(user_data);
551 if (nullptr == manager) return;
553 boost::optional<bool> activated =
554 manager->get_bool(MULTI_ASSISTANT_SETTINGS_ACTIVATED);
556 MAS_LOGD("multi-assistant active state : %d\n", *activated);
558 CServicePlugin *plugin = nullptr;
559 if (g_service_main) {
560 plugin = g_service_main->get_service_plugin();
566 plugin->deactivate();
569 MAS_LOGE("Could not change plugin state : %p %p", g_service_main, plugin);
574 int CServiceMain::initialize_service_plugin(void)
576 if (0 != mServicePlugin.initialize()) {
577 MAS_LOGE("Fail to ws intialize");
581 if (0 != mServicePlugin.set_language(mCurrentLanguage.c_str())) {
582 MAS_LOGE("Fail to ws set language");
586 if (0 == mServiceConfig.get_assistant_info(mas_assistant_info_cb, this)) {
587 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
589 if (mClientInfo[loop].used &&
590 0 < strlen(mClientInfo[loop].appid)) {
591 mServiceConfig.load_custom_wake_words(mClientInfo[loop].appid,
592 mClientInfo[loop].wakeup_word, mClientInfo[loop].wakeup_language);
593 if (0 < strlen(mClientInfo[loop].wakeup_engine)) {
594 mServicePlugin.set_assistant_wakeup_engine(
595 mClientInfo[loop].appid,
596 mClientInfo[loop].wakeup_engine);
598 for (inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
599 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
600 MAS_LOGD("Registering wakeup word %s for app %s",
601 mClientInfo[loop].wakeup_word[inner_loop], mClientInfo[loop].appid);
602 if (0 != mServicePlugin.add_assistant_wakeup_word(
603 mClientInfo[loop].appid,
604 mClientInfo[loop].wakeup_word[inner_loop],
605 mClientInfo[loop].wakeup_language[inner_loop])) {
606 MAS_LOGE("Fail to add assistant's wakeup word");
610 for (inner_loop = 0; inner_loop < MAX_SUPPORTED_LANGUAGE_NUM; inner_loop++) {
611 if (0 < strlen(mClientInfo[loop].supported_language[inner_loop])) {
612 MAS_LOGD("Adding language %s for app %s",
613 mClientInfo[loop].supported_language[inner_loop], mClientInfo[loop].appid);
614 if (0 != mServicePlugin.add_assistant_language(
615 mClientInfo[loop].appid,
616 mClientInfo[loop].supported_language[inner_loop])) {
617 MAS_LOGE("Fail to add assistant's language");
624 MAS_LOGE("Fail to load assistant info");
627 if (0 != mServicePlugin.set_callbacks()) {
628 MAS_LOGE("Fail to set callbacks");
635 int CServiceMain::deinitialize_service_plugin(void)
638 if (0 != mServicePlugin.deactivate()) {
639 MAS_LOGE("Fail to deactivate");
641 if (0 != mServicePlugin.deinitialize()) {
642 MAS_LOGE("Fail to deinitialize");
648 int CServiceMain::process_activated_setting()
650 if (mPreferenceManager.register_changed_callback(
651 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb, &mPreferenceManager)) {
652 /* Activate / deactivate according to the vconf key setting */
653 active_state_changed_cb(std::string{}, &mPreferenceManager);
655 #ifdef ENABLE_MULTI_ASSISTANT_BY_DEFAULT
656 /* Multi-assistant needs to be enabled by default, unless disabled explicitly */
657 mServicePlugin.activate();
658 const char *default_assistant = NULL;
659 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
660 if (NULL == default_assistant) {
661 if (mClientInfo[0].used) {
662 default_assistant = mClientInfo[0].appid;
663 MAS_LOGW("No default assistant, setting %s as default", default_assistant);
664 mServicePlugin.set_default_assistant(default_assistant);
666 MAS_LOGE("No default assistant, and no assistant installed");
675 int CServiceMain::mas_get_current_client_pid()
678 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
679 const char *appid = mClientInfo[mCurrentClientInfo].appid;
681 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
687 int CServiceMain::mas_get_current_preprocessing_client_pid()
690 if (mCurrentPreprocessingClientInfo >= 0 && mCurrentPreprocessingClientInfo < MAX_MACLIENT_INFO_NUM) {
691 const char *appid = mClientInfo[mCurrentPreprocessingClientInfo].appid;
693 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
699 int CServiceMain::mas_get_client_pid_by_appid(const char *appid)
704 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
707 if (-1 != ret && !mApplicationManager.is_application_running(ret)) {
708 MAS_LOGE("The PID for %s was %d, but it seems to be terminated", appid, ret);
709 on_deinitialize(ret);
716 bool CServiceMain::mas_get_client_custom_ui_option_by_appid(const char *appid)
719 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
720 if (mClientInfo[loop].used &&
721 0 < strlen(mClientInfo[loop].appid) &&
722 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
723 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
724 ret = mClientInfo[loop].custom_ui_option;
731 int CServiceMain::mas_get_client_pid_by_wakeup_word(const char *wakeup_word)
733 const char *appid = mas_get_client_appid_by_wakeup_word(wakeup_word);
734 return mas_get_client_pid_by_appid(appid);
737 const char* CServiceMain::mas_get_client_appid_by_wakeup_word(const char *wakeup_word)
740 const char *appid = NULL;
742 if (NULL == wakeup_word) return NULL;
744 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
745 if (mClientInfo[loop].used &&
746 0 < strlen(mClientInfo[loop].appid)) {
747 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
748 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
749 if (0 == strncmp(wakeup_word, mClientInfo[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
750 appid = mClientInfo[loop].appid;
757 /* Perform extended search, by eliminating blank characters */
759 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
760 if (mClientInfo[loop].used &&
761 0 < strlen(mClientInfo[loop].appid)) {
762 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
763 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
764 char comparand[MAX_WAKEUP_WORD_LEN];
765 int comparand_index = 0;
766 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
767 if (' ' != mClientInfo[loop].wakeup_word[inner_loop][index]) {
768 comparand[comparand_index++] = mClientInfo[loop].wakeup_word[inner_loop][index];
771 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
772 appid = mClientInfo[loop].appid;
783 int CServiceMain::mas_set_current_client_by_wakeup_word(const char *wakeup_word)
787 int prev_selection = mCurrentClientInfo;
789 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
790 if (mClientInfo[loop].used &&
791 0 < strlen(mClientInfo[loop].appid)) {
792 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
793 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
794 if (0 == strncmp(wakeup_word, mClientInfo[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
795 mCurrentClientInfo = loop;
802 /* Perform extended search, by eliminating blank characters */
804 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
805 if (mClientInfo[loop].used &&
806 0 < strlen(mClientInfo[loop].appid)) {
807 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
808 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
809 char comparand[MAX_WAKEUP_WORD_LEN];
810 int comparand_index = 0;
811 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
812 if (' ' != mClientInfo[loop].wakeup_word[inner_loop][index]) {
813 comparand[comparand_index++] = mClientInfo[loop].wakeup_word[inner_loop][index];
816 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
817 mCurrentClientInfo = loop;
826 if (mCurrentClientInfo != prev_selection) {
827 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
828 int pid = mas_get_client_pid_by_appid(mClientInfo[prev_selection].appid);
829 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_INACTIVE);
836 int CServiceMain::mas_set_current_client_by_appid(const char *appid)
839 int prev_selection = mCurrentClientInfo;
841 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
842 if (mClientInfo[loop].used &&
843 0 < strlen(mClientInfo[loop].appid) &&
844 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
845 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
846 mCurrentClientInfo = loop;
852 if (mCurrentClientInfo != prev_selection) {
853 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
854 int pid = mas_get_client_pid_by_appid(mClientInfo[prev_selection].appid);
855 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_INACTIVE);
862 int CServiceMain::mas_launch_client_by_appid(const char *appid, CLIENT_LAUNCH_MODE launch_mode)
866 if (NULL == appid || 0 == strlen(appid)) {
867 MAS_LOGE("appid invalid, failed launching MA Client");
871 if (CLIENT_LAUNCH_MODE_PRELAUNCH == launch_mode) {
872 if (mApplicationManager.is_application_running(appid)) {
873 MAS_LOGE("appid %s is already running, no need for a prelaunch", appid);
877 result = mApplicationManager.launch_app_async(appid, true);
879 result = mApplicationManager.launch_app_async(appid, false);
882 if (CLIENT_LAUNCH_MODE_ACTIVATION == launch_mode) {
884 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
885 if (mClientInfo[loop].used &&
886 0 < strlen(mClientInfo[loop].appid)) {
887 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
888 mWakeupClientAppId = mClientInfo[loop].appid;
893 MAS_LOGD("mWakeupClientAppId : %s, %d", mWakeupClientAppId.c_str(), found);
899 int CServiceMain::mas_bring_client_to_foreground(const char* appid)
903 if (NULL == appid || 0 == strlen(appid)) {
904 MAS_LOGE("appid invalid, failed launching MA Client");
908 if (!mApplicationManager.bring_app_to_foreground(appid)) {
915 int CServiceMain::mas_launch_client_by_wakeup_word(const char *wakeup_word)
917 const char *appid = mas_get_client_appid_by_wakeup_word(wakeup_word);
918 return mas_launch_client_by_appid(appid, CLIENT_LAUNCH_MODE_ACTIVATION);
921 int CServiceMain::mas_prelaunch_default_assistant()
923 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
924 boost::optional<bool> prelaunch_mode =
925 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PRELAUNCH_MODE);
926 if (prelaunch_mode && *prelaunch_mode) {
927 const char *default_assistant = NULL;
928 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
929 if (!(mApplicationManager.is_application_running(default_assistant))) {
930 MAS_LOGD("prelaunching default_assistant_appid : %s", default_assistant);
931 mas_launch_client_by_appid(default_assistant, CLIENT_LAUNCH_MODE_PRELAUNCH);
938 int CServiceMain::mas_update_voice_key_support_mode()
940 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
941 bool successful = false;
942 const char *default_assistant = NULL;
943 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
944 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
945 if (mClientInfo[loop].used) {
946 if (default_assistant &&
947 strncmp(default_assistant, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
948 float duration = mClientInfo[loop].voice_key_tap_duration;
949 if (0.0f < duration) {
950 mServicePlugin.set_voice_key_tap_duration(duration);
952 mServicePlugin.unset_voice_key_tap_duration();
954 mServicePlugin.set_voice_key_support_mode(
955 mClientInfo[loop].voice_key_support_mode);
963 mServicePlugin.unset_voice_key_tap_duration();
964 mServicePlugin.set_voice_key_support_mode(VOICE_KEY_SUPPORT_MODE_NONE);
969 ma_preprocessing_allow_mode_e CServiceMain::get_preprocessing_allow_mode(const char* appid)
971 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
972 if (appid && mClientInfo[loop].used) {
973 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
974 return mClientInfo[loop].preprocessing_allow_mode;
978 return MA_PREPROCESSING_ALLOW_NONE;
981 /* This might need to be read from settings in the future, but using macro for now */
982 //#define BRING_PREPROCESSING_ASSISTANT_TO_FRONT
984 int CServiceMain::mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT event)
986 const char* current_maclient_appid = NULL;
987 const char* preprocessing_allow_appid = NULL;
988 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
989 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
990 preprocessing_allow_appid = mClientInfo[mCurrentClientInfo].preprocessing_allow_appid;
992 ma_preprocessing_allow_mode_e mode = get_preprocessing_allow_mode(current_maclient_appid);
995 case PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED:
997 #ifndef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
998 /* If there is no need to bring preprocessing assistant to front,
999 current_maclient should always be brought to front */
1000 mas_bring_client_to_foreground(current_maclient_appid);
1002 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1003 if (check_preprocessing_assistant_exists()) {
1004 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1005 MA_PREPROCESSING_ALLOW_ALL == mode) {
1006 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1007 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1011 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1012 /* If preprocessing assistant does not exist, there is no way to enable
1013 preprocessing assistant, so bring current maclient to front right away */
1014 mas_bring_client_to_foreground(current_maclient_appid);
1019 case PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED:
1021 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1022 /* Enable preprocessing mode only if the preprocessing assistant exists */
1023 if (check_preprocessing_assistant_exists()) {
1024 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1025 MA_PREPROCESSING_ALLOW_ALL == mode) {
1026 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1027 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1033 case PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED:
1035 if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED == mCurrentPreprocessingState) {
1036 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_UTTERANCE;
1037 } else if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED == mCurrentPreprocessingState) {
1038 /* If preprocessing assistant does not exist, the current_maclient
1039 would have been brought to front already on wakeup event */
1040 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1041 if (check_preprocessing_assistant_exists()) {
1042 mas_bring_client_to_foreground(current_maclient_appid);
1045 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1049 case PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED:
1051 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1052 if (check_preprocessing_assistant_exists()) {
1053 if (MA_PREPROCESSING_ALLOW_FOLLOW_UP == mode ||
1054 MA_PREPROCESSING_ALLOW_ALL == mode) {
1055 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_FOLLOW_UP;
1060 case PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED:
1062 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1063 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1064 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1065 boost::optional<std::string> preprocessing_assistant =
1066 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1067 if (preprocessing_assistant) {
1068 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1069 mas_bring_client_to_foreground((*preprocessing_assistant).c_str());
1073 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1076 case PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED:
1078 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1079 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1080 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1081 mas_bring_client_to_foreground(current_maclient_appid);
1084 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1091 int CServiceMain::mas_set_current_service_state(ma_service_state_e state)
1093 mCurrentServiceState = state;
1095 ma_client_s *data = NULL;
1097 int count = mClientManager.get_client_num();
1100 for (i = 0; i < count; i++) {
1101 int pid = mClientManager.find_client_pid_by_index(i);
1104 int ret = mServiceIpc.service_state_change(pid, state);
1106 MAS_LOGE("[ERROR] Fail to set service state change to %d, ret(%d)", pid, ret);
1113 ma_service_state_e CServiceMain::mas_get_current_service_state()
1115 return mCurrentServiceState;
1118 bool CServiceMain::is_valid_wakeup_engine(const char* appid)
1120 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM;loop++) {
1121 if (mClientInfo[loop].used) {
1122 LOGD("comparing appid : %s %s", mClientInfo[loop].wakeup_engine, appid);
1123 if (0 == strncmp(mClientInfo[loop].wakeup_engine, appid, MAX_APPID_LEN)) {
1131 int pkg_app_list_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
1133 if (nullptr == g_service_main) return -1;
1137 int ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
1138 if (PMINFO_R_OK == ret && NULL != appid) {
1139 int *result = (int*)user_data;
1141 bool exists = g_service_main->is_valid_wakeup_engine(appid);
1147 LOGE("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1154 INFO: Package install/update/uninstall scenario
1155 Install and Uninstall are obviously simple.
1156 Install: just INSTALL
1157 Uninstall: just UNINSTALL
1158 Update package (change the source codes and Run As again), there are four scenarios:
1161 2. UNINSTALL -> INSTALL
1162 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1163 and change Application ID in tizen-manifest.xml file and Run As.
1164 3. UPDATE -> INSTALL
1165 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1166 and change Application ID in tizen-manifest.xml file and Run As.
1167 At UPDATE event, pkgid (package parameter) is invalid...
1169 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1170 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1172 static void _package_manager_event_cb(const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data)
1174 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
1177 uid_t uid = getuid();
1178 pkgmgrinfo_pkginfo_h handle = NULL;
1179 static bool in_progress = false;
1180 bool should_exit = false;
1182 if (!package || !type)
1185 if (PACKAGE_MANAGER_EVENT_TYPE_UPDATE != event_type &&
1186 PACKAGE_MANAGER_EVENT_TYPE_INSTALL != event_type &&
1187 PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL != event_type)
1190 if (PACKAGE_MANAGER_EVENT_STATE_STARTED != event_state &&
1191 PACKAGE_MANAGER_EVENT_STATE_COMPLETED != event_state)
1195 MAS_LOGD("type=%s package=%s event_type=%d event_state=%d progress=%d error=%d",
1196 type, package, event_type, event_state, progress, error);
1197 ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
1198 if (ret != PMINFO_R_OK || NULL == handle) {
1199 MAS_LOGW("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", package, ret, getuid());
1200 /* Try to get in user packages */
1202 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(package, uid, &handle);
1203 if (ret != PMINFO_R_OK || NULL == handle) {
1204 MAS_LOGW("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", package, ret, getuid());
1210 /* Try to get in user packages */
1211 pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, pkg_app_list_cb, (void *)&ret, uid);
1213 /* Try to get in global packages */
1214 pkgmgrinfo_appinfo_get_list(handle, PMINFO_ALL_APP, pkg_app_list_cb, (void *)&ret);
1217 if (PACKAGE_MANAGER_EVENT_STATE_STARTED == event_state) {
1218 MAS_LOGI("processing PACKAGE_MANAGER_EVENT_STATE_STARTED event : %d", event_type);
1219 if (false == in_progress) {
1222 service_main->deinitialize_service_plugin();
1224 MAS_LOGE("service_main is NULL");
1227 } else if (PACKAGE_MANAGER_EVENT_STATE_COMPLETED == event_state) {
1228 MAS_LOGI("processing PACKAGE_MANAGER_EVENT_STATE_COMPLETED event : %d", event_type);
1229 if (false == in_progress) {
1231 service_main->deinitialize_service_plugin();
1233 MAS_LOGE("service_main is NULL");
1238 service_main->initialize_service_plugin();
1239 service_main->process_activated_setting();
1241 MAS_LOGE("service_main is NULL");
1245 in_progress = false;
1249 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1252 LOGI("Now restarting multi-assistant-service for reloading updated modules");
1259 bool CServiceMain::app_create(void *data)
1261 // Todo: add your code here.
1262 MAS_LOGD("[Enter] Service app create");
1264 g_service_main = this;
1266 mClientManager.set_application_manager(&mApplicationManager);
1268 mServiceIpc.set_client_manager(&mClientManager);
1269 mServiceIpc.set_service_ipc_observer(this);
1271 mServicePlugin.set_service_ipc(&mServiceIpc);
1272 mServicePlugin.set_service_main(this);
1274 int ret = mServiceIpc.open_connection();
1276 MAS_LOGE("[ERROR] Fail to open connection");
1279 initialize_service_plugin();
1281 process_activated_setting();
1283 mas_prelaunch_default_assistant();
1284 mas_update_voice_key_support_mode();
1286 /* For the case of preprocessing assistant, it always have to be launched beforehand */
1287 boost::optional<std::string> preprocessing_assistant =
1288 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1289 if (preprocessing_assistant) {
1290 MAS_LOGD("prelaunching preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1291 mas_launch_client_by_appid((*preprocessing_assistant).c_str(), CLIENT_LAUNCH_MODE_PRELAUNCH);
1294 if (!mPackageManagerHandle) {
1295 int ret = package_manager_create(&mPackageManagerHandle);
1296 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
1297 ret = package_manager_set_event_cb(mPackageManagerHandle, _package_manager_event_cb, this);
1298 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
1299 LOGD("package_manager_set_event_cb succeeded.");
1301 LOGE("package_manager_set_event_cb failed(%d)", ret);
1304 LOGE("package_manager_create failed(%d)", ret);
1311 void CServiceMain::app_terminate(void *data)
1313 MAS_LOGI("[ENTER]");
1314 if (mPackageManagerHandle) {
1315 package_manager_unset_event_cb(mPackageManagerHandle);
1316 package_manager_destroy(mPackageManagerHandle);
1317 mPackageManagerHandle = NULL;
1320 deinitialize_service_plugin();
1322 mPreferenceManager.unregister_changed_callback(
1323 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb);
1325 int ret = mServiceIpc.close_connection();
1327 MAS_LOGE("[ERROR] Fail to close connection");
1330 g_service_main = nullptr;
1336 int CServiceMain::on_initialize(int pid) {
1337 MAS_LOGD("[Enter] pid(%d)", pid);
1339 std::string pid_appid;
1340 boost::optional<std::string> appid_by_pid = mApplicationManager.get_appid_by_pid(pid);
1342 pid_appid = *appid_by_pid;
1343 MAS_LOGD("appid for pid %d is : %s", pid, pid_appid.c_str());
1345 /* Remove existing client that has same appid, if there's any */
1346 mClientManager.destroy_client_by_appid(pid_appid.c_str());
1348 /* And remove a client that has same pid also */
1349 mClientManager.destroy_client_by_pid(pid);
1351 mClientManager.create_client(pid, pid_appid.c_str());
1353 const char *current_maclient_appid = NULL;
1354 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1355 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
1358 mas_client_send_preprocessing_information(pid);
1359 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
1360 mas_client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
1362 if (current_maclient_appid && 0 == pid_appid.compare(current_maclient_appid)) {
1363 MAS_LOGD("MA client with current maclient appid connected!");
1365 if (0 == mWakeupClientAppId.compare(pid_appid)) {
1366 mWakeupClientAppId.clear();
1367 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_ACTIVE);
1368 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED);
1370 MAS_LOGE("[ERROR] mWakeupClientAppId and appid differ : %s %s",
1371 mWakeupClientAppId.c_str(), pid_appid.c_str());
1374 MAS_LOGD("MA client connected, but its appid does not match with current maclient");
1377 mServiceIpc.service_state_change(pid, mas_get_current_service_state());
1379 MAS_LOGE("[ERROR] Fail to retrieve appid");
1385 int CServiceMain::on_deinitialize(int pid) {
1386 MAS_LOGD("[Enter] pid(%d)", pid);
1387 mClientManager.destroy_client_by_pid(pid);
1391 int CServiceMain::on_get_audio_format(int pid, int& rate, int& channel, int& audio_type) {
1392 int main_rate, main_channel, main_audio_type;
1393 int ret = mas_client_get_audio_format(pid,
1394 &main_rate, &main_channel, &main_audio_type);
1396 channel = main_channel;
1397 audio_type = main_audio_type;
1401 int CServiceMain::on_get_audio_source_type(int pid, std::string& type) {
1402 char *main_type = nullptr;
1403 int ret = mas_client_get_audio_source_type(pid, &main_type);
1404 if (0 == ret && main_type) {
1405 type = std::string{main_type};
1410 int CServiceMain::on_send_asr_result(int pid, int event, std::string asr_result) {
1411 return mas_client_send_asr_result(pid, event, asr_result.c_str());
1414 int CServiceMain::on_send_result(int pid, std::string display_text,
1415 std::string utterance_text, std::string result_json) {
1416 return mas_client_send_result(pid,
1417 display_text.c_str(), utterance_text.c_str(), result_json.c_str());
1420 int CServiceMain::on_send_recognition_result(int pid, int result) {
1421 return mas_client_send_recognition_result(pid, result);
1424 int CServiceMain::on_start_streaming_audio_data(int pid, int type) {
1425 return mas_client_start_streaming_audio_data(pid, type);
1428 int CServiceMain::on_stop_streaming_audio_data(int pid, int type) {
1429 return mas_client_stop_streaming_audio_data(pid, type);
1432 int CServiceMain::on_update_voice_feedback_state(int pid, int state) {
1433 return mas_client_update_voice_feedback_state(pid, state);
1436 int CServiceMain::on_send_assistant_specific_command(int pid, std::string command) {
1437 return mas_client_set_assistant_specific_command(pid, command.c_str());
1440 int CServiceMain::on_set_background_volume(int pid, double ratio) {
1441 return mas_client_set_background_volume(pid, ratio);
1444 int CServiceMain::on_set_preprocessing_allow_mode(int pid, int mode, std::string app_id) {
1445 return mas_client_set_preprocessing_allow_mode(pid,
1446 static_cast<ma_preprocessing_allow_mode_e>(mode), app_id.c_str());
1449 int CServiceMain::on_send_preprocessing_result(int pid, int result) {
1450 return mas_client_send_preprocessing_result(pid, result);
1453 int CServiceMain::on_set_wake_word_audio_require_flag(int pid, int require) {
1454 return mas_client_set_wake_word_audio_require_flag(pid, require);
1457 int CServiceMain::on_set_assistant_language(int pid, std::string language) {
1458 return mas_client_set_assistant_language(pid, language.c_str());
1461 int CServiceMain::on_add_wake_word(int pid, std::string wake_word, std::string language) {
1462 return mas_client_add_wake_word(pid, wake_word.c_str(), language.c_str());
1465 int CServiceMain::on_remove_wake_word(int pid, std::string wake_word, std::string language) {
1466 return mas_client_remove_wake_word(pid, wake_word.c_str(), language.c_str());
1469 int CServiceMain::on_ui_initialize(int pid)
1471 return mas_ui_client_initialize(pid);
1474 int CServiceMain::on_ui_deinitialize(int pid)
1476 return mas_ui_client_deinitialize(pid);
1479 int CServiceMain::on_ui_change_assistant(std::string app_id)
1481 return mas_ui_client_change_assistant(app_id.c_str());