• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  * *    * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above
10  *       copyright notice, this list of conditions and the following
11  *       disclaimer in the documentation and/or other materials provided
12  *       with the distribution.
13  *     * Neither the name of The Linux Foundation nor the names of its
14  *       contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #define LOG_NIDEBUG 0
31 #define LOG_TAG "android.hardware.power@1.2-service.wahoo-libperfmgr"
32 
33 #include <errno.h>
34 #include <inttypes.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <dlfcn.h>
40 #include <stdlib.h>
41 
42 #include <log/log.h>
43 
44 #include "power-helper.h"
45 
46 #ifndef RPM_SYSTEM_STAT
47 #define RPM_SYSTEM_STAT "/d/system_stats"
48 #endif
49 
50 #ifndef WLAN_POWER_STAT
51 #define WLAN_POWER_STAT "/d/wlan0/power_stats"
52 #endif
53 
54 #ifndef EASEL_STATE_FILE
55 #define EASEL_STATE_FILE "/sys/devices/virtual/misc/mnh_sm/state"
56 #endif
57 
58 #define ARRAY_SIZE(x) (sizeof((x))/sizeof((x)[0]))
59 #define LINE_SIZE 128
60 
61 const char *rpm_stat_params[MAX_RPM_PARAMS] = {
62     "count",
63     "actual last sleep(msec)",
64 };
65 
66 const char *master_stat_params[MAX_RPM_PARAMS] = {
67     "Accumulated XO duration",
68     "XO Count",
69 };
70 
71 struct stat_pair rpm_stat_map[] = {
72     { RPM_MODE_XO,   "RPM Mode:vlow", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
73     { RPM_MODE_VMIN, "RPM Mode:vmin", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
74     { VOTER_APSS,    "APSS",    master_stat_params, ARRAY_SIZE(master_stat_params) },
75     { VOTER_MPSS,    "MPSS",    master_stat_params, ARRAY_SIZE(master_stat_params) },
76     { VOTER_ADSP,    "ADSP",    master_stat_params, ARRAY_SIZE(master_stat_params) },
77     { VOTER_SLPI,    "SLPI",    master_stat_params, ARRAY_SIZE(master_stat_params) },
78 };
79 
80 
81 const char *wlan_power_stat_params[] = {
82     "cumulative_sleep_time_ms",
83     "cumulative_total_on_time_ms",
84     "deep_sleep_enter_counter",
85     "last_deep_sleep_enter_tstamp_ms"
86 };
87 
88 struct stat_pair wlan_stat_map[] = {
89     { WLAN_POWER_DEBUG_STATS, "POWER DEBUG STATS", wlan_power_stat_params, ARRAY_SIZE(wlan_power_stat_params) },
90 };
91 
parse_stats(const char ** params,size_t params_size,uint64_t * list,FILE * fp)92 static int parse_stats(const char **params, size_t params_size,
93                        uint64_t *list, FILE *fp) {
94     ssize_t nread;
95     size_t len = LINE_SIZE;
96     char *line;
97     size_t params_read = 0;
98     size_t i;
99 
100     line = malloc(len);
101     if (!line) {
102         ALOGE("%s: no memory to hold line", __func__);
103         return -ENOMEM;
104     }
105 
106     while ((params_read < params_size) &&
107         (nread = getline(&line, &len, fp) > 0)) {
108         char *key = line + strspn(line, " \t");
109         char *value = strchr(key, ':');
110         if (!value || (value > (line + len)))
111             continue;
112         *value++ = '\0';
113 
114         for (i = 0; i < params_size; i++) {
115             if (!strcmp(key, params[i])) {
116                 list[i] = strtoull(value, NULL, 0);
117                 params_read++;
118                 break;
119             }
120         }
121     }
122     free(line);
123 
124     return 0;
125 }
126 
127 
extract_stats(uint64_t * list,char * file,struct stat_pair * map,size_t map_size)128 static int extract_stats(uint64_t *list, char *file,
129                          struct stat_pair *map, size_t map_size) {
130     FILE *fp;
131     ssize_t read;
132     size_t len = LINE_SIZE;
133     char *line;
134     size_t i, stats_read = 0;
135     int ret = 0;
136 
137     fp = fopen(file, "re");
138     if (fp == NULL) {
139         ALOGE("%s: failed to open: %s Error = %s", __func__, file, strerror(errno));
140         return -errno;
141     }
142 
143     line = malloc(len);
144     if (!line) {
145         ALOGE("%s: no memory to hold line", __func__);
146         fclose(fp);
147         return -ENOMEM;
148     }
149 
150     while ((stats_read < map_size) && (read = getline(&line, &len, fp) != -1)) {
151         size_t begin = strspn(line, " \t");
152 
153         for (i = 0; i < map_size; i++) {
154             if (!strncmp(line + begin, map[i].label, strlen(map[i].label))) {
155                 stats_read++;
156                 break;
157             }
158         }
159 
160         if (i == map_size)
161             continue;
162 
163         ret = parse_stats(map[i].parameters, map[i].num_parameters,
164                           &list[map[i].stat * MAX_RPM_PARAMS], fp);
165         if (ret < 0)
166             break;
167     }
168     free(line);
169     fclose(fp);
170 
171     return ret;
172 }
173 
extract_platform_stats(uint64_t * list)174 int extract_platform_stats(uint64_t *list) {
175     return extract_stats(list, RPM_SYSTEM_STAT, rpm_stat_map, ARRAY_SIZE(rpm_stat_map));
176 }
177 
extract_wlan_stats(uint64_t * list)178 int extract_wlan_stats(uint64_t *list) {
179     return extract_stats(list, WLAN_POWER_STAT, wlan_stat_map, ARRAY_SIZE(wlan_stat_map));
180 }
181 
get_easel_state(unsigned long * current_state)182 int get_easel_state(unsigned long *current_state) {
183     FILE *fp = NULL;
184     static const size_t EASEL_STATE_LINE_SIZE = 16;
185     char buffer[EASEL_STATE_LINE_SIZE];
186     char *parse_end = buffer;
187     unsigned long state;
188 
189     if (current_state == NULL) {
190         ALOGD("%s: null current_state pointer from caller", __func__);
191         return -1;
192     }
193 
194     fp = fopen(EASEL_STATE_FILE, "re");
195     if (fp == NULL) {
196         ALOGE("%s: failed to open: %s Error = %s", __func__, EASEL_STATE_FILE,
197                 strerror(errno));
198         return -errno;
199     }
200 
201     if (fgets(buffer, EASEL_STATE_LINE_SIZE, fp) == NULL) {
202         fclose(fp);
203         ALOGE("%s: failed to read: %s", __func__, EASEL_STATE_FILE);
204         return -1;
205     }
206 
207     fclose(fp);
208 
209     parse_end = buffer;
210     state = strtoul(buffer, &parse_end, 10);
211     if ((parse_end == buffer) || (state > 2)) {
212         ALOGE("%s: unrecognized format: %s '%s'", __func__, EASEL_STATE_FILE,
213                 buffer);
214         return -1;
215     }
216 
217     *current_state = state;
218 
219     return 0;
220 }
221 
222