Thermal SW Architectures on HAL

来源:互联网 发布:java 打印map的所有值 编辑:程序博客网 时间:2024/04/29 04:49

Thermal SW Architectures on HAL

Peter xu, 2012.08

*************************************************************************************************************

Agenda

SW Architecture

HAL part (System_monitor service)

How to start

System_monitor workflow

Parse startup options

Load plugin

Parse configure file

Open server socket

Enable all sensors

How to create plugin(type=SENSOR)

How to create plugin(type=MITIGATION)

*************************************************************************************************************

Architecture

*************************************************************************************************************

 

HAL PART:  System_monitor service

How to start

System_monitor workflow

Parse startup options

Load plugin

Parse configure file

Open server socket

Enable all sensors

How to create plugin(type=SENSOR)

How to create plugin(type=MITIGATION)

 

*************************************************************************************************************

How to start

@ device/semc/viscan/files/init.viskan.rc

                # use system_monitor

                service system_monitor /system/bin/system_monitor

                    class core

                    user root

System_monitor run as service, that is the process cannot be killed and run always.

No startup options

Check the process

$adb shell ps | grep system_monitor

*************************************************************************************************************

System_monitor workflow

*************************************************************************************************************

Parse startup options (parse_options)

$adb shell

#system/bin/system_monitor –h

-h Print this help text

-c Complete path and name of config file

-n Number of clients this server can support

-p Path to the plugins

-s Complete path and name where the communication socket will be created

-l  List all available sensors

-a List all available actions

For example:

#system/bin/system_monitor –c /system/etc/sysmon.cfg

#system/bin/system_monitor –n 5

#system/bin/system_monitor –p /system/lib/sysmon/

#system/bin/system_monitor –s /tmp/sysmon.skt

#system/bin/system_monitor –l  //register plug in type=SENSOR

#system/bin/system_monitor –a  //register plug in type=MITIGATION

*************************************************************************************************************

Load plugin (load_plugins)

The path of share library

/system/lib/sysmon/*.so

Each plugin share library must include the function, as following

struct sysmon_plugin *tp_init(void)

struct sysmon_plugin {

  const char *name;  /* Name of sensor or mitigation   */

  const enum plugin_type type;  /* Type of plugin                 */

  int (*start_plugin)(void);  /* Start plugin. Always be called */

  …

   union {

  struct sensor_if {…

   void (*listen_for_event)(event_callback_t callback, void *data);

   } sensor;

  struct mitigation_if {

  int (*execute_action)(void *data);

  } mitigation;

  /* Add new types below this line */

 } interface;

Add plugin into plugin_list[2] according to the plugin type(SENSOR, MITIGATION)

Run initial function: start_plugin

*************************************************************************************************************

Load plugin workflow

*************************************************************************************************************

Parse configure file (parse_config_file)

The default path of configure file:  /system/etc/sysmon.cfg

Configure Format:

<Sensor> <Level> <MinAlarm> <MaxAlarm> <poll freq> <Actions>:<Parameter> [...<Actions>:<Parameter>]

For example:

bat_ctrl 2 18 43 5 NOTIFY lcd_brightness_reset

batt_therm CRITICAL 1 NONE    // critical level without min/max threshold

Sensor name:   bat_ctrl  batt_therm

Alarm level:   2  CRITICAL

Min alarm:   18

Max alarm:   43

Poll times:   5  1

Actions:  NOTIFY, lcd_brightness_reset  NONE

Important struct

struct sensor {

  pthread_mutex_t lock;

  struct sensor *next;

  char *sensor_name; //one of plugin names

  int last_level;

  int current_level;  //initial value is the lowest level

  struct alarm_level *levels[NUM_LEVELS]; //NUM_LEVELS=33, the number of alarm level must be less than 33, ascending sort for alarm level from level=0 to level=32

};

struct alarm_level {

  int level;  //alarm level >= 0, CRITICAL=0, others +=1, for example: if Alarm Level=0 in configure file, the level will be 1.

  int max_alarm;  //the threshold of max alarm value

  int min_alarm;  //the threshold of min alarm value

  int poll_time;  //the poll delay time

  int shutdown;  //for the alarm, mobile phone should be shutdown if shutdown=1

  int notify;  // for the alarm, send notify message to application/framework if notify=1

  struct action_entry *action_list; //for one alarm level, there could be more actions

};

struct action_entry {

  char *action;  //action name

  int variable_param;  //action parameter value

  struct action_entry *next;

};

*************************************************************************************************************

Parse configure file workflow

*************************************************************************************************************

Create server socket (socket_open)

Main purpose:

Listen client connect from application and framework

Send notify message to client socket

Socket file default path: /tmp/sysmon.skt

Max number of unconnected client socket in the connection queue: 5

Create server socket thread

socket(AF_UNIX, SOCK_STREAM, 0) //socket type= SOCK_STREAM

bind(…)  //set socket file path

listen(…)  //start listen

accept(…)   //wait for a new client to arrived & build our localstruct

Add client socket into socket_clients

Send notify message from server to client

Create client socket thread //manage communication with the client

Receive command from client

Send response from server to client

Main structs

