device-notifier: add priority to device-notifier 70/268970/5
authorYoungjae Cho <y0.cho@samsung.com>
Wed, 5 Jan 2022 09:45:12 +0000 (18:45 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Wed, 5 Jan 2022 12:34:10 +0000 (21:34 +0900)
The priority is sorted in descending order, therefore the higher
a priority is, the earlier it is invoked compared to the lower one.

Change-Id: I30c995cdb4d8b84faf1d4542b81e27052b94a9ab
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
src/shared/device-notifier.c
src/shared/device-notifier.h
tests/deviced-common-private-test/test-device-notifier.c

index 6eacafe..661fae7 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 
+#include <glib.h>
 #include <errno.h>
 #include "log.h"
 #include "device-notifier.h"
@@ -28,8 +29,9 @@
 
 struct device_notifier {
        int id;
-
+       int priority; /* descending order */
        bool deleted;
+
        enum device_notifier_type type;
        int (*func)(void *data);
 
@@ -41,7 +43,6 @@ struct device_notifier {
 static GList *device_notifier_list;
 static guint idl;
 
-
 #define FIND_NOTIFIER(a, b, d, e, f) \
        SYS_G_LIST_FOREACH(a, b, d) \
                if (e == d->e && f == (d->f))
@@ -84,7 +85,13 @@ static const char *device_notifier_type_str[DEVICE_NOTIFIER_MAX] = {
        NOTIFY_STR(DEVICE_NOTIFIER_ULTRAPOWERSAVING),
 };
 
-int __register_notifier(enum device_notifier_type type, notify_cb func, const char *caller)
+static gint compare_priority(gconstpointer a, gconstpointer b)
+{
+       /* descending order */
+       return ((const struct device_notifier *)b)->priority - ((const struct device_notifier *)a)->priority + 1;
+}
+
+int __register_notifier(enum device_notifier_type type, notify_cb func, int priority, const char *caller)
 {
        GList *n;
        struct device_notifier *notifier;
@@ -109,16 +116,17 @@ int __register_notifier(enum device_notifier_type type, notify_cb func, const ch
        }
 
        notifier->type = type;
+       notifier->priority = priority;
        notifier->func = func;
 
-       SYS_G_LIST_APPEND(device_notifier_list, notifier);
+       device_notifier_list = g_list_insert_sorted(device_notifier_list, notifier, compare_priority);
 
        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)
+       destroy_cb_udata func_destroy_udata, int priority, const char *caller)
 {
        struct device_notifier *notifier;
        static int id = 1;
@@ -137,12 +145,13 @@ int __register_notifier_udata(enum device_notifier_type type,
        }
 
        notifier->id = id;
+       notifier->priority = priority;
        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);
+       device_notifier_list = g_list_insert_sorted(device_notifier_list, notifier, compare_priority);
 
        ++id;
 
index ec7cfd3..241b339 100644 (file)
@@ -91,15 +91,20 @@ typedef void (*destroy_cb_udata)(void *user_data);
 /*
  * This is for internal callback method.
  */
-int __register_notifier(enum device_notifier_type type, notify_cb func, const char *caller);
-#define register_notifier(type, func) __register_notifier(type, func, __func__)
+int __register_notifier(enum device_notifier_type type, notify_cb func, int priority, const char *caller);
+#define register_notifier(type, func) __register_notifier(type, func, 0, __func__)
+#define register_notifier_priority(type, func, prio) __register_notifier(type, func, prio, __func__)
+
 int __unregister_notifier(enum device_notifier_type type, notify_cb func, const char *caller);
 #define unregister_notifier(type, func) __unregister_notifier(type, func, __func__)
 
-int __register_notifier_udata(enum device_notifier_type type, notify_cb_udata func, void *user_data,
-       destroy_cb_udata func_destroy, const char *caller);
+int __register_notifier_udata(enum device_notifier_type type, notify_cb_udata func,
+       void *user_data, destroy_cb_udata func_destroy, int priority, const char *caller);
 #define register_notifier_udata(type, func, user_data, func_destroy) \
-       __register_notifier_udata(type, func, user_data, func_destroy, __func__)
+       __register_notifier_udata(type, func, user_data, func_destroy, 0, __func__)
+#define register_notifier_udata_priority(type, func, user_data, func_destroy, prio) \
+       __register_notifier_udata(type, func, user_data, func_destroy, prio, __func__)
+
 int __unregister_notifier_udata(int id, const char *caller);
 #define unregister_notifier_udata(id) __unregister_notifier_udata(id, __func__)
 
index b654887..6f882a6 100644 (file)
@@ -1,4 +1,3 @@
-#include <stdio.h>
 #include <stdint.h>
 #include <errno.h>
 #include <shared/device-notifier.h>
@@ -185,6 +184,35 @@ static void test_destroy_callback_p2(void **state)
        device_notify_once(DEVICE_NOTIFIER_LOWBAT, (void *)(intptr_t) 0x9a9a9a9a);
 }
 
+static void test_device_notify_priority_p1(void **state)
+{
+       int id1, id2, id3;
+
+       id1 = register_notifier_udata_priority(DEVICE_NOTIFIER_DISPLAY_LOCK, notify_callback_udata,
+               (void *)(intptr_t) 0x11111111, NULL, -300);
+       assert_in_range(id1, 1, INT_MAX);
+
+       id2 = register_notifier_udata_priority(DEVICE_NOTIFIER_DISPLAY_LOCK, notify_callback_udata,
+               (void *)(intptr_t) 0x22222222, NULL, 500);
+       assert_in_range(id2, 1, INT_MAX);
+
+       id3 = register_notifier_udata_priority(DEVICE_NOTIFIER_DISPLAY_LOCK, notify_callback_udata,
+               (void *)(intptr_t) 0x33333333, NULL, -300);
+       assert_in_range(id3, 1, INT_MAX);
+
+       /* id2 will be invoked first */
+       expect_value(notify_callback_udata, data, 0x1234);
+       expect_value(notify_callback_udata, udata, 0x22222222);
+       /* id1, id3 invocation follows it,
+        * and those are invoked in the order in which they were registered */
+       expect_value(notify_callback_udata, data, 0x1234);
+       expect_value(notify_callback_udata, udata, 0x11111111);
+       expect_value(notify_callback_udata, data, 0x1234);
+       expect_value(notify_callback_udata, udata, 0x33333333);
+
+       device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)(intptr_t)0x1234);
+}
+
 static int run_device_notifier_test(void)
 {
        static const struct CMUnitTest testsuite[] = {
@@ -195,6 +223,7 @@ static int run_device_notifier_test(void)
                cmocka_unit_test(test_device_notify_once_p),
                cmocka_unit_test(test_destroy_callback_p1),
                cmocka_unit_test(test_destroy_callback_p2),
+               cmocka_unit_test(test_device_notify_priority_p1),
        };
 
        return cmocka_run_group_tests(testsuite, NULL, NULL);