--- /dev/null
+#include <glib.h>
+#include <stdint.h>
+#include <linux/input.h>
+
+#include "shared/bitmap.h"
+#include "shared/device-notifier.h"
+#include "shared/log.h"
+#include "power-event-lock.h"
+
+/* eventlock is another wakelock than mainlock.
+ *
+ * The eventlock works independently of mainlock, which is controlled by
+ * power state. The main purpose of eventlock is to prevent the subroutine
+ * of an event from going to sleep regardless of the power state. */
+#define EVENT_LOCK "eventlock"
+#define EVENT_LOCK_MARGIN_MS 1000
+
+enum eventlock_type {
+ EL_MIN,
+ /* On receiving key event, expands EL_KEY to EL_KEY_* according to keycode */
+ EL_KEY,
+ EL_KEY_POWER = EL_KEY,
+ EL_KEY_BLUETOOTH,
+ /* add eventlock type here */
+ EL_MAX,
+};
+
+static struct dd_bitmap *eventlock;
+static int notifier_id[EL_MAX][2];
+
+static void event_wake_lock(enum eventlock_type type)
+{
+ int setcount;
+
+ if (type <= EL_MIN || type >= EL_MAX)
+ return;
+
+ set_bit(eventlock, type);
+ setcount = count_set_bit(eventlock);
+
+ _D("Set eventlock of type=%d, current number of eventlock=%d", type, setcount);
+
+ if (setcount == 1) {
+ sys_set_str("/sys/power/wake_lock", EVENT_LOCK);
+ _D("Acquired eventlock");
+ }
+}
+
+static void event_wake_unlock(enum eventlock_type type)
+{
+ int setcount;
+
+ if (type <= EL_MIN || type >= EL_MAX)
+ return;
+
+ clear_bit(eventlock, type);
+ setcount = count_set_bit(eventlock);
+
+ _D("Unset eventlock of type=%d, current number of eventlock=%d", type, setcount);
+
+ if (setcount == 0) {
+ sys_set_str("/sys/power/wake_unlock", EVENT_LOCK);
+ _D("Released eventlock");
+ }
+}
+
+static enum eventlock_type expand_key_eventlock_type(int keycode)
+{
+ if (keycode == KEY_POWER)
+ return EL_KEY_POWER;
+ if (keycode == KEY_BLUETOOTH)
+ return EL_KEY_BLUETOOTH;
+ /* add mapping for keycode to eventlock_type here */
+
+ return EL_MAX;
+}
+
+static int power_event_lock_callback(void *data, void *udata)
+{
+ enum eventlock_type type = (enum eventlock_type)(intptr_t) udata;
+
+ if (type == EL_KEY) {
+ /* On receiving key event, expand EL_KEY to EL_KEY_* according to the keycode */
+ int keycode = (int)(intptr_t) data;
+ type = expand_key_eventlock_type(keycode);
+ }
+
+ event_wake_lock(type);
+
+ return 0;
+}
+
+static int power_event_unlock_callback(void *data, void *udata)
+{
+ enum eventlock_type type = (enum eventlock_type)(intptr_t) udata;
+
+ if (type == EL_KEY) {
+ /* On receiving key event, expand EL_KEY to EL_KEY_* according to the keycode */
+ int keycode = (int)(intptr_t) data;
+ type = expand_key_eventlock_type(keycode);
+ }
+
+ event_wake_unlock(type);
+
+ return 0;
+}
+
+static void register_power_event_lock_controller(enum eventlock_type type,
+ enum device_notifier_type lock_notify,
+ enum device_notifier_type unlock_notify)
+{
+ /* Acquiring lock must be followed by all the other notifiers, therefore
+ * give a large enough number as priority to make it be at the head of notifier list.
+ * On the other hand, releasing lock must follow all the other notifiers, therefore
+ * give a small enough number as priority to make it be at the tail of notifier list. */
+ notifier_id[type][0] = register_notifier_udata_priority(lock_notify,
+ power_event_lock_callback, (void *)(intptr_t) type, NULL, 1000);
+ notifier_id[type][1] = register_notifier_udata_priority(unlock_notify,
+ power_event_unlock_callback, (void *)(intptr_t) type, NULL, -1000);
+}
+
+void power_event_lock_init(void)
+{
+ eventlock = init_bitmap(EL_MAX);
+ if (!eventlock) {
+ _E("Failed to init event lock bitmap");
+ return;
+ }
+
+ register_power_event_lock_controller(EL_KEY,
+ DEVICE_NOTIFIER_KEY_PRESS,
+ DEVICE_NOTIFIER_KEY_RELEASE);
+}
#include "power-state-manager.h"
#include "power-dbus.h"
#include "power-state-wait.h"
-
-/* Temporal wakelock of powerkey input */
-#define KEY_PRESSED_TEMPORAL_LOCK "templock"
-#define TEMPORAL_LOCK_WAKE_MARGIN 1000 /* milisecond */
+#include "power-event-lock.h"
#define EVENT_TYPE_SLEEP 0
#define EVENT_TYPE_WAKEUP 1
-static guint keypress_temporal_timer_id;
-
char *psm_name[PSM_MAX] = {
[PSM_NORMAL] = "PSM_NORMAL",
[PSM_SLEEP] = "PSM_SLEEP",
static guint64 state_transition_counter = 0;
static enum psm_state current;
-static gboolean temporal_lock_expired_cb(void *data)
-{
- sys_set_str("/sys/power/wake_unlock", KEY_PRESSED_TEMPORAL_LOCK);
- keypress_temporal_timer_id = 0;
-
- return G_SOURCE_REMOVE;
-}
-
-static int acquire_temporal_lock(void *data)
-{
- int keycode = (int)(intptr_t) data;
-
- if (keycode != KEY_POWER)
- return 0;
-
- if (keypress_temporal_timer_id) {
- g_source_remove(keypress_temporal_timer_id);
- keypress_temporal_timer_id = 0;
- }
-
- sys_set_str("/sys/power/wake_lock", KEY_PRESSED_TEMPORAL_LOCK);
-
- return 0;
-}
-
-static int release_temporal_lock(void * data)
-{
- int keycode = (int)(intptr_t) data;
-
- if (keycode != KEY_POWER)
- return 0;
-
- if (keypress_temporal_timer_id) {
- g_source_remove(keypress_temporal_timer_id);
- keypress_temporal_timer_id = 0;
- }
-
- /* templock margin */
- keypress_temporal_timer_id = g_timeout_add(TEMPORAL_LOCK_WAKE_MARGIN,
- temporal_lock_expired_cb, NULL);
-
- return 0;
-}
-
static void psm_wake_unlock(void)
{
/* for PSM_NORMAL, PSM_POWEROFF, do not wake unlock */
device_notify(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, NULL);
device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
- register_notifier(DEVICE_NOTIFIER_KEY_PRESS, acquire_temporal_lock);
- register_notifier(DEVICE_NOTIFIER_KEY_RELEASE, release_temporal_lock);
register_notifier(DEVICE_NOTIFIER_INPUT_TRANSITION_STATE, psm_transition_state_cb);
power_plugin_dbus_init(NULL);
+ power_event_lock_init();
}
static const struct device_ops power_state_manager_device_ops = {