struct socket_data {

  pthread_t socket_server_pid;  //socket server thread id

  int socket_server_fd;  //server socket id

  socket_client_t *socket_clients;  //save the all connected client socket

  pthread_mutex_t socket_clients_lock; 

  char *unix_socket_path;  //socket file path

  int max_clients;  //the max number of unconnected clients in the connection queue

};

typedef struct socket_client_s {

  int fd;  //client socket id

  pthread_t pid;  //socket client thread id

  struct socket_client_s *next;

} socket_client_t;

*************************************************************************************************************

Create server socket workflow

*************************************************************************************************************

Enable all sensors (sensor_enable_all_sensors)

Only start listening on those sensors registered via the configure file.

That is the sensors must be in configured_sensors.

The sensor must have matched plugin

All plugins(type=SENSOR) should have the function interface.sensor.listen_for_event

All plugins(type=MITIGATION) should have the function interface.mitigation.execute_action

The function of alarm_callback@sysmons.c is the key callback function for all sensors.

Main functions

void sensor_enable_all_sensors(event_callback_t cb, void *data)

{…

     p = find_plugin_by_name(s->sensor_name); //find the matchedplugin

  …

      if (p->interface.sensor.listen_for_event)

  p->interface.sensor.listen_for_event(cb, data); //calllisten_for_event

  …

}

*************************************************************************************************************

System_monitor process block (socket_wait)

Hold the process of system_monitor

The key function

pthread_join(data->socket_server_pid, NULL);

The main thread will wait for the socket server thread to terminate

Blocking call that waits for the server thread to shutdown

*************************************************************************************************************

How to create plugin(type=SENSOR)

For example: @device/semc/viskan/sysmon/pm8921_sensor.c

Create more plugins(type=SENSOR) with same one file of pm8921_sensor.c by different complier configure settings.

@device/semc/viskan/sysmon/Android.mk

  # xo_therm

  ifeq ($(SEMC_CFG_SYSMON_SENSOR_PM8921_XO_THERM),yes)

  include $(CLEAR_VARS)

  LOCAL_CFLAGS := -DTZ_USE_HW_UNIT

  LOCAL_CFLAGS += -DPM8921_SENSOR_NAME=\"xo_therm\"

  LOCAL_SRC_FILES := pm8921_sensor.c

  LOCAL_MODULE := sysmon_xo_therm

  include $(LOCAL_PATH)/main.mk

  endif

  # batt_therm

  ifeq ($(SEMC_CFG_SYSMON_SENSOR_PM8921_BATT_THERM),yes)

  include $(CLEAR_VARS)

  LOCAL_CFLAGS := -DPM8921_SENSOR_NAME=\"batt_therm\"

  LOCAL_SRC_FILES := pm8921_sensor.c

  LOCAL_MODULE := sysmon_batt_therm

  include $(LOCAL_PATH)/main.mk

  endif

Only change macro of PM8921_SENSOR_NAME,  the source file is same file of pm8921_sensor.c.

The module name is different too, so generate different share library *.so

How to create plugin(type=SENSOR) cont’

Main structs and functions

struct sysmon_plugin *tp_init(void)

  {  return &plg;}

static struct sysmon_plugin plg = {

  .name = SENSOR_NAME,  // #define SENSOR_NAME PM8921_SENSOR_NAME

  .type = SENSOR,

  .start_plugin = start_plugin,

  …

  .interface.sensor = {…

  .listen_for_event = listen_for_event,

  },

};

struct plg_data {

  char *sensor_name;  /* sensor_name */

  char *input_path;  /*the matched driver file node*/

  int poll_delay;  /* polling delay time */

  int temp_value;  /* temperature_value */

  int min_alarm;  /* min alarm value */

  int max_alarm;  /* max alarm value */

  pthread_t thread_id;  /* sensor thread ID */

  sem_t sem;

  event_callback_t cb;  /* callback function when to trigger alarm*/

  void *call_data;

  pthread_mutex_t lock;

};

How to create plugin(type=SENSOR) cont’

static int start_plugin(void)

{…

  rc = find_pm8921_sensor_path(plg.name); //check whether there is the driver file node or not

  if (rc < 0) {

  LOGE("%s - Failed to find correct sysfs interface. Aborting\n",

       __func__);

  return -ENODEV;

  } else {

  memset(buf, 0, sizeof(buf));

  snprintf(buf, sizeof(buf) - 1, PM8921_SENSOR_PATH SENSOR_NAME_PARAM, plg.name);// for example: /sys/bus/platform/devices/pm8xxx-adc/batt_therm

  }

  data.sensor_name = strdup(plg.name);

  data.input_path = strdup(buf); //set driver file path

…}

static void listen_for_event(event_callback_t callback, void *d)

