#define __stringify(x...) __stringify_1(x)
struct device_notifier {
+ int id;
+
bool deleted;
enum device_notifier_type type;
int (*func)(void *data);
+
+ int (*func_udata)(void *data, void *user_data);
+ void (*destroyer)(void *user_data);
+ void *user_data;
};
static GList *device_notifier_list;
return 0;
}
+int __register_notifier_udata(enum device_notifier_type type,
+ notify_cb_udata func_udata, void *user_data,
+ destroy_cb_udata func_destroy_udata, const char *caller)
+{
+ struct device_notifier *notifier;
+ static int id = 1;
+
+ _I("%s, %p by %s", device_notifier_type_str[type], func_udata, caller);
+
+ if (!func_udata) {
+ _E("invalid func address! by %s", caller);
+ return -EINVAL;
+ }
+
+ notifier = calloc(1, sizeof(struct device_notifier));
+ if (!notifier) {
+ _E("Fail to malloc for %s notifier! by %s", device_notifier_type_str[type], caller);
+ return -ENOMEM;
+ }
+
+ notifier->id = id;
+ notifier->type = type;
+ notifier->func_udata = func_udata;
+ notifier->user_data = user_data;
+ notifier->destroyer = func_destroy_udata;
+
+ SYS_G_LIST_APPEND(device_notifier_list, notifier);
+
+ ++id;
+
+ return notifier->id;
+}
+
int __unregister_notifier(enum device_notifier_type type, notify_cb func, const char *caller)
{
GList *n;
return 0;
}
+int __unregister_notifier_udata(int id, const char *caller)
+{
+ GList *n;
+ struct device_notifier *notifier;
+
+ SYS_G_LIST_FOREACH(device_notifier_list, n, notifier) {
+ if (notifier->id == id) {
+ if (notifier->destroyer)
+ notifier->destroyer(notifier->user_data);
+ notifier->deleted = true;
+ }
+ }
+
+ return 0;
+}
+
static gboolean delete_unused_notifier_cb(void *data)
{
GList *n;
if (!notifier->deleted && type == notifier->type) {
if (notifier->func)
notifier->func(data);
+ else if (notifier->func_udata)
+ notifier->func_udata(data, notifier->user_data);
}
}
SYS_G_LIST_FOREACH(device_notifier_list, n, notifier) {
if (!notifier->deleted && type == notifier->type) {
- if (notifier->func)
+ if (notifier->func) {
notifier->func(data);
+ } else if (notifier->func_udata) {
+ notifier->func_udata(data, notifier->user_data);
+ if (notifier->destroyer)
+ notifier->destroyer(notifier->user_data);
+ }
notifier->deleted = true;
}
+#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <shared/device-notifier.h>
#include "test-main.h"
-static int notified;
+#define INT_MAX ((~0) >> 1)
static int notify_callback(void *data)
{
- notified = (int)(intptr_t) data;
+ check_expected(data);
return 0;
}
+static int notify_callback_udata(void *data, void *udata)
+{
+ check_expected(data);
+ check_expected(udata);
+
+ return 0;
+}
+
+static void destroy_callback_udata(void *udata)
+{
+ check_expected(udata);
+}
+
static void test_device_notify_n(void **state)
{
int retval;
retval = register_notifier(DEVICE_NOTIFIER_MAX, NULL);
assert_int_equal(retval, -EINVAL);
+
+ retval = register_notifier_udata(DEVICE_NOTIFIER_MAX, NULL, NULL, NULL);
+ assert_int_equal(retval, -EINVAL);
}
-static void test_device_notify_p(void **state)
+static void test_device_notify_p1(void **state)
{
int retval;
- notified = 999;
-
retval = register_notifier(DEVICE_NOTIFIER_LCD, notify_callback);
assert_int_equal(retval, 0);
+ expect_value(notify_callback, data, 0x3f3f3f3f);
- for (int i = 3; i < 8; ++i) {
- device_notify(DEVICE_NOTIFIER_LCD, (void *)(intptr_t) i);
- assert_int_equal(notified, i);
- }
+ device_notify(DEVICE_NOTIFIER_LCD, (void *)(intptr_t) 0x3f3f3f3f);
}
-static void test_device_notify_once_p(void **state)
+static void test_device_notify_p2(void **state)
{
int retval;
- int value = 721;
+ int notify_data;
+ const int udata2 = 0xaeaeaeae;
+ const int udata3 = 0x99997777;
+
+ notify_data = 0x12456321;
+
+ /* 1st notifier */
+ retval = register_notifier(DEVICE_NOTIFIER_PMQOS, notify_callback);
+ assert_int_equal(retval, 0);
+
+ /* 2nd notifier */
+ retval = register_notifier_udata(DEVICE_NOTIFIER_PMQOS, notify_callback_udata, (void *)(intptr_t) udata2, NULL);
+ assert_in_range(retval, 1, INT_MAX);
+
+ /* expect invocation of 1st callback and check parameter */
+ expect_value(notify_callback, data, notify_data);
+ /* expect invocation of 2nd callback and check parameter */
+ expect_value(notify_callback_udata, data, notify_data);
+ expect_value(notify_callback_udata, udata, udata2);
+
+ device_notify(DEVICE_NOTIFIER_PMQOS, (void *)(intptr_t) notify_data);
+
+ notify_data = 0x888899dd;
+
+ /* 3rd notifier */
+ retval = register_notifier_udata(DEVICE_NOTIFIER_PMQOS, notify_callback_udata, (void *)(intptr_t) udata3, NULL);
+ assert_in_range(retval, 1, INT_MAX);
+
+ /* expect invocation of 1st callback and check parameter */
+ expect_value(notify_callback, data, notify_data);
+ /* expect invocation of 2nd callback and check parameter */
+ expect_value(notify_callback_udata, data, notify_data);
+ expect_value(notify_callback_udata, udata, udata2);
+ /* expect invocation of 3rd callback and check parameter */
+ expect_value(notify_callback_udata, data, notify_data);
+ expect_value(notify_callback_udata, udata, udata3);
+
+ device_notify(DEVICE_NOTIFIER_PMQOS, (void *)(intptr_t) notify_data);
+}
+
+static void test_device_notify_p3(void **state)
+{
+ int notify_data;
+ int id1, id2;
+ const int udata1 = 0x41a41a41;
+ const int udata2 = 0x77777777;
+
+ /* first run */
+ notify_data = 0x8575ddff;
+
+ /* 1st notifier */
+ id1 = register_notifier_udata(DEVICE_NOTIFIER_POWEROFF, notify_callback_udata, (void *)(intptr_t) udata1, NULL);
+ assert_in_range(id1, 1, INT_MAX);
- notified = 999;
+ /* 2nd notifier */
+ id2 = register_notifier_udata(DEVICE_NOTIFIER_POWEROFF, notify_callback_udata, (void *)(intptr_t) udata2, NULL);
+ assert_in_range(id2, 1, INT_MAX);
+
+ /* expect invocation of 1st callback and check parameter */
+ expect_value(notify_callback_udata, data, notify_data);
+ expect_value(notify_callback_udata, udata, udata1);
+ /* expect invocation of 2nd callback and check parameter */
+ expect_value(notify_callback_udata, data, notify_data);
+ expect_value(notify_callback_udata, udata, udata2);
+
+ device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)(intptr_t) notify_data);
+
+ /* second run. at this time device_notify() after unregistering 1st notifier */
+ notify_data = 0x345;
+
+ unregister_notifier_udata(id1);
+
+ /* only expect invocation of 2nd callback and check parameter */
+ expect_value(notify_callback_udata, data, notify_data);
+ expect_value(notify_callback_udata, udata, udata2);
+
+ device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)(intptr_t) notify_data);
+}
+
+static void test_device_notify_once_p(void **state)
+{
+ int retval;
retval = register_notifier(DEVICE_NOTIFIER_LCD_OFF, notify_callback);
assert_int_equal(retval, 0);
- device_notify_once(DEVICE_NOTIFIER_LCD_OFF, (void *)(intptr_t) value);
- assert_int_equal(notified, value);
+ expect_value(notify_callback, data, 0xabcdabcd);
+ device_notify_once(DEVICE_NOTIFIER_LCD_OFF, (void *)(intptr_t) 0xabcdabcd);
+
+ /* Don't add expect_value() for callback at this time.
+ * Therefore if the callback is invoked, check_expected() returns error */
+ device_notify(DEVICE_NOTIFIER_LCD_OFF, (void *)(intptr_t) 0xabcdabcd);
+
+ retval = register_notifier_udata(DEVICE_NOTIFIER_BATTERY_CHARGING, notify_callback_udata, (void *)(intptr_t) 0xfefefefe, NULL);
+ assert_in_range(retval, 1, INT_MAX);
+
+ expect_value(notify_callback_udata, data, 0x34343434);
+ expect_value(notify_callback_udata, udata, 0xfefefefe);
+ device_notify_once(DEVICE_NOTIFIER_BATTERY_CHARGING, (void *)(intptr_t) 0x34343434);
+
+ /* Don't add expect_value() for callback at this time.
+ * Therefore if the callback is invoked, check_expected() returns error */
+ device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, (void *)(intptr_t) 0x34343434);
+}
+
+static void test_destroy_callback_p1(void **state)
+{
+ int id;
+
+ id = register_notifier_udata(DEVICE_NOTIFIER_LOWBAT, notify_callback_udata,
+ (void *)(intptr_t) 0x4848, destroy_callback_udata);
+ assert_in_range(id, 1, INT_MAX);
+
+ expect_value(destroy_callback_udata, udata, 0x4848);
+
+ unregister_notifier_udata(id);
+}
+
+static void test_destroy_callback_p2(void **state)
+{
+ int id;
+
+ id = register_notifier_udata(DEVICE_NOTIFIER_LOWBAT, notify_callback_udata,
+ (void *)(intptr_t) 0x1177, destroy_callback_udata);
+ assert_in_range(id, 1, INT_MAX);
+
+ expect_value(notify_callback_udata, data, 0x9a9a9a9a);
+ expect_value(notify_callback_udata, udata, 0x1177);
+ expect_value(destroy_callback_udata, udata, 0x1177);
- device_notify(DEVICE_NOTIFIER_LCD_OFF, (void *)(intptr_t) (value - 1));
- assert_int_equal(notified, value);
+ device_notify_once(DEVICE_NOTIFIER_LOWBAT, (void *)(intptr_t) 0x9a9a9a9a);
}
static int run_device_notifier_test(void)
{
static const struct CMUnitTest testsuite[] = {
cmocka_unit_test(test_device_notify_n),
- cmocka_unit_test(test_device_notify_p),
+ cmocka_unit_test(test_device_notify_p1),
+ cmocka_unit_test(test_device_notify_p2),
+ cmocka_unit_test(test_device_notify_p3),
cmocka_unit_test(test_device_notify_once_p),
+ cmocka_unit_test(test_destroy_callback_p1),
+ cmocka_unit_test(test_destroy_callback_p2),
};
return cmocka_run_group_tests(testsuite, NULL, NULL);