Fix NULL pointer dereference
[platform/core/multimedia/libmm-sound.git] / mm_sound_keysound.c
index b2e014b..3c6c95c 100644 (file)
 
 #include "include/mm_sound_common.h"
 
+#ifdef USE_LWIPC
+#include <lwipc.h>
+#define PULSEAUDIO_READY "/tmp/.pulseaudio_ready"
+#endif
+
 #define PA_BUS_NAME                              "org.pulseaudio.Server"
 #define PA_SOUND_PLAYER_OBJECT_PATH              "/org/pulseaudio/SoundPlayer"
 #define PA_SOUND_PLAYER_INTERFACE                "org.pulseaudio.SoundPlayer"
 #define AUDIO_VOLUME_CONFIG_TYPE(vol) (vol & 0x00FF)
 #define AUDIO_VOLUME_CONFIG_GAIN(vol) (vol & 0xFF00)
 
+#define MAX_WRITE_RETRY 50
+#define WRITE_RETRY_INTERVAL_MS 20
+
 typedef struct ipc_data {
-    char filename[FILE_FULL_PATH];
-    char role[ROLE_NAME_LEN];
-    char volume_gain_type[VOLUME_GAIN_TYPE_LEN];
-}ipc_t;
+       char filename[FILE_FULL_PATH];
+       char role[ROLE_NAME_LEN];
+       char volume_gain_type[VOLUME_GAIN_TYPE_LEN];
+} ipc_t;
 
 typedef enum {
        IPC_TYPE_PIPE,
        IPC_TYPE_DBUS,
-}ipc_type_t;
+} ipc_type_t;
 
 static int _mm_sound_play_keysound(const char *filename, int volume_config, ipc_type_t ipc_type);
 
 static const char* convert_volume_type_to_role(int volume_type)
 {
-       debug_warning ("volume_type(%d)", volume_type);
-       switch(volume_type) {
+       debug_log("volume_type(%d)", volume_type);
+       switch (volume_type) {
        case VOLUME_TYPE_MEDIA:
                return "media";
        case VOLUME_TYPE_SYSTEM:
@@ -73,16 +81,18 @@ static const char* convert_volume_type_to_role(int volume_type)
                return "alarm";
        case VOLUME_TYPE_VOICE:
                return "voice";
+       case VOLUME_TYPE_RINGTONE:
+               return "ringtone-call";
        default:
-               debug_warning ("not supported type(%d), we change it SYSTEM type forcibly" );
+               debug_warning("not supported type(%d), we change it SYSTEM type forcibly", volume_type);
                return "system";
        }
 }
 
 static const char* convert_volume_gain_type_to_string(int volume_gain_type)
 {
-       debug_warning ("volume_gain_type(0x%x)", volume_gain_type);
-       switch(volume_gain_type) {
+       debug_log("volume_gain_type(0x%x)", volume_gain_type);
+       switch (volume_gain_type) {
        case VOLUME_GAIN_DEFAULT:
                return "";
        case VOLUME_GAIN_DIALER:
@@ -113,74 +123,108 @@ static const char* convert_volume_gain_type_to_string(int volume_gain_type)
 EXPORT_API
 int mm_sound_play_keysound(const char *filename, int volume_config)
 {
-       return _mm_sound_play_keysound(filename, volume_config, IPC_TYPE_DBUS);
+       return _mm_sound_play_keysound(filename, volume_config, IPC_TYPE_PIPE);
+}
+
+#ifdef USE_LWIPC
+static bool _mm_sound_check_pa_ready()
+{
+       int ret = 0;
+       static bool is_pa_ready = false;
+
+       if (is_pa_ready)
+               return true;
+
+       debug_msg("LwipcIsDone start >> ");
+       ret = LwipcIsDone(PULSEAUDIO_READY);
+       debug_msg("LwipcIsDone end << %d", ret);
+
+       is_pa_ready = (ret > 0) ? true : false;
+
+       return is_pa_ready;
 }
+#endif
 
 static int _mm_sound_play_keysound(const char *filename, int volume_config, ipc_type_t ipc_type)
 {
        int ret = MM_ERROR_NONE;
        const char *role = NULL;
        const char *vol_gain_type = NULL;
+       int retry_remaining = MAX_WRITE_RETRY;
+
+#ifdef USE_LWIPC
+       if (!_mm_sound_check_pa_ready()) {
+               debug_error("Pulseaudio is not ready!");
+               return MM_ERROR_SOUND_INVALID_STATE;
+       }
+#endif
 
        if (!filename)
                return MM_ERROR_SOUND_INVALID_FILE;
 
+       /* Check whether file exists */
+       if (access(filename, F_OK) == -1) {
+               char str_error[256];
+
+               strerror_r(errno, str_error, sizeof(str_error));
+               debug_error("file [%s] doesn't exists : [%s][%d]", filename, str_error, errno);
+
+               return MM_ERROR_SOUND_FILE_NOT_FOUND;
+       }
+
        /* convert volume type to role/volume gain */
        role = convert_volume_type_to_role(AUDIO_VOLUME_CONFIG_TYPE(volume_config));
-       if (role) {
+       if (role)
                vol_gain_type = convert_volume_gain_type_to_string(AUDIO_VOLUME_CONFIG_GAIN(volume_config));
-       }
 
        if (ipc_type == IPC_TYPE_PIPE) {
-               int res = 0;
+               size_t size_to_write = sizeof(ipc_t);
+               ssize_t written = 0;
                int fd = -1;
-               int size = 0;
-               ipc_t data = {{0,},{0,},{0,}};
+               ipc_t data = { { 0, }, { 0, }, { 0, } };
 
-               /* Check whether file exists */
-               fd = open(filename, O_RDONLY);
+               /* Open PIPE */
+               fd = open(KEYTONE_PATH, O_WRONLY | O_NONBLOCK);
                if (fd == -1) {
                        char str_error[256];
+
                        strerror_r(errno, str_error, sizeof(str_error));
-                       debug_error("file open failed with [%s][%d]\n", str_error, errno);
-                       switch (errno) {
-                       case ENOENT:
-                               return MM_ERROR_SOUND_FILE_NOT_FOUND;
-                       default:
-                               return MM_ERROR_SOUND_INTERNAL;
-                       }
-               }
-               close(fd);
-               fd = -1;
+                       debug_error("Fail to open pipe: [%s][%d]", str_error, errno);
 
-               /* Open PIPE */
-               fd = open(KEYTONE_PATH, O_WRONLY | O_NONBLOCK);
-               if (fd == -1) {
-                       debug_error("Fail to open pipe\n");
-                       return MM_ERROR_SOUND_FILE_NOT_FOUND;
+                       return MM_ERROR_SOUND_INTERNAL;
                }
 
                /* convert volume type to role/volume gain */
-               if (role) {
+               if (role)
                        MMSOUND_STRNCPY(data.role, role, ROLE_NAME_LEN);
-               }
-               if (vol_gain_type) {
+               if (vol_gain_type)
                        MMSOUND_STRNCPY(data.volume_gain_type, vol_gain_type, VOLUME_GAIN_TYPE_LEN);
-               }
-
                MMSOUND_STRNCPY(data.filename, filename, FILE_FULL_PATH);
 
-               debug_msg("filepath=[%s], role=[%s], volume_gain_type=[%s]\n", data.filename, data.role, data.volume_gain_type);
-               size = sizeof(ipc_t);
+               debug_msg("filepath=[%s], role=[%s], volume_gain_type=[%s]", data.filename, data.role, data.volume_gain_type);
 
                /* Write to PIPE */
-               res = write(fd, &data, size);
-               if (res < 0) {
-                       char str_error[256];
-                       strerror_r(errno, str_error, sizeof(str_error));
-                       debug_error("Fail to write data: [%s][%d]\n", str_error, errno);
-                       ret = MM_ERROR_SOUND_INTERNAL;
-               }
+               do {
+                       written = write(fd, &data, size_to_write);
+                       if (written == -1) {
+                               char str_error[256];
+                               int errsv = errno;
+
+                               strerror_r(errsv, str_error, sizeof(str_error));
+                               debug_error("[%d] Fail to write, written = %zd, [%s][%d]",
+                                                       MAX_WRITE_RETRY - retry_remaining, written, str_error, errsv);
+
+                               if (errsv != EAGAIN || --retry_remaining == 0) {
+                                       ret = MM_ERROR_SOUND_INTERNAL;
+                                       break;
+                               }
+
+                               usleep(WRITE_RETRY_INTERVAL_MS * 1000);
+                       } else if (retry_remaining != MAX_WRITE_RETRY) {
+                               debug_msg("retry success!!");
+                       }
+               } while (written != size_to_write);
+
                /* Close PIPE */
                close(fd);
 
@@ -191,23 +235,23 @@ static int _mm_sound_play_keysound(const char *filename, int volume_config, ipc_
                int idx = 0;
 
                conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
-               if (!conn && err) {
-                       debug_error("g_bus_get_sync() error (%s)", err->message);
+               if (!conn || err) {
+                       debug_error("g_bus_get_sync() error (%s)", err ? err->message : NULL);
                        ret = MM_ERROR_SOUND_INTERNAL;
                } else {
-                       result = g_dbus_connection_call_sync (conn,
+                       result = g_dbus_connection_call_sync(conn,
                                                                        PA_BUS_NAME,
                                                                        PA_SOUND_PLAYER_OBJECT_PATH,
                                                                        PA_SOUND_PLAYER_INTERFACE,
                                                                        PA_SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY,
-                                                                       g_variant_new ("(sss)", filename, role, vol_gain_type),
+                                                                       g_variant_new("(sss)", filename, role, vol_gain_type),
                                                                        NULL,
                                                                        G_DBUS_CALL_FLAGS_NONE,
                                                                        2000,
                                                                        NULL,
                                                                        &err);
-                       if (!result && err) {
-                               debug_error("g_dbus_connection_call_sync() for SIMPLE_PLAY error (%s)", err->message);
+                       if (!result || err) {
+                               debug_error("g_dbus_connection_call_sync() for SIMPLE_PLAY error (%s)", err ? err->message : NULL);
                                ret = MM_ERROR_SOUND_INTERNAL;
                        } else {
                                g_variant_get(result, "(i)", &idx);
@@ -221,9 +265,7 @@ static int _mm_sound_play_keysound(const char *filename, int volume_config, ipc_
                        }
                        g_object_unref(conn);
                }
-               if (err) {
-                       g_error_free(err);
-               }
+               g_error_free(err);
        }
 
        return ret;