{

  if (callback && NULL == data.cb) {

  if (pthread_create(&data.thread_id, PTHREAD_CREATE_JOINABLE,   sensor_work, (void *)&data)) {

  LOGE("%s - Failed to start worker thread\n“,    __func__);

  } else {

  data.cb = callback; //callback=alarm_callback@sysmon.c 

  data.call_data = d; //that is static structsysmon *td;@sysmons.c

  sem_post(&data.sem);

  }

  } else {

  pthread_create(&tid, NULL, stop_sensor_work, (void *)&data); // Since the thread can be sleeping, we need to start another thread that will kill it

  }

}

How to create plugin(type=SENSOR) cont’

static void *sensor_work(void *data)

{…

  fd = open(d->input_path, O_RDONLY); //open the driver file node, for example: /sys/bus/platform/devices/pm8xxx-adc/batt_therm

  while (1) { //get the value of batt_therm, and check whether is more thanmax_alarm and less thanmin_alarm. If so, triggeralarm_callback

  lseek(fd, 0, SEEK_SET);

  memset(read_buf, 0, sizeof(read_buf));

  /* get tsens temperature */

  if (read(fd, read_buf, sizeof(read_buf)) != -1) { //get temperature value

            /* read_buf: "Result:%lld Raw:%d\n" */

           sscanf(read_buf, "Result:%d Raw:%*d\n", &val);

           …

  }

  …

  d->temp_value = val;  //set current temperature value

  min_val = d->min_alarm;

  max_val = d->max_alarm;

 

  if (val > max_val) {

          d->cb(MAX_ALARM, d->sensor_name, d->call_data);  //for example: alarm_callback(MAX_ALARM,batt_therm, td;@sysmons.c)

  } else if (val < min_val) {

          d->cb(MIN_ALARM, d->sensor_name, d->call_data);

  }

wait:

  /* Without locking, the worst that can happen is that we

   * sleep an incorrect amount of time during one loop. Don't

   * think this is something that should be avoided */

  poll_sleep(d->poll_delay);  //delay fixed time for next polling

  }

  ….

}

*************************************************************************************************************

How to create plugin(type=SENSOR) workflow

*************************************************************************************************************

List all ready plugins (type=SENSOR) for viskan

*************************************************************************************************************

 

How to create plugin(type=MITIGATION)

For example: @vendor/semc/hardware/sysmon/plugins/brightness_level.c

@vendor/semc/hardware/sysmon/Android.mk

#sysmon_lcd_brightness_level module

ifeq ($(SEMC_CFG_SYSMON_MITIGATION_LCD_LEVEL),yes)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := brightness_level.c

LOCAL_MODULE := sysmon_lcd_brightness_level

include $(LOCAL_PATH)/main.mk

Endif

the source file is pm8921_sensor.c.

generate the share library /system/lib/sysmon/sysmon_lcd_brightness_level.so

*************************************************************************************************************

How to create plugin(type=MITIGATION) cont’

Main structs and functions

struct sysmon_plugin *tp_init(void)

  {  return &plg;}

static struct sysmon_plugin plg = {

  .name = MITIGATION_NAME,    // #define MITIGATION_NAME "lcd_brightnesslevel"

  .type = MITIGATION,

  .start_plugin = start_plugin,

  .deinit_plugin = deinit_plugin,

  .enable_test_mode = enable_test_mode,

  .interface.mitigation.execute_action = execute_action,

};

static int execute_action(void *data)

{

  struct sensor *s = (struct sensor *)data;

  …

  l = s->levels[s->current_level];

  a = l->action_list;

  while (a) {

  if (!strncmp(a->action, MITIGATION_NAME, strlen(a->action)))

  break;

  else

  a = a->next;

  }

  …

  log_idd(s, a);

  return set_soft_level(BR_TO_RGB((unsigned int)a->variable_param));

  …

}

*************************************************************************************************************

How to create plugin(type=MITIGATION) cont’

void alarm_callback(enum event_type type, const char *name,void *data)

{ …

  if (l->notify) {

  pi = find_plugin_by_name(NOTIFY_STRING);

  if (pi && pi->interface.mitigation.execute_action)

  pi->interface.mitigation.execute_action(s); //only call the notifysysmon_plugin inbuiltin.c

  }

  /* Perform all supported actions registered on this level */

  a = l->action_list;

  while (a) {

  pi = find_plugin_by_name(a->action); //find matchedplugin with the same action name

  if (pi)

  LOGV("%s - found plugin name: %s", __func__, pi->name);

  if (pi && strcmp(pi->name, NOTIFY_STRING)) //plugin name must not NOTIFY_STRING ("NOTIFY“)

  if (pi->interface.mitigation.execute_action)

  pi->interface.mitigation.execute_action(s); //do special action

  a = a->next;

  }

  …

}

*************************************************************************************************************

List all ready plugins (type=MITIGATION) for viskan

*************************************************************************************************************

Conclusion

Easily to add new sensor for monitoring temperature of special component in future because of loading dynamic plugin(type=SENSOR) share library(*.so)

Easily to add new mitigation(action if the temperature of special component is abnormal) in future because of loading dynamic plugin(type=MITIGATION) share library(*.so)

Easily notify the message to application or framework which need monitor temperatures when some special component temperatures become abnormal because of the server-client socket mode

Easily to manage how to respond when abnormal temperature happens because of setting different configure file by user, such as what is the reasonable threshold of battery high temperature, what kind of actions should be done for mitigating the rising temperature.

原创粉丝点击