Add multi-assistant audio processing client library 80/230680/4
authorJi-hoon Lee <dalton.lee@samsung.com>
Mon, 13 Apr 2020 10:27:35 +0000 (19:27 +0900)
committerJi-hoon Lee <dalton.lee@samsung.com>
Tue, 14 Apr 2020 07:01:14 +0000 (16:01 +0900)
To support voice assistants that have separated
processes each for rendering UI and processing
utterance audio data, provide a client library
that enables receiving audio data on behalf of
the process that is linked with multi-assistant
client library. For now this feature is provided
internally but might be open to public as well
in the future.

Change-Id: Ied125f8260ee3923c49443f66ecfcdb808bb2684

client/CMakeLists.txt
client/ma_ap.c [new file with mode: 0644]
client/ma_ap_client.c [new file with mode: 0644]
client/ma_ap_client.h [new file with mode: 0644]
client/ma_ap_dbus.c [new file with mode: 0644]
client/ma_ap_dbus.h [new file with mode: 0644]
common/ma_main.h
include/CMakeLists.txt
packaging/multi-assistant.spec

index 87fb2cb095a001216112de6a9fa631a8f6fc45e1..5c106e4f2ec108bb71fff55344603df584e2b75e 100644 (file)
@@ -14,6 +14,12 @@ SET(UI_SRCS
        ../common/multi_assistant_settings.c
 )
 
+SET(AP_SRCS
+       ma_ap.c
+       ma_ap_client.c
+       ma_ap_dbus.c
+)
+
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
@@ -28,6 +34,11 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
 ADD_LIBRARY("${PROJECT_NAME}_ui" SHARED ${UI_SRCS})
 TARGET_LINK_LIBRARIES("${PROJECT_NAME}_ui" ${pkgs_LDFLAGS})
 
+## multi assistant ap library ##
+ADD_LIBRARY("${PROJECT_NAME}_ap" SHARED ${AP_SRCS})
+TARGET_LINK_LIBRARIES("${PROJECT_NAME}_ap" ${pkgs_LDFLAGS})
+
 ## Install library files ##
-INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)
+INSTALL(TARGETS "${PROJECT_NAME}" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)
 INSTALL(TARGETS "${PROJECT_NAME}_ui" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)
