tklock.c 221 KB
Newer Older
1 2 3 4 5
/**
 * @file tklock.c
 * This file implements the touchscreen/keypad lock component
 * of the Mode Control Entity
 * <p>
Santtu Lakkala's avatar
Santtu Lakkala committed
6
 * Copyright © 2004-2011 Nokia Corporation and/or its subsidiary(-ies).
7
 * Copyright (C) 2012-2019 Jolla Ltd.
8 9
 * <p>
 * @author David Weinehall <david.weinehall@nokia.com>
10 11 12 13 14 15 16
 * @author Tapio Rantala <ext-tapio.rantala@nokia.com>
 * @author Santtu Lakkala <ext-santtu.1.lakkala@nokia.com>
 * @author Jukka Turunen <ext-jukka.t.turunen@nokia.com>
 * @author Irina Bezruk <ext-irina.bezruk@nokia.com>
 * @author Kalle Jokiniemi <kalle.jokiniemi@jolla.com>
 * @author Mika Laitio <lamikr@pilppa.org>
 * @author Markus Lehtonen <markus.lehtonen@iki.fi>
17
 * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
18 19
 * @author Vesa Halttunen <vesa.halttunen@jollamobile.com>
 * @author Andrew den Exter <andrew.den.exter@jolla.com>
20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 * mce is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * mce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with mce.  If not, see <http://www.gnu.org/licenses/>.
 */

34
#include "tklock.h"
35

36
#include "mce-common.h"
37
#include "mce-log.h"
38
#include "mce-lib.h"
39
#include "mce-io.h"
40
#include "mce-setting.h"
41
#include "mce-dbus.h"
42
#include "mce-hbtimer.h"
43
#include "evdev.h"
44

45 46 47 48
#ifdef ENABLE_WAKELOCKS
# include "libwakelock.h"
#endif

49
#include "modules/doubletap.h"
50
#include "modules/display.h"
51

52 53 54 55 56 57 58
#include "systemui/dbus-names.h"
#include "systemui/tklock-dbus-names.h"

#include <linux/input.h>

#include <unistd.h>
#include <string.h>
59 60
#include <fcntl.h>
#include <errno.h>
61 62 63 64 65 66

#include <mce/dbus-names.h>
#include <mce/mode-names.h>

#include <glib/gstdio.h>

67 68 69 70 71 72 73 74 75 76 77
typedef enum
{
    /** No autorelock triggers */
    AUTORELOCK_NO_TRIGGERS,

    /** Autorelock on keyboard slide closed */
    AUTORELOCK_KBD_SLIDE,

    /** Autorelock on lens cover */
    AUTORELOCK_LENS_COVER,
} autorelock_t;
78

79 80 81
/** Helper for evaluation number of items in an array */
#define numof(a) (sizeof(a)/sizeof*(a))

82 83 84 85
/* ========================================================================= *
 * CONSTANTS
 * ========================================================================= */

86 87
#define MODULE_NAME "tklock"

88 89 90 91 92 93
/** Max valid time_t value in milliseconds */
#define MAX_TICK (INT_MAX * (int64_t)1000)

/** Min valid time_t value in milliseconds */
#define MIN_TICK  0

94 95 96
/** Maximum number of concurrent notification ui exceptions */
#define TKLOCK_NOTIF_SLOTS 32

97 98 99 100 101 102 103 104 105
/** How long to wait for lid close after low lux [ms] */
#define TKLOCK_LIDFILTER_SET_WAIT_FOR_CLOSE_DELAY 1500

/** How long to wait for low lux after lid close [ms] */
#define TKLOCK_LIDFILTER_SET_WAIT_FOR_DARK_DELAY  1200

/** How long to wait for high lux after lid open [ms] */
#define TKLOCK_LIDFILTER_SET_WAIT_FOR_LIGHT_DELAY 1200

106 107 108 109
/* ========================================================================= *
 * DATATYPES
 * ========================================================================= */

110 111 112 113 114 115 116 117
typedef struct
{
    /** BOOTTIME tick when notification autostops */
    int64_t  ns_until;

    /** Amount of ms autostop extends from user input */
    int64_t  ns_renew;

118 119 120
    /** Private D-Bus name of the slot owner */
    gchar   *ns_owner;

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
    /** Assumed unique identification string */
    gchar   *ns_name;

} tklock_notif_slot_t;

typedef struct
{
    /** Array of notification slots */
    tklock_notif_slot_t tn_slot[TKLOCK_NOTIF_SLOTS];

    /** BOOTTIME linger tick from deactivated slots */
    int64_t             tn_linger;

    /** Timer id for autostopping notification slots */
    guint               tn_autostop_id;

137 138 139
    /** Slot owner D-Bus name monitoring list */
    GSList             *tn_monitor_list;

140 141
} tklock_notif_state_t;

142 143 144 145 146 147 148 149 150 151 152
/** Proximity sensor history */
typedef struct
{
    /** Monotonic timestamp, ms resolution */
    int64_t       tick;

    /** Proximity sensor state */
    cover_state_t state;

} ps_history_t;

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
/** Ambient light lux value mapped into enumerated states
 *
 * In case the lid sensor can't be trusted for some reason, data from
 * ambient light sensor heuristics can be used for avoiding incorrect
 * blank/unblank actions.
 *
 * For this purpose the raw data from ambient light sensor is tracked
 * and mapped in to three states:
 *
 * - TKLOCK_LIDLIGHT_NA: The data from als is not applicable for filtering.
 * - TKLOCK_LIDLIGHT_LO: The als indicates darkness.
 * - TKLOCK_LIDLIGHT_HI: The als indicates some amount of light.
 */
typedef enum
{
    /* Light level is not applicable for state evaluation */
    TKLOCK_LIDLIGHT_NA,

    /* Light level equals complete darkness */
    TKLOCK_LIDLIGHT_LO,

    /* Light level equals at least some light */
    TKLOCK_LIDLIGHT_HI,
} tklock_lidlight_t;

178 179 180
/* ========================================================================= *
 * PROTOTYPES
 * ========================================================================= */
181

182 183 184
// datapipe values and triggers

