Skip to content

Commit

Permalink
[dsme] Track thermal state from thermal manager. Fixes JB#43907
Browse files Browse the repository at this point in the history
MCE has functionality like PowerSaveMode that depends on device thermal
state, however the thermal state datapipe that is supposed to carry
thermal status information within MCE is not connected to any data source.

Query current thermal status from thermal manager when the service shows
up on D-Bus SystemBus, listen to thermal status change notifications, and
feed the state information to thermal state datapipe.

Signed-off-by: Simo Piiroinen <simo.piiroinen@jollamobile.com>
  • Loading branch information
spiiroin committed Nov 23, 2018
1 parent 7be6216 commit e82c1a3
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 3 deletions.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -281,6 +281,7 @@ MCE_PKG_NAMES += dsme
MCE_PKG_NAMES += libiphb
MCE_PKG_NAMES += libsystemd-daemon
MCE_PKG_NAMES += libngf0
MCE_PKG_NAMES += thermalmanager_dbus_if

MCE_PKG_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(MCE_PKG_NAMES))
MCE_PKG_LDLIBS := $(shell $(PKG_CONFIG) --libs $(MCE_PKG_NAMES))
Expand Down
23 changes: 23 additions & 0 deletions datapipe.c
Expand Up @@ -388,6 +388,9 @@ datapipe_t ngfd_event_request_pipe;
/** dsme availability; read only */
datapipe_t dsme_service_state_pipe;

/** thermalmanager availability; read only */
datapipe_t thermalmanager_service_state_pipe;

/** bluez availability; read only */
datapipe_t bluez_service_state_pipe;

Expand Down Expand Up @@ -944,6 +947,7 @@ void mce_datapipe_init(void)
datapipe_init(usbmoded_service_state_pipe, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT, 0, GINT_TO_POINTER(SERVICE_STATE_UNDEF));
datapipe_init(ngfd_service_state_pipe, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT, 0, GINT_TO_POINTER(SERVICE_STATE_UNDEF));
datapipe_init(dsme_service_state_pipe, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT, 0, GINT_TO_POINTER(SERVICE_STATE_UNDEF));
datapipe_init(thermalmanager_service_state_pipe,DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT, 0, GINT_TO_POINTER(SERVICE_STATE_UNDEF));
datapipe_init(bluez_service_state_pipe, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT, 0, GINT_TO_POINTER(SERVICE_STATE_UNDEF));
datapipe_init(packagekit_locked_pipe, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT, 0, GINT_TO_POINTER(FALSE));
datapipe_init(osupdate_running_pipe, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT, 0, GINT_TO_POINTER(FALSE));
Expand Down Expand Up @@ -1022,6 +1026,7 @@ void mce_datapipe_quit(void)
datapipe_free(&ngfd_service_state_pipe);
datapipe_free(&ngfd_event_request_pipe);
datapipe_free(&dsme_service_state_pipe);
datapipe_free(&thermalmanager_service_state_pipe);
datapipe_free(&bluez_service_state_pipe);
datapipe_free(&packagekit_locked_pipe);
datapipe_free(&osupdate_running_pipe);
Expand Down Expand Up @@ -1151,6 +1156,24 @@ const char *devicelock_state_repr(devicelock_state_t state)
return res;
}

/** Convert thermal_state_t enum to human readable string
*
* @param state thermal state as thermal_state_t type
*
* @return human readable representation of state
*/
const char *thermal_state_repr(thermal_state_t state)
{
const char *res = "unknown";
switch( state ) {
case THERMAL_STATE_UNDEF: res = "undef"; break;
case THERMAL_STATE_OK: res = "ok"; break;
case THERMAL_STATE_OVERHEATED: res = "overheated"; break;
default: break;
}
return res;
}