+INSTALL(TARGETS "${PROJECT_NAME}_ap" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)
diff --git a/client/ma_ap.c b/client/ma_ap.c
new file mode 100644 (file)
index 0000000..6c11150
--- /dev/null
@@ -0,0 +1,596 @@
+/**
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <cynara-client.h>
+#include <cynara-error.h>
+#include <cynara-session.h>
+#include <system_info.h>
+#include <vconf/vconf.h>
+#include <stdlib.h>
+
+
+#include "multi_assistant_ap.h"
+#include "ma_ap_client.h"
+#include "ma_ap_dbus.h"
+#include "ma_main.h"
+#include "ma_defs.h"
+
+/* Sound buf save for test */
+#if 0
+#define BUF_SAVE_MODE
+#endif
+
+static ma_h g_ma_ap = NULL;
+
+static int g_feature_enabled = -1;
+static int g_recorder_privilege_allowed = -1;
+static cynara *p_cynara = NULL;
+
+static void __ma_ap_notify_error(void* data);
+
+static int __ma_ap_get_feature_enabled()
+{
+       if (0 == g_feature_enabled) {
+               //LCOV_EXCL_START
+               MAAP_SLOGE("[ERROR] Multi-assistant feature NOT supported");
+               return MA_ERROR_NOT_SUPPORTED;
+               //LCOV_EXCL_STOP
+       } else if (-1 == g_feature_enabled) {
+               bool ma_supported = false;
+               bool mic_supported = false;
+               if (0 == system_info_get_platform_bool(MA_FEATURE_PATH, &ma_supported)) {
+                       if (0 == system_info_get_platform_bool(MA_MIC_FEATURE_PATH, &mic_supported)) {
+                               if (false == ma_supported || false == mic_supported) {
+                                       MAAP_SLOGE("[ERROR] Multi-assistant feature NOT supported");
+                                       g_feature_enabled = 0;
+                                       return MA_ERROR_NOT_SUPPORTED;
+                               }
+
+                               g_feature_enabled = 1;
+                       } else {
+                               MAAP_SLOGE("[ERROR] Fail to get feature value"); //LCOV_EXCL_LINE
+                               return MA_ERROR_NOT_SUPPORTED;
+                       }
+               } else {
+                       MAAP_SLOGE("[ERROR] Fail to get feature value"); //LCOV_EXCL_LINE
+                       return MA_ERROR_NOT_SUPPORTED;
+               }
+       }
+       return 0;
+}
+
+static int __check_privilege_initialize()
+{
+       int ret = cynara_initialize(&p_cynara, NULL);
+       if (CYNARA_API_SUCCESS != ret)
+               MAAP_SLOGE("[ERROR] fail to initialize"); //LCOV_EXCL_LINE
+
+       return ret == CYNARA_API_SUCCESS;
+}
+
+static int __check_privilege(const char* uid, const char * privilege)
+{
+       FILE *fp = NULL;
+       char label_path[1024] = "/proc/self/attr/current";
+       char smack_label[1024] = {'\0',};
+
+       if (!p_cynara) {
+               return false;
+       }
+
+       fp = fopen(label_path, "r");
+       if (fp != NULL) {
+               if (0 >= fread(smack_label, 1, sizeof(smack_label), fp))
+                       MAAP_SLOGE("[ERROR] fail to fread"); //LCOV_EXCL_LINE
+
+               fclose(fp);
+       }
+
+       pid_t pid = getpid();
+       char *session = cynara_session_from_pid(pid);
+       int ret = cynara_check(p_cynara, smack_label, session, uid, privilege);
+       MAAP_SLOGD("[Client]cynara_check returned %d(%s)", ret, (CYNARA_API_ACCESS_ALLOWED == ret) ? "Allowed" : "Denied");
+       if (session)
+               free(session);
+
+       if (ret != CYNARA_API_ACCESS_ALLOWED)
+               return false;
+       return true;
+}
+
+static void __check_privilege_deinitialize()
+{
+       if (p_cynara)
+               cynara_finish(p_cynara);
+       p_cynara = NULL;
+}
+
+static int __ma_ap_check_recorder_privilege()
+{
+       char uid[16];
+
+       if (0 == g_recorder_privilege_allowed) {
+               //LCOV_EXCL_START
+               MAAP_SLOGE("[ERROR] Permission for recording is denied");
+               return MA_ERROR_PERMISSION_DENIED;
+               //LCOV_EXCL_STOP
+       } else if (-1 == g_recorder_privilege_allowed) {
+               if (false == __check_privilege_initialize()) {
+                       MAAP_SLOGE("[ERROR] privilege initialize is failed"); //LCOV_EXCL_LINE
+                       return MA_ERROR_PERMISSION_DENIED;
+               }
+               snprintf(uid, 16, "%d", getuid());
+               if (false == __check_privilege(uid, MA_RECORDER_PRIVILEGE)) {
+                       MAAP_SLOGE("[ERROR] Permission for recording is denied");
+                       g_recorder_privilege_allowed = 0;
+                       __check_privilege_deinitialize();
+                       return MA_ERROR_PERMISSION_DENIED;
+               }
+               __check_privilege_deinitialize();
+       }
+
+       g_recorder_privilege_allowed = 1;
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_initialize(void)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       if (0 != __ma_ap_check_recorder_privilege()) {
+               return MA_ERROR_PERMISSION_DENIED;
+       }
+
+       MAAP_SLOGI("[Client DEBUG] Initialize");
+
+       /* check handle */
+       if (true == ma_ap_client_is_valid(g_ma_ap)) {
+               MAAP_SLOGD("[DEBUG] Already initialized"); //LCOV_EXCL_LINE
+               return MA_ERROR_NONE; //LCOV_EXCL_LINE
+       }
+
+       if (0 < ma_ap_client_get_count()) {
+               MAAP_SLOGD("[DEBUG] Already initialized"); //LCOV_EXCL_LINE
+               return MA_ERROR_NONE; //LCOV_EXCL_LINE
+       }
+
+       if (0 != ma_ap_dbus_open_connection()) {
+               MAAP_SLOGE("[ERROR] Fail to open connection"); //LCOV_EXCL_LINE
+               return MA_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
+       }
+
+       if (0 != ma_ap_client_create(&g_ma_ap)) {
+               MAAP_SLOGE("[ERROR] Fail to create client!!!!!"); //LCOV_EXCL_LINE
+               return MA_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
+       }
+
+       return MA_ERROR_NONE;
+}
+
+static void __ma_ap_internal_unprepare(void)
+{
+       return;
+}
+
+int ma_ap_deinitialize(void)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       if (0 != __ma_ap_check_recorder_privilege()) {
+               return MA_ERROR_PERMISSION_DENIED;
+       }
+
+       MAAP_SLOGI("[Client DEBUG] Deinitialize");
+
+       if (false == ma_ap_client_is_valid(g_ma_ap)) {
+               MAAP_SLOGE("[ERROR] NOT initialized");
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       ma_state_e state;
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+       }
+
+       /* check state */
+       switch (state) {
+       case MA_STATE_READY:
+               __ma_ap_internal_unprepare();
+               /* no break. need to next step*/
+       case MA_STATE_INITIALIZED:
+               /* Free client resources */
+               ma_ap_client_destroy(g_ma_ap);
+               g_ma_ap = NULL;
+               break;
+       case MA_STATE_NONE:
+               break;
+       }
+
+       MAAP_SLOGD("Success: destroy");
+
+       if (0 != ma_ap_dbus_close_connection()) {
+               MAAP_SLOGE("[ERROR] Fail to close connection"); //LCOV_EXCL_LINE
+       }
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_prepare(void)
+{
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_unprepare(void)
+{
+       return MA_ERROR_NONE;
+}
+
+static Eina_Bool __ma_ap_notify_state_changed(void* data)
+{
+       ma_state_changed_cb callback = NULL;
+       void* user_data;
+
+       ma_ap_client_get_state_changed_cb(g_ma_ap, &callback, &user_data);
+
+       ma_state_e current_state;
+       ma_state_e previous_state;
+
+       ma_ap_client_get_previous_state(g_ma_ap, &current_state, &previous_state);
+
+       if (NULL != callback) {
+               ma_ap_client_use_callback(g_ma_ap);
+               callback(previous_state, current_state, user_data);
+               ma_ap_client_not_use_callback(g_ma_ap);
+               MAAP_SLOGD("[DEBUG] State changed callback is called");
+       } else {
+               MAAP_SLOGD("[WARNING] State changed callback is NULL");
+       }
+
+       return EINA_FALSE;
+}
+
+int __ma_ap_cb_audio_streaming(int event, char* buffer, int len)
+{
+       ma_audio_streaming_cb callback = NULL;
+       void* user_data;
+
+#ifdef BUF_SAVE_MODE
+       static char g_temp_file_name[128] = {'\0',};
+       static FILE* g_pFile = NULL;
+       static int g_count = 1;
+       if (MA_AUDIO_STREAMING_EVENT_START == event) {
+               if (g_pFile) {
+                       fclose(g_pFile);
+                       g_pFile = NULL;
+               } else {
+                       MA_LOGD("[Recorder Info] File not found!");
+               }
+
+               while (1) {
+                       snprintf(g_temp_file_name, sizeof(g_temp_file_name), "/tmp/ma_%d_%d", getpid(), g_count);
+                       int ret = access(g_temp_file_name, 0);
+
+                       if (0 == ret) {
+                               MA_LOGD("[Recorder ERROR] File is already exist");
+                               if (0 == remove(g_temp_file_name)) {
+                                       MA_LOGD("[Recorder] Remove file");
+                                       break;
+                               } else {
+                                       g_count++;
+                               }
+                       } else {
+                               break;
+                       }
+               }
+
+               MA_LOGD("[Recorder] Temp file name=[%s]", g_temp_file_name);
+
+               /* open test file */
+               g_pFile = fopen(g_temp_file_name, "wb+x");
+               if (!g_pFile) {
+                       MA_LOGD("[Recorder ERROR] File not found!");
+               }
+               g_count++;
+       }
+
+       if (g_pFile)
+               fwrite(buffer, 1, len, g_pFile);
+
+       if (MA_AUDIO_STREAMING_EVENT_FINISH == event) {
+               if (g_pFile) {
+                       MA_LOGE("[Recorder SUCCESS] File Close");
+                       fclose(g_pFile);
+                       g_pFile = NULL;
+               } else {
+                       MA_LOGE("[Recorder ERROR] File not found!");
+               }
+       }
+#endif
+
+       ma_ap_client_get_audio_streaming_cb(g_ma_ap, &callback, &user_data);
+
+       if (NULL != callback) {
+               static ma_audio_streaming_event_e last_event = MA_AUDIO_STREAMING_EVENT_FAIL;
+               ma_ap_client_use_callback(g_ma_ap);
+               callback((ma_audio_streaming_event_e)event, buffer, len, user_data);
+               ma_ap_client_not_use_callback(g_ma_ap);
+               if (last_event != event) {
+                       last_event = event;
+                       MAAP_SLOGI("[INFO] Audio streaming callback is called, event(%d)", event);
+               }
+       } else {
+               MAAP_SLOGD("[WARNING] Audio streaming callback is NULL");
+       }
+
+       return 0;
+}
+
+int __ma_ap_cb_error(int reason, char* msg)
+{
+       ma_state_e state;
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] Invalid client");
+               return MA_ERROR_INVALID_PARAMETER;
+       }
+
+       /* check state */
+       if (state != MA_STATE_READY) {
+               MAAP_SLOGD("[DEBUG] Current state is not 'READY'"); //LCOV_EXCL_LINE
+               if (MA_ERROR_SERVICE_RESET != reason) {
+                       MAAP_SLOGE("[ERROR] client is not connected yet");
+                       return MA_ERROR_INVALID_STATE;
+               }
+               return MA_ERROR_NONE;
+       }
+
+       if (MA_ERROR_SERVICE_RESET == reason) {
+               MAAP_SLOGE("[ERROR] multi-assistant service reset");
+
+               ma_ap_client_set_client_state(g_ma_ap, MA_STATE_INITIALIZED);
+               __ma_ap_notify_state_changed((void*)g_ma_ap);
+       }
+
+       MAAP_SLOGE("[ERROR] Error reason(%d), msg(%s)", reason, msg);
+
+       ma_ap_client_set_error(g_ma_ap, reason);
+       __ma_ap_notify_error((void*)g_ma_ap);
+
+       if (MA_ERROR_SERVICE_RESET == reason) {
+               if (0 != ma_ap_prepare()) {
+                       MAAP_SLOGE("[ERROR] Fail to prepare");
+               }
+       }
+
+       return MA_ERROR_NONE;
+}
+
+static void __ma_ap_notify_error(void* data)
+{
+       ma_error_cb callback = NULL;
+       void* user_data;
+       ma_error_e reason;
+
+       ma_ap_client_get_error_cb(g_ma_ap, &callback, &user_data);
+       ma_ap_client_get_error(g_ma_ap, &reason);
+
+       if (NULL != callback) {
+               ma_ap_client_use_callback(g_ma_ap);
+               callback(reason, user_data);
+               ma_ap_client_not_use_callback(g_ma_ap);
+               MAUI_SLOGD("[DEBUG] Error callback is called");
+       } else {
+               MAUI_SLOGD("[WARNING] Error callback is NULL");
+       }
+}
+
+int __ma_ap_cb_audio_streaming_data_section_changed(ma_audio_streaming_data_section_e section)
+{
+       ma_audio_streaming_data_section_changed_cb callback = NULL;
+       void* user_data;
+
+       ma_ap_client_get_audio_streaming_data_section_changed_cb(g_ma_ap, &callback, &user_data);
+
+       if (NULL != callback) {
+               ma_ap_client_use_callback(g_ma_ap);
+               callback(section, user_data);
+               ma_ap_client_not_use_callback(g_ma_ap);
+               MAAP_SLOGD("[DEBUG] Audio streaming data section changed callback is called, (%d)", section);
+       } else {
+               MAAP_SLOGD("[WARNING] Audio streaming data section changed callback is NULL");
+       }
+
+       return 0;
+}
+
+int ma_ap_set_error_cb(ma_error_cb callback, void* user_data)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       MAAP_SLOGD("[Client DEBUG] Set Multi-assistant client error cb");
+
+
+       if (NULL == callback) {
+               MAAP_SLOGE("[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_PARAMETER;
+       }
+
+       ma_state_e state;
+
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != MA_STATE_INITIALIZED) {
+               MAAP_SLOGE("[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       ma_ap_client_set_error_cb(g_ma_ap, callback, user_data);
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_unset_error_cb(void)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       MAAP_SLOGD("[Client DEBUG] Unset Multi-assistant client error cb");
+
+       ma_state_e state;
+
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != MA_STATE_INITIALIZED) {
+               MAAP_SLOGE("[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       ma_ap_client_set_error_cb(g_ma_ap, NULL, NULL);
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_set_audio_streaming_cb(ma_audio_streaming_cb callback, void* user_data)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       MAAP_SLOGD("[Client DEBUG] Set Multi-assistant audio streaming cb");
+
+       if (NULL == callback) {
+               MAAP_SLOGE("[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_PARAMETER;
+       }
+
+       ma_state_e state;
+
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != MA_STATE_INITIALIZED) {
+               MAAP_SLOGE("[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       ma_ap_client_set_audio_streaming_cb(g_ma_ap, callback, user_data);
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_unset_audio_streaming_cb(void)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       MAAP_SLOGD("[Client DEBUG] Unset Multi-assistant audio streaming cb");
+
+       ma_state_e state;
+
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != MA_STATE_INITIALIZED) {
+               MAAP_SLOGE("[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       ma_ap_client_set_audio_streaming_cb(g_ma_ap, NULL, NULL);
+
+       return MA_ERROR_NONE;
+}
+
+
+int ma_ap_set_audio_streaming_data_section_changed_cb(ma_audio_streaming_data_section_changed_cb callback, void* user_data)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       MAAP_SLOGD("[Client DEBUG] Set Multi-assistant audio streaming data section changed cb");
+
+       if (NULL == callback) {
+               MAAP_SLOGE("[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_PARAMETER;
+       }
+
+       ma_state_e state;
+
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != MA_STATE_INITIALIZED) {
+               MAAP_SLOGE("[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       ma_ap_client_set_audio_streaming_data_section_changed_cb(g_ma_ap, callback, user_data);
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_unset_audio_streaming_data_section_changed_cb(void)
+{
+       if (0 != __ma_ap_get_feature_enabled()) {
+               return MA_ERROR_NOT_SUPPORTED;
+       }
+
+       MAAP_SLOGD("[Client DEBUG] Unset Multi-assistant audio streaming data section changed cb");
+
+       ma_state_e state;
+
+       if (0 != ma_ap_client_get_client_state(g_ma_ap, &state)) {
+               MAAP_SLOGE("[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != MA_STATE_INITIALIZED) {
+               MAAP_SLOGE("[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+               return MA_ERROR_INVALID_STATE;
+       }
+
+       ma_ap_client_set_audio_streaming_data_section_changed_cb(g_ma_ap, NULL, NULL);
+
+       return MA_ERROR_NONE;
+}
+
+//LCOV_EXCL_STOP
diff --git a/client/ma_ap_client.c b/client/ma_ap_client.c
new file mode 100644 (file)
index 0000000..f4dcf24
--- /dev/null
@@ -0,0 +1,376 @@
+/**
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "ma_ap_client.h"
+
+
+typedef struct {
+       ma_h    ma;
+       int     pid;
+       int     uid;            /*<< unique id = pid + handle */
+
+       ma_error_cb                     error_cb;
+       void*                           error_user_data;
+       ma_state_changed_cb             state_changed_cb;
+       void*                           state_changed_user_data;
+       ma_audio_streaming_cb   audio_streaming_cb;
+       void*                           audio_streaming_user_data;
+       ma_audio_streaming_data_section_changed_cb      audio_streaming_data_section_changed_cb;
+       void*                           audio_streaming_data_section_changed_user_data;
+
+       /* state */
+       ma_state_e              previous_state;
+       ma_state_e              current_state;
+
+       /* mutex */
+       int                     cb_ref_count;
+
+       /* error data */
+       int                     reason;
+       char*           err_msg;
+} ma_ap_client_s;
+
+static GSList* g_ap_client_list = NULL;
+
+static ma_ap_client_s* __ap_client_get(ma_h ma)
+{
+       if (NULL == ma) {
+               MAAP_SLOGE("[ERROR] Input parameter is NULL");
+               return NULL;
+       }
+
+       if (NULL == g_ap_client_list) {
+               MAAP_SLOGE("[ERROR] Client List is NULL");
+               return NULL;
+       }
+
+       ma_ap_client_s* data = NULL;
+       int count = g_slist_length(g_ap_client_list);
+       int i;
+
+       for (i = 0 ; i < count ; i++) {
+               data = g_slist_nth_data(g_ap_client_list, i);
+
+               if (NULL != data) {
+                       if (ma->handle == data->ma->handle) {
+                               return data;
+                       }
+               }
+       }
+
+       MAAP_SLOGD("[DEBUG] Fail to get ui client");
+       return NULL;
+}
+
+int ma_ap_client_create(ma_h* ma)
+{
+       ma_ap_client_s *client = NULL;
+
+       client = (ma_ap_client_s*)calloc(1, sizeof(ma_ap_client_s));
+       if (NULL == client) {
+               MAAP_SLOGE("[ERROR] Fail to allocate memory");
+               return MA_ERROR_OUT_OF_MEMORY;
+       }
+
+       ma_h temp = (ma_h)calloc(1, sizeof(struct ma_s));
+       if (NULL == temp) {
+               MAAP_SLOGE("[ERROR] Fail to allocate memory");
+               free(client);
+               return MA_ERROR_OUT_OF_MEMORY;
+       }
+
+       temp->handle = getpid();
+
+       /* initialize client data */
+       client->ma = temp;
+       client->pid = getpid();
+       client->uid = temp->handle;
+
+       client->error_cb = NULL;
+       client->error_user_data = NULL;
+       client->state_changed_cb = NULL;
+       client->state_changed_user_data = NULL;
+       client->audio_streaming_cb = NULL;
+       client->audio_streaming_user_data = NULL;
+       client->audio_streaming_data_section_changed_cb = NULL;
+       client->audio_streaming_data_section_changed_user_data = NULL;
+
+       client->previous_state = MA_STATE_INITIALIZED;
+       client->current_state = MA_STATE_INITIALIZED;
+
+       client->reason = 0;
+       client->err_msg = NULL;
+
+       client->cb_ref_count = 0;
+
+       g_ap_client_list = g_slist_append(g_ap_client_list, client);
+
+       *ma = temp;
+
+       return 0;}
+
+int ma_ap_client_destroy(ma_h ma)
+{
+       if (ma == NULL) {
+               MAAP_SLOGE("Input parameter is NULL");
+               return 0;
+       }
+
+       ma_ap_client_s *data = NULL;
+
+       int count = g_slist_length(g_ap_client_list);
+       int i;
+
+       for (i = 0; i < count; i++) {
+               data = g_slist_nth_data(g_ap_client_list, i);
+
+               if (NULL != data) {
+                       if (ma->handle == data->ma->handle) {
+                               g_ap_client_list =  g_slist_remove(g_ap_client_list, data);
+
+                               while (0 != data->cb_ref_count) {
+                                       /* wait for release callback function */
+                               }
+
+                               if (NULL != data->err_msg) {
+                                       free(data->err_msg);
+                               }
+
+                               free(data);
+                               free(ma);
+
+                               data = NULL;
+                               ma = NULL;
+
+                               return 0;
+                       }
+               }
+       }
+
+       MAAP_SLOGE("[ERROR] client Not found");
+
+       return -1;}
+
+bool ma_ap_client_is_valid(ma_h ma)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client) {
+               MAAP_SLOGE("[ERROR] ma handle is not valid");
+               return false;
+       }
+
+       return true;
+}
+
+int ma_ap_client_get_count(void)
+{
+       return g_slist_length(g_ap_client_list);
+}
+
+int ma_ap_client_use_callback(ma_h ma)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->cb_ref_count++;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_not_use_callback(ma_h ma)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->cb_ref_count--;
+
+       return MA_ERROR_NONE;
+}
+
+
+int ma_ap_client_set_client_state(ma_h ma, ma_state_e state)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->previous_state = client->current_state;
+       client->current_state = state;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_get_client_state(ma_h ma, ma_state_e* state)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       *state = client->current_state;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_get_previous_state(ma_h ma, ma_state_e* current_state, ma_state_e* previous_state)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       if (current_state) *current_state = client->current_state;
+       if (previous_state) *previous_state = client->previous_state;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_set_error(ma_h ma, ma_error_e reason)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->reason = reason;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_get_error(ma_h ma, ma_error_e* reason)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       *reason = client->reason;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_set_error_cb(ma_h ma, ma_error_cb callback, void* user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->error_cb = callback;
+       client->error_user_data = user_data;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_get_error_cb(ma_h ma, ma_error_cb* callback, void** user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       *callback = client->error_cb;
+       *user_data = client->error_user_data;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_set_state_changed_cb(ma_h ma, ma_state_changed_cb callback, void* user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->state_changed_cb = callback;
+       client->state_changed_user_data = user_data;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_get_state_changed_cb(ma_h ma, ma_state_changed_cb* callback, void** user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       *callback = client->state_changed_cb;
+       *user_data = client->state_changed_user_data;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_set_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb callback, void* user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->audio_streaming_cb = callback;
+       client->audio_streaming_user_data = user_data;
+
+       return MA_ERROR_NONE;
+}
+
+int ma_ap_client_get_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb* callback, void** user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       *callback = client->audio_streaming_cb;
+       *user_data = client->audio_streaming_user_data;
+
+       return MA_ERROR_NONE;
+}
+//LCOV_EXCL_STOP
+
+int ma_ap_client_set_audio_streaming_data_section_changed_cb(ma_h ma, ma_audio_streaming_data_section_changed_cb callback, void* user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       client->audio_streaming_data_section_changed_cb = callback;
+       client->audio_streaming_data_section_changed_user_data = user_data;
+
+       return MA_ERROR_NONE;
+}
+
+//LCOV_EXCL_START
+int ma_ap_client_get_audio_streaming_data_section_changed_cb(ma_h ma, ma_audio_streaming_data_section_changed_cb* callback, void** user_data)
+{
+       ma_ap_client_s* client = __ap_client_get(ma);
+
+       if (NULL == client)
+               return MA_ERROR_INVALID_PARAMETER;
+
+       *callback = client->audio_streaming_data_section_changed_cb;
+       *user_data = client->audio_streaming_data_section_changed_user_data;
+
+       return MA_ERROR_NONE;
+}
diff --git a/client/ma_ap_client.h b/client/ma_ap_client.h
new file mode 100644 (file)
index 0000000..2f81656
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __MA_AP_CLIENT_H__
+#define __MA_AP_CLIENT_H__
+
+#include "ma_main.h"
+#include "multi_assistant_common.h"
+#include "multi_assistant_ui.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+int ma_ap_client_create(ma_h* ma);
+
+int ma_ap_client_destroy(ma_h ma);
+
+bool ma_ap_client_is_valid(ma_h ma);
+
+int ma_ap_client_get_count(void);
+
+int ma_ap_client_use_callback(ma_h ma);
+
+int ma_ap_client_not_use_callback(ma_h ma);
+
+
+int ma_ap_client_set_client_state(ma_h ma, ma_state_e state);
+
+int ma_ap_client_get_client_state(ma_h ma, ma_state_e* state);
+
+int ma_ap_client_get_previous_state(ma_h ma, ma_state_e* current_state, ma_state_e* previous_state);
+
+int ma_ap_client_set_error(ma_h ma, ma_error_e reason);
+
+int ma_ap_client_get_error(ma_h ma, ma_error_e* reason);
+
+
+int ma_ap_client_set_error_cb(ma_h ma, ma_error_cb callback, void* user_data);
+
+int ma_ap_client_get_error_cb(ma_h ma, ma_error_cb* callback, void** user_data);
+
+int ma_ap_client_set_state_changed_cb(ma_h ma, ma_state_changed_cb callback, void* user_data);
+
+int ma_ap_client_get_state_changed_cb(ma_h ma, ma_state_changed_cb* callback, void** user_data);
+
+int ma_ap_client_set_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb callback, void* user_data);
+
+int ma_ap_client_get_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb* callback, void** user_data);
+
+int ma_ap_client_set_audio_streaming_data_section_changed_cb(ma_h ma, ma_audio_streaming_data_section_changed_cb callback, void* user_data);
+
+int ma_ap_client_get_audio_streaming_data_section_changed_cb(ma_h ma, ma_audio_streaming_data_section_changed_cb* callback, void** user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_AP_CLIENT_H__ */
+
diff --git a/client/ma_ap_dbus.c b/client/ma_ap_dbus.c
new file mode 100644 (file)
index 0000000..9d3e267
--- /dev/null
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "ma_ap_dbus.h"
+#include "ma_defs.h"
+#include "ma_main.h"
+
+#include <message_port.h>
+
+static bool g_streaming_requested = false;
+
+extern int __ma_ap_cb_error(int reason, char* msg);
+extern int __ma_ap_cb_audio_streaming(int event, char* buffer, int len);
+extern int __ma_ap_cb_audio_streaming_data_section_changed(ma_audio_streaming_data_section_e section);
+
+#define STREAMING_BUFFER_SIZE 4096
+
+typedef enum {
+       streaming_data_type_audio_data,
+       streaming_data_type_streaming_section
+} streaming_data_type_e;
+
+typedef struct {
+       unsigned int streaming_data_size;
+       int streaming_data_type;
+       int streaming_data_serial;
+} streaming_data_header;
+
+typedef struct {
+       int event;
+       unsigned int data_size;
+} streaming_data_audio_data_header;
+
+typedef struct {
+       int section;
+} streaming_data_streaming_section_header;
+
+const char *message_port = "ma_streaming_port";
+static int g_local_port_id = -1;
+
+static void message_port_cb(int local_port_id,
+       const char *remote_app_id, const char *remote_port,
+       bool trusted_remote_port, bundle *message, void *user_data)
+{
+       static char pending_buffer[STREAMING_BUFFER_SIZE * 2];
+       static unsigned int pending_buffer_size = 0;
+
+       char buffer[STREAMING_BUFFER_SIZE];
+       size_t size;
+
+       unsigned char *v = NULL;
+       bundle_get_byte(message, "content", (void**)(&v), &size);
+
+       if (size > STREAMING_BUFFER_SIZE) {
+               MA_SLOGE("[ERROR] bundle contains data bigger than %d : %zu", STREAMING_BUFFER_SIZE, size);
+               return;
+       } else {
+               memcpy(buffer, v, size);
+       }
+
+       memcpy(pending_buffer + pending_buffer_size, buffer, size);
+       pending_buffer_size += size;
+
+       while (pending_buffer_size >= sizeof(streaming_data_header)) {
+               streaming_data_header header;
+               memcpy(&header, pending_buffer, sizeof(streaming_data_header));
+               if (pending_buffer_size >= header.streaming_data_size) {
+                       static int last_serial = 0;
+                       if (header.streaming_data_serial != last_serial + 1) {
+                               MA_SLOGE("[ERROR] SERIAL MISMATCH in [%d] : %d => %d",
+                                       header.streaming_data_type, last_serial, header.streaming_data_serial);
+                       }
+                       last_serial = header.streaming_data_serial;
+
+                       if (streaming_data_type_audio_data == header.streaming_data_type) {
+                               streaming_data_audio_data_header audio_data_header;
+                               memcpy(&audio_data_header, pending_buffer + sizeof(streaming_data_header),
+                                       sizeof(streaming_data_audio_data_header));
+
+                               /* Don't invoke audio streaming callback for CONTINUE audio events
+                                       if the streaming request is no more valid, since it would not provide
+                                       any useful information to the client application */
+                               if (g_streaming_requested || MA_AUDIO_STREAMING_EVENT_CONTINUE != audio_data_header.event) {
+                                       __ma_ap_cb_audio_streaming(audio_data_header.event,
+                                               pending_buffer + sizeof(streaming_data_header) + sizeof(streaming_data_audio_data_header),
+                                               audio_data_header.data_size);
+                                       if (0 == header.streaming_data_serial % 50) {
+                                               MA_SLOGI("__ma_ap_cb_audio_streaming() called, serial : %d", header.streaming_data_serial);
+                                       }
+                               }
+                       } else if (streaming_data_type_streaming_section == header.streaming_data_type) {
+                               streaming_data_streaming_section_header streaming_section_header;
+                               memcpy(&streaming_section_header, pending_buffer + sizeof(streaming_data_header),
+                                       sizeof(streaming_data_streaming_section_header));
+
+                               __ma_ap_cb_audio_streaming_data_section_changed(streaming_section_header.section);
+                       }
+
+                       memmove(pending_buffer, pending_buffer + header.streaming_data_size,
+                               sizeof(pending_buffer) - header.streaming_data_size);
+                       pending_buffer_size -= header.streaming_data_size;
+               } else {
+                       break;
+               }
+       }
+}
+
+static int streaming_ipc_initialize()
+{
+       int port_id = message_port_register_local_port(message_port, message_port_cb, NULL);
+       if (port_id < 0) {
+               MA_SLOGD("Port register error: %d", port_id);
+       } else {
+               MA_SLOGD("port_id: %d", port_id);
+               g_local_port_id = port_id;
+       }
+
+       return 0;
+}
+
+static int streaming_ipc_deinitialize()
+{
+       if (-1 != g_local_port_id) message_port_unregister_local_port(g_local_port_id);
+       g_local_port_id = -1;
+       return 0;
+}
+
+int ma_ap_dbus_open_connection()
+{
+       /* For now assume streaming is requested when initialized */
+       g_streaming_requested = true;
+       return streaming_ipc_initialize();
+}
+
+int ma_ap_dbus_close_connection()
+{
+       g_streaming_requested = false;
+       return streaming_ipc_deinitialize();
+}
+
diff --git a/client/ma_ap_dbus.h b/client/ma_ap_dbus.h
new file mode 100644 (file)
index 0000000..f565e06
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __MA_AP_DBUS_H__
+#define __MA_AP_DBUS_H__
+
+#include "multi_assistant_common.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+int ma_ap_dbus_open_connection();
+
+int ma_ap_dbus_close_connection();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_AP_DBUS_H__ */
+
index 0027fbd0c4ef49a6aae5e9fd053069e451bb7a57..dce233759b17503927b153aa8acaff156568828a 100644 (file)
@@ -40,6 +40,7 @@ extern "C"
  *************************************************************************************/
 #define TAG_MAC                        "mac"           /* Multi-assistant client log tag */
 #define TAG_MAUI               "maui"          /* Multi-assistant UI client log tag */
+#define TAG_MAAP               "maap"          /* Multi-assistant AP client log tag */
 
 /**************************************************************************************
  *** Logging macros
@@ -74,6 +75,16 @@ extern "C"
 #define MAUI_SLOGW(fmt, args...) MA_SECURE_LOG_(DLOG_WARN, TAG_MAUI, fmt, ##args)
 #define MAUI_SLOGE(fmt, args...) MA_SECURE_LOG_(DLOG_ERROR, TAG_MAUI, fmt, ##args)
 
+#define MAAP_LOGD(fmt, args...) MA_LOG_(DLOG_DEBUG, TAG_MAAP, fmt, ##args)
+#define MAAP_LOGI(fmt, args...) MA_LOG_(DLOG_INFO, TAG_MAAP, fmt, ##args)
+#define MAAP_LOGW(fmt, args...) MA_LOG_(DLOG_WARN, TAG_MAAP, fmt, ##args)
+#define MAAP_LOGE(fmt, args...) MA_LOG_(DLOG_ERROR, TAG_MAAP, fmt, ##args)
+
+#define MAAP_SLOGD(fmt, args...) MA_SECURE_LOG_(DLOG_DEBUG, TAG_MAAP, fmt, ##args)
+#define MAAP_SLOGI(fmt, args...) MA_SECURE_LOG_(DLOG_INFO, TAG_MAAP, fmt, ##args)
+#define MAAP_SLOGW(fmt, args...) MA_SECURE_LOG_(DLOG_WARN, TAG_MAAP, fmt, ##args)
+#define MAAP_SLOGE(fmt, args...) MA_SECURE_LOG_(DLOG_ERROR, TAG_MAAP, fmt, ##args)
+
 /**************************************************************************************
  *** Structures for multi-assistant handle
  *************************************************************************************/
index 2d2056a30b9abf2184f7e05b448345164aed5e62..923b3b370b14c71a93d5cc091e310a0cbc48ab16 100644 (file)
@@ -1,14 +1,17 @@
 ## configure pkgconfig files ##
 CONFIGURE_FILE(multi-assistant.pc.in multi-assistant.pc @ONLY)
 CONFIGURE_FILE(multi-assistant-ui.pc.in multi-assistant-ui.pc @ONLY)
+CONFIGURE_FILE(multi-assistant-ap.pc.in multi-assistant-ap.pc @ONLY)
 
 ## Install pc files ##
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi-assistant.pc DESTINATION ${LIBDIR}/pkgconfig)
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi-assistant-ui.pc DESTINATION ${LIBDIR}/pkgconfig)
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi-assistant-ap.pc DESTINATION ${LIBDIR}/pkgconfig)
 
 ## Install header files ##
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant.h DESTINATION ${INCLUDEDIR})
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant_ui.h DESTINATION ${INCLUDEDIR})
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant_ap.h DESTINATION ${INCLUDEDIR})
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant_common.h DESTINATION ${INCLUDEDIR})
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant_settings.h DESTINATION ${INCLUDEDIR})
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant_internal.h DESTINATION ${INCLUDEDIR})
index 9f4477ace86a9e099fe6d40b0e7490979d7cffd9..3aa6f4c144d627310ccf20c2e7a590e454df48fb 100644 (file)
@@ -51,6 +51,15 @@ Requires:   %{name} = %{version}-%{release}
 Multi assistant manager header files for MA development.
 
 
