[SQE][LibFuzzer] Fix opened file descriptors cleanup in libmm-sound
[platform/core/multimedia/libmm-sound.git] / mm_sound_device.c
index e6d3b26..fc72e58 100644 (file)
 
 #include <stdlib.h>
 #include <unistd.h>
-#include <stdio.h>
-#include <vconf.h>
 
 #include <mm_debug.h>
 
 #include "include/mm_sound.h"
 #include "include/mm_sound_device.h"
+#include "include/mm_sound_client.h"
 
-bool is_new_device_list = true;
+#define VOLUME_TYPE_LEN 64
 
-static int check_for_valid_mask (mm_sound_device_flags_e flags)
+mm_sound_device_list_t g_device_list;
+pthread_mutex_t g_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int _check_for_valid_mask (int flags)
 {
        int ret = MM_ERROR_NONE;
        bool at_least_cond = false;
@@ -63,18 +65,64 @@ static int check_for_valid_mask (mm_sound_device_flags_e flags)
        return ret;
 }
 
+static int __convert_device_type_to_enum (char *device_type, mm_sound_device_type_e *device_type_enum)
+{
+       int ret = MM_ERROR_NONE;
+
+       if (!device_type || !device_type_enum) {
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       if (!strncmp(device_type, "builtin-speaker", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER;
+       } else if (!strncmp(device_type, "builtin-receiver", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER;
+       } else if (!strncmp(device_type, "builtin-mic", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_BUILTIN_MIC;
+       } else if (!strncmp(device_type, "audio-jack", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_AUDIOJACK;
+       } else if (!strncmp(device_type, "bt-a2dp", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP;
+       } else if (!strncmp(device_type, "bt-sco", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO;
+       } else if (!strncmp(device_type, "hdmi", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_HDMI;
+       } else if (!strncmp(device_type, "forwarding", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_MIRRORING;
+       } else if (!strncmp(device_type, "usb-audio", VOLUME_TYPE_LEN)) {
+               *device_type_enum = MM_SOUND_DEVICE_TYPE_USB_AUDIO;
+       } else {
+               ret = MM_ERROR_INVALID_ARGUMENT;
+               debug_error("not supported device_type(%s), err(0x%08x)", device_type, ret);
+       }
+
+       return ret;
+}
+
+static int __free_device_list(mm_sound_device_list_t *device_list_t)
+{
+       if (!device_list_t)
+               return MM_ERROR_INVALID_ARGUMENT;
+
+       debug_log("free device list %p", device_list_t);
+       g_list_free_full(device_list_t->list, g_free);
+       g_free(device_list_t);
+
+       return MM_ERROR_NONE;
+}
+
 EXPORT_API
-int mm_sound_add_device_connected_callback(mm_sound_device_flags_e flags, mm_sound_device_connected_cb func, void *user_data)
+int mm_sound_add_device_connected_callback(int flags, mm_sound_device_connected_cb func, void *user_data, unsigned int *id)
 {
        int ret = MM_ERROR_NONE;
 
-       if (func == NULL) {
+       if (func == NULL || id == NULL) {
                debug_error("argument is not valid\n");
                return MM_ERROR_INVALID_ARGUMENT;
        }
-       ret = check_for_valid_mask(flags);
+       ret = _check_for_valid_mask(flags);
        if (ret == MM_ERROR_NONE) {
-               ret = _mm_sound_client_add_device_connected_callback(flags, func, user_data);
+               ret = mm_sound_client_add_device_connected_callback(flags, func, user_data, id);
                if (ret < 0) {
                        debug_error("Could not add device connected callback, ret = %x\n", ret);
                }
@@ -84,11 +132,11 @@ int mm_sound_add_device_connected_callback(mm_sound_device_flags_e flags, mm_sou
 }
 
 EXPORT_API
-int mm_sound_remove_device_connected_callback(void)
+int mm_sound_remove_device_connected_callback(unsigned int id)
 {
        int ret = MM_ERROR_NONE;
 
-       ret = _mm_sound_client_remove_device_connected_callback();
+       ret = mm_sound_client_remove_device_connected_callback(id);
        if (ret < 0) {
                debug_error("Could not remove device connected callback, ret = %x\n", ret);
        }
@@ -97,17 +145,17 @@ int mm_sound_remove_device_connected_callback(void)
 }
 
 EXPORT_API
-int mm_sound_add_device_information_changed_callback(mm_sound_device_flags_e flags, mm_sound_device_info_changed_cb func, void *user_data)
+int mm_sound_add_device_information_changed_callback(int flags, mm_sound_device_info_changed_cb func, void *user_data, unsigned int *id)
 {
        int ret = MM_ERROR_NONE;
 
-       if (func == NULL) {
+       if (func == NULL || id == NULL) {
                debug_error("argument is not valid\n");
                return MM_ERROR_INVALID_ARGUMENT;
        }
-       ret = check_for_valid_mask(flags);
+       ret = _check_for_valid_mask(flags);
        if (ret == MM_ERROR_NONE) {
-               ret = _mm_sound_client_add_device_info_changed_callback(flags, func, user_data);
+               ret = mm_sound_client_add_device_info_changed_callback(flags, func, user_data, id);
                if (ret < 0) {
                        debug_error("Could not add device information changed callback, ret = %x\n", ret);
                }
@@ -117,11 +165,11 @@ int mm_sound_add_device_information_changed_callback(mm_sound_device_flags_e fla
 }
 
 EXPORT_API
-int mm_sound_remove_device_information_changed_callback()
+int mm_sound_remove_device_information_changed_callback(unsigned int id)
 {
        int ret = MM_ERROR_NONE;
 
-       ret = _mm_sound_client_remove_device_info_changed_callback();
+       ret = mm_sound_client_remove_device_info_changed_callback(id);
        if (ret < 0) {
                debug_error("Could not remove device information changed callback, ret = %x\n", ret);
        }
@@ -130,20 +178,19 @@ int mm_sound_remove_device_information_changed_callback()
 }
 
 EXPORT_API
-int mm_sound_get_current_device_list(mm_sound_device_flags_e flags, MMSoundDeviceList_t *device_list)
+int mm_sound_add_device_state_changed_callback(int flags, mm_sound_device_state_changed_cb func, void *user_data, unsigned int *id)
 {
        int ret = MM_ERROR_NONE;
 
-       if (!device_list) {
+       if (func == NULL || id == NULL) {
+               debug_error("argument is not valid\n");
                return MM_ERROR_INVALID_ARGUMENT;
        }
-       ret = check_for_valid_mask(flags);
+       ret = _check_for_valid_mask(flags);
        if (ret == MM_ERROR_NONE) {
-               ret = _mm_sound_client_get_current_connected_device_list(flags, (mm_sound_device_list_t**)device_list);
+               ret = mm_sound_client_add_device_state_changed_callback(flags, func, user_data, id);
                if (ret < 0) {
-                       debug_error("Could not get current connected device list, ret = %x\n", ret);
-               } else {
-                       is_new_device_list = true;
+                       debug_error("Could not add device state changed callback, ret = %x\n", ret);
                }
        }
 
@@ -151,17 +198,134 @@ int mm_sound_get_current_device_list(mm_sound_device_flags_e flags, MMSoundDevic
 }
 
 EXPORT_API
+int mm_sound_remove_device_state_changed_callback(unsigned int id)
+{
+       int ret = MM_ERROR_NONE;
+
+       ret = mm_sound_client_remove_device_state_changed_callback(id);
+       if (ret < 0) {
+               debug_error("Could not remove device state changed callback, ret = %x\n", ret);
+       }
+
+       return ret;
+}
+
+
+EXPORT_API
+int mm_sound_get_current_device_list(mm_sound_device_flags_e flags, MMSoundDeviceList_t *device_list)
+{
+       int ret = MM_ERROR_NONE;
+
+       if (!device_list) {
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+       ret = _check_for_valid_mask(flags);
+       if (ret != MM_ERROR_NONE) {
+               debug_error("mask[0x%x] is invalid, ret=0x%x", flags, ret);
+               return ret;
+       }
+
+       pthread_mutex_lock(&g_thread_mutex);
+
+       if (g_device_list.list != NULL) {
+               g_list_free_full(g_device_list.list, g_free);
+               g_device_list.list = NULL;
+       }
+
+       g_device_list.is_new_device_list = true;
+
+       ret = mm_sound_client_get_current_connected_device_list(flags, &g_device_list);
+       if (ret < 0) {
+               debug_error("Could not get current connected device list, ret = %x\n", ret);
+               g_device_list.list = NULL;
+       } else {
+               *device_list = &g_device_list;
+       }
+
+       pthread_mutex_unlock(&g_thread_mutex);
+
+       return ret;
+}
+
+EXPORT_API
+int mm_sound_get_device_list(int flags, MMSoundDeviceList_t *device_list)
+{
+       int ret = MM_ERROR_NONE;
+       mm_sound_device_list_t *_device_list;
+
+       if (!device_list) {
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+       ret = _check_for_valid_mask(flags);
+       if (ret != MM_ERROR_NONE) {
+               debug_error("mask[0x%x] is invalid, ret=0x%x", flags, ret);
+               return ret;
+       }
+
+       if (!(_device_list = g_malloc0(sizeof(mm_sound_device_list_t)))) {
+               debug_error("[Client] Allocate device list failed");
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       _device_list->is_new_device_list = true;
+
+       ret = mm_sound_client_get_current_connected_device_list(flags, _device_list);
+       if (ret < 0) {
+               debug_error("Could not get current connected device list, ret = %x\n", ret);
+               g_free(_device_list);
+       } else {
+               *device_list = _device_list;
+       }
+
+       return ret;
+}
+
+EXPORT_API
+int mm_sound_free_device_list(MMSoundDeviceList_t device_list)
+{
+       return __free_device_list((mm_sound_device_list_t*) device_list);
+}
+
+EXPORT_API
+int mm_sound_free_device(MMSoundDevice_t device_h)
+{
+       if (device_h == NULL)
+               return MM_ERROR_INVALID_ARGUMENT;
+
+       g_free(device_h);
+
+       return MM_ERROR_NONE;
+}
+
+EXPORT_API
+int mm_sound_get_device_by_id(int device_id, MMSoundDevice_t *device_h)
+{
+       int ret = MM_ERROR_NONE;
+       mm_sound_device_t *device = NULL;
+
+       if (device_id < 1 || device_h == NULL)
+               return MM_ERROR_INVALID_ARGUMENT;
+
+       ret = mm_sound_client_get_device_by_id(device_id, &device);
+       if (ret < 0)
+               debug_error("Could not get device by id, ret = %x\n", ret);
+       else
+               *device_h = device;
+
+       return ret;
+}
+
+EXPORT_API
 int mm_sound_get_next_device (MMSoundDeviceList_t device_list, MMSoundDevice_t *device)
 {
        int ret = MM_ERROR_NONE;
        mm_sound_device_list_t *device_list_t = NULL;
-       mm_sound_device_t *device_h = NULL;
        GList *node = NULL;
        if (!device_list || !device) {
                return MM_ERROR_INVALID_ARGUMENT;
        }
        device_list_t = (mm_sound_device_list_t*) device_list;
-       if (is_new_device_list) {
+       if (device_list_t->is_new_device_list) {
                node = g_list_first(device_list_t->list);
        } else {
                node = g_list_next(device_list_t->list);
@@ -169,8 +333,8 @@ int mm_sound_get_next_device (MMSoundDeviceList_t device_list, MMSoundDevice_t *
        if (!node) {
                ret = MM_ERROR_SOUND_NO_DATA;
        } else {
-               if (is_new_device_list) {
-                       is_new_device_list = false;
+               if (device_list_t->is_new_device_list) {
+                       device_list_t->is_new_device_list = false;
                } else {
                        device_list_t->list = node;
                }
@@ -185,7 +349,6 @@ int mm_sound_get_prev_device (MMSoundDeviceList_t device_list, MMSoundDevice_t *
 {
        int ret = MM_ERROR_NONE;
        mm_sound_device_list_t *device_list_t = NULL;
-       mm_sound_device_t *device_h = NULL;
        GList *node = NULL;
        if (!device_list || !device) {
                return MM_ERROR_INVALID_ARGUMENT;
@@ -207,11 +370,11 @@ EXPORT_API
 int mm_sound_get_device_type(MMSoundDevice_t device_h, mm_sound_device_type_e *type)
 {
        mm_sound_device_t *device = (mm_sound_device_t*)device_h;
-       if(!device) {
-               debug_error("invalid handle\n");
+       if(!device || !type) {
+               debug_error("invalid argument\n");
                return MM_ERROR_INVALID_ARGUMENT;
        }
-       *type = device->type;
+       __convert_device_type_to_enum(device->type, type);
        debug_log("device_handle:0x%x, type:%d\n", device, *type);
 
        return MM_ERROR_NONE;
@@ -226,7 +389,7 @@ int mm_sound_get_device_io_direction(MMSoundDevice_t device_h, mm_sound_device_i
                return MM_ERROR_INVALID_ARGUMENT;
        }
        *io_direction = device->io_direction;
-       debug_log("device_handle:0x%x, io_direction:%d (0:IN,1:OUT,2:INOUT)\n", device, *io_direction);
+       debug_log("device_handle:0x%x, io_direction:%d (1:IN,2:OUT,3:INOUT)\n", device, *io_direction);
 
        return MM_ERROR_NONE;
 }
@@ -239,8 +402,8 @@ int mm_sound_get_device_id(MMSoundDevice_t device_h, int *id)
                debug_error("invalid handle\n");
                return MM_ERROR_INVALID_ARGUMENT;
        }
-       debug_log("device_handle:0x%x, id:%d\n", device, *id);
        *id = device->id;
+       debug_log("device_handle:0x%x, id:%d\n", device, *id);
 
        return MM_ERROR_NONE;
 }
@@ -253,8 +416,8 @@ int mm_sound_get_device_state(MMSoundDevice_t device_h, mm_sound_device_state_e
                debug_error("invalid handle\n");
                return MM_ERROR_INVALID_ARGUMENT;
        }
-       debug_log("device_handle:0x%x, state:%d (0:INACTIVATED,1:ACTIVATED)\n", device, *state);
        *state = device->state;
+       debug_log("device_handle:0x%x, state:%d (0:INACTIVATED,1:ACTIVATED)\n", device, *state);
 
        return MM_ERROR_NONE;
 }
@@ -273,3 +436,38 @@ int mm_sound_get_device_name(MMSoundDevice_t device_h, char **name)
        return MM_ERROR_NONE;
 }
 
+EXPORT_API
+int mm_sound_is_stream_on_device(int stream_id, MMSoundDevice_t device_h, bool *is_on)
+{
+       int ret = MM_ERROR_NONE;
+       int i;
+       mm_sound_device_t *device = (mm_sound_device_t*)device_h;
+       bool _is_on = false;
+
+       if(!device || !is_on) {
+               debug_error("invalid argument\n");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       if (device->stream_num >= 0) {
+               debug_log("device_handle has stream id");
+               for (i = 0; i < device->stream_num; i++) {
+                       if (device->stream_id[i] == stream_id) {
+                               _is_on = true;
+                               break;
+                       }
+               }
+       } else {
+               debug_log("device_handle dosn't have stream id");
+               /* No information about stream in client-side, should ask to server-side */
+               if ((ret = mm_sound_client_is_stream_on_device(stream_id, device->id, &_is_on)) < 0) {
+                       debug_error("Failed to query is stream on");
+                       return MM_ERROR_SOUND_INTERNAL;
+               }
+       }
+
+       debug_log("device(%d) %s stream(%d)\n", device->id, _is_on ? "has" : "doesn't have", stream_id);
+       *is_on = _is_on;
+
+       return ret;
+}