if (ret < 0)
_E("failed to pet Thermal Monitor scenario\n");
+ g_ptr_array_free(g_thermal->resources, TRUE);
+
free(g_thermal);
g_thermal = NULL;
}
return ret;
}
+ g_thermal->resources = g_ptr_array_new_with_free_func(free);
+
for (i = 0; i < g_thermal->num; i++) {
if (g_thermal->list[i].support)
_I("Support \'%-12s\' thermal scenario",
g_thermal->list[i].name);
}
+ /* FIXME:
+ * Currently, initial thermal scenario among multiple resources are not
+ * settled properly; it is rather determined by one of scenario initialized
+ * lastly. So, it is required that the method for retrieving the current
+ * state of each device here.
+ */
+
device_notify(DEVICE_NOTIFIER_THERMAL_GET_SCENARIO, &scenario);
if (!scenario) {
_E("failed to get current scenario for thermal\n");
+ g_ptr_array_free(g_thermal->resources, TRUE);
free(g_thermal);
g_thermal = NULL;
return -EINVAL;
ret = thermal_put_scenario(g_thermal);
if (ret < 0) {
_E("failed to put Thermal Monitor scenario\n");
+ g_ptr_array_free(g_thermal->resources, TRUE);
free(g_thermal);
g_thermal = NULL;
}
},
};
+/**
+ * @brief Add thermal devices using key as thermal_device_name from
+ * thermal data, or update current scenario of each thermal device
+ *
+ * @param [in] data thermal data from thermal monitors
+ */
+static int thermal_handle_notifier_data(struct device_notifier_thermal_data *data)
+{
+ struct device_notifier_thermal_data *entry = NULL;
+ int priority = data->priority;
+ int i;
+
+ if (priority < 0)
+ return -EINVAL;
+
+ /*
+ * If current notification has highest priority, then discards
+ * previous ones and makes the new list. Otherwise, check existence
+ * of current thermal data and if so, updates scenario, or else adds
+ * data into current resource list.
+ */
+ if (priority > g_thermal->cur_priority) {
+ g_thermal->cur_priority = priority;
+ g_ptr_array_free(g_thermal->resources, TRUE);
+ g_thermal->resources = g_ptr_array_new_with_free_func(free);
+ } else {
+ int n = strlen(data->name);
+
+ for (i = 0; i < g_thermal->resources->len; i++) {
+ struct device_notifier_thermal_data *e;
+
+ e = g_ptr_array_index(g_thermal->resources, i);
+ if (!strncmp(e->name, data->name, n)) {
+ entry = e;
+ break;
+ }
+ }
+ }
+
+ if (entry) {
+ strncpy(entry->scenario, data->scenario, strlen(data->scenario) + 1);
+ } else {
+ entry = malloc(sizeof(*data));
+ if (!entry)
+ return -ENOMEM;
+
+ memcpy(entry, data, sizeof(*data));
+
+ g_ptr_array_add(g_thermal->resources, entry);
+ }
+
+ return 0;
+}
+
/**
* @brief Send broadcasting signal with the decided scenario name from
* pass-thermal before checking whether the scenario is supported
{
struct device_notifier_thermal_data *thermal_data = data;
GVariant *gvar;
- const char *scenario;
+ const char *scenario = "Undefined";
+ int scenario_idx = -1;
int ret;
- int i;
+ int i, j;
if (!g_thermal || !g_thermal->support || g_thermal->num <= 0) {
_I("Thermal Monitor is stopped\n");
scenario = thermal_data->scenario;
- /* Find the available thermal scenario */
- for (i = 0; i < g_thermal->num; i++) {
- if (!g_thermal->list[i].support)
- continue;
- if (!strncmp(g_thermal->list[i].name, scenario, strlen(scenario)))
- break;
+ /* Ignore the notification of lower priority resources */
+ if (thermal_data->priority < g_thermal->cur_priority)
+ return 0;
+
+ ret = thermal_handle_notifier_data(thermal_data);
+ if (ret)
+ return ret;
+
+ /* Find the highest scenario among available thermal resources */
+ for (i = 0; i < g_thermal->resources->len; i++) {
+ struct device_notifier_thermal_data *e;
+
+ e = (g_ptr_array_index(g_thermal->resources, i));
+ for (j = 0; j < g_thermal->num; j++) {
+ if (!strncmp(g_thermal->list[j].name,
+ e->scenario, strlen(e->scenario))) {
+ if (j > scenario_idx) {
+ if (g_thermal->list[j].support)
+ scenario_idx = j;
+ scenario = e->scenario;
+ }
+ break;
+ }
+ }
}
/* If there is no available thermal scenario, just return */
- if (i >= g_thermal->num) {
+ if (scenario_idx < 0) {
_I("Not supported \'%s\' scenario", scenario);
return 0;
}
- g_thermal->cur_scenario_idx = i;
+ g_thermal->cur_scenario_idx = scenario_idx;
/* If there is available thermal scenario, send the broadcast signal */
gvar = g_variant_new("(s)", scenario);