static void     tklock_datapipe_system_state_cb(gconstpointer data);
185
static void     tklock_datapipe_devicelock_state_cb(gconstpointer data);
186
static void     tklock_datapipe_devicelock_state_cb2(gpointer aptr);
187
static void     tklock_datapipe_resume_detected_event_cb(gconstpointer data);
188
static void     tklock_datapipe_devicelock_service_state_cb(gconstpointer data);
189 190
static void     tklock_datapipe_lipstick_service_state_cb(gconstpointer data);
static void     tklock_datapipe_osupdate_running_cb(gconstpointer data);
191
static void     tklock_datapipe_shutting_down_cb(gconstpointer data);
192
static void     tklock_datapipe_display_state_curr_cb(gconstpointer data);
193 194
static void     tklock_datapipe_display_state_next_cb(gconstpointer data);
static void     tklock_datapipe_proximity_eval_led(void);
195 196 197 198
static void     tklock_datapipe_proximity_update(void);
static gboolean tklock_datapipe_proximity_uncover_cb(gpointer data);
static void     tklock_datapipe_proximity_uncover_cancel(void);
static void     tklock_datapipe_proximity_uncover_schedule(void);
199
static void     tklock_datapipe_proximity_sensor_actual_cb(gconstpointer data);
200
static void     tklock_datapipe_call_state_cb(gconstpointer data);
201
static void     tklock_datapipe_music_playback_ongoing_cb(gconstpointer data);
202 203 204
static void     tklock_datapipe_alarm_ui_state_cb(gconstpointer data);
static void     tklock_datapipe_charger_state_cb(gconstpointer data);
static void     tklock_datapipe_battery_status_cb(gconstpointer data);
205 206 207 208 209
static void     tklock_datapipe_usb_cable_state_cb(gconstpointer data);
static void     tklock_datapipe_jack_sense_state_cb(gconstpointer data);
static void     tklock_datapipe_camera_button_state_cb(gconstpointer const data);
static void     tklock_datapipe_keypress_event_cb(gconstpointer const data);
static void     tklock_datapipe_uiexception_type_cb(gconstpointer data);
210
static void     tklock_datapipe_audio_route_cb(gconstpointer data);
211
static void     tklock_datapipe_tklock_request_cb(gconstpointer data);
212
static void     tklock_datapipe_interaction_expected_cb(gconstpointer data);
213
static gpointer tklock_datapipe_submode_filter_cb(gpointer data);
214
static void     tklock_datapipe_submode_cb(gconstpointer data);
215 216 217 218 219 220
static void     tklock_datapipe_lockkey_state_cb(gconstpointer const data);
static void     tklock_datapipe_heartbeat_event_cb(gconstpointer data);
static void     tklock_datapipe_keyboard_slide_input_state_cb(gconstpointer const data);
static void     tklock_datapipe_keyboard_slide_output_state_cb(gconstpointer const data);
static void     tklock_datapipe_keyboard_available_state_cb(gconstpointer const data);
static void     tklock_datapipe_light_sensor_poll_request_cb(gconstpointer const data);
221
static void     tklock_datapipe_topmost_window_pid_cb(gconstpointer data);
222
static void     tklock_datapipe_light_sensor_actual_cb(gconstpointer data);
223
static void     tklock_datapipe_lid_sensor_is_working_cb(gconstpointer data);
224 225 226
static void     tklock_datapipe_lid_sensor_actual_cb(gconstpointer data);
static void     tklock_datapipe_lid_sensor_filtered_cb(gconstpointer data);
static void     tklock_datapipe_lens_cover_state_cb(gconstpointer data);
227
static bool     tklock_touch_activity_event_p(const struct input_event *ev);
228
static void     tklock_datapipe_user_activity_event_cb(gconstpointer data);
229
static void     tklock_datapipe_init_done_cb(gconstpointer data);
230

231 232
static bool     tklock_datapipe_in_tklock_submode(void);
static void     tklock_datapipe_set_tklock_submode(bool lock);
233
static void     tklock_datapipe_set_devicelock_state(devicelock_state_t state);
234 235
static void     tklock_datapipe_rethink_interaction_expected(void);
static void     tklock_datapipe_update_interaction_expected(bool expected);
236 237 238 239

static void     tklock_datapipe_init(void);
static void     tklock_datapipe_quit(void);

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
// LID_SENSOR

static bool              tklock_lidsensor_is_enabled          (void);
static void              tklock_lidsensor_init                (void);

// LID_LIGHT

static const char       *tklock_lidlight_repr                 (tklock_lidlight_t state);
static tklock_lidlight_t tklock_lidlight_from_lux             (int lux);

// LID_FILTER

static bool              tklock_lidfilter_is_enabled          (void);

static void              tklock_lidfilter_set_allow_close     (bool allow);
255

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
static tklock_lidlight_t tklock_lidfilter_map_als_state       (void);
static void              tklock_lidfilter_set_als_state       (tklock_lidlight_t state);

static gboolean          tklock_lidfilter_wait_for_close_cb   (gpointer aptr);
static bool              tklock_lidfilter_get_wait_for_close  (void);
static void              tklock_lidfilter_set_wait_for_close  (bool state);

static gboolean          tklock_lidfilter_wait_for_dark_cb    (gpointer aptr);
static bool              tklock_lidfilter_get_wait_for_dark   (void);
static void              tklock_lidfilter_set_wait_for_dark   (bool state);

static gboolean          tklock_lidfilter_wait_for_light_cb   (gpointer aptr);
static bool              tklock_lidfilter_get_wait_for_light  (void);
static void              tklock_lidfilter_set_wait_for_light  (bool state);

static void              tklock_lidfilter_rethink_als_poll    (void);
static void              tklock_lidfilter_rethink_allow_close (void);
static void              tklock_lidfilter_rethink_als_state   (void);
static void              tklock_lidfilter_rethink_lid_state   (void);

// LID_POLICY

static void              tklock_lidpolicy_rethink             (void);
279

280 281
// keyboard slide state machine

282 283 284
static void     tklock_keyboard_slide_opened(void);
static void     tklock_keyboard_slide_opened_cb(gpointer aptr);
static void     tklock_keyboard_slide_closed(void);
285 286
static void     tklock_keyboard_slide_rethink(void);

287 288 289
// autolock state machine

static gboolean tklock_autolock_cb(gpointer aptr);
290 291 292
static void     tklock_autolock_evaluate(void);
static void     tklock_autolock_enable(void);
static void     tklock_autolock_disable(void);
293
static void     tklock_autolock_rethink(void);
294 295
static void     tklock_autolock_init(void);
static void     tklock_autolock_quit(void);
296 297 298 299

// proximity locking state machine

static gboolean tklock_proxlock_cb(gpointer aptr);
300 301 302 303
static void     tklock_proxlock_resume(void);
static void     tklock_proxlock_evaluate(void);
static void     tklock_proxlock_enable(void);
static void     tklock_proxlock_disable(void);
304 305
static void     tklock_proxlock_rethink(void);

306 307
// autolock based on device lock changes

308
static void     tklock_autolock_on_devlock_block(int duration_ms);
309 310 311
static void     tklock_autolock_on_devlock_prime(void);
static void     tklock_autolock_on_devlock_trigger(void);

312 313
// ui exception handling state machine

314 315 316 317 318 319 320 321 322 323
static uiexception_type_t topmost_active(uiexception_type_t mask);

