Sync internal API behavior with product code
[platform/core/system/libsvi.git] / src / feedback.c
index 7cb65be..02e083a 100644 (file)
 #include <limits.h>
 
 #include "feedback.h"
+#include "feedback-internal.h"
 #include "profiles.h"
 #include "devices.h"
 #include "log.h"
+#include "dbus.h"
 
 #ifndef API
 #define API __attribute__ ((visibility("default")))
 #endif
 
-static bool binit;
+static unsigned int init_cnt;
+static pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;
+
+//LCOV_EXCL_START Not called Callback
+static int restart_callback()
+{
+       const struct device_ops *dev;
+
+       dev = find_device(FEEDBACK_TYPE_VIBRATION);
+       if (!dev) {
+               _E("Not supported device : type(FEEDBACK_TYPE_VIBRATION)"); //LCOV_EXCL_LINE
+               return -1;
+       }
+       if (dev->init)
+               dev->init();
+       return 0;
+}
+//LCOV_EXCL_STOP
 
 API int feedback_initialize(void)
 {
-       if (binit)
-               return FEEDBACK_ERROR_NONE;
+       int ret;
 
+       pthread_mutex_lock(&fmutex);
        if (!profile) {
-               _E("there is no valid profile module.");
-               return FEEDBACK_ERROR_NOT_SUPPORTED;
+               _E("there is no valid profile module."); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NOT_SUPPORTED; //LCOV_EXCL_LINE System Error
+       }
+
+       if (init_cnt++ > 0) {
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NONE;
        }
 
+       ret = register_signal_handler(restart_callback);
+       if (ret < 0)
+               _E("Fail to register signal handler: %d", ret); //LCOV_EXCL_LINE System Error
+
        /* initialize device */
        devices_init();
 
@@ -49,14 +78,28 @@ API int feedback_initialize(void)
        if (profile->init)
                profile->init();
 
-       binit = true;
+       pthread_mutex_unlock(&fmutex);
        return FEEDBACK_ERROR_NONE;
 }
 
 API int feedback_deinitialize(void)
 {
-       if (!binit)
+       int ret;
+
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               pthread_mutex_unlock(&fmutex);
                return FEEDBACK_ERROR_NOT_INITIALIZED;
+       }
+
+       if (init_cnt-- > 1) {
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NONE;
+       }
+
+       ret = unregister_signal_handler(restart_callback);
+       if (ret < 0)
+               _E("Fail to unregister signal handler: %d", ret); //LCOV_EXCL_LINE System Error
 
        /* deinitialize device */
        devices_exit();
@@ -65,21 +108,45 @@ API int feedback_deinitialize(void)
        if (profile->exit)
                profile->exit();
 
-       binit = false;
+       pthread_mutex_unlock(&fmutex);
        return FEEDBACK_ERROR_NONE;
 }
 
