#include <stdbool.h>
#include <string.h>
#include <limits.h>
-#include <vconf.h>
#include "feedback.h"
-#include "common.h"
-#include "log.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
-int callstatus;
+static unsigned int init_cnt;
+static pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;
-static bool binit;
-
-static void feedback_callstatus_cb(keynode_t *key, void* data)
+//LCOV_EXCL_START Not called Callback
+static int restart_callback()
{
- callstatus = vconf_keynode_get_int(key);
-}
+ const struct device_ops *dev;
-static feedback_pattern_e get_alert_on_call_key(feedback_pattern_e pattern)
-{
- switch(pattern) {
- case FEEDBACK_PATTERN_MESSAGE:
- case FEEDBACK_PATTERN_EMAIL:
- case FEEDBACK_PATTERN_WAKEUP:
- case FEEDBACK_PATTERN_SCHEDULE:
- case FEEDBACK_PATTERN_TIMER:
- case FEEDBACK_PATTERN_GENERAL:
- case FEEDBACK_PATTERN_CHARGERCONN:
- case FEEDBACK_PATTERN_FULLCHARGED:
- case FEEDBACK_PATTERN_LOWBATT:
- return (feedback_pattern_e)(pattern+1);
- default:
- break;
- }
-
- return pattern;
+ 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()
+API int feedback_initialize(void)
{
- if (binit)
- return FEEDBACK_ERROR_NONE;
+ int ret;
- /* check call status */
- if (vconf_get_int(VCONFKEY_CALL_STATE, &callstatus) < 0)
- FEEDBACK_ERROR("vconf_get_int(VCONFKEY_CALL_STATE, &callstatus) ==> FAIL!!");
+ pthread_mutex_lock(&fmutex);
+ if (!profile) {
+ _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;
+ }
- /* add watch for status value */
- vconf_notify_key_changed(VCONFKEY_CALL_STATE, feedback_callstatus_cb, NULL);
+ 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();
- binit = true;
+ /* initialize profile feature */
+ if (profile->init)
+ profile->init();
+
+ pthread_mutex_unlock(&fmutex);
return FEEDBACK_ERROR_NONE;
}
-API int feedback_deinitialize()
+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;
+ }
- vconf_ignore_key_changed(VCONFKEY_CALL_STATE, feedback_callstatus_cb);
+ 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();
- binit = false;
+ /* deinitialize profile feature */
+ if (profile->exit)
+ profile->exit();
+
+ 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;
+
/* check initialize */
- if (!binit) {
- FEEDBACK_ERROR("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 >= FEEDBACK_PATTERN_END) {
- FEEDBACK_ERROR("Invalid parameter : pattern(%d)", pattern);
+ if (pattern <= FEEDBACK_PATTERN_NONE ||
+ pattern >= profile->max_pattern) {
+ _E("Invalid parameter : pattern(%d)", pattern);
return FEEDBACK_ERROR_INVALID_PARAMETER;
}
- if (pattern == FEEDBACK_PATTERN_NONE) {
- FEEDBACK_LOG("pattern is NONE");
- return FEEDBACK_ERROR_NONE;
- }
-
- /* in case of call connected or connecting */
- if (callstatus != VCONFKEY_CALL_OFF) {
- pattern = get_alert_on_call_key(pattern);
- FEEDBACK_LOG("Call status is connected or connecting. pattern changed : %s", str_pattern[pattern]);
- }
-
+ _D("request all type with pattern %s(%d)", profile->str_pattern(pattern), pattern);
/* play all device */
- 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,
+ * 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;
}
int err;
/* check initialize */
- if (!binit) {
- FEEDBACK_ERROR("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 >= FEEDBACK_TYPE_END) {
- FEEDBACK_ERROR("Invalid parameter : type(%d)", type);
+ 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 || pattern >= FEEDBACK_PATTERN_END) {
- FEEDBACK_ERROR("Invalid parameter : pattern(%d)", pattern);
+ if (pattern <= FEEDBACK_PATTERN_NONE ||
+ pattern >= profile->max_pattern) {
+ _E("Invalid parameter : pattern(%d)", pattern);
return FEEDBACK_ERROR_INVALID_PARAMETER;
}
- if (pattern == FEEDBACK_PATTERN_NONE) {
- FEEDBACK_LOG("pattern is NONE");
- return FEEDBACK_ERROR_NONE;
+ /* play proper device */
+ dev = find_device(type);
+ if (!dev) {
+ _E("Not supported device : type(%s)", profile->str_type[type]); //LCOV_EXCL_LINE
+ return FEEDBACK_ERROR_NOT_SUPPORTED;
}
- /* in case of call connected or connecting */
- if (callstatus != VCONFKEY_CALL_OFF) {
- pattern = get_alert_on_call_key(pattern);
- FEEDBACK_LOG("Call status is connected or connecting. pattern changed : %s", str_pattern[pattern]);
+ err = dev->play(check_pattern(type, pattern, __func__), false);
+ 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_stop(void)
+{
+ 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);
+
+ /* stop all device */
+ err = devices_stop();
+ 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_is_supported_pattern(feedback_type_e type, feedback_pattern_e pattern, bool *status)
+{
+ const struct device_ops *dev;
+ bool supported;
+ 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 (!status) {
+ _E("Invalid parameter : status(NULL)");
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
+ }
+
+ 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 ||
+ pattern >= profile->max_pattern) {
+ _E("Invalid parameter : pattern(%d)", pattern);
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
}
/* play proper device */
dev = find_device(type);
- if (dev) {
- err = dev->play(pattern);
- if (err < 0)
- FEEDBACK_ERROR("fail to play sound");
+ if (!dev) {
+ _E("Not supported device : type(%s)", profile->str_type[type]); //LCOV_EXCL_LINE
+ return FEEDBACK_ERROR_NOT_SUPPORTED;
+ }
+
+ 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;
}
+ *status = supported;
+
return FEEDBACK_ERROR_NONE;
}
-API int feedback_get_resource_path(feedback_type_e type, feedback_pattern_e pattern, char** path)
+/* Internal APIs */
+API int feedback_play_type_by_name(char *type, char *pattern)
+{
+ feedback_type_e etype;
+ feedback_pattern_e epattern;
+ int type_max;
+ int pattern_max;
+
+ if (!type || !pattern) {
+ _E("Invalid parameter : type(%s), pattern(%s)", type, pattern);
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
+ }
+
+ type_max = profile->max_type;
+ for (etype = 0; etype < type_max; ++etype) {
+ if (!strncmp(type, profile->str_type[etype], strlen(type)))
+ break;
+ }
+
+ if (etype == type_max) {
+ _E("Invalid parameter : type(%s)", type);
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
+ }
+
+ pattern_max = profile->max_pattern;
+ for (epattern = 0; epattern < pattern_max; ++epattern) {
+ if (!strncmp(pattern, profile->str_pattern(epattern), strlen(pattern)))
+ break;
+ }
+
+ if (epattern == pattern_max) {
+ _E("Invalid parameter : pattern(%s)", pattern);
+ return FEEDBACK_ERROR_INVALID_PARAMETER;
+ }
+
+ return feedback_play_type(etype, epattern);
+}
+
+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) {
- FEEDBACK_ERROR("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;
}
- if (type <= FEEDBACK_TYPE_NONE || type >= FEEDBACK_TYPE_END) {
- FEEDBACK_ERROR("Invalid parameter : type(%d)", type);
+ _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 || pattern >= FEEDBACK_PATTERN_END) {
- FEEDBACK_ERROR("Invalid parameter : pattern(%d)", pattern);
+ 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;
- *path = strdup(buf);
return FEEDBACK_ERROR_NONE;
}
-API int feedback_set_resource_path(feedback_type_e type, feedback_pattern_e pattern, char *path)
+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;
+ }
+
+ _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_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;
- if (path == NULL) {
- FEEDBACK_ERROR("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 (type <= FEEDBACK_TYPE_NONE ||
+ type >= profile->max_type) {
+ _E("Invalid parameter : type(%d)", type);
return FEEDBACK_ERROR_INVALID_PARAMETER;
}
- if (type <= FEEDBACK_TYPE_NONE || type >= FEEDBACK_TYPE_END) {
- FEEDBACK_ERROR("Invalid parameter : type(%d)", type);
+ if (pattern <= FEEDBACK_PATTERN_NONE ||
+ pattern >= profile->max_pattern) {
+ _E("Invalid parameter : pattern(%d)", pattern);
return FEEDBACK_ERROR_INVALID_PARAMETER;
}
- if (pattern <= FEEDBACK_PATTERN_NONE || pattern >= FEEDBACK_PATTERN_END) {
- FEEDBACK_ERROR("Invalid parameter : pattern(%d)", pattern);
+ if ((type == FEEDBACK_TYPE_SOUND) && (soundpath == NULL)) {
+ _E("Invalid parameter : sound path(NULL)");
return FEEDBACK_ERROR_INVALID_PARAMETER;
}
- /* proper device set path */
+ /* 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;
}