static void     tklock_uiexception_sync_to_datapipe(void);
static gboolean tklock_uiexception_linger_cb(gpointer aptr);
static void     tklock_uiexception_begin(uiexception_type_t type, int64_t linger);
static void     tklock_uiexception_end(uiexception_type_t type, int64_t linger);
static void     tklock_uiexception_cancel(void);
static void     tklock_uiexception_finish(void);
static bool     tklock_uiexception_deny_state_restore(bool force, const char *cause);
static void     tklock_uiexception_rethink(void);
324

325 326 327 328 329 330 331 332 333 334 335
// low power mode ui state machine

static void     tklock_lpmui_set_state(bool enable);
static void     tklock_lpmui_reset_history(void);
static void     tklock_lpmui_update_history(cover_state_t state);
static bool     tklock_lpmui_probe_from_pocket(void);
static bool     tklock_lpmui_probe_on_table(void);
static bool     tklock_lpmui_probe(void);
static void     tklock_lpmui_rethink(void);
static void     tklock_lpmui_pre_transition_actions(void);

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
// legacy hw event input enable/disable state machine

static void     tklock_evctrl_set_state(output_state_t *output, bool enable);
static void     tklock_evctrl_set_kp_state(bool enable);
static void     tklock_evctrl_set_ts_state(bool enable);
static void     tklock_evctrl_set_dt_state(bool enable);
static void     tklock_evctrl_rethink(void);

// legacy hw double tap calibration

static void     tklock_dtcalib_now(void);
static void     tklock_dtcalib_from_heartbeat(void);
static gboolean tklock_dtcalib_cb(gpointer data);

static void     tklock_dtcalib_start(void);
static void     tklock_dtcalib_stop(void);

353
// DYNAMIC_SETTINGS
354

355 356
static void     tklock_setting_sanitize_lid_open_actions(void);
static void     tklock_setting_sanitize_lid_close_actions(void);
357 358 359 360
static void     tklock_setting_sanitize_kbd_open_trigger(void);
static void     tklock_setting_sanitize_kbd_open_actions(void);
static void     tklock_setting_sanitize_kbd_close_trigger(void);
static void     tklock_setting_sanitize_kbd_close_actions(void);
361

362
static void     tklock_setting_cb(GConfClient *const gcc, const guint id, GConfEntry *const entry, gpointer const data);
363

364 365
static void     tklock_setting_init(void);
static void     tklock_setting_quit(void);
Santtu Lakkala's avatar
Santtu Lakkala committed
366

367
// sysfs probing
368

369
static void     tklock_sysfs_probe(void);
370

371
// dbus ipc with systemui
372

373
static void     tklock_ui_send_tklock_signal(void);
374 375 376 377 378
static void     tklock_ui_notify_rethink_wakelock(void);
static bool     tklock_ui_notify_must_be_delayed(void);
static gboolean tklock_ui_notify_end_cb(gpointer data);
static gboolean tklock_ui_notify_beg_cb(gpointer data);
static void     tklock_ui_notify_schdule(void);
379
static gboolean tklock_ui_sync_cb(gpointer aptr);
380 381
static void     tklock_ui_notify_cancel(void);

382 383 384
static void     tklock_ui_eat_event(void);
static void     tklock_ui_open(void);
static void     tklock_ui_close(void);
385 386
static bool     tklock_ui_is_enabled(void);
static void     tklock_ui_set_enabled(bool enable);
Santtu Lakkala's avatar
Santtu Lakkala committed
387

388 389
static void     tklock_ui_get_devicelock_cb(DBusPendingCall *pc, void *aptr);
static void     tklock_ui_get_devicelock(void);
390

391
static void     tklock_ui_send_lpm_signal(void);
392 393
static void     tklock_ui_enable_lpm(void);
static void     tklock_ui_disable_lpm(void);
394
static void     tklock_ui_show_device_unlock(void);;
395

396 397
// dbus ipc

398 399 400
static void     tklock_dbus_send_display_blanking_policy(DBusMessage *const req);
static gboolean tklock_dbus_display_blanking_policy_get_cb(DBusMessage *const msg);

401 402
static void     tklock_dbus_send_keyboard_slide_state(DBusMessage *const req);
static gboolean tklock_dbus_keyboard_slide_state_get_req_cb(DBusMessage *const msg);
403

404 405
static void     tklock_dbus_send_keyboard_available_state(DBusMessage *const req);
static gboolean tklock_dbus_keyboard_available_state_get_req_cb(DBusMessage *const msg);
406

407 408 409
static gboolean tklock_dbus_send_tklock_mode(DBusMessage *const method_call);

static gboolean tklock_dbus_mode_get_req_cb(DBusMessage *const msg);
410 411
static tklock_request_t tklock_dbus_sanitize_requested_mode(tklock_request_t state);

412
static gboolean tklock_dbus_mode_change_req_cb(DBusMessage *const msg);
413
static gboolean tklock_dbus_interaction_expected_cb(DBusMessage *const msg);
414 415
static gboolean tklock_dbus_systemui_callback_cb(DBusMessage *const msg);

416
static gboolean tklock_dbus_devicelock_changed_cb(DBusMessage *const msg);
417

418 419 420
static gboolean tklock_dbus_notification_beg_cb(DBusMessage *const msg);
static gboolean tklock_dbus_notification_end_cb(DBusMessage *const msg);

421 422 423
static void     mce_tklock_init_dbus(void);
static void     mce_tklock_quit_dbus(void);

424 425 426 427
// NOTIFICATION_SLOTS

static void     tklock_notif_slot_init(tklock_notif_slot_t *self);
static void     tklock_notif_slot_free(tklock_notif_slot_t *self);
428
static void     tklock_notif_slot_set(tklock_notif_slot_t *self, const char *owner, const char *name, int64_t until, int64_t renew);
429 430 431 432
static bool     tklock_notif_slot_is_free(const tklock_notif_slot_t *self);
static bool     tklock_notif_slot_has_name(const tklock_notif_slot_t *self, const char *name);
static bool     tklock_notif_slot_validate(tklock_notif_slot_t *self, int64_t now);
static bool     tklock_notif_slot_renew(tklock_notif_slot_t *self, int64_t now);
433 434
static bool     tklock_notif_slot_has_owner(const tklock_notif_slot_t *self, const char *owner);
static gchar   *tklock_notif_slot_steal_owner(tklock_notif_slot_t *self);
435 436 437 438 439 440 441 442 443 444

// NOTIFICATION_API

static void     tklock_notif_init(void);
static void     tklock_notif_quit(void);
static gboolean tklock_notif_autostop_cb(gpointer aptr);
static void     tklock_notif_cancel_autostop(void);
static void     tklock_notif_schedule_autostop(gint delay);
static void     tklock_notif_update_state(void);
static void     tklock_notif_extend_by_renew(void);
445 446 447 448 449 450 451 452
static void     tklock_notif_vacate_slot(const char *owner, const char *name, int64_t linger);
static void     tklock_notif_reserve_slot(const char *owner, const char *name, int64_t length, int64_t renew);
static void     tklock_notif_vacate_slots_from(const char *owner);
static size_t   tklock_notif_count_slots_from(const char *owner);

