../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)
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)
--- /dev/null
+/**
+ * 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, ¤t_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
--- /dev/null
+/**
+ * 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;
+}
--- /dev/null
+/**
+ * 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__ */
+
--- /dev/null
+/**
+ * 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();
+}
+
--- /dev/null
+/**
+ * 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__ */
+
*************************************************************************************/
#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
#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
*************************************************************************************/
## 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})
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)
%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
%{_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
%{_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/*