+%package ap-devel
+Summary:    Multi assistant manager header files for MA AP development
+Group:      libdevel
+Requires:   %{name} = %{version}-%{release}
+
+%description ap-devel
+Multi assistant manager header files for MA AP development.
+
+
 %if 0%{?gcov:1}
 %package gcov
 Summary:  Multi assistant (gcov)
@@ -106,6 +115,7 @@ mkdir -p %{_libdir}/multiassistant/ma
 %defattr(-,root,root,-)
 %{_libdir}/libma.so
 %{_libdir}/libma_ui.so
+%{_libdir}/libma_ap.so
 %{TZ_SYS_RO_SHARE}/multiassistant/ma/1.0/ma-config.xml
 %{TZ_SYS_RO_SHARE}/dbus-1/services/org.tizen.multiassistant*
 %{TZ_SYS_RO_SHARE}/parser-plugins/multi-assistant.info
@@ -117,6 +127,7 @@ mkdir -p %{_libdir}/multiassistant/ma
 %{_libdir}/pkgconfig/multi-assistant.pc
 %{_includedir}/multi_assistant.h
 %{_includedir}/multi_assistant_ui.h
+%{_includedir}/multi_assistant_ap.h
 %{_includedir}/multi_assistant_common.h
 %{_includedir}/multi_assistant_settings.h
 %{_includedir}/multi_assistant_internal.h
@@ -129,6 +140,12 @@ mkdir -p %{_libdir}/multiassistant/ma
 %{_includedir}/multi_assistant_common.h
 %{_includedir}/multi_assistant_settings.h
 
+%files ap-devel
+%defattr(-,root,root,-)
+%{_libdir}/pkgconfig/multi-assistant-ap.pc
+%{_includedir}/multi_assistant_ap.h
+%{_includedir}/multi_assistant_common.h
+
 %if 0%{?gcov:1}
 %files gcov
 %{_datadir}/gcov/obj/*