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>
26 #include <pkgmgr-info.h>
33 #include "service_common.h"
34 #include "service_main.h"
35 #include "service_plugin.h"
36 #include "service_ipc_dbus.h"
37 #include "service_config.h"
39 static CServiceMain* g_service_main = nullptr;
41 bool CServiceMain::check_preprocessing_assistant_exists()
45 boost::optional<std::string> preprocessing_appid =
46 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
47 if (preprocessing_appid) {
48 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
49 if (mClientInfo[loop].used &&
50 strncmp((*preprocessing_appid).c_str(), mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
51 if (mClientManager.check_client_validity_by_appid(*preprocessing_appid)) {
58 MAS_LOGD("result : %d", ret);
63 bool CServiceMain::is_current_preprocessing_assistant(const char* appid)
65 if (NULL == appid) return false;
69 boost::optional<std::string> preprocessing_appid =
70 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
71 if (preprocessing_appid) {
72 if (strncmp((*preprocessing_appid).c_str(), appid, MAX_APPID_LEN) == 0) {
80 int CServiceMain::mas_client_get_audio_format(int pid, int* rate, int* channel, int* audio_type)
82 MAS_LOGD("[Enter] pid(%d)", pid);
84 int ret = mServicePlugin.get_recording_audio_format(rate, channel, audio_type);
86 MAS_LOGE("[ERROR] Fail to get recording audio format, ret(%d)", ret);
92 #define MAX_LOCAL_VARIABLE_STRING_LEN 256
93 int CServiceMain::mas_client_get_audio_source_type(int pid, char** type)
95 MAS_LOGD("[Enter] pid(%d)", pid);
97 if (NULL == type) return -1;
99 static char cached[MAX_LOCAL_VARIABLE_STRING_LEN] = {'\0'};
100 int ret = mServicePlugin.get_recording_audio_source_type(type);
102 MAS_LOGE("[ERROR] Fail to get recording audio source type, ret(%d)", ret);
105 strncpy(cached, *type, MAX_LOCAL_VARIABLE_STRING_LEN - 1);
106 cached[MAX_LOCAL_VARIABLE_STRING_LEN - 1] = '\0';
112 int CServiceMain::mas_client_send_preprocessing_information(int pid)
115 MAS_LOGD("[Enter] pid(%d)", pid);
117 boost::optional<std::string> preprocessing_appid =
118 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
119 if (preprocessing_appid) {
120 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_appid).c_str());
121 ret = mServiceIpc.send_preprocessing_information(pid, (*preprocessing_appid).c_str());
127 int CServiceMain::mas_client_send_voice_key_status_change(int pid, ma_voice_key_status_e status)
130 MAS_LOGD("[Enter] pid(%d)", pid);
132 ret = mServiceIpc.voice_key_status_change(pid, status);
134 MAS_LOGE("[ERROR] Fail to send voice key status changed information, ret(%d)", ret);
136 mLastVoiceKeyStatus = status;
141 int CServiceMain::mas_client_send_asr_result(int pid, int event, const char* asr_result)
143 MAS_LOGD("[Enter] pid(%d), event(%d), asr_result(%s)", pid, event, asr_result);
144 int ret = mServiceIpc.masc_ui_dbus_send_asr_result(pid, event, asr_result);
146 MAS_LOGE("[ERROR] Fail to send asr result, ret(%d)", ret);
149 // if final event is , launch assistant app which is invoked with wakeup word.
154 int CServiceMain::mas_client_send_result(int pid, const char* display_text,
155 const char* utterance_text, const char* result_json)
157 MAS_LOGD("[Enter] pid(%d), display_text(%s), utterance_text(%s), result_json(%s)", pid, display_text, utterance_text, result_json);
158 int ret = mServiceIpc.masc_ui_dbus_send_result(pid, display_text, utterance_text, result_json);
160 MAS_LOGE("[ERROR] Fail to send result, ret(%d)", ret);
163 const char* pid_appid = NULL;
164 char buf[MAX_APPID_LEN] = {'\0', };
165 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
166 buf[MAX_APPID_LEN - 1] = '\0';
169 mServicePlugin.update_recognition_result(pid_appid, MA_RECOGNITION_RESULT_EVENT_SUCCESS);
174 int CServiceMain::mas_client_send_recognition_result(int pid, int result)
176 MAS_LOGD("[Enter] pid(%d), result(%d)", pid, result);
177 int ret = mServiceIpc.masc_ui_dbus_send_recognition_result(pid, result);
179 MAS_LOGE("[ERROR] Fail to send recognition result, ret(%d)", ret);
182 const char* pid_appid = NULL;
183 char buf[MAX_APPID_LEN] = {'\0', };
184 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
185 buf[MAX_APPID_LEN - 1] = '\0';
188 mServicePlugin.update_recognition_result(pid_appid, result);
193 int CServiceMain::mas_client_start_streaming_audio_data(int pid, int type)
197 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
198 ret = mServicePlugin.start_streaming_utterance_data();
199 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED);
201 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
202 ret = mServicePlugin.start_streaming_previous_utterance_data();
203 /* Preprocessing is not required for previous utterance streaming */
205 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
206 ret = mServicePlugin.start_streaming_follow_up_data();
207 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED);
213 int CServiceMain::mas_client_stop_streaming_audio_data(int pid, int type)
217 case MA_AUDIO_STREAMING_DATA_TYPE_CURRENT_UTTERANCE:
218 ret = mServicePlugin.stop_streaming_utterance_data();
220 case MA_AUDIO_STREAMING_DATA_TYPE_PREVIOUS_UTTERANCE:
221 ret = mServicePlugin.stop_streaming_previous_utterance_data();
223 case MA_AUDIO_STREAMING_DATA_TYPE_FOLLOW_UP_SPEECH:
224 ret = mServicePlugin.stop_streaming_follow_up_data();
230 int CServiceMain::mas_client_update_voice_feedback_state(int pid, int state)
232 const char* pid_appid = NULL;
233 char buf[MAX_APPID_LEN] = {'\0', };
234 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
235 buf[MAX_APPID_LEN - 1] = '\0';
238 mServicePlugin.update_voice_feedback_state(pid_appid, state);
242 int CServiceMain::mas_client_set_assistant_specific_command(int pid, const char *command)
244 const char* pid_appid = NULL;
245 char buf[MAX_APPID_LEN] = {'\0', };
246 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
247 buf[MAX_APPID_LEN - 1] = '\0';
250 mServicePlugin.set_assistant_specific_command(pid_appid, command);
254 int CServiceMain::mas_client_set_background_volume(int pid, double ratio)
256 const char* pid_appid = NULL;
257 char buf[MAX_APPID_LEN] = {'\0', };
258 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
259 buf[MAX_APPID_LEN - 1] = '\0';
262 mServicePlugin.set_background_volume(pid_appid, ratio);
266 int CServiceMain::mas_client_set_preprocessing_allow_mode(int pid, ma_preprocessing_allow_mode_e mode, const char* appid)
268 const char* pid_appid = NULL;
269 char buf[MAX_APPID_LEN] = {'\0', };
270 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
271 buf[MAX_APPID_LEN - 1] = '\0';
275 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
276 if (mClientInfo[loop].used) {
277 if (pid_appid && strncmp(pid_appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
278 mClientInfo[loop].preprocessing_allow_mode = mode;
280 strncpy(mClientInfo[loop].preprocessing_allow_appid, appid, MAX_APPID_LEN);
281 mClientInfo[loop].preprocessing_allow_appid[MAX_APPID_LEN - 1] = '\0';
283 mClientInfo[loop].preprocessing_allow_appid[0] = '\0';
289 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED);
294 int CServiceMain::mas_client_send_preprocessing_result(int pid, bool result)
296 const char* pid_appid = NULL;
297 char buf[MAX_APPID_LEN] = {'\0', };
298 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
299 buf[MAX_APPID_LEN - 1] = '\0';
302 if (!is_current_preprocessing_assistant(pid_appid)) return -1;
304 const char *current_maclient_appid = NULL;
305 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
306 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
310 MAS_LOGD("Preprocessing succeeded, bring (%s) to foreground", pid_appid);
311 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED);
313 MAS_LOGD("Preprocessing failed, bring (%s) to foreground", current_maclient_appid);
314 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED);
317 if (current_maclient_appid) {
318 int pid = mClientManager.find_client_pid_by_appid(
319 std::string{current_maclient_appid});
320 mServiceIpc.send_preprocessing_result(pid, result);
326 int CServiceMain::mas_client_set_wake_word_audio_require_flag(int pid, bool require)
328 const char* pid_appid = NULL;
329 char buf[MAX_APPID_LEN] = {'\0', };
330 if (AUL_R_OK == aul_app_get_appid_bypid(pid, buf, sizeof(buf))) {
331 buf[MAX_APPID_LEN - 1] = '\0';
335 mServicePlugin.set_wake_word_audio_require_flag(pid_appid, require);
339 int CServiceMain::mas_client_set_assistant_language(int pid, const char* language)
341 const char* pid_appid = NULL;
342 char buf[MAX_APPID_LEN] = {'\0', };
343 int ret = aul_app_get_appid_bypid(pid, buf, sizeof(buf));
344 if (AUL_R_OK == ret) {
345 buf[MAX_APPID_LEN - 1] = '\0';
349 mServicePlugin.set_assistant_language(pid_appid, language);
353 int CServiceMain::mas_client_add_wake_word(int pid, const char* wake_word, const char* language)
355 const char* pid_appid = NULL;
356 char buf[MAX_APPID_LEN] = {'\0', };
357 int ret = aul_app_get_appid_bypid(pid, buf, sizeof(buf));
358 if (AUL_R_OK == ret) {
359 buf[MAX_APPID_LEN - 1] = '\0';
363 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
364 if (mClientInfo[loop].used &&
365 0 == strncmp(buf, mClientInfo[loop].appid, MAX_APPID_LEN)) {
366 ret = mServiceConfig.add_custom_wake_word(wake_word, language,
367 mClientInfo[loop].wakeup_word,
368 mClientInfo[loop].wakeup_language);
370 mServiceConfig.save_custom_wake_words(pid_appid,
371 mClientInfo[loop].wakeup_word,
372 mClientInfo[loop].wakeup_language);
374 LOGE("add new wake word failed!");
380 mServicePlugin.add_assistant_wakeup_word(pid_appid, wake_word, language);
384 int CServiceMain::mas_client_remove_wake_word(int pid, const char* wake_word, const char* language)
386 const char* pid_appid = NULL;
387 char buf[MAX_APPID_LEN] = {'\0', };
388 int ret = aul_app_get_appid_bypid(pid, buf, sizeof(buf));
389 if (AUL_R_OK == ret) {
390 buf[MAX_APPID_LEN - 1] = '\0';
394 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
395 if (mClientInfo[loop].used &&
396 0 == strncmp(buf, mClientInfo[loop].appid, MAX_APPID_LEN)) {
397 ret = mServiceConfig.remove_custom_wake_word(wake_word, language,
398 mClientInfo[loop].wakeup_word,
399 mClientInfo[loop].wakeup_language);
401 mServiceConfig.save_custom_wake_words(pid_appid,
402 mClientInfo[loop].wakeup_word,
403 mClientInfo[loop].wakeup_language);
408 mServicePlugin.remove_assistant_wakeup_word(pid_appid, wake_word, language);
412 int CServiceMain::mas_ui_client_initialize(int pid)
414 MAS_LOGD("[Enter] pid(%d)", pid);
419 int CServiceMain::mas_ui_client_deinitialize(int pid)
421 MAS_LOGD("[Enter] pid(%d)", pid);
426 int CServiceMain::mas_ui_client_change_assistant(const char* appid)
431 MAS_LOGE("NULL parameter");
435 bool use_custom_ui = mas_get_client_custom_ui_option_by_appid(appid);
436 mServiceIpc.masc_ui_dbus_enable_common_ui(!use_custom_ui);
438 mas_set_current_client_by_appid(appid);
439 int pid = mas_get_client_pid_by_appid(appid);
441 mas_bring_client_to_foreground(appid);
442 mas_client_send_preprocessing_information(pid);
443 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
444 mas_client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
447 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_ACTIVE);
448 MAS_LOGD("MA Client with appid %s exists, requesting speech data", (appid ? appid : "NULL"));
450 int ret = mServicePlugin.start_streaming_utterance_data();
452 MAS_LOGE("[ERROR] Fail to start streaming utterance data(%d)", ret);
456 // Appropriate MA Client not available, trying to launch new one
457 MAS_LOGD("MA Client with appid %s does not exist, launching client", (appid ? appid : "NULL"));
459 /* The appid parameter might not exist after this function call, so we use appid string in our mClientInfo */
460 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
461 if (mClientInfo[loop].used &&
462 0 < strlen(mClientInfo[loop].appid) &&
463 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
464 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
465 mas_launch_client_by_appid(mClientInfo[loop].appid, CLIENT_LAUNCH_MODE_ACTIVATION);
474 static int mas_assistant_info_cb(ma_assistant_info_s* info, void* user_data) {
476 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
478 ret = service_main->add_assistant_info(info);
483 int CServiceMain::add_assistant_info(ma_assistant_info_s* info) {
484 MAS_LOGD("__mas_assistant_info_cb called");
487 MAS_LOGE("info NULL, returning");
490 if (NULL == info->app_id) {
491 MAS_LOGE("app_id NULL, returning");
497 while(-1 == index && loop < MAX_MACLIENT_INFO_NUM) {
498 if (false == mClientInfo[loop].used) {
504 mClientInfo[index].used = true;
505 mClientInfo[index].preprocessing_allow_mode = MA_PREPROCESSING_ALLOW_NONE;
506 mClientInfo[index].preprocessing_allow_appid[0] = '\0';
507 MAS_LOGD("app_id(%s)", info->app_id);
508 strncpy(mClientInfo[index].appid, info->app_id, MAX_APPID_LEN);
509 mClientInfo[index].appid[MAX_APPID_LEN - 1] = '\0';
511 if (is_current_preprocessing_assistant(mClientInfo[index].appid)) {
512 mCurrentPreprocessingClientInfo = index;
515 for (loop = 0;loop < MAX_WAKEUP_WORDS_NUM;loop++) {
516 if (loop < info->cnt_wakeup && info->wakeup_list[loop]) {
517 MAS_LOGD("wakeup_list(%d)(%s)(%s)", loop, info->wakeup_list[loop], info->wakeup_language[loop]);
518 strncpy(mClientInfo[index].wakeup_word[loop], info->wakeup_list[loop], MAX_WAKEUP_WORD_LEN);
519 mClientInfo[index].wakeup_word[loop][MAX_WAKEUP_WORD_LEN - 1] = '\0';
520 if (info->wakeup_language[loop]) {
521 strncpy(mClientInfo[index].wakeup_language[loop], info->wakeup_language[loop], MAX_SUPPORTED_LANGUAGE_LEN);
522 mClientInfo[index].wakeup_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
524 strncpy(mClientInfo[index].wakeup_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
527 strncpy(mClientInfo[index].wakeup_word[loop], "", MAX_WAKEUP_WORD_LEN);
531 for (loop = 0;loop < MAX_SUPPORTED_LANGUAGES_NUM;loop++) {
532 if (loop < info->cnt_lang && info->supported_lang[loop]) {
533 MAS_LOGD("supported_lang(%d)(%s)", loop, info->supported_lang[loop]);
534 strncpy(mClientInfo[index].supported_language[loop], info->supported_lang[loop], MAX_SUPPORTED_LANGUAGE_LEN);
535 mClientInfo[index].supported_language[loop][MAX_SUPPORTED_LANGUAGE_LEN - 1] = '\0';
537 strncpy(mClientInfo[index].supported_language[loop], "", MAX_SUPPORTED_LANGUAGE_LEN);
541 MAS_LOGD("wakeup_engine(%s)", info->wakeup_engine);
542 if (info->wakeup_engine) {
543 strncpy(mClientInfo[index].wakeup_engine, info->wakeup_engine, MAX_APPID_LEN);
544 mClientInfo[index].wakeup_engine[MAX_APPID_LEN - 1] = '\0';
546 mClientInfo[index].wakeup_engine[0] = '\0';
547 MAS_LOGW("Wakeup engine information not provided for : %s", info->app_id);
549 mClientInfo[index].custom_ui_option = info->custom_ui_option;
551 MAS_LOGD("voice_key_support_mode(%d)", info->voice_key_support_mode);
552 mClientInfo[index].voice_key_support_mode = info->voice_key_support_mode;
553 MAS_LOGD("voice_key_tap_duration(%f)", info->voice_key_tap_duration);
554 mClientInfo[index].voice_key_tap_duration = info->voice_key_tap_duration;
556 MAS_LOGD("Couldn't find an empty slot for storing assistant info");
559 MAS_LOGD("__mas_assistant_info_cb end");
564 static void active_state_changed_cb(std::string key, void* user_data)
566 IPreferenceManager* manager = static_cast<IPreferenceManager*>(user_data);
567 if (nullptr == manager) return;
569 boost::optional<bool> activated =
570 manager->get_bool(MULTI_ASSISTANT_SETTINGS_ACTIVATED);
572 MAS_LOGD("multi-assistant active state : %d\n", *activated);
574 CServicePlugin *plugin = nullptr;
575 if (g_service_main) {
576 plugin = g_service_main->get_service_plugin();
582 plugin->deactivate();
585 MAS_LOGE("Could not change plugin state : %p %p", g_service_main, plugin);
590 int CServiceMain::initialize_service_plugin(void)
592 if (0 != mServicePlugin.initialize()) {
593 MAS_LOGE("Fail to ws intialize");
597 if (0 != mServicePlugin.set_language(mCurrentLanguage.c_str())) {
598 MAS_LOGE("Fail to ws set language");
602 if (0 == mServiceConfig.get_assistant_info(mas_assistant_info_cb, this)) {
603 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
605 if (mClientInfo[loop].used &&
606 0 < strlen(mClientInfo[loop].appid)) {
607 mServiceConfig.load_custom_wake_words(mClientInfo[loop].appid,
608 mClientInfo[loop].wakeup_word, mClientInfo[loop].wakeup_language);
609 if (0 < strlen(mClientInfo[loop].wakeup_engine)) {
610 mServicePlugin.set_assistant_wakeup_engine(
611 mClientInfo[loop].appid,
612 mClientInfo[loop].wakeup_engine);
614 for (inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
615 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
616 MAS_LOGD("Registering wakeup word %s for app %s",
617 mClientInfo[loop].wakeup_word[inner_loop], mClientInfo[loop].appid);
618 if (0 != mServicePlugin.add_assistant_wakeup_word(
619 mClientInfo[loop].appid,
620 mClientInfo[loop].wakeup_word[inner_loop],
621 mClientInfo[loop].wakeup_language[inner_loop])) {
622 MAS_LOGE("Fail to add assistant's wakeup word");
626 for (inner_loop = 0; inner_loop < MAX_SUPPORTED_LANGUAGE_NUM; inner_loop++) {
627 if (0 < strlen(mClientInfo[loop].supported_language[inner_loop])) {
628 MAS_LOGD("Adding language %s for app %s",
629 mClientInfo[loop].supported_language[inner_loop], mClientInfo[loop].appid);
630 if (0 != mServicePlugin.add_assistant_language(
631 mClientInfo[loop].appid,
632 mClientInfo[loop].supported_language[inner_loop])) {
633 MAS_LOGE("Fail to add assistant's language");
640 MAS_LOGE("Fail to load assistant info");
643 if (0 != mServicePlugin.set_callbacks()) {
644 MAS_LOGE("Fail to set callbacks");
651 int CServiceMain::deinitialize_service_plugin(void)
654 if (0 != mServicePlugin.deactivate()) {
655 MAS_LOGE("Fail to deactivate");
657 if (0 != mServicePlugin.deinitialize()) {
658 MAS_LOGE("Fail to deinitialize");
664 int CServiceMain::process_activated_setting()
666 if (mPreferenceManager.register_changed_callback(
667 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb, &mPreferenceManager)) {
668 /* Activate / deactivate according to the vconf key setting */
669 active_state_changed_cb(std::string{}, &mPreferenceManager);
671 #ifdef ENABLE_MULTI_ASSISTANT_BY_DEFAULT
672 /* Multi-assistant needs to be enabled by default, unless disabled explicitly */
673 mServicePlugin.activate();
674 const char *default_assistant = NULL;
675 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
676 if (NULL == default_assistant) {
677 if (mClientInfo[0].used) {
678 default_assistant = mClientInfo[0].appid;
679 MAS_LOGW("No default assistant, setting %s as default", default_assistant);
680 mServicePlugin.set_default_assistant(default_assistant);
682 MAS_LOGE("No default assistant, and no assistant installed");
691 int CServiceMain::mas_get_current_client_pid()
694 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
695 const char *appid = mClientInfo[mCurrentClientInfo].appid;
697 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
703 int CServiceMain::mas_get_current_preprocessing_client_pid()
706 if (mCurrentPreprocessingClientInfo >= 0 && mCurrentPreprocessingClientInfo < MAX_MACLIENT_INFO_NUM) {
707 const char *appid = mClientInfo[mCurrentPreprocessingClientInfo].appid;
709 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
715 int CServiceMain::mas_get_client_pid_by_appid(const char *appid)
720 ret = mClientManager.find_client_pid_by_appid(std::string{appid});
723 int status = aul_app_get_status_bypid(ret);
724 if (-1 != ret && 0 > status) {
725 MAS_LOGE("The PID for %s was %d, but it seems to be terminated : %d",
726 (appid ? appid : "NULL"), ret, status);
727 on_deinitialize(ret);
734 bool CServiceMain::mas_get_client_custom_ui_option_by_appid(const char *appid)
737 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
738 if (mClientInfo[loop].used &&
739 0 < strlen(mClientInfo[loop].appid) &&
740 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
741 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
742 ret = mClientInfo[loop].custom_ui_option;
749 int CServiceMain::mas_get_client_pid_by_wakeup_word(const char *wakeup_word)
751 const char *appid = mas_get_client_appid_by_wakeup_word(wakeup_word);
752 return mas_get_client_pid_by_appid(appid);
755 const char* CServiceMain::mas_get_client_appid_by_wakeup_word(const char *wakeup_word)
758 const char *appid = NULL;
760 if (NULL == wakeup_word) return NULL;
762 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
763 if (mClientInfo[loop].used &&
764 0 < strlen(mClientInfo[loop].appid)) {
765 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
766 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
767 if (0 == strncmp(wakeup_word, mClientInfo[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
768 appid = mClientInfo[loop].appid;
775 /* Perform extended search, by eliminating blank characters */
777 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && NULL == appid; loop++) {
778 if (mClientInfo[loop].used &&
779 0 < strlen(mClientInfo[loop].appid)) {
780 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
781 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
782 char comparand[MAX_WAKEUP_WORD_LEN];
783 int comparand_index = 0;
784 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
785 if (' ' != mClientInfo[loop].wakeup_word[inner_loop][index]) {
786 comparand[comparand_index++] = mClientInfo[loop].wakeup_word[inner_loop][index];
789 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
790 appid = mClientInfo[loop].appid;
801 int CServiceMain::mas_set_current_client_by_wakeup_word(const char *wakeup_word)
805 int prev_selection = mCurrentClientInfo;
807 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
808 if (mClientInfo[loop].used &&
809 0 < strlen(mClientInfo[loop].appid)) {
810 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
811 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
812 if (0 == strncmp(wakeup_word, mClientInfo[loop].wakeup_word[inner_loop], MAX_WAKEUP_WORD_LEN)) {
813 mCurrentClientInfo = loop;
820 /* Perform extended search, by eliminating blank characters */
822 for (loop = 0; loop < MAX_MACLIENT_INFO_NUM && -1 == ret; loop++) {
823 if (mClientInfo[loop].used &&
824 0 < strlen(mClientInfo[loop].appid)) {
825 for (int inner_loop = 0; inner_loop < MAX_WAKEUP_WORDS_NUM; inner_loop++) {
826 if (0 < strlen(mClientInfo[loop].wakeup_word[inner_loop])) {
827 char comparand[MAX_WAKEUP_WORD_LEN];
828 int comparand_index = 0;
829 for (int index = 0; index < MAX_WAKEUP_WORD_LEN; index++) {
830 if (' ' != mClientInfo[loop].wakeup_word[inner_loop][index]) {
831 comparand[comparand_index++] = mClientInfo[loop].wakeup_word[inner_loop][index];
834 if (0 == strncmp(wakeup_word, comparand, MAX_WAKEUP_WORD_LEN)) {
835 mCurrentClientInfo = loop;
844 if (mCurrentClientInfo != prev_selection) {
845 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
846 int pid = mas_get_client_pid_by_appid(mClientInfo[prev_selection].appid);
847 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_INACTIVE);
854 int CServiceMain::mas_set_current_client_by_appid(const char *appid)
857 int prev_selection = mCurrentClientInfo;
859 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
860 if (mClientInfo[loop].used &&
861 0 < strlen(mClientInfo[loop].appid) &&
862 0 < strlen(mClientInfo[loop].wakeup_word[0])) {
863 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
864 mCurrentClientInfo = loop;
870 if (mCurrentClientInfo != prev_selection) {
871 if (prev_selection >= 0 && prev_selection < MAX_MACLIENT_INFO_NUM) {
872 int pid = mas_get_client_pid_by_appid(mClientInfo[prev_selection].appid);
873 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_INACTIVE);
880 int CServiceMain::mas_launch_client_by_appid(const char *appid, CLIENT_LAUNCH_MODE launch_mode)
882 if (NULL == appid || 0 == strlen(appid)) {
883 MAS_LOGE("appid invalid, failed launching MA Client");
887 if (CLIENT_LAUNCH_MODE_PRELAUNCH == launch_mode) {
888 if (1 == aul_app_is_running(appid)) {
889 MAS_LOGE("appid %s is already running, no need for a prelaunch", appid);
897 MAS_LOGE("Failed creating bundle for aul operation");
901 int result = aul_svc_set_background_launch(b,
902 (CLIENT_LAUNCH_MODE_PRELAUNCH == launch_mode ? TRUE : FALSE));
903 if (result < AUL_R_OK) {
904 MAS_LOGE("ERROR : aul_svc_set_background_launch failed. app_id [%s] bundle[%p] result[%d : %s]",
905 appid, b, result, get_error_message(result));
908 result = aul_launch_app_async(appid, b);
909 if (result < AUL_R_OK) {
910 MAS_LOGE("ERROR : aul_launch_app_async failed. app_id [%s] bundle[%p] result[%d : %s]",
911 appid, b, result, get_error_message(result));
914 if (CLIENT_LAUNCH_MODE_ACTIVATION == launch_mode) {
916 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
917 if (mClientInfo[loop].used &&
918 0 < strlen(mClientInfo[loop].appid)) {
919 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
920 mWakeupClientAppId = mClientInfo[loop].appid;
925 MAS_LOGD("mWakeupClientAppId : %s, %d", mWakeupClientAppId.c_str(), found);
928 if (b) bundle_free(b);
934 int CServiceMain::mas_bring_client_to_foreground(const char* appid)
936 /* Bring MA client to foreground - is there a better way other than launching? */
937 if (NULL == appid || 0 == strlen(appid)) {
938 MAS_LOGE("appid invalid, failed launching MA Client");
945 MAS_LOGE("Failed creating bundle for aul operation");
949 int result = aul_launch_app(appid, b);
950 if (result < AUL_R_OK) {
951 MAS_LOGE("ERROR : aul_launch_app failed. app_id [%s] bundle[%p] result[%d : %s]",
952 appid, b, result, get_error_message(result));
955 if (b) bundle_free(b);
961 int CServiceMain::mas_launch_client_by_wakeup_word(const char *wakeup_word)
963 const char *appid = mas_get_client_appid_by_wakeup_word(wakeup_word);
964 return mas_launch_client_by_appid(appid, CLIENT_LAUNCH_MODE_ACTIVATION);
967 int CServiceMain::mas_prelaunch_default_assistant()
969 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
970 boost::optional<bool> prelaunch_mode =
971 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PRELAUNCH_MODE);
972 if (prelaunch_mode && *prelaunch_mode) {
973 const char *default_assistant = NULL;
974 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
975 if (0 == aul_app_is_running(default_assistant)) {
976 MAS_LOGD("prelaunching default_assistant_appid : %s", default_assistant);
977 mas_launch_client_by_appid(default_assistant, CLIENT_LAUNCH_MODE_PRELAUNCH);
984 int CServiceMain::mas_update_voice_key_support_mode()
986 /* CHECK NEEDED : should the code segment below and activation logic above be moved to wakeup manger? */
987 bool successful = false;
988 const char *default_assistant = NULL;
989 if (0 == mServicePlugin.get_default_assistant(&default_assistant)) {
990 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
991 if (mClientInfo[loop].used) {
992 if (default_assistant &&
993 strncmp(default_assistant, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
994 float duration = mClientInfo[loop].voice_key_tap_duration;
995 if (0.0f < duration) {
996 mServicePlugin.set_voice_key_tap_duration(duration);
998 mServicePlugin.unset_voice_key_tap_duration();
1000 mServicePlugin.set_voice_key_support_mode(
1001 mClientInfo[loop].voice_key_support_mode);
1009 mServicePlugin.unset_voice_key_tap_duration();
1010 mServicePlugin.set_voice_key_support_mode(VOICE_KEY_SUPPORT_MODE_NONE);
1015 ma_preprocessing_allow_mode_e CServiceMain::get_preprocessing_allow_mode(const char* appid)
1017 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM; loop++) {
1018 if (appid && mClientInfo[loop].used) {
1019 if (strncmp(appid, mClientInfo[loop].appid, MAX_APPID_LEN) == 0) {
1020 return mClientInfo[loop].preprocessing_allow_mode;
1024 return MA_PREPROCESSING_ALLOW_NONE;
1027 /* This might need to be read from settings in the future, but using macro for now */
1028 //#define BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1030 int CServiceMain::mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT event)
1032 const char* current_maclient_appid = NULL;
1033 const char* preprocessing_allow_appid = NULL;
1034 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1035 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
1036 preprocessing_allow_appid = mClientInfo[mCurrentClientInfo].preprocessing_allow_appid;
1038 ma_preprocessing_allow_mode_e mode = get_preprocessing_allow_mode(current_maclient_appid);
1041 case PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED:
1043 #ifndef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1044 /* If there is no need to bring preprocessing assistant to front,
1045 current_maclient should always be brought to front */
1046 mas_bring_client_to_foreground(current_maclient_appid);
1048 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1049 if (check_preprocessing_assistant_exists()) {
1050 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1051 MA_PREPROCESSING_ALLOW_ALL == mode) {
1052 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1053 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1057 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1058 /* If preprocessing assistant does not exist, there is no way to enable
1059 preprocessing assistant, so bring current maclient to front right away */
1060 mas_bring_client_to_foreground(current_maclient_appid);
1065 case PREPROCESSING_STATE_EVENT_PREPROCESSING_ALLOW_MODE_CHANGED:
1067 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED;
1068 /* Enable preprocessing mode only if the preprocessing assistant exists */
1069 if (check_preprocessing_assistant_exists()) {
1070 if (MA_PREPROCESSING_ALLOW_UTTERANCE == mode ||
1071 MA_PREPROCESSING_ALLOW_ALL == mode) {
1072 if (is_current_preprocessing_assistant(preprocessing_allow_appid)) {
1073 mCurrentPreprocessingState = PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED;
1079 case PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED:
1081 if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_ENABLED == mCurrentPreprocessingState) {
1082 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_UTTERANCE;
1083 } else if (PREPROCESSING_STATE_WAKEUP_PREPROCESS_DISABLED == mCurrentPreprocessingState) {
1084 /* If preprocessing assistant does not exist, the current_maclient
1085 would have been brought to front already on wakeup event */
1086 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1087 if (check_preprocessing_assistant_exists()) {
1088 mas_bring_client_to_foreground(current_maclient_appid);
1091 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1095 case PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED:
1097 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1098 if (check_preprocessing_assistant_exists()) {
1099 if (MA_PREPROCESSING_ALLOW_FOLLOW_UP == mode ||
1100 MA_PREPROCESSING_ALLOW_ALL == mode) {
1101 mCurrentPreprocessingState = PREPROCESSING_STATE_PREPROCESSING_FOLLOW_UP;
1106 case PREPROCESSING_STATE_EVENT_PREPROCESSING_SUCCEEDED:
1108 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1109 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1110 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1111 boost::optional<std::string> preprocessing_assistant =
1112 mPreferenceManager.get_bool(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1113 if (preprocessing_assistant) {
1114 MAS_LOGD("preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1115 mas_bring_client_to_foreground((*preprocessing_assistant).c_str());
1119 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1122 case PREPROCESSING_STATE_EVENT_PREPROCESSING_FAILED:
1124 #ifdef BRING_PREPROCESSING_ASSISTANT_TO_FRONT
1125 if (PREPROCESSING_STATE_EVENT_UTTERANCE_STREAMING_STARTED == mCurrentPreprocessingState ||
1126 PREPROCESSING_STATE_EVENT_FOLLOW_UP_STREAMING_STARTED == mCurrentPreprocessingState) {
1127 mas_bring_client_to_foreground(current_maclient_appid);
1130 mCurrentPreprocessingState = PREPROCESSING_STATE_NONE;
1137 int CServiceMain::mas_set_current_service_state(ma_service_state_e state)
1139 mCurrentServiceState = state;
1141 ma_client_s *data = NULL;
1143 int count = mClientManager.get_client_num();
1146 for (i = 0; i < count; i++) {
1147 int pid = mClientManager.find_client_pid_by_index(i);
1150 int ret = mServiceIpc.service_state_change(pid, state);
1152 MAS_LOGE("[ERROR] Fail to set service state change to %d, ret(%d)", pid, ret);
1159 ma_service_state_e CServiceMain::mas_get_current_service_state()
1161 return mCurrentServiceState;
1164 bool CServiceMain::is_valid_wakeup_engine(const char* appid)
1166 for (int loop = 0; loop < MAX_MACLIENT_INFO_NUM;loop++) {
1167 if (mClientInfo[loop].used) {
1168 LOGD("comparing appid : %s %s", mClientInfo[loop].wakeup_engine, appid);
1169 if (0 == strncmp(mClientInfo[loop].wakeup_engine, appid, MAX_APPID_LEN)) {
1177 int pkg_app_list_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
1179 if (nullptr == g_service_main) return -1;
1183 int ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
1184 if (PMINFO_R_OK == ret && NULL != appid) {
1185 int *result = (int*)user_data;
1187 bool exists = g_service_main->is_valid_wakeup_engine(appid);
1193 LOGE("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1200 INFO: Package install/update/uninstall scenario
1201 Install and Uninstall are obviously simple.
1202 Install: just INSTALL
1203 Uninstall: just UNINSTALL
1204 Update package (change the source codes and Run As again), there are four scenarios:
1207 2. UNINSTALL -> INSTALL
1208 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1209 and change Application ID in tizen-manifest.xml file and Run As.
1210 3. UPDATE -> INSTALL
1211 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1212 and change Application ID in tizen-manifest.xml file and Run As.
1213 At UPDATE event, pkgid (package parameter) is invalid...
1215 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1216 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1218 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)
1220 CServiceMain* service_main = static_cast<CServiceMain*>(user_data);
1223 uid_t uid = getuid();
1224 pkgmgrinfo_pkginfo_h handle = NULL;
1225 static bool in_progress = false;
1226 bool should_exit = false;
1228 if (!package || !type)
1231 if (PACKAGE_MANAGER_EVENT_TYPE_UPDATE != event_type &&
1232 PACKAGE_MANAGER_EVENT_TYPE_INSTALL != event_type &&
1233 PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL != event_type)
1236 if (PACKAGE_MANAGER_EVENT_STATE_STARTED != event_state &&
1237 PACKAGE_MANAGER_EVENT_STATE_COMPLETED != event_state)
1241 MAS_LOGD("type=%s package=%s event_type=%d event_state=%d progress=%d error=%d",
1242 type, package, event_type, event_state, progress, error);
1243 ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
1244 if (ret != PMINFO_R_OK || NULL == handle) {
1245 MAS_LOGW("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", package, ret, getuid());
1246 /* Try to get in user packages */
1248 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(package, uid, &handle);
1249 if (ret != PMINFO_R_OK || NULL == handle) {
1250 MAS_LOGW("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", package, ret, getuid());
1256 /* Try to get in user packages */
1257 pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, pkg_app_list_cb, (void *)&ret, uid);
1259 /* Try to get in global packages */
1260 pkgmgrinfo_appinfo_get_list(handle, PMINFO_ALL_APP, pkg_app_list_cb, (void *)&ret);
1263 if (PACKAGE_MANAGER_EVENT_STATE_STARTED == event_state) {
1264 MAS_LOGI("processing PACKAGE_MANAGER_EVENT_STATE_STARTED event : %d", event_type);
1265 if (false == in_progress) {
1268 service_main->deinitialize_service_plugin();
1270 MAS_LOGE("service_main is NULL");
1273 } else if (PACKAGE_MANAGER_EVENT_STATE_COMPLETED == event_state) {
1274 MAS_LOGI("processing PACKAGE_MANAGER_EVENT_STATE_COMPLETED event : %d", event_type);
1275 if (false == in_progress) {
1277 service_main->deinitialize_service_plugin();
1279 MAS_LOGE("service_main is NULL");
1284 service_main->initialize_service_plugin();
1285 service_main->process_activated_setting();
1287 MAS_LOGE("service_main is NULL");
1291 in_progress = false;
1295 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1298 LOGI("Now restarting multi-assistant-service for reloading updated modules");
1305 bool CServiceMain::app_create(void *data)
1307 // Todo: add your code here.
1308 MAS_LOGD("[Enter] Service app create");
1310 g_service_main = this;
1312 mClientManager.set_application_manager(&mApplicationManager);
1314 mServiceIpc.set_client_manager(&mClientManager);
1315 mServiceIpc.set_service_ipc_observer(this);
1317 mServicePlugin.set_service_ipc(&mServiceIpc);
1318 mServicePlugin.set_service_main(this);
1320 int ret = mServiceIpc.open_connection();
1322 MAS_LOGE("[ERROR] Fail to open connection");
1325 initialize_service_plugin();
1327 process_activated_setting();
1329 mas_prelaunch_default_assistant();
1330 mas_update_voice_key_support_mode();
1332 /* For the case of preprocessing assistant, it always have to be launched beforehand */
1333 boost::optional<std::string> preprocessing_assistant =
1334 mPreferenceManager.get_string(WAKEUP_SETTINGS_KEY_PREPROCESSING_ASSISTANT_APPID);
1335 if (preprocessing_assistant) {
1336 MAS_LOGD("prelaunching preprocessing_assistant_appid : %s", (*preprocessing_assistant).c_str());
1337 mas_launch_client_by_appid((*preprocessing_assistant).c_str(), CLIENT_LAUNCH_MODE_PRELAUNCH);
1340 if (!mPackageManagerHandle) {
1341 int ret = package_manager_create(&mPackageManagerHandle);
1342 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
1343 ret = package_manager_set_event_cb(mPackageManagerHandle, _package_manager_event_cb, this);
1344 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
1345 LOGD("package_manager_set_event_cb succeeded.");
1347 LOGE("package_manager_set_event_cb failed(%d)", ret);
1350 LOGE("package_manager_create failed(%d)", ret);
1357 void CServiceMain::app_terminate(void *data)
1359 MAS_LOGI("[ENTER]");
1360 if (mPackageManagerHandle) {
1361 package_manager_unset_event_cb(mPackageManagerHandle);
1362 package_manager_destroy(mPackageManagerHandle);
1363 mPackageManagerHandle = NULL;
1366 deinitialize_service_plugin();
1368 mPreferenceManager.unregister_changed_callback(
1369 MULTI_ASSISTANT_SETTINGS_ACTIVATED, active_state_changed_cb);
1371 int ret = mServiceIpc.close_connection();
1373 MAS_LOGE("[ERROR] Fail to close connection");
1376 g_service_main = nullptr;
1382 int CServiceMain::on_initialize(int pid) {
1383 MAS_LOGD("[Enter] pid(%d)", pid);
1385 char appid[MAX_APPID_LEN] = {'\0', };
1386 if (AUL_R_OK == aul_app_get_appid_bypid(pid, appid, sizeof(appid))) {
1387 appid[MAX_APPID_LEN - 1] = '\0';
1389 MAS_LOGD("appid for pid %d is : %s", pid, (appid ? appid : "Unknown"));
1391 /* Remove existing client that has same appid, if there's any */
1392 mClientManager.destroy_client_by_appid(appid);
1394 /* And remove a client that has same pid also */
1395 mClientManager.destroy_client_by_pid(pid);
1397 mClientManager.create_client(pid, appid);
1399 const char *current_maclient_appid = NULL;
1400 if (mCurrentClientInfo >= 0 && mCurrentClientInfo < MAX_MACLIENT_INFO_NUM) {
1401 current_maclient_appid = mClientInfo[mCurrentClientInfo].appid;
1404 mas_client_send_preprocessing_information(pid);
1405 if (MA_VOICE_KEY_STATUS_PRESSED == mLastVoiceKeyStatus) {
1406 mas_client_send_voice_key_status_change(pid, mLastVoiceKeyStatus);
1408 if (current_maclient_appid && 0 == strncmp(current_maclient_appid, appid, MAX_APPID_LEN)) {
1409 MAS_LOGD("MA client with current maclient appid connected!");
1411 if (0 == mWakeupClientAppId.compare(appid)) {
1412 mWakeupClientAppId.clear();
1413 mServiceIpc.active_state_change(pid, MA_ACTIVE_STATE_ACTIVE);
1414 mas_process_preprocessing_state_event(PREPROCESSING_STATE_EVENT_ASSISTANT_ACTIVATED);
1416 MAS_LOGE("[ERROR] mWakeupClientAppId and appid differ : %s %s",
1417 mWakeupClientAppId.c_str(), appid);
1420 MAS_LOGD("MA client connected, but its appid does not match with current maclient");
1423 mServiceIpc.service_state_change(pid, mas_get_current_service_state());
1425 MAS_LOGE("[ERROR] Fail to retrieve appid");
1431 int CServiceMain::on_deinitialize(int pid) {
1432 MAS_LOGD("[Enter] pid(%d)", pid);
1433 mClientManager.destroy_client_by_pid(pid);
1437 int CServiceMain::on_get_audio_format(int pid, int& rate, int& channel, int& audio_type) {
1438 int main_rate, main_channel, main_audio_type;
1439 int ret = mas_client_get_audio_format(pid,
1440 &main_rate, &main_channel, &main_audio_type);
1442 channel = main_channel;
1443 audio_type = main_audio_type;
1447 int CServiceMain::on_get_audio_source_type(int pid, std::string& type) {
1448 char *main_type = nullptr;
1449 int ret = mas_client_get_audio_source_type(pid, &main_type);
1450 if (0 == ret && main_type) {
1451 type = std::string{main_type};
1456 int CServiceMain::on_send_asr_result(int pid, int event, std::string asr_result) {
1457 return mas_client_send_asr_result(pid, event, asr_result.c_str());
1460 int CServiceMain::on_send_result(int pid, std::string display_text,
1461 std::string utterance_text, std::string result_json) {
1462 return mas_client_send_result(pid,
1463 display_text.c_str(), utterance_text.c_str(), result_json.c_str());
1466 int CServiceMain::on_send_recognition_result(int pid, int result) {
1467 return mas_client_send_recognition_result(pid, result);
1470 int CServiceMain::on_start_streaming_audio_data(int pid, int type) {
1471 return mas_client_start_streaming_audio_data(pid, type);
1474 int CServiceMain::on_stop_streaming_audio_data(int pid, int type) {
1475 return mas_client_stop_streaming_audio_data(pid, type);
1478 int CServiceMain::on_update_voice_feedback_state(int pid, int state) {
1479 return mas_client_update_voice_feedback_state(pid, state);
1482 int CServiceMain::on_send_assistant_specific_command(int pid, std::string command) {
1483 return mas_client_set_assistant_specific_command(pid, command.c_str());
1486 int CServiceMain::on_set_background_volume(int pid, double ratio) {
1487 return mas_client_set_background_volume(pid, ratio);
1490 int CServiceMain::on_set_preprocessing_allow_mode(int pid, int mode, std::string app_id) {
1491 return mas_client_set_preprocessing_allow_mode(pid,
1492 static_cast<ma_preprocessing_allow_mode_e>(mode), app_id.c_str());
1495 int CServiceMain::on_send_preprocessing_result(int pid, int result) {
1496 return mas_client_send_preprocessing_result(pid, result);
1499 int CServiceMain::on_set_wake_word_audio_require_flag(int pid, int require) {
1500 return mas_client_set_wake_word_audio_require_flag(pid, require);
1503 int CServiceMain::on_set_assistant_language(int pid, std::string language) {
1504 return mas_client_set_assistant_language(pid, language.c_str());
1507 int CServiceMain::on_add_wake_word(int pid, std::string wake_word, std::string language) {
1508 return mas_client_add_wake_word(pid, wake_word.c_str(), language.c_str());
1511 int CServiceMain::on_remove_wake_word(int pid, std::string wake_word, std::string language) {
1512 return mas_client_remove_wake_word(pid, wake_word.c_str(), language.c_str());
1515 int CServiceMain::on_ui_initialize(int pid)
1517 return mas_ui_client_initialize(pid);
1520 int CServiceMain::on_ui_deinitialize(int pid)
1522 return mas_ui_client_deinitialize(pid);
1525 int CServiceMain::on_ui_change_assistant(std::string app_id)
1527 return mas_ui_client_change_assistant(app_id.c_str());