power: rewrite battery stats parser

Make parsing battery stats more extendable and switch to system_stats for
the battery stats.

Bug: 36064954
Test: dumpsys batterystats shows non-zero stats
Change-Id: I39c59f86cbb335da5796d23c0ff4a7435745b31e
This commit is contained in:
Adrian Salido
2017-04-06 12:47:20 -07:00
committed by Ajay Dudani
parent 25eaf09f91
commit a60c8d7e89
2 changed files with 133 additions and 95 deletions

View File

@@ -49,37 +49,57 @@
#include "performance.h"
#include "power-common.h"
#define PLATFORM_SLEEP_MODES 2
#define XO_VOTERS 4
#define VMIN_VOTERS 0
#define RPM_PARAMETERS 4
#define NUM_PARAMETERS 12
#ifndef RPM_STAT
#define RPM_STAT "/d/rpm_stats"
#endif
#ifndef RPM_MASTER_STAT
#define RPM_MASTER_STAT "/d/rpm_master_stats"
#ifndef RPM_SYSTEM_STAT
#define RPM_SYSTEM_STAT "/d/system_stats"
#endif
/* RPM runs at 19.2Mhz. Divide by 19200 for msec */
#define RPM_CLK 19200
const char *parameter_names[] = {
"vlow_count",
"accumulated_vlow_time",
"vmin_count",
"accumulated_vmin_time",
"xo_accumulated_duration",
"xo_count",
"xo_accumulated_duration",
"xo_count",
"xo_accumulated_duration",
"xo_count",
"xo_accumulated_duration",
"xo_count"
#define ARRAY_SIZE(x) (sizeof((x))/sizeof((x)[0]))
#define LINE_SIZE 128
#define MAX_RPM_PARAMS 2
#define PLATFORM_SLEEP_MODES RPM_MODE_MAX
#define XO_VOTERS (MAX_STATS - XO_VOTERS_START)
#define VMIN_VOTERS 0
enum stats_type {
RPM_MODE_XO,
RPM_MODE_VMIN,
RPM_MODE_MAX,
XO_VOTERS_START = RPM_MODE_MAX,
VOTER_APSS = XO_VOTERS_START,
VOTER_MPSS,
VOTER_ADSP,
VOTER_SLPI,
MAX_STATS,
};
struct stat_pair {
enum stats_type stat;
const char *label;
const char **parameters;
size_t num_parameters;
};
const char *rpm_stat_params[MAX_RPM_PARAMS] = {
"count",
"actual last sleep(msec)",
};
const char *master_stat_params[MAX_RPM_PARAMS] = {
"Accumulated XO duration",
"XO Count",
};
struct stat_pair rpm_stat_map[] = {
{ RPM_MODE_XO, "RPM Mode:vlow", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
{ RPM_MODE_VMIN, "RPM Mode:vmin", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
{ VOTER_APSS, "APSS", master_stat_params, ARRAY_SIZE(master_stat_params) },
{ VOTER_MPSS, "MPSS", master_stat_params, ARRAY_SIZE(master_stat_params) },
{ VOTER_ADSP, "ADSP", master_stat_params, ARRAY_SIZE(master_stat_params) },
{ VOTER_SLPI, "SLPI", master_stat_params, ARRAY_SIZE(master_stat_params) },
};
static int saved_dcvs_cpu0_slack_max = -1;
@@ -470,109 +490,126 @@ static int get_voter_list(struct power_module *UNUSED(module), size_t *voter) {
return 0;
}
static int extract_stats(uint64_t *list, char *file,
unsigned int num_parameters, unsigned int index) {
FILE *fp;
ssize_t read;
size_t len;
static int parse_stats(const char **params, size_t params_size,
uint64_t *list, FILE *fp) {
ssize_t nread;
size_t len = LINE_SIZE;
char *line;
int ret;
size_t params_read = 0;
size_t i;
fp = fopen(file, "r");
if (fp == NULL) {
ret = -errno;
ALOGE("%s: failed to open: %s", __func__, strerror(errno));
return ret;
line = malloc(len);
if (!line) {
ALOGE("%s: no memory to hold line", __func__);
return -ENOMEM;
}
for (line = NULL, len = 0;
((read = getline(&line, &len, fp) != -1) && (index < num_parameters));
free(line), line = NULL, len = 0) {
uint64_t value;
char* offset;
size_t begin = strspn(line, " \t");
if (strncmp(line + begin, parameter_names[index], strlen(parameter_names[index]))) {
while ((params_read < params_size) &&
(nread = getline(&line, &len, fp) > 0)) {
char *key = line + strspn(line, " \t");
char *value = strchr(key, ':');
if (!value || (value > (line + len)))
continue;
}
*value++ = '\0';
offset = memchr(line, ':', len);
if (!offset) {
continue;
}
if (!strcmp(file, RPM_MASTER_STAT)) {
/* RPM_MASTER_STAT is reported in hex */
sscanf(offset, ":%" SCNx64, &value);
/* Duration is reported in rpm SLEEP TICKS */
if (!strcmp(parameter_names[index], "xo_accumulated_duration")) {
value /= RPM_CLK;
for (i = 0; i < params_size; i++) {
if (!strcmp(key, params[i])) {
list[i] = strtoull(value, NULL, 0);
params_read++;
break;
}
} else {
/* RPM_STAT is reported in decimal */
sscanf(offset, ":%" SCNu64, &value);
}
list[index] = value;
index++;
}
free(line);
fclose(fp);
return 0;
}
static int extract_stats(uint64_t *list, char *file,
struct stat_pair *map, size_t map_size) {
FILE *fp;
ssize_t read;
size_t len = LINE_SIZE;
char *line;
size_t i, stats_read = 0;
int ret = 0;
fp = fopen(file, "re");
if (fp == NULL) {
ALOGE("%s: failed to open '%s': %s", __func__, file, strerror(errno));
return -errno;
}
line = malloc(len);
if (!line) {
ALOGE("%s: no memory to hold line", __func__);
fclose(fp);
return -ENOMEM;
}
while ((stats_read < map_size) && (read = getline(&line, &len, fp) != -1)) {
size_t begin = strspn(line, " \t");
for (i = 0; i < map_size; i++) {
if (!strncmp(line + begin, map[i].label, strlen(map[i].label))) {
stats_read++;
break;
}
}
if (i == map_size)
continue;
ret = parse_stats(map[i].parameters, map[i].num_parameters,
&list[map[i].stat * MAX_RPM_PARAMS], fp);
if (ret < 0)
break;
}
free(line);
fclose(fp);
return ret;
}
static int get_platform_low_power_stats(struct power_module *UNUSED(module),
power_state_platform_sleep_state_t *list) {
uint64_t stats[sizeof(parameter_names)] = {0};
uint64_t stats[MAX_STATS * MAX_RPM_PARAMS] = {0};
uint64_t *values;
int ret;
unsigned i;
if (!list) {
return -EINVAL;
}
ret = extract_stats(stats, RPM_STAT, RPM_PARAMETERS, 0);
if (ret) {
return ret;
}
ret = extract_stats(stats, RPM_MASTER_STAT, NUM_PARAMETERS, RPM_PARAMETERS);
ret = extract_stats(stats, RPM_SYSTEM_STAT,
rpm_stat_map, ARRAY_SIZE(rpm_stat_map));
if (ret) {
return ret;
}
/* Update statistics for XO_shutdown */
strcpy(list[0].name, "XO_shutdown");
list[0].total_transitions = stats[0];
list[0].residency_in_msec_since_boot = stats[1];
values = stats + (RPM_MODE_XO * MAX_RPM_PARAMS);
list[0].total_transitions = values[0];
list[0].residency_in_msec_since_boot = values[1];
list[0].supported_only_in_suspend = false;
list[0].number_of_voters = XO_VOTERS;
/* Update statistics for APSS voter */
strcpy(list[0].voters[0].name, "APSS");
list[0].voters[0].total_time_in_msec_voted_for_since_boot = stats[4];
list[0].voters[0].total_number_of_times_voted_since_boot = stats[5];
/* Update statistics for MPSS voter */
strcpy(list[0].voters[1].name, "MPSS");
list[0].voters[1].total_time_in_msec_voted_for_since_boot = stats[6];
list[0].voters[1].total_number_of_times_voted_since_boot = stats[7];
/* Update statistics for ADSP voter */
strcpy(list[0].voters[2].name, "ADSP");
list[0].voters[2].total_time_in_msec_voted_for_since_boot = stats[8];
list[0].voters[2].total_number_of_times_voted_since_boot = stats[9];
/* Update statistics for SLPI voter */
strcpy(list[0].voters[3].name, "SLPI");
list[0].voters[3].total_time_in_msec_voted_for_since_boot = stats[10];
list[0].voters[3].total_number_of_times_voted_since_boot = stats[11];
for (i = 0; i < XO_VOTERS; i++) {
int voter = i + XO_VOTERS_START;
strlcpy(list[0].voters[i].name, rpm_stat_map[voter].label,
POWER_STATE_VOTER_NAME_MAX_LENGTH);
values = stats + (voter * MAX_RPM_PARAMS);
list[0].voters[i].total_time_in_msec_voted_for_since_boot = values[0] / RPM_CLK;
list[0].voters[i].total_number_of_times_voted_since_boot = values[1];
}
/* Update statistics for VMIN state */
strcpy(list[1].name, "VMIN");
list[1].total_transitions = stats[2];
list[1].residency_in_msec_since_boot = stats[3];
values = stats + (RPM_MODE_VMIN * MAX_RPM_PARAMS);
list[1].total_transitions = values[0];
list[1].residency_in_msec_since_boot = values[1];
list[1].supported_only_in_suspend = false;
list[1].number_of_voters = VMIN_VOTERS;

View File

@@ -144,6 +144,7 @@
/sys/kernel/debug/rpm_stats u:object_r:debugfs_rpm:s0
/sys/kernel/debug/rpm_master_stats u:object_r:debugfs_rpm:s0
/sys/kernel/debug/ion(/.*)? u:object_r:debugfs_ion:s0
/sys/kernel/debug/system_stats u:object_r:debugfs_rpm:s0
# files in /system
/system/bin/init\.power\.sh u:object_r:init_power_exec:s0