static gboolean tklock_notif_owner_dropped_cb(DBusMessage *const msg);
static void     tklock_notif_add_owner_monitor(const char *owner);
static void     tklock_notif_remove_owner_monitor(const char *owner);
453

454 455
static void     mce_tklock_begin_notification(const char *owner, const char *name, int64_t length, int64_t renew);
static void     mce_tklock_end_notification(const char *owner, const char *name, int64_t linger);
456

457 458 459
// "module" load/unload
extern gboolean mce_tklock_init(void);
extern void     mce_tklock_exit(void);
460
extern void     mce_tklock_unblank(display_state_t to_state);
461 462

/* ========================================================================= *
463
 * DYNAMIC_SETTINGS
464 465
 * ========================================================================= */

466
/** Flag: Devicelock is handled in lockscreen */
467
static gboolean tklock_devicelock_in_lockscreen = MCE_DEFAULT_TK_DEVICELOCK_IN_LOCKSCREEN;
468
static guint    tklock_devicelock_in_lockscreen_setting_id = 0;
469

470 471 472
/** Flag: Convert denied tklock removal attempt to: show device unlock view */
static bool tklock_devicelock_want_to_unlock = false;

473
/** Flag: Automatically lock (after ON->DIM->OFF cycle) */
474
static gboolean tk_autolock_enabled = MCE_DEFAULT_TK_AUTOLOCK_ENABLED;
475
static guint    tk_autolock_enabled_setting_id = 0;
476

477
/** Flag: Grabbing input devices is allowed */
478
static gboolean tk_input_policy_enabled = MCE_DEFAULT_TK_INPUT_POLICY_ENABLED;
479
static guint    tk_input_policy_enabled_setting_id = 0;
480

481
/** Delay for automatick locking (after ON->DIM->OFF cycle) */
482
static gint    tklock_autolock_delay = MCE_DEFAULT_TK_AUTOLOCK_DELAY;
483
static guint   tklock_autolock_delay_setting_id = 0;
484

485
/** Flag: Proximity sensor can block touch input */
486
static gboolean proximity_blocks_touch = MCE_DEFAULT_TK_PROXIMITY_BLOCKS_TOUCH;
487
static guint    proximity_blocks_touch_setting_id = 0;
488

489
/** Volume key input policy */
490
static gint  volkey_policy = MCE_DEFAULT_TK_VOLKEY_POLICY;
491
static guint volkey_policy_setting_id = 0;
492

493
/** Touchscreen gesture (doubletap etc) enable mode */
494
static gint  touchscreen_gesture_enable_mode = MCE_DEFAULT_DOUBLETAP_MODE;
495
static guint touchscreen_gesture_enable_mode_setting_id = 0;
496

497
/** Lid sensor open actions */
498 499
static gint  tklock_lid_open_actions = MCE_DEFAULT_TK_LID_OPEN_ACTIONS;
static guint tklock_lid_open_actions_setting_id = 0;
500 501

/** Lid sensor close actions */
502 503
static gint  tklock_lid_close_actions = MCE_DEFAULT_TK_LID_CLOSE_ACTIONS;
static guint tklock_lid_close_actions_setting_id = 0;
504

505
/** Flag: Is the lid sensor used for display blanking */
506
static gboolean lid_sensor_enabled = MCE_DEFAULT_TK_LID_SENSOR_ENABLED;
507
static guint    lid_sensor_enabled_setting_id = 0;
508

509
/** When to react to keyboard open */
510 511
static gint   tklock_kbd_open_trigger = MCE_DEFAULT_TK_KBD_OPEN_TRIGGER;
static guint  tklock_kbd_open_trigger_setting_id = 0;
512 513

/** How to react to keyboard open */
514 515
static gint   tklock_kbd_open_actions = MCE_DEFAULT_TK_KBD_OPEN_ACTIONS;
static guint  tklock_kbd_open_actions_setting_id = 0;
516 517

/** When to react to keyboard close */
518 519
static gint   tklock_kbd_close_trigger = MCE_DEFAULT_TK_KBD_CLOSE_TRIGGER;
static guint  tklock_kbd_close_trigger_setting_id = 0;
520 521

/** How to react to keyboard close */
522 523
static gint   tklock_kbd_close_actions = MCE_DEFAULT_TK_KBD_CLOSE_ACTIONS;
static guint  tklock_kbd_close_actions_setting_id = 0;
524

525
/** Flag for: Using ALS is allowed */
526
static gboolean als_enabled = MCE_DEFAULT_DISPLAY_ALS_ENABLED;
527
static guint    als_enabled_setting_id = 0;
528 529

/** Flag: Use ALS for lid close filtering */
530
static gboolean filter_lid_with_als = MCE_DEFAULT_TK_FILTER_LID_WITH_ALS;
531
static guint    filter_lid_with_als_setting_id = 0;
532

533
/** Maximum amount of light ALS should report when LID is closed */
534 535
static gint  filter_lid_als_limit = MCE_DEFAULT_TK_FILTER_LID_ALS_LIMIT;
static guint filter_lid_als_limit_setting_id = 0;
536

537
/** How long to keep display on after incoming call ends [ms] */
538 539
static gint  exception_length_call_in = MCE_DEFAULT_TK_EXCEPT_LEN_CALL_IN;
static guint exception_length_call_in_setting_id = 0;
540 541

/** How long to keep display on after outgoing call ends [ms] */
542 543
static gint  exception_length_call_out = MCE_DEFAULT_TK_EXCEPT_LEN_CALL_OUT;
static guint exception_length_call_out_setting_id = 0;
544 545

/** How long to keep display on after alarm is handled [ms] */
546 547
static gint  exception_length_alarm = MCE_DEFAULT_TK_EXCEPT_LEN_ALARM;
static guint exception_length_alarm_setting_id = 0;
548 549

/** How long to keep display on when usb cable is connected [ms] */
550 551
static gint  exception_length_usb_connect = MCE_DEFAULT_TK_EXCEPT_LEN_USB_CONNECT;
static guint exception_length_usb_connect_setting_id = 0;
552 553

/** How long to keep display on when usb mode dialog is shown [ms] */
554 555
static gint  exception_length_usb_dialog = MCE_DEFAULT_TK_EXCEPT_LEN_USB_DIALOG;
static guint exception_length_usb_dialog_setting_id = 0;
556 557

/** How long to keep display on when charging starts [ms] */
558 559
static gint  exception_length_charger = MCE_DEFAULT_TK_EXCEPT_LEN_CHARGER;
static guint exception_length_charger_setting_id = 0;
560 561

/** How long to keep display on after battery full [ms] */
562 563
static gint  exception_length_battery = MCE_DEFAULT_TK_EXCEPT_LEN_BATTERY;
static guint exception_length_battery_setting_id = 0;
564 565

/** How long to keep display on when audio jack is inserted [ms] */
566 567
static gint  exception_length_jack_in = MCE_DEFAULT_TK_EXCEPT_LEN_JACK_IN;
static guint exception_length_jack_in_setting_id = 0;
568 569

/** How long to keep display on when audio jack is removed [ms] */
570 571
static gint  exception_length_jack_out = MCE_DEFAULT_TK_EXCEPT_LEN_JACK_OUT;
static guint exception_length_jack_out_setting_id = 0;
572 573

/** How long to keep display on when camera button is pressed [ms] */
574 575
static gint  exception_length_camera = MCE_DEFAULT_TK_EXCEPT_LEN_CAMERA;
static guint exception_length_camera_setting_id = 0;
576 577

/** How long to keep display on when volume button is pressed [ms] */
578 579
static gint  exception_length_volume = MCE_DEFAULT_TK_EXCEPT_LEN_VOLUME;
static guint exception_length_volume_setting_id = 0;
580 581

/** How long to extend display on when there is user activity [ms] */
582 583
static gint  exception_length_activity = MCE_DEFAULT_TK_EXCEPT_LEN_ACTIVITY;
static guint exception_length_activity_setting_id = 0;
584

585
/** Flag for: Allow lockscreen animation during unblanking */
586
static gboolean lockscreen_anim_enabled = MCE_DEFAULT_TK_LOCKSCREEN_ANIM_ENABLED;
587
static guint    lockscreen_anim_enabled_setting_id = 0;
588

589 590 591 592 593 594 595 596
/** Default delay for delaying proximity uncovered handling [ms] */
static gint  tklock_proximity_delay_default = MCE_DEFAULT_TK_PROXIMITY_DELAY_DEFAULT;
static guint tklock_proximity_delay_default_setting_id = 0;

/** Delay for delaying proximity uncovered handling during calls [ms] */
static gint  tklock_proximity_delay_incall = MCE_DEFAULT_TK_PROXIMITY_DELAY_INCALL;
static guint tklock_proximity_delay_incall_setting_id = 0;

597 598 599 600
/* ========================================================================= *
 * probed control file paths
 * ========================================================================= */

601
/** SysFS path to touchscreen event disable */
602 603
static output_state_t mce_touchscreen_sysfs_disable_output =
{
604 605 606
    .context = "touchscreen_disable",
    .truncate_file = TRUE,
    .close_on_exit = TRUE,
607
};
608

Santtu Lakkala's avatar
Santtu Lakkala committed
609
/** SysFS path to touchscreen double-tap gesture control */
610
static const gchar *mce_touchscreen_gesture_enable_path = NULL;
Santtu Lakkala's avatar
Santtu Lakkala committed
611

612 613 614
/** SysFS path to touchscreen recalibration control */
static const gchar *mce_touchscreen_calibration_control_path = NULL;

615
/** SysFS path to keypad event disable */
616 617
static output_state_t mce_keypad_sysfs_disable_output =
{
618 619 620
    .context = "keypad_disable",
    .truncate_file = TRUE,
    .close_on_exit = TRUE,
621
};
622

623 624 625
/* ========================================================================= *
 * DATAPIPE VALUES AND TRIGGERS
 * ========================================================================= */
626

627 628 629 630 631 632
/** Cached submode_pipe state; assume invalid */
static submode_t submode = MCE_SUBMODE_INVALID;

/** Cached PID of process owning the topmost window on UI */
static int topmost_window_pid = -1;

633 634 635
/** Cached init_done state; assume unknown */
static tristate_t init_done = TRISTATE_UNKNOWN;

636 637 638
/** Proximity state history for triggering low power mode ui */
static ps_history_t tklock_lpmui_hist[8];

639 640 641 642 643
/** Current tklock ui state
 *
 * Access only via tklock_ui_is_enabled() / tklock_ui_set_enabled().
 */
static bool tklock_ui_enabled_pvt = false;
644

645
/** Current tklock ui state that has been sent to lipstick */
646
static int  tklock_ui_notified = -1; // does not match bool values
647

648
/** System state; is undefined at bootup, can't assume anything */
649
static system_state_t system_state = MCE_SYSTEM_STATE_UNDEF;
650

651 652 653 654 655 656
/** Display state; undefined initially, can't assume anything */
static display_state_t display_state_curr = MCE_DISPLAY_UNDEF;

/** Next Display state; undefined initially, can't assume anything */
static display_state_t display_state_next = MCE_DISPLAY_UNDEF;

657 658 659 660
/** Call state; assume no active calls */
static call_state_t call_state = CALL_STATE_NONE;

/** Actual proximity state; assume not covered */
661
static cover_state_t proximity_sensor_actual = COVER_UNDEF;
662 663

/** Effective proximity state; assume not covered */
664
static cover_state_t proximity_sensor_effective = COVER_UNDEF;
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680

/** Lid cover sensor state; assume unkown
 *
 * When in covered state, it is assumed that it is not physically
 * possible to see/interact with the display and thus it should
 * stay powered off.
 *
 * Originally was used to track Nokia N770 slidable cover. Now
 * it is used also for things like the hammerhead magnetic lid
 * sensor.
 */
static cover_state_t lid_sensor_actual = COVER_UNDEF;

/** Lid cover policy state; assume unknown */
static cover_state_t lid_sensor_filtered = COVER_UNDEF;

681
/** Change notifications for system_state
682
 */
683
static void tklock_datapipe_system_state_cb(gconstpointer data)
684
{
685 686
    system_state_t prev = system_state;
    system_state = GPOINTER_TO_INT(data);
687

688 689
    if( prev == system_state )
        goto EXIT;
690

691 692 693
    mce_log(LL_DEBUG, "system_state: %s -> %s",
            system_state_repr(prev),
            system_state_repr(system_state));
694

695
    tklock_ui_set_enabled(false);
696 697 698

EXIT:
    return;
699 700
}

701
/** Device lock state; assume undefined */
702
static devicelock_state_t devicelock_state = DEVICELOCK_STATE_UNDEFINED;
703

704
/** Push device lock state value into devicelock_state_pipe datapipe
705
 */
706
static void tklock_datapipe_set_devicelock_state(devicelock_state_t state)
707
{
708
    switch( state ) {
709 710 711
    case DEVICELOCK_STATE_UNLOCKED:
    case DEVICELOCK_STATE_UNDEFINED:
    case DEVICELOCK_STATE_LOCKED:
712 713 714 715 716
        break;

    default:
        mce_log(LL_WARN, "unknown device lock state=%d; assuming locked",
                state);
717
        state = DEVICELOCK_STATE_LOCKED;
718 719
        break;
    }
720

721 722
    if( devicelock_state != state ) {
        datapipe_exec_full(&devicelock_state_pipe,
723
                           GINT_TO_POINTER(state));
724 725 726
    }
}

727
/** Change notifications for devicelock_state
728
 */
729
static void tklock_datapipe_devicelock_state_cb(gconstpointer data)
730
{
731 732
    devicelock_state_t prev = devicelock_state;
    devicelock_state = GPOINTER_TO_INT(data);
733

734
    if( devicelock_state == prev )
735 736
        goto EXIT;

737 738 739
    mce_log(LL_DEVEL, "devicelock_state = %s -> %s",
            devicelock_state_repr(prev),
            devicelock_state_repr(devicelock_state));
740

741
    tklock_uiexception_rethink();
742

743 744
    tklock_autolock_rethink();

745 746 747 748 749
    /* When lipstick is starting up we see device lock
     * going through undefined -> locked/unlocked change.
     * We must not trigger autolock due to these initial
     * device lock transitions */
    switch( prev ) {
750
    case DEVICELOCK_STATE_UNDEFINED:
751 752 753 754 755
        /* Block autolock for 60 seconds when leaving
         * undefined state (= lipstick startup) */
        tklock_autolock_on_devlock_block(60 * 1000);
        break;

756
    case DEVICELOCK_STATE_LOCKED:
757 758 759 760 761 762 763 764 765
        /* Unblock autolock earlier if we see transition
         * away from locked state (=unlocked by user) */
        tklock_autolock_on_devlock_block(0);
        break;

    default:
        break;
    }

766 767
    switch( devicelock_state ) {
    case DEVICELOCK_STATE_LOCKED:
768
        tklock_autolock_on_devlock_trigger();
769 770
        break;
    case DEVICELOCK_STATE_UNLOCKED:
771 772 773 774 775 776 777 778 779 780 781
        switch( display_state_next ) {
        case MCE_DISPLAY_OFF:
        case MCE_DISPLAY_LPM_OFF:
        case MCE_DISPLAY_LPM_ON:
            /* Transitions from undefined -> unlocked state occur
             * during device bootup / mce restart and should not
             * cause any actions.
             */
            if( prev == DEVICELOCK_STATE_UNDEFINED )
                break;

782 783 784 785
            /* Devicelock ui keeps fingerprint scanner active in LPM state
             * and unlocks device on identify, but omits unlock feedback
             * and leaves the display state as-is.
             *
786 787 788 789 790 791 792 793 794
             * As a workaround, execute unlock feedback from mce. Then
             * exit from LPM by requesting display power up and removal
             * of tklock submode.
             *
             * While this is mostly relevant to LPM, apply the same logic
             * also when in actually powered off display states to guard
             * against timing glitches (getting fingerprint identification
             * when already decided to exit LPM, etc) and changes in device
             * lock ui side logic.
795
             */
796 797
            mce_log(LL_WARN, "device got unlocked while display is off; "
                    "assume fingerprint authentication occurred");
798 799
            datapipe_exec_full(&ngfd_event_request_pipe,
                               "unlock_device");
800

801 802 803 804 805
            /* Delay display state / tklock processing until proximity
             * sensor state is known */
            common_on_proximity_schedule(MODULE_NAME,
                                         tklock_datapipe_devicelock_state_cb2,
                                         0);
806 807 808
            break;
        default:
            break;
809 810 811 812 813
        }
        break;
    default:
        break;
    }
814

815 816 817 818
EXIT:
    return;
}

819
/** Wait for proximity sensor -callback for fingerprint unlock handling
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
 *
 * @param aptr unused
 */
static void tklock_datapipe_devicelock_state_cb2(gpointer aptr)
{
    (void)aptr;

    /* Still unlocked ? */
    if( devicelock_state == DEVICELOCK_STATE_UNLOCKED ) {
        if( proximity_sensor_actual != COVER_OPEN ) {
            mce_log(LL_WARN, "unblank skipped due to proximity sensor");
        }
        else {
            mce_datapipe_request_display_state(MCE_DISPLAY_ON);
            mce_datapipe_request_tklock(TKLOCK_REQUEST_OFF);
        }
    }

}

840
/** Resumed from suspend notification */
841
static void tklock_datapipe_resume_detected_event_cb(gconstpointer data)
842
{
843 844
    (void) data;

845 846
    /* Re-evaluate proximity locking after resuming from
     * suspend. */
847
    tklock_proxlock_resume();
848 849
}

850
/** devicelock dbus name is reserved; assume unknown */
851
static service_state_t devicelock_service_state = SERVICE_STATE_UNDEF;
852

853
/** Change notifications for devicelock_service_state
854
 */
855
static void tklock_datapipe_devicelock_service_state_cb(gconstpointer data)
856
{
857 858
    service_state_t prev = devicelock_service_state;
    devicelock_service_state = GPOINTER_TO_INT(data);
859

860
    if( devicelock_service_state == prev )
861 862
        goto EXIT;

863
    mce_log(LL_DEBUG, "devicelock_service_state = %s -> %s",
864
            service_state_repr(prev),
865
            service_state_repr(devicelock_service_state));
866

867
    if( devicelock_service_state == SERVICE_STATE_RUNNING ) {
868
        /* query initial device lock state on devicelock/mce startup */
869
        tklock_ui_get_devicelock();
870 871 872 873
    }
    else {
        /* if device lock service is not running, the device lock
         * state is undefined */
874
        tklock_datapipe_set_devicelock_state(DEVICELOCK_STATE_UNDEFINED);
875 876 877 878 879 880
    }

EXIT:
    return;
}

881
/** Lipstick dbus name is reserved; assume false */
882
static service_state_t lipstick_service_state = SERVICE_STATE_UNDEF;
883

884
/** Change notifications for lipstick_service_state
885
 */
886
static void tklock_datapipe_lipstick_service_state_cb(gconstpointer data)
887
{
888 889
    service_state_t prev = lipstick_service_state;
    lipstick_service_state = GPOINTER_TO_INT(data);
890

891
    if( lipstick_service_state == prev )
892 893
        goto EXIT;

894
    mce_log(LL_DEBUG, "lipstick_service_state = %s -> %s",
895
            service_state_repr(prev),
896
            service_state_repr(lipstick_service_state));
897

898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
    bool enable_tklock = false;

    /* Tklock is applicable only when lipstick is running */
    if( lipstick_service_state == SERVICE_STATE_RUNNING ) {
        /* STOPPED -> RUNNING: Implies lipstick start / restart.
         * In this case lockscreen status is decided by lipstick.
         * We achieve tklock state synchronization by making a
         * lockscreen deactivation request - which lipstick can
         * then choose to honor or override.
         *
         * UNDEF -> RUNNING: Implies a mce restart while lipstick
         * is running. What we would like to happen is that
         * things stay exactly as they were. However there is
         * no way to recover lockscreen state from lipstick.
         * So in order to err on the safer side, we activate
         * lockscreen to get tklock state in sync again.
         */
        if( prev == SERVICE_STATE_UNDEF )
            enable_tklock = true;
    }

919
    // force tklock ipc
920
    tklock_ui_notified = -1;
921
    tklock_ui_set_enabled(enable_tklock);
922 923 924

EXIT:
    return;
925 926
}

927
/** Update mode is active; assume false */
928
static bool osupdate_running = false;
929

930
/** Change notifications for osupdate_running
931
 */
932
static void tklock_datapipe_osupdate_running_cb(gconstpointer data)
933
{
934 935
    bool prev = osupdate_running;
    osupdate_running = GPOINTER_TO_INT(data);
936

937
    if( osupdate_running == prev )
938 939
        goto EXIT;

940
    mce_log(LL_DEBUG, "osupdate_running = %d -> %d", prev, osupdate_running);
941

942
    if( osupdate_running ) {
943
        /* undo tklock when update mode starts */
944
        mce_datapipe_request_tklock(TKLOCK_REQUEST_OFF);
945 946 947 948 949 950
    }

EXIT:
    return;
}

951 952 953 954 955 956 957 958 959 960 961 962 963
/** Device is shutting down; assume false */
static bool shutting_down = false;

/** Change notifications for shutting_down
 */
static void tklock_datapipe_shutting_down_cb(gconstpointer data)
{
    bool prev = shutting_down;
    shutting_down = GPOINTER_TO_INT(data);

    if( shutting_down == prev )
        goto EXIT;

964 965
    mce_log(LL_DEBUG, "shutting_down = %d -> %d",
            prev, shutting_down);
966 967 968 969 970 971 972

    tklock_evctrl_rethink();

EXIT:
    return;
}

973 974 975
/** Autorelock trigger: assume disabled */
static autorelock_t autorelock_trigger = AUTORELOCK_NO_TRIGGERS;

976
/** Change notifications for display_state_curr
977
 */
978
static void tklock_datapipe_display_state_curr_cb(gconstpointer data)
979
{
980 981
    display_state_t prev = display_state_curr;
    display_state_curr = GPOINTER_TO_INT(data);
982

983
    if( display_state_curr == prev )
984
        goto EXIT;
985

986
    mce_log(LL_DEBUG, "display_state_curr = %s -> %s",
987
            display_state_repr(prev),
988
            display_state_repr(display_state_curr));
989

990 991
    tklock_datapipe_rethink_interaction_expected();

992 993
    tklock_lidfilter_rethink_allow_close();

994 995
    /* Disable "wakeup with fake policy" hack
     * when any stable display state is reached */
996 997 998
    if( display_state_curr != MCE_DISPLAY_POWER_UP &&
        display_state_curr != MCE_DISPLAY_POWER_DOWN )
        tklock_uiexception_end(UIEXCEPTION_TYPE_NOANIM, 0);
999

1000
    if( display_state_curr == MCE_DISPLAY_DIM )
1001
        tklock_ui_eat_event();
1002

1003
    tklock_uiexception_rethink();
1004

1005 1006 1007 1008
    tklock_autolock_rethink();
    tklock_proxlock_rethink();

    tklock_evctrl_rethink();
1009 1010 1011

    tklock_ui_notify_schdule();

1012 1013
EXIT:
    return;
1014 1015
}

1016
/** Pre-change notifications for display_state_curr
1017 1018 1019 1020 1021
 */
static void tklock_datapipe_display_state_next_cb(gconstpointer data)
{
    display_state_next = GPOINTER_TO_INT(data);

1022
    mce_log(LL_DEBUG, "display_state_next = %s -> %s",
1023
            display_state_repr(display_state_curr),
1024
            display_state_repr(display_state_next));
1025

1026
    if( display_state_next == display_state_curr )
1027 1028
        goto EXIT;

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
    /* Cancel autorelock on display off */
    switch( display_state_next ) {
    case MCE_DISPLAY_ON:
    case MCE_DISPLAY_DIM:
        /* display states that use normal ui */
        break;

    default:
        /* display powered off, showing lpm, etc */
        if( autorelock_trigger != AUTORELOCK_NO_TRIGGERS ) {
            mce_log(LL_DEBUG, "autorelock canceled: display off");
            autorelock_trigger = AUTORELOCK_NO_TRIGGERS;
        }
        break;
    }

1045 1046
    tklock_autolock_on_devlock_prime();

1047 1048 1049
    tklock_autolock_rethink();
    tklock_proxlock_rethink();

1050 1051
    tklock_lpmui_pre_transition_actions();

1052 1053
    tklock_ui_notify_schdule();

1054 1055 1056 1057 1058
EXIT:
    return;

}

1059 1060
/** Timer id for delayed proximity uncovering */
static guint tklock_datapipe_proximity_uncover_id = 0;
1061

1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
/** Re-evaluate proximity sensor debugging led pattern state
 */
static void tklock_datapipe_proximity_eval_led(void)
{
    typedef enum {
        PROXIMITY_LED_STATE_UNDEFINED  = 0,
        PROXIMITY_LED_STATE_COVERED    = 1,
        PROXIMITY_LED_STATE_UNCOVERING = 2,
        PROXIMITY_LED_STATE_UNCOVERED  = 3,
    } proximity_led_state_t;

    static proximity_led_state_t prev = PROXIMITY_LED_STATE_UNDEFINED;

    /* Evaluate what led pattern should be active */
    proximity_led_state_t curr = PROXIMITY_LED_STATE_UNDEFINED;

    if( proximity_sensor_effective == COVER_OPEN )
        curr = PROXIMITY_LED_STATE_UNCOVERED;
    else if( proximity_sensor_actual == COVER_OPEN )
        curr = PROXIMITY_LED_STATE_UNCOVERING;
    else if( proximity_sensor_actual == COVER_CLOSED )
        curr = PROXIMITY_LED_STATE_COVERED;

    if( prev == curr )
        goto EXIT;

    /* Activate new pattern 1st, then deactivate old pattern
     * to avoid transition via no active pattern.
     */

    switch( curr )
    {
    case PROXIMITY_LED_STATE_UNCOVERED:
        datapipe_exec_full(&led_pattern_activate_pipe,
                           MCE_LED_PATTERN_PROXIMITY_UNCOVERED);
        break;
    case PROXIMITY_LED_STATE_UNCOVERING:
        datapipe_exec_full(&led_pattern_activate_pipe,
                           MCE_LED_PATTERN_PROXIMITY_UNCOVERING);
        break;
    case PROXIMITY_LED_STATE_COVERED:
        datapipe_exec_full(&led_pattern_activate_pipe,
                           MCE_LED_PATTERN_PROXIMITY_COVERED);
        break;
    default:
        break;
    }

    switch( prev )
    {
    case PROXIMITY_LED_STATE_UNCOVERED:
        datapipe_exec_full(&led_pattern_deactivate_pipe,
                           MCE_LED_PATTERN_PROXIMITY_UNCOVERED);
        break;
    case PROXIMITY_LED_STATE_UNCOVERING:
        datapipe_exec_full(&led_pattern_deactivate_pipe,
                           MCE_LED_PATTERN_PROXIMITY_UNCOVERING);
        break;
    case PROXIMITY_LED_STATE_COVERED:
        datapipe_exec_full(&led_pattern_deactivate_pipe,
                           MCE_LED_PATTERN_PROXIMITY_COVERED);
        break;
    default:
        break;
    }

    prev = curr;

EXIT:
    return;
}

1134
/** Set effective proximity state from current sensor state
1135
 */
1136
static void tklock_datapipe_proximity_update(void)
1137
{
1138
    if( proximity_sensor_effective == proximity_sensor_actual )
1139 1140
        goto EXIT;

1141 1142 1143
    mce_log(LL_DEBUG, "proximity_sensor_effective = %s -> %s",
            proximity_state_repr(proximity_sensor_effective),
            proximity_state_repr(proximity_sensor_actual));
1144

1145
    proximity_sensor_effective = proximity_sensor_actual;
1146

1147 1148 1149
    datapipe_exec_full(&proximity_sensor_effective_pipe,
                       GINT_TO_POINTER(proximity_sensor_effective));

1150
    tklock_datapipe_proximity_eval_led();
1151
    tklock_uiexception_rethink();
1152 1153 1154
    tklock_proxlock_rethink();
    tklock_evctrl_rethink();

1155 1156 1157
    /* consider moving to lpm ui */
    tklock_lpmui_rethink();

1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
EXIT:
    return;
}

/** Timer callback for handling delayed proximity uncover
 */
static gboolean tklock_datapipe_proximity_uncover_cb(gpointer data)
{
    (void)data;

    if( !tklock_datapipe_proximity_uncover_id )
1169 1170
        goto EXIT;

1171
    tklock_datapipe_proximity_uncover_id = 0;
1172

1173
    tklock_datapipe_proximity_update();
1174

1175
    wakelock_unlock("mce_proximity_stm");
1176

1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
EXIT:
    return FALSE;
}

/** Cancel delayed proximity uncovering
 */
static void tklock_datapipe_proximity_uncover_cancel(void)
{
    if( tklock_datapipe_proximity_uncover_id ) {
        g_source_remove(tklock_datapipe_proximity_uncover_id),
            tklock_datapipe_proximity_uncover_id = 0;
        wakelock_unlock("mce_proximity_stm");
    }
}

/** Schedule delayed proximity uncovering
 */
static void tklock_datapipe_proximity_uncover_schedule(void)
{
    if( tklock_datapipe_proximity_uncover_id )
        g_source_remove(tklock_datapipe_proximity_uncover_id);
    else
        wakelock_lock("mce_proximity_stm", -1);

1201
    int delay = tklock_proximity_delay_default;
1202 1203

    if( call_state == CALL_STATE_ACTIVE )
1204 1205 1206 1207 1208 1209
        delay = tklock_proximity_delay_incall;

    if( delay < MCE_MINIMUM_TK_PROXIMITY_DELAY )
        delay = MCE_MINIMUM_TK_PROXIMITY_DELAY;
    else if( delay > MCE_MAXIMUM_TK_PROXIMITY_DELAY )
        delay = MCE_MAXIMUM_TK_PROXIMITY_DELAY;
1210

1211
    tklock_datapipe_proximity_uncover_id =
1212
        g_timeout_add(delay, tklock_datapipe_proximity_uncover_cb, 0);
1213 1214
}

1215
/** Change notifications for proximity_sensor_actual
1216
 */
1217
static void tklock_datapipe_proximity_sensor_actual_cb(gconstpointer data)
1218
{
1219 1220
    cover_state_t prev = proximity_sensor_actual;
    proximity_sensor_actual = GPOINTER_TO_INT(data);
1221

1222
    if( proximity_sensor_actual == prev )
1223 1224
        goto EXIT;

1225
    mce_log(LL_DEBUG, "proximity_sensor_actual = %s -> %s",
1226
            proximity_state_repr(prev),
1227
            proximity_state_repr(proximity_sensor_actual));
1228

1229 1230
    tklock_datapipe_proximity_eval_led();

1231
    /* update lpm ui proximity history using raw data */
1232
    tklock_lpmui_update_history(proximity_sensor_actual);
1233

1234
    if( proximity_sensor_actual == COVER_OPEN ) {
1235 1236 1237 1238 1239 1240
        tklock_datapipe_proximity_uncover_schedule();
    }
    else {
        tklock_datapipe_proximity_uncover_cancel();
        tklock_datapipe_proximity_update();
    }
1241 1242 1243

EXIT:
    return;
1244 1245
}

1246
/** Change notifications for call_state
1247
 */
1248
static void tklock_datapipe_call_state_cb(gconstpointer data)
1249
{
1250
    /* Default to using shorter outgoing call linger time */
1251
    static bool incoming = false;
1252

1253 1254
    call_state_t prev = call_state;
    call_state = GPOINTER_TO_INT(data);
1255

1256 1257 1258
    if( call_state == CALL_STATE_INVALID )
        call_state = CALL_STATE_NONE;

1259 1260
    if( call_state == prev )
        goto EXIT;
1261

1262 1263 1264
    mce_log(LL_DEBUG, "call_state = %s -> %s",
            call_state_repr(prev),
            call_state_repr(call_state));
1265

1266 1267
    switch( call_state ) {
    case CALL_STATE_RINGING:
1268
        /* Switch to using longer incoming call linger time */
1269
        incoming = true;
1270 1271 1272

        /* Fall through */

1273
    case CALL_STATE_ACTIVE:
1274
        tklock_uiexception_begin(UIEXCEPTION_TYPE_CALL, 0);
1275
        break;
1276

1277
    default:
1278 1279 1280
        tklock_uiexception_end(UIEXCEPTION_TYPE_CALL, incoming ?
                               exception_length_call_in :
                               exception_length_call_out);
1281 1282

        /* Restore linger time to default again */
1283
        incoming = false;
1284 1285
        break;
    }
1286

1287
    // display on/off policy
1288
    tklock_uiexception_rethink();
1289

1290 1291 1292 1293
    // volume keys during call
    tklock_evctrl_rethink();
EXIT:
    return;
1294 1295
}

1296
/** Music playback state; assume not playing */
1297
static bool music_playback_ongoing = false;
1298

1299
/** Change notifications for music_playback_ongoing
1300
 */
1301
static void tklock_datapipe_music_playback_ongoing_cb(gconstpointer data)
1302
{
1303 1304
    bool prev = music_playback_ongoing;
    music_playback_ongoing = GPOINTER_TO_INT(data);
1305

1306
    if( music_playback_ongoing == prev )
1307 1308
        goto EXIT<