+static feedback_pattern_e check_pattern(feedback_type_e type, feedback_pattern_e pattern, const char *func)
+{
+    feedback_pattern_e switched = pattern;
+    bool result = false;
+
+    if (type < FEEDBACK_TYPE_NONE || type >= FEEDBACK_TYPE_END)
+        type = FEEDBACK_TYPE_NONE;
+
+    /* if you need to switch pattern */
+    if (profile->get_switched_pattern)
+        result = profile->get_switched_pattern(pattern, &switched);
+
+    if (pattern != switched && result)
+        _W("pattern is changed : %s %s(%d) -> %s(%d) by %s", //LCOV_EXCL_LINE
+                profile->str_type[type],
+                profile->str_pattern(pattern), pattern , profile->str_pattern(switched), switched, func);
+    else
+        _W("pattern is : %s %s(%d) by %s", //LCOV_EXCL_LINE
+                profile->str_type[type],
+                profile->str_pattern(pattern), pattern, func);
+    return switched;
+}
+
 API int feedback_play(feedback_pattern_e pattern)
 {
        int err;
-       bool result;
-       int switched;
 
        /* check initialize */
-       if (!binit) {
-               _E("Not initialized");
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
                return FEEDBACK_ERROR_NOT_INITIALIZED;
        }
+       pthread_mutex_unlock(&fmutex);
 
        if (pattern <= FEEDBACK_PATTERN_NONE ||
            pattern >= profile->max_pattern) {
@@ -87,18 +154,9 @@ API int feedback_play(feedback_pattern_e pattern)
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
-       /* if you need to switch pattern */
-       if (profile->get_switched_pattern) {
-               result = profile->get_switched_pattern(pattern, &switched);
-               if (result) {
-                       _W("pattern is changed : (%s) -> (%s)",
-                                       profile->str_pattern[pattern], profile->str_pattern[switched]);
-                       pattern = switched;
-               }
-       }
-
+       _D("request all type with pattern %s(%d)", profile->str_pattern(pattern), pattern);
        /* play all device */
-       err = devices_play(pattern);
+       err = devices_play(check_pattern(FEEDBACK_TYPE_NONE, pattern, __func__), false);
        /**
         * devices_play() returns error even if all devices are failed.
         * It means if to play anything is successful,
@@ -116,14 +174,15 @@ API int feedback_play_type(feedback_type_e type, feedback_pattern_e pattern)
 {
        const struct device_ops *dev;
        int err;
-       bool result;
-       int switched;
 
        /* check initialize */
-       if (!binit) {
-               _E("Not initialized");
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
                return FEEDBACK_ERROR_NOT_INITIALIZED;
        }
+       pthread_mutex_unlock(&fmutex);
 
        if (type <= FEEDBACK_TYPE_NONE ||
            type >= profile->max_type) {
@@ -137,27 +196,17 @@ API int feedback_play_type(feedback_type_e type, feedback_pattern_e pattern)
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
-       /* if you need to switch pattern */
-       if (profile->get_switched_pattern) {
-               result = profile->get_switched_pattern(pattern, &switched);
-               if (result) {
-                       _W("pattern is changed : (%s) -> (%s)",
-                                       profile->str_pattern[pattern], profile->str_pattern[switched]);
-                       pattern = switched;
-               }
-       }
-
        /* play proper device */
        dev = find_device(type);
        if (!dev) {
-               _E("Not supported device : type(%s)", profile->str_type[type]);
+               _E("Not supported device : type(%s)", profile->str_type[type]); //LCOV_EXCL_LINE
                return FEEDBACK_ERROR_NOT_SUPPORTED;
        }
 
-       err = dev->play(pattern);
+       err = dev->play(check_pattern(type, pattern, __func__), false);
        if (err == -ENOTSUP)
                return FEEDBACK_ERROR_NOT_SUPPORTED;
-       else if (err == -ECOMM)
+       else if (err == -ECOMM || err == -EACCES)
                return FEEDBACK_ERROR_PERMISSION_DENIED;
        else if (err < 0)
                return FEEDBACK_ERROR_OPERATION_FAILED;
@@ -170,16 +219,19 @@ API int feedback_stop(void)
        int err;
 
        /* check initialize */
-       if (!binit) {
-               _E("Not initialized");
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
                return FEEDBACK_ERROR_NOT_INITIALIZED;
        }
+       pthread_mutex_unlock(&fmutex);
 
        /* stop all device */
        err = devices_stop();
        if (err == -ENOTSUP)
                return FEEDBACK_ERROR_NOT_SUPPORTED;
-       else if (err == -ECOMM)
+       else if (err == -ECOMM || err == -EACCES)
                return FEEDBACK_ERROR_PERMISSION_DENIED;
        else if (err < 0)
                return FEEDBACK_ERROR_OPERATION_FAILED;
@@ -192,14 +244,15 @@ API int feedback_is_supported_pattern(feedback_type_e type, feedback_pattern_e p
        const struct device_ops *dev;
        bool supported;
        int err;
-       bool result;
-       int switched;
 
        /* check initialize */
-       if (!binit) {
-               _E("Not initialized");
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
                return FEEDBACK_ERROR_NOT_INITIALIZED;
        }
+       pthread_mutex_unlock(&fmutex);
 
        if (!status) {
                _E("Invalid parameter : status(NULL)");
@@ -218,26 +271,20 @@ API int feedback_is_supported_pattern(feedback_type_e type, feedback_pattern_e p
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
-       /* if you need to switch pattern */
-       if (profile->get_switched_pattern) {
-               result = profile->get_switched_pattern(pattern, &switched);
-               if (result) {
-                       _W("pattern is changed : (%s) -> (%s)",
-                                       profile->str_pattern[pattern], profile->str_pattern[switched]);
-                       pattern = switched;
-               }
-       }
-
        /* play proper device */
        dev = find_device(type);
        if (!dev) {
-               _E("Not supported device : type(%s)", profile->str_type[type]);
+               _E("Not supported device : type(%s)", profile->str_type[type]); //LCOV_EXCL_LINE
                return FEEDBACK_ERROR_NOT_SUPPORTED;
        }
 
-       err = dev->is_supported(pattern, &supported);
-       if (err < 0) {
-               _E("fail to invoke is_supported() : pattern(%s)", profile->str_pattern[pattern]);
+       err = dev->is_supported(check_pattern(type, pattern, __func__), &supported);
+       if (err == -ENOTSUP)
+               return FEEDBACK_ERROR_NOT_SUPPORTED; //LCOV_EXCL_LINE System Error
+       else if (err == -ECOMM || err == -EACCES)
+               return FEEDBACK_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE System Error
+       else if (err < 0) {
+               _E("fail to invoke is_supported() : pattern(%d)", pattern); //LCOV_EXCL_LINE
                return FEEDBACK_ERROR_OPERATION_FAILED;
        }
 
@@ -255,7 +302,7 @@ API int feedback_play_type_by_name(char *type, char *pattern)
        int pattern_max;
 
        if (!type || !pattern) {
-               _E("Invalid parameter : type(%x), pattern(%x)", type, pattern);
+               _E("Invalid parameter : type(%s), pattern(%s)", type, pattern);
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
@@ -272,7 +319,7 @@ API int feedback_play_type_by_name(char *type, char *pattern)
 
        pattern_max = profile->max_pattern;
        for (epattern = 0; epattern < pattern_max; ++epattern) {
-               if (!strncmp(pattern, profile->str_pattern[epattern], strlen(pattern)))
+               if (!strncmp(pattern, profile->str_pattern(epattern), strlen(pattern)))
                        break;
        }
 
@@ -284,45 +331,140 @@ API int feedback_play_type_by_name(char *type, char *pattern)
        return feedback_play_type(etype, epattern);
 }
 
-API int feedback_get_resource_path(feedback_type_e type, feedback_pattern_e pattern, char** path)
+API int feedback_play_internal(feedback_pattern_internal_e pattern)
 {
-       const struct device_ops *dev;
-       char buf[PATH_MAX] = {0,};
        int err;
 
-       if (path == NULL) {
-               _E("Invalid parameter : path(NULL)");
+       /* check initialize */
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NOT_INITIALIZED;
+       }
+       pthread_mutex_unlock(&fmutex);
+
+       if (pattern <= FEEDBACK_PATTERN_INTERNAL_NONE ||
+           pattern >= profile->max_pattern) {
+               _E("Invalid parameter : pattern(%d)", pattern);
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
+       _D("request all type with pattern %s(%d)", profile->str_pattern(pattern), pattern);
+       /* play all device */
+       err = devices_play(check_pattern(FEEDBACK_TYPE_NONE, pattern, __func__), true);
+       /**
+        * devices_play() returns error even if all devices are failed.
+        * It means if to play anything is successful,
+        * this function regards as success.
+        */
+       if (err == -ENOTSUP)
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       else if (err < 0)
+               return FEEDBACK_ERROR_OPERATION_FAILED;
+
+       return FEEDBACK_ERROR_NONE;
+}
+
+API int feedback_play_type_internal(feedback_type_e type, feedback_pattern_internal_e pattern)
+{
+       const struct device_ops *dev;
+       int err;
+
+       /* check initialize */
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NOT_INITIALIZED;
+       }
+       pthread_mutex_unlock(&fmutex);
+
        if (type <= FEEDBACK_TYPE_NONE ||
            type >= profile->max_type) {
                _E("Invalid parameter : type(%d)", type);
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
-       if (pattern <= FEEDBACK_PATTERN_NONE ||
+       if (pattern <= FEEDBACK_PATTERN_INTERNAL_NONE ||
            pattern >= profile->max_pattern) {
                _E("Invalid parameter : pattern(%d)", pattern);
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
-       /* proper device get path */
+       /* play proper device */
        dev = find_device(type);
-       if (dev) {
-               err = dev->get_path(pattern, buf, sizeof(buf));
-               if (err < 0)
-                       return FEEDBACK_ERROR_OPERATION_FAILED;
+       if (!dev) {
+               _E("Not supported device : type(%s)", profile->str_type[type]); //LCOV_EXCL_LINE
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       }
+       _D("request type %s with pattern %s(%d)", profile->str_type[type], profile->str_pattern(pattern), pattern);
+       err = dev->play(check_pattern(type, pattern, __func__), true);
+       if (err == -ENOTSUP)
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       else if (err == -ECOMM || err == -EACCES)
+               return FEEDBACK_ERROR_PERMISSION_DENIED;
+       else if (err < 0)
+               return FEEDBACK_ERROR_OPERATION_FAILED;
+
+       return FEEDBACK_ERROR_NONE;
+}
+
+API int feedback_play_soundpath_internal(feedback_pattern_internal_e internal_pattern, const char *soundpath)
+{
+       int err;
+       feedback_pattern_e pattern = (feedback_pattern_e)internal_pattern;
+
+       /* check initialize */
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NOT_INITIALIZED;
+       }
+       pthread_mutex_unlock(&fmutex);
+
+       if (pattern <= FEEDBACK_PATTERN_NONE ||
+               pattern >= profile->max_pattern) {
+               _E("Invalid parameter : pattern(%d)", pattern);
+               return FEEDBACK_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!soundpath) {
+               _E("Invalid parameter : pattern path(NULL)");
+               return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
-       *path = strdup(buf);
+       _D("request all type with pattern %s(%d), soundpath %s", profile->str_pattern(pattern), pattern, soundpath);
+       /* play all device */
+       err = devices_play_soundpath(check_pattern(FEEDBACK_TYPE_NONE, pattern, __func__), soundpath, true);
+       /**
+        * devices_play() returns error even if all devices are failed.
+        * It means if to play anything is successful,
+        * this function regards as success.
+        */
+       if (err == -ENOTSUP)
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       else if (err < 0)
+               return FEEDBACK_ERROR_OPERATION_FAILED;
+
        return FEEDBACK_ERROR_NONE;
 }
 
-API int feedback_set_resource_path(feedback_type_e type, feedback_pattern_e pattern, char *path)
+API int feedback_play_type_soundpath_internal(feedback_type_e type, feedback_pattern_internal_e internal_pattern, const char *soundpath)
 {
        const struct device_ops *dev;
        int err;
+       feedback_pattern_e pattern = (feedback_pattern_e)internal_pattern;
+
+       /* check initialize */
+       pthread_mutex_lock(&fmutex);
+       if (!init_cnt) {
+               _E("Not initialized"); //LCOV_EXCL_LINE
+               pthread_mutex_unlock(&fmutex);
+               return FEEDBACK_ERROR_NOT_INITIALIZED;
+       }
+       pthread_mutex_unlock(&fmutex);
 
        if (type <= FEEDBACK_TYPE_NONE ||
            type >= profile->max_type) {
@@ -336,13 +478,36 @@ API int feedback_set_resource_path(feedback_type_e type, feedback_pattern_e patt
                return FEEDBACK_ERROR_INVALID_PARAMETER;
        }
 
-       /* proper device set path */
+       if ((type == FEEDBACK_TYPE_SOUND) && (soundpath == NULL)) {
+               _E("Invalid parameter : sound path(NULL)");
+               return FEEDBACK_ERROR_INVALID_PARAMETER;
+       }
+
+       /* play proper device */
        dev = find_device(type);
-       if (dev) {
-               err = dev->set_path(pattern, path);
-               if (err < 0)
-                       return FEEDBACK_ERROR_OPERATION_FAILED;
+       if (!dev) {
+               _E("Not supported device : type(%s)", profile->str_type[type]); //LCOV_EXCL_LINE
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
        }
+       _D("request type %s with pattern(%s), soundpath(%s)", profile->str_type[type], profile->str_pattern(pattern), soundpath?soundpath:"NULL");
+       if (type == FEEDBACK_TYPE_SOUND) {
+               if (dev->play_path)
+                       err = dev->play_path(check_pattern(type, pattern, __func__), soundpath, true);
+               else
+                       err = -ENOTSUP; //LCOV_EXCL_LINE
+       } else {
+               if (dev->play)
+                       err = dev->play(check_pattern(type, pattern, __func__), true);
+               else
+                       err = -ENOTSUP; //LCOV_EXCL_LINE
+       }
+
+       if (err == -ENOTSUP)
+               return FEEDBACK_ERROR_NOT_SUPPORTED;
+       else if (err == -ECOMM || err == -EACCES)
+               return FEEDBACK_ERROR_PERMISSION_DENIED;
+       else if (err < 0)
+               return FEEDBACK_ERROR_OPERATION_FAILED;
 
        return FEEDBACK_ERROR_NONE;
 }