Skip to content

Commit

Permalink
Detect and broadcast device flip over gestures
Browse files Browse the repository at this point in the history
If the device orientation changes from face up to face down while
the display is on and there is active call or alarm, an appropriate
ui feedback signal is sent over D-Bus System Bus.

[mce] Detect and broadcast device flip over gestures. Fixes JB#17820
  • Loading branch information
spiiroin committed Apr 1, 2014
1 parent eca84d0 commit 17dad91
Show file tree
Hide file tree
Showing 4 changed files with 341 additions and 1 deletion.
18 changes: 18 additions & 0 deletions .depend
Expand Up @@ -684,6 +684,24 @@ modules/radiostates.pic.o:\
mce.h\
modules/radiostates.h\

modules/sensor-gestures.o:\
modules/sensor-gestures.c\
datapipe.h\
datapipe.h\
mce-dbus.h\
mce-log.h\
mce-sensorfw.h\
mce.h\

modules/sensor-gestures.pic.o:\
modules/sensor-gestures.c\
datapipe.h\
datapipe.h\
mce-dbus.h\
mce-log.h\
mce-sensorfw.h\
mce.h\

powerkey.o:\
powerkey.c\
datapipe.h\
Expand Down
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -170,6 +170,7 @@ MODULES += $(MODULE_DIR)/battery-bme.so
MODULES += $(MODULE_DIR)/battery-upower.so
MODULES += $(MODULE_DIR)/display.so
MODULES += $(MODULE_DIR)/doubletap.so
MODULES += $(MODULE_DIR)/sensor-gestures.so
MODULES += $(MODULE_DIR)/led.so
MODULES += $(MODULE_DIR)/callstate.so
MODULES += $(MODULE_DIR)/audiorouting.so
Expand Down
2 changes: 1 addition & 1 deletion inifiles/mce.ini
Expand Up @@ -16,7 +16,7 @@ ModulePath=/usr/lib/mce/modules
# to avoid unnecessary brightness fluctuations on mce startup
#
# Note: the name should not include the "lib"-prefix
Modules=radiostates;filter-brightness-als;display;keypad;led;battery-upower;inactivity;alarm;callstate;audiorouting;proximity;powersavemode;cpu-keepalive;doubletap;packagekit
Modules=radiostates;filter-brightness-als;display;keypad;led;battery-upower;inactivity;alarm;callstate;audiorouting;proximity;powersavemode;cpu-keepalive;doubletap;packagekit;sensor-gestures;


[HomeKey]
Expand Down
321 changes: 321 additions & 0 deletions modules/sensor-gestures.c
@@ -0,0 +1,321 @@
/**
* @file sensor-gestures.c
*
* Sensor gesture module for the Mode Control Entity
* <p>
* Copyright © 2014 Jolla Ltd.
* <p>
* @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
*
* 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/>.
*/

#include "../mce.h"
#include "../mce-log.h"
#include "../mce-dbus.h"
#include "../mce-sensorfw.h"
#include "../datapipe.h"

#include <glib.h>
#include <gmodule.h>

/** Cached display state */
static display_state_t display_state = MCE_DISPLAY_UNDEF;

/** Cached alarm ui state */
static alarm_ui_state_t alarm_ui_state = MCE_ALARM_UI_INVALID_INT32;

/** Cached call state */
static call_state_t call_state = CALL_STATE_INVALID;

/** Cached raw orientation sensor value */
static orientation_state_t orientation_state_raw = MCE_ORIENTATION_UNDEFINED;

/** Cached delayed orientation sensor value */
static orientation_state_t orientation_state_eff = MCE_ORIENTATION_UNDEFINED;

/** Timer id for delayed orientation_state_eff updating */
static gint orientation_state_eff_id = 0;

/** Helper for checking if there is an active alarm dialog
*
* @return true if there is alarm, false otherwise
*/
static bool sg_have_alarm_dialog(void)
{
bool res = false;

switch( alarm_ui_state ) {
case MCE_ALARM_UI_RINGING_INT32:
case MCE_ALARM_UI_VISIBLE_INT32:
res = true;
break;
default:
break;
}

return res;
}

/** Helper for checking if there is an incoming call
*
* @return true if there is incoming call, false otherwise
*/
static bool sg_have_incoming_call(void)
{
bool res = false;

switch( call_state ) {
case CALL_STATE_RINGING:
res = true;
break;
default:
break;
}

return res;
}

/** Helper for sending flipover dbus signal
*
* @param signal name
*/
static void sg_send_flipover_signal(const char *sig)
{
const char *arg = "flipover";
mce_log(LL_DEVEL, "sending dbus signal: %s %s", sig, arg);
dbus_send(0, MCE_SIGNAL_PATH, MCE_SIGNAL_IF, sig, 0,
DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
}

/** Detect and broadcast device flipover during alarm
*
* While display is on and alarm active,
* send "flipover" signal over dbus, if
* we first see orientation = face up,
* followed by orientation = face down.
*/
static void sg_detect_flipover_gesture(void)
{
static bool primed = false;

/* Check display state */
if( display_state != MCE_DISPLAY_ON ) {
primed = false;
goto EXIT;
}

/* Check active alarm / incoming call */
if( !sg_have_alarm_dialog() &&
!sg_have_incoming_call() ) {
primed = false;
goto EXIT;
}

/* Check orientation state */
if( orientation_state_eff == MCE_ORIENTATION_FACE_UP ) {
primed = true;
}
else if( orientation_state_eff != MCE_ORIENTATION_FACE_DOWN ) {
// nop
}
else if( primed ) {
primed = false;

if( sg_have_alarm_dialog() )
sg_send_flipover_signal("alarm_ui_feedback_ind");

if( sg_have_incoming_call() )
sg_send_flipover_signal("call_ui_feedback_ind");
}

EXIT:

return;
}

/** Handle call_state_pipe notifications
*
* @param data The call state stored in a pointer
*/
static void sg_call_state_cb(gconstpointer const data)
{
call_state_t prev = call_state;
call_state = GPOINTER_TO_INT(data);

if( call_state == prev )
goto EXIT;

sg_detect_flipover_gesture();
EXIT:

return;
}

/** Handle alarm_ui_state_pipe notifications
*
* @param data The alarm state stored in a pointer
*/
static void sg_alarm_ui_state_cb(gconstpointer data)
{
alarm_ui_state_t prev = alarm_ui_state;
alarm_ui_state = GPOINTER_TO_INT(data);

if( alarm_ui_state == prev )
goto EXIT;

sg_detect_flipover_gesture();

EXIT:
return;
}

/** Handle display_state_pipe notifications
*
* @param data The display state stored in a pointer
*/
static void sg_display_state_cb(gconstpointer data)
{
display_state_t prev = display_state;
display_state = GPOINTER_TO_INT(data);

if( display_state == prev )
goto EXIT;

sg_detect_flipover_gesture();

EXIT:
return;
}

/** Update effective orientation state from raw sensor state
*/
static void sg_orientation_state_update(void)
{
orientation_state_t prev = orientation_state_eff;
orientation_state_eff = orientation_state_raw;

if( orientation_state_eff == prev )
goto EXIT;

sg_detect_flipover_gesture();

EXIT:
return;
}

/** Handle delayed orientation_sensor_pipe notifications
*
* @param data (unused)
*
* @return FALSE to stop the timer from repeating
*/
static gboolean sg_orientation_state_eff_cb(gpointer data)
{
(void)data;

if( !orientation_state_eff_id )
goto EXIT;

orientation_state_eff_id = 0;

sg_orientation_state_update();

EXIT:
return FALSE;
}

/** Handle orientation_sensor_pipe notifications
*
* @param data The orientation state stored in a pointer
*/
static void sg_orientation_state_raw_cb(gconstpointer data)
{
orientation_state_t prev = orientation_state_raw;
orientation_state_raw = GPOINTER_TO_INT(data);

/* When the orientation sensor is stopped and restarted,
* sensord reports initially the last state that was seen
* before the sensor was stopped.
*
* To avoid false positives, the acceptance of face up
* orientation after sensor startup is delayed by bit
* more than what the sensor ramp up is expected to take.
*/

/* Remove existing delay timer */
if( orientation_state_eff_id ) {
g_source_remove(orientation_state_eff_id);
orientation_state_eff_id = 0;
}

if( prev == MCE_ORIENTATION_UNDEFINED &&
orientation_state_raw == MCE_ORIENTATION_FACE_UP ) {
/* Invalidate effective sensor value */
orientation_state_eff = MCE_ORIENTATION_UNDEFINED;

/* Schedule re-validation after 500 ms */
orientation_state_eff_id =
g_timeout_add(500, sg_orientation_state_eff_cb, 0);
}
else {
/* Update effective sensor value immediately */
sg_orientation_state_update();
}

return;
}

/** Init function for the sensor-gestures module
*
* @param module (not used)
*
* @return NULL on success, a string with an error message on failure
*/
G_MODULE_EXPORT const gchar *g_module_check_init(GModule *module);
const gchar *g_module_check_init(GModule *module)
{
(void)module;

/* Add datapipe triggers */
append_output_trigger_to_datapipe(&orientation_sensor_pipe,
sg_orientation_state_raw_cb);
append_output_trigger_to_datapipe(&display_state_pipe,
sg_display_state_cb);
append_output_trigger_to_datapipe(&alarm_ui_state_pipe,
sg_alarm_ui_state_cb);
append_input_trigger_to_datapipe(&call_state_pipe,
sg_call_state_cb);
return NULL;
}

/** Exit function for the sensor-gestures module
*
* @param module (not used)
*/
G_MODULE_EXPORT void g_module_unload(GModule *module);
void g_module_unload(GModule *module)
{
(void)module;

/* Remove datapipe triggers */
remove_output_trigger_from_datapipe(&orientation_sensor_pipe,
sg_orientation_state_raw_cb);
remove_output_trigger_from_datapipe(&display_state_pipe,
sg_display_state_cb);
remove_output_trigger_from_datapipe(&alarm_ui_state_pipe,
sg_alarm_ui_state_cb);
remove_input_trigger_from_datapipe(&call_state_pipe,
sg_call_state_cb);
return;
}

0 comments on commit 17dad91

Please sign in to comment.