/** Convert uiexception_type_t enum to human readable string
*
* Note that while uiexception_type_t actually is a bitmask
Expand Down
1 change: 1 addition & 0 deletions datapipe.h
Expand Up @@ -235,6 +235,7 @@ extern datapipe_t usbmoded_service_state_pipe;
extern datapipe_t ngfd_service_state_pipe;
extern datapipe_t ngfd_event_request_pipe;
extern datapipe_t dsme_service_state_pipe;
extern datapipe_t thermalmanager_service_state_pipe;
extern datapipe_t bluez_service_state_pipe;
extern datapipe_t packagekit_locked_pipe;
extern datapipe_t osupdate_running_pipe;
Expand Down
5 changes: 5 additions & 0 deletions mce-dbus.c
Expand Up @@ -43,6 +43,7 @@
#include <dbus/dbus-glib-lowlevel.h>

#include <mce/dbus-names.h>
#include <dsme/thermalmanager_dbus_if.h>

/* ========================================================================= *
* TYPES & CONSTANTS
Expand Down Expand Up @@ -2021,6 +2022,10 @@ static struct
.name = DSME_DBUS_SERVICE,
.datapipe = &dsme_service_state_pipe,
},
{
.name = thermalmanager_service,
.datapipe = &thermalmanager_service_state_pipe,
},
{
.name = "org.bluez",
.datapipe = &bluez_service_state_pipe,
Expand Down
207 changes: 204 additions & 3 deletions mce-dsme.c
Expand Up @@ -37,6 +37,7 @@
#include <dsme/state.h>
#include <dsme/protocol.h>
#include <dsme/processwd.h>
#include <dsme/thermalmanager_dbus_if.h>

/* ========================================================================= *
* MODULE DATA
Expand All @@ -54,9 +55,15 @@ static guint mce_dsme_transition_id = 0;
/** Availability of dsme; from dsme_service_state_pipe */
static service_state_t dsme_service_state = SERVICE_STATE_UNDEF;

/** Availability of thermalmanager; from thermalmanager_service_state_pipe */
static service_state_t thermalmanager_service_state = SERVICE_STATE_UNDEF;

/** System state from dsme; fed to system_state_pipe */
static system_state_t system_state = MCE_SYSTEM_STATE_UNDEF;

/** Thermal state from thermalmanager (dsme); fed to thermal_state_pipe */
static thermal_state_t thermal_state = THERMAL_STATE_UNDEF;

/** Shutdown warning from dsme; fed to shutting_down_pipe */
static bool mce_dsme_shutting_down_flag = false;

Expand All @@ -71,7 +78,8 @@ static tristate_t init_done = TRISTATE_UNKNOWN;
* UTILITY_FUNCTIONS
* ------------------------------------------------------------------------- */

static system_state_t mce_dsme_normalise_system_state (dsme_state_t dsmestate);
static thermal_state_t mce_dsme_parse_thermal_state (const char *name);
static system_state_t mce_dsme_normalise_system_state (dsme_state_t dsmestate);

/* ------------------------------------------------------------------------- *
* WORKER_WATCHDOG
Expand Down Expand Up @@ -127,6 +135,11 @@ static void mce_dsme_socket_disconnect (void);
* DBUS_HANDLERS
* ------------------------------------------------------------------------- */

static gboolean mce_dsme_dbus_thermal_state_change_cb (DBusMessage *const msg);
static void mce_dsme_dbus_thermal_state_reply_cb (DBusPendingCall *pc, void *aptr);
static void mce_dsme_dbus_cancel_thermal_state_query(void);
static void mce_dsme_dbus_start_thermal_state_query (void);

static gboolean mce_dsme_dbus_init_done_cb (DBusMessage *const msg);
static gboolean mce_dsme_dbus_shutdown_cb (DBusMessage *const msg);
static gboolean mce_dsme_dbus_thermal_shutdown_cb (DBusMessage *const msg);
Expand All @@ -139,7 +152,10 @@ static void mce_dsme_dbus_quit(void);
* DATAPIPE_TRACKING
* ------------------------------------------------------------------------- */

static void mce_dsme_datapipe_set_thermal_state (thermal_state_t state);

static void mce_dsme_datapipe_dsme_service_state_cb (gconstpointer data);
static void mce_dsme_datapipe_thermalmanager_service_state_cb(gconstpointer const data);
static void mce_dsme_datapipe_init_done_cb (gconstpointer data);
static void mce_dsme_datapipe_system_state_cb (gconstpointer data);

Expand Down Expand Up @@ -216,6 +232,32 @@ static system_state_t mce_dsme_normalise_system_state(dsme_state_t dsmestate)
return state;
}

/** Convert thermal manager thermal state name to mce thermal_state_t
*
* @param name Thermal state name as received over D-Bus
*
* @return name mapped to thermal_state_t enumeration value
*/
static thermal_state_t mce_dsme_parse_thermal_state(const char *name)
{
thermal_state_t state = THERMAL_STATE_UNDEF;

if( name == 0 )
;
else if( !strcmp(name, thermalmanager_thermal_status_low) )
state = THERMAL_STATE_OK;
else if( !strcmp(name, thermalmanager_thermal_status_normal) )
state = THERMAL_STATE_OK;
else if( !strcmp(name, thermalmanager_thermal_status_warning) )
state = THERMAL_STATE_OK;
else if( !strcmp(name, thermalmanager_thermal_status_alert) )
state = THERMAL_STATE_OVERHEATED;
else if( !strcmp(name, thermalmanager_thermal_status_fatal) )
state = THERMAL_STATE_OVERHEATED;

return state;
}

/* ========================================================================= *
* WORKER_WATCHDOG
* ========================================================================= */
Expand Down Expand Up @@ -709,6 +751,114 @@ static void mce_dsme_socket_disconnect(void)
* DBUS_HANDLERS
* ========================================================================= */

/** Pending thermal state query */
static DBusPendingCall *mce_dsme_thermal_state_query_pc = 0;

/** D-Bus callback for the thermal state change notification signal
*
* @param msg The D-Bus message
*
* @return TRUE
*/
static gboolean
mce_dsme_dbus_thermal_state_change_cb(DBusMessage *const msg)
{
DBusError error = DBUS_ERROR_INIT;
const char *name = 0;

if( !dbus_message_get_args(msg, &error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID)) {
mce_log(LL_ERR, "Failed to parse %s.%s; %s: %s",
dbus_message_get_interface(msg),
dbus_message_get_member(msg),
error.name, error.message);
goto EXIT;
}

mce_log(LL_WARN, "thermal state signal: %s", name);
thermal_state_t state = mce_dsme_parse_thermal_state(name);
mce_dsme_datapipe_set_thermal_state(state);

EXIT:
dbus_error_free(&error);
return TRUE;
}

/** Handle reply to async query made from mce_dsme_thermal_state_query_async()
*/
static void
mce_dsme_dbus_thermal_state_reply_cb(DBusPendingCall *pc, void *aptr)
{
(void)aptr;

DBusMessage *rsp = 0;
DBusError err = DBUS_ERROR_INIT;
const char *name = 0;

if( pc != mce_dsme_thermal_state_query_pc )
goto EXIT;

dbus_pending_call_unref(mce_dsme_thermal_state_query_pc),
mce_dsme_thermal_state_query_pc = 0;

if( !(rsp = dbus_pending_call_steal_reply(pc)) ) {
mce_log(LL_WARN, "no reply");
goto EXIT;
}

if( dbus_set_error_from_message(&err, rsp) ) {
mce_log(LL_WARN, "error reply: %s: %s", err.name, err.message);
goto EXIT;
}

if( !dbus_message_get_args(rsp, &err,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID) ) {
mce_log(LL_WARN, "parse error: %s: %s", err.name, err.message);
goto EXIT;
}

mce_log(LL_DEBUG, "thermal state reply: %s", name);
thermal_state_t state = mce_dsme_parse_thermal_state(name);
mce_dsme_datapipe_set_thermal_state(state);

EXIT:
if( rsp ) dbus_message_unref(rsp);
dbus_error_free(&err);
return;
}

/** Cancel pending async thermal state query
*/
static void
mce_dsme_dbus_cancel_thermal_state_query(void)
{
if( mce_dsme_thermal_state_query_pc ) {
mce_log(LL_DEBUG, "cancel thermal state query");
dbus_pending_call_cancel(mce_dsme_thermal_state_query_pc);
dbus_pending_call_unref(mce_dsme_thermal_state_query_pc);
mce_dsme_thermal_state_query_pc = 0;
}
}

/** Initiate async query to find out current thermal state
*/
static void
mce_dsme_dbus_start_thermal_state_query(void)
{
mce_dsme_dbus_cancel_thermal_state_query();

mce_log(LL_DEBUG, "start thermal state query");
dbus_send_ex(thermalmanager_service,
thermalmanager_path,
thermalmanager_interface,
thermalmanager_get_thermal_state,
mce_dsme_dbus_thermal_state_reply_cb, 0, 0,
&mce_dsme_thermal_state_query_pc,
DBUS_TYPE_INVALID);
}

/** D-Bus callback for the init done notification signal
*
* @param msg The D-Bus message
Expand Down Expand Up @@ -805,6 +955,12 @@ static mce_dbus_handler_t mce_dsme_dbus_handlers[] =
.type = DBUS_MESSAGE_TYPE_SIGNAL,
.callback = mce_dsme_dbus_battery_empty_shutdown_cb,
},
{
.interface = thermalmanager_interface,
.name = thermalmanager_state_change_ind,
.type = DBUS_MESSAGE_TYPE_SIGNAL,
.callback = mce_dsme_dbus_thermal_state_change_cb,
},
/* sentinel */
{
.interface = 0
Expand All @@ -829,6 +985,22 @@ static void mce_dsme_dbus_quit(void)
* DATAPIPE_TRACKING
* ========================================================================= */

static void mce_dsme_datapipe_set_thermal_state(thermal_state_t state)
{
if( thermal_state != state ) {
/* All thermal state transitions are of interest - except for the
* UNDEF -> OK that is expected to happen during mce startup. */
int level = LL_WARN;
if( thermal_state == THERMAL_STATE_UNDEF && state == THERMAL_STATE_OK )
level = LL_DEBUG;
mce_log(level, "thermal state changed: %s -> %s",
thermal_state_repr(thermal_state),
thermal_state_repr(state));
thermal_state = state;
datapipe_exec_full(&thermal_state_pipe, GINT_TO_POINTER(thermal_state));
}
}

/** Datapipe trigger for dsme availability
*
* @param data DSME D-Bus service availability (as a void pointer)
Expand All @@ -853,6 +1025,31 @@ static void mce_dsme_datapipe_dsme_service_state_cb(gconstpointer const data)
return;
}

/** Datapipe trigger for thermalmanager availability
*
* @param data thermalmanager D-Bus service availability (as a void pointer)
*/
static void mce_dsme_datapipe_thermalmanager_service_state_cb(gconstpointer const data)
{
service_state_t prev = thermalmanager_service_state;
thermalmanager_service_state = GPOINTER_TO_INT(data);

if( thermalmanager_service_state == prev )
goto EXIT;

mce_log(LL_DEBUG, "thermalmanager dbus service: %s -> %s",
service_state_repr(prev),
service_state_repr(thermalmanager_service_state));

if( thermalmanager_service_state == SERVICE_STATE_RUNNING )
mce_dsme_dbus_start_thermal_state_query();
else
mce_dsme_dbus_cancel_thermal_state_query();

EXIT:
return;
}

/** Change notifications for init_done
*/
static void mce_dsme_datapipe_init_done_cb(gconstpointer data)
Expand Down Expand Up @@ -951,6 +1148,10 @@ static datapipe_handler_t mce_dsme_datapipe_handlers[] =
.datapipe = &dsme_service_state_pipe,
.output_cb = mce_dsme_datapipe_dsme_service_state_cb,
},
{
.datapipe = &thermalmanager_service_state_pipe,
.output_cb = mce_dsme_datapipe_thermalmanager_service_state_cb,
},
{
.datapipe = &init_done_pipe,
.output_cb = mce_dsme_datapipe_init_done_cb,
Expand Down Expand Up @@ -1012,8 +1213,8 @@ void mce_dsme_exit(void)

mce_dsme_datapipe_quit();

/* Remove all timer sources before returning */
/* Remove all timer sources & pending calls before returning */
mce_dsme_transition_cancel();

mce_dsme_dbus_cancel_thermal_state_query();
return;
}
2 changes: 2 additions & 0 deletions mce.h
Expand Up @@ -374,6 +374,8 @@ typedef enum {
THERMAL_STATE_OVERHEATED = 1,
} thermal_state_t;

const char *thermal_state_repr(thermal_state_t state);

/** Exceptional UI status */
typedef enum {
UIEXCEPTION_TYPE_NONE = 0,
Expand Down
1 change: 1 addition & 0 deletions rpm/mce.spec
Expand Up @@ -17,6 +17,7 @@ Conflicts: lipstick-qt5 < 0.24.7
BuildRequires: pkgconfig(dbus-1) >= 1.0.2
BuildRequires: pkgconfig(dbus-glib-1)
BuildRequires: pkgconfig(dsme) >= 0.65.0
BuildRequires: pkgconfig(thermalmanager_dbus_if)
BuildRequires: pkgconfig(libiphb)
BuildRequires: pkgconfig(glib-2.0) >= 2.36.0
BuildRequires: pkgconfig(mce) >= 1.26.0
Expand Down

0 comments on commit e82c1a3

Please sign in to comment.