blob: 7c3b1470a58a38a2822a61d03297defb6606bce8 [file] [log] [blame]
Anurag Singh9cec85b2012-09-04 21:46:24 -07001/*
Ananth Raghavan Subramaniane432dbf2017-03-24 16:30:12 -07002 * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +02003 * Copyright (C) 2017 The Android Open Source Project
dianlujitao5ec37732018-01-18 21:24:30 +08004 * Copyright (C) 2017-2018 The LineageOS Project
Anurag Singh9cec85b2012-09-04 21:46:24 -07005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 * * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
Duy Truong70222452013-02-10 06:35:11 -080015 * * Neither the name of The Linux Foundation nor the names of its
Anurag Singh9cec85b2012-09-04 21:46:24 -070016 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
Anurag Singh6ec12062012-10-02 09:59:01 -070032#define LOG_NIDEBUG 0
33
Anurag Singh9cec85b2012-09-04 21:46:24 -070034#include <errno.h>
35#include <string.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <dlfcn.h>
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +020040#include <inttypes.h>
Anurag Singh9cec85b2012-09-04 21:46:24 -070041#include <stdlib.h>
Rashed Abdel-Tawab9c14c9f2017-12-26 23:11:03 +020042#include <unistd.h>
Anurag Singh9cec85b2012-09-04 21:46:24 -070043
44#define LOG_TAG "QCOM PowerHAL"
Rashed Abdel-Tawab9c14c9f2017-12-26 23:11:03 +020045#include <log/log.h>
Anurag Singh9cec85b2012-09-04 21:46:24 -070046#include <hardware/power.h>
47
Anurag Singh6ec12062012-10-02 09:59:01 -070048#include "utils.h"
Anurag Singh9cec85b2012-09-04 21:46:24 -070049#include "metadata-defs.h"
Anurag Singh6ec12062012-10-02 09:59:01 -070050#include "hint-data.h"
51#include "performance.h"
Anurag Singh057806b2013-04-16 16:53:45 -070052#include "power-common.h"
Keith Mok72201a02015-11-13 09:46:14 -080053#include "power-feature.h"
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070054#include "power-helper.h"
55
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +020056#define USINSEC 1000000L
57#define NSINUS 1000L
58
59#ifndef RPM_STAT
60#define RPM_STAT "/d/rpm_stats"
61#endif
62
63#ifndef RPM_MASTER_STAT
64#define RPM_MASTER_STAT "/d/rpm_master_stats"
65#endif
66
67#ifndef RPM_SYSTEM_STAT
68#define RPM_SYSTEM_STAT "/d/system_stats"
69#endif
70
71/*
72 Set with TARGET_WLAN_POWER_STAT in BoardConfig.mk
73 Defaults to QCACLD3 path
74 Path for QCACLD3: /d/wlan0/power_stats
75 Path for QCACLD2 and Prima: /d/wlan_wcnss/power_stats
76 */
77
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -070078#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070079#ifndef WLAN_POWER_STAT
80#define WLAN_POWER_STAT "/d/wlan0/power_stats"
81#endif
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +020082#endif
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070083
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070084#define LINE_SIZE 128
85
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +020086#ifdef LEGACY_STATS
87/* Use these stats on pre-nougat qualcomm kernels */
88static const char *rpm_param_names[] = {
89 "vlow_count",
90 "accumulated_vlow_time",
91 "vmin_count",
92 "accumulated_vmin_time"
93};
94
95static const char *rpm_master_param_names[] = {
96 "xo_accumulated_duration",
97 "xo_count",
98 "xo_accumulated_duration",
99 "xo_count",
100 "xo_accumulated_duration",
101 "xo_count",
102 "xo_accumulated_duration",
103 "xo_count"
104};
Rashed Abdel-Tawab34990dd2018-01-09 20:31:32 -0500105
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700106#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab34990dd2018-01-09 20:31:32 -0500107static const char *wlan_param_names[] = {
108 "cumulative_sleep_time_ms",
109 "cumulative_total_on_time_ms",
110 "deep_sleep_enter_counter",
111 "last_deep_sleep_enter_tstamp_ms"
112};
Michael Bestas593b9d02018-03-26 01:00:20 +0300113#endif
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200114#else
Rashed Abdel-Tawab34990dd2018-01-09 20:31:32 -0500115/* Use these stats on nougat kernels and forward */
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200116const char *rpm_stat_params[MAX_RPM_PARAMS] = {
117 "count",
118 "actual last sleep(msec)",
119};
120
121const char *master_stat_params[MAX_RPM_PARAMS] = {
122 "Accumulated XO duration",
123 "XO Count",
124};
125
126struct stat_pair rpm_stat_map[] = {
127 { RPM_MODE_XO, "RPM Mode:vlow", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
128 { RPM_MODE_VMIN, "RPM Mode:vmin", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
129 { VOTER_APSS, "APSS", master_stat_params, ARRAY_SIZE(master_stat_params) },
130 { VOTER_MPSS, "MPSS", master_stat_params, ARRAY_SIZE(master_stat_params) },
131 { VOTER_ADSP, "ADSP", master_stat_params, ARRAY_SIZE(master_stat_params) },
132 { VOTER_SLPI, "SLPI", master_stat_params, ARRAY_SIZE(master_stat_params) },
Michael Bestas3e0af9c2018-06-09 23:05:31 +0300133 { VOTER_PRONTO, "PRONTO", master_stat_params, ARRAY_SIZE(master_stat_params) },
134 { VOTER_TZ, "TZ", master_stat_params, ARRAY_SIZE(master_stat_params) },
135 { VOTER_LPASS, "LPASS", master_stat_params, ARRAY_SIZE(master_stat_params) },
136 { VOTER_SPSS, "SPSS", master_stat_params, ARRAY_SIZE(master_stat_params) },
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200137};
138#endif
139
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700140#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700141const char *wlan_power_stat_params[] = {
142 "cumulative_sleep_time_ms",
143 "cumulative_total_on_time_ms",
144 "deep_sleep_enter_counter",
145 "last_deep_sleep_enter_tstamp_ms"
146};
147
148struct stat_pair wlan_stat_map[] = {
149 { WLAN_POWER_DEBUG_STATS, "POWER DEBUG STATS", wlan_power_stat_params, ARRAY_SIZE(wlan_power_stat_params) },
150};
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200151#endif
Anurag Singh9cec85b2012-09-04 21:46:24 -0700152
Anurag Singhb15323a2013-06-08 16:55:44 -0700153static int display_hint_sent;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700154
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700155void power_init(void)
Anurag Singh9cec85b2012-09-04 21:46:24 -0700156{
157 ALOGI("QCOM power HAL initing.");
158}
159
Anurag Singh6ec12062012-10-02 09:59:01 -0700160static void process_video_decode_hint(void *metadata)
161{
162 char governor[80];
163 struct video_decode_metadata_t video_decode_metadata;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700164
Anurag Singh6ec12062012-10-02 09:59:01 -0700165 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
166 ALOGE("Can't obtain scaling governor.");
Anurag Singh9cec85b2012-09-04 21:46:24 -0700167
Anurag Singh6ec12062012-10-02 09:59:01 -0700168 return;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700169 }
170
Anurag Singh6ec12062012-10-02 09:59:01 -0700171 if (metadata) {
172 ALOGI("Processing video decode hint. Metadata: %s", (char *)metadata);
173 }
174
175 /* Initialize encode metadata struct fields. */
176 memset(&video_decode_metadata, 0, sizeof(struct video_decode_metadata_t));
177 video_decode_metadata.state = -1;
178 video_decode_metadata.hint_id = DEFAULT_VIDEO_DECODE_HINT_ID;
179
180 if (metadata) {
181 if (parse_video_decode_metadata((char *)metadata, &video_decode_metadata) ==
182 -1) {
183 ALOGE("Error occurred while parsing metadata.");
184 return;
185 }
186 } else {
187 return;
188 }
189
190 if (video_decode_metadata.state == 1) {
Michael Bestasfc62e7c2018-03-25 23:14:21 +0300191 if (is_ondemand_governor(governor)) {
Vince Leungf72adfb2013-05-03 15:13:29 -0700192 int resource_values[] = {THREAD_MIGRATION_SYNC_OFF};
193
194 perform_hint_action(video_decode_metadata.hint_id,
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800195 resource_values, ARRAY_SIZE(resource_values));
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800196 } else if (is_interactive_governor(governor)) {
Vince Leungf72adfb2013-05-03 15:13:29 -0700197 int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF};
Anurag Singh6ec12062012-10-02 09:59:01 -0700198
199 perform_hint_action(video_decode_metadata.hint_id,
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800200 resource_values, ARRAY_SIZE(resource_values));
Anurag Singh6ec12062012-10-02 09:59:01 -0700201 }
202 } else if (video_decode_metadata.state == 0) {
Michael Bestasfc62e7c2018-03-25 23:14:21 +0300203 if (is_ondemand_governor(governor)) {
Paul Keithc931ea02016-07-31 19:22:50 -0700204 undo_hint_action(video_decode_metadata.hint_id);
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800205 } else if (is_interactive_governor(governor)) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700206 undo_hint_action(video_decode_metadata.hint_id);
207 }
208 }
Anurag Singh9cec85b2012-09-04 21:46:24 -0700209}
210
211static void process_video_encode_hint(void *metadata)
212{
Anurag Singh9cec85b2012-09-04 21:46:24 -0700213 char governor[80];
214 struct video_encode_metadata_t video_encode_metadata;
215
216 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
217 ALOGE("Can't obtain scaling governor.");
218
219 return;
220 }
221
222 /* Initialize encode metadata struct fields. */
Anurag Singh6ec12062012-10-02 09:59:01 -0700223 memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
Anurag Singh9cec85b2012-09-04 21:46:24 -0700224 video_encode_metadata.state = -1;
Anurag Singh6ec12062012-10-02 09:59:01 -0700225 video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700226
227 if (metadata) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700228 if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
Anurag Singh9cec85b2012-09-04 21:46:24 -0700229 -1) {
230 ALOGE("Error occurred while parsing metadata.");
231 return;
232 }
233 } else {
234 return;
235 }
236
Anurag Singh6ec12062012-10-02 09:59:01 -0700237 if (video_encode_metadata.state == 1) {
Michael Bestasfc62e7c2018-03-25 23:14:21 +0300238 if (is_ondemand_governor(governor)) {
Vince Leungf72adfb2013-05-03 15:13:29 -0700239 int resource_values[] = {IO_BUSY_OFF, SAMPLING_DOWN_FACTOR_1, THREAD_MIGRATION_SYNC_OFF};
Anurag Singh9cec85b2012-09-04 21:46:24 -0700240
Anurag Singh6ec12062012-10-02 09:59:01 -0700241 perform_hint_action(video_encode_metadata.hint_id,
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800242 resource_values, ARRAY_SIZE(resource_values));
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800243 } else if (is_interactive_governor(governor)) {
Anurag Singh6cda91c2013-12-18 18:24:14 -0800244 int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF,
245 INTERACTIVE_IO_BUSY_OFF};
Anurag Singh9cec85b2012-09-04 21:46:24 -0700246
Anurag Singh6ec12062012-10-02 09:59:01 -0700247 perform_hint_action(video_encode_metadata.hint_id,
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800248 resource_values, ARRAY_SIZE(resource_values));
Anurag Singh6ec12062012-10-02 09:59:01 -0700249 }
250 } else if (video_encode_metadata.state == 0) {
Michael Bestasfc62e7c2018-03-25 23:14:21 +0300251 if (is_ondemand_governor(governor)) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700252 undo_hint_action(video_encode_metadata.hint_id);
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800253 } else if (is_interactive_governor(governor)) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700254 undo_hint_action(video_encode_metadata.hint_id);
Anurag Singh9cec85b2012-09-04 21:46:24 -0700255 }
256 }
257}
258
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700259int __attribute__ ((weak)) power_hint_override(power_hint_t UNUSED(hint),
Adrian Salidoff139872017-03-29 15:58:38 -0700260 void *UNUSED(data))
Anurag Singh9cec85b2012-09-04 21:46:24 -0700261{
Anurag Singh057806b2013-04-16 16:53:45 -0700262 return HINT_NONE;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700263}
264
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700265void power_hint(power_hint_t hint, void *data)
Anurag Singh9cec85b2012-09-04 21:46:24 -0700266{
267 /* Check if this hint has been overridden. */
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700268 if (power_hint_override(hint, data) == HINT_HANDLED) {
Anurag Singh9cec85b2012-09-04 21:46:24 -0700269 /* The power_hint has been handled. We can skip the rest. */
270 return;
271 }
272
273 switch(hint) {
Ananth Raghavan Subramaniane432dbf2017-03-24 16:30:12 -0700274 case POWER_HINT_SUSTAINED_PERFORMANCE:
275 ALOGI("Sustained perf power hint not handled in power_hint_override");
Paul Keithd524aea2017-12-31 02:17:32 +0100276 break;
Ananth Raghavan Subramaniane432dbf2017-03-24 16:30:12 -0700277 case POWER_HINT_VR_MODE:
278 ALOGI("VR mode power hint not handled in power_hint_override");
Paul Keithd524aea2017-12-31 02:17:32 +0100279 break;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700280 case POWER_HINT_VIDEO_ENCODE:
281 process_video_encode_hint(data);
282 break;
Anurag Singh6ec12062012-10-02 09:59:01 -0700283 case POWER_HINT_VIDEO_DECODE:
284 process_video_decode_hint(data);
285 break;
dianlujitao5ec37732018-01-18 21:24:30 +0800286 case POWER_HINT_SET_PROFILE:
287 ALOGI("set profile power hint not handled in power_hint_override");
288 break;
Paul Keithd524aea2017-12-31 02:17:32 +0100289 default:
290 break;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700291 }
292}
293
dianlujitao5ec37732018-01-18 21:24:30 +0800294int get_number_of_profiles()
295{
296 return 0;
297}
298
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700299int __attribute__ ((weak)) set_interactive_override(int UNUSED(on))
Anurag Singh6ec12062012-10-02 09:59:01 -0700300{
Anurag Singh057806b2013-04-16 16:53:45 -0700301 return HINT_NONE;
Anurag Singh6ec12062012-10-02 09:59:01 -0700302}
303
Steve Kondika0e04952014-03-27 22:00:00 -0700304#ifdef SET_INTERACTIVE_EXT
305extern void power_set_interactive_ext(int on);
306#endif
307
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700308void power_set_interactive(int on)
Anurag Singh9cec85b2012-09-04 21:46:24 -0700309{
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700310 char governor[80];
Anurag Singh6ec12062012-10-02 09:59:01 -0700311
Balamurugan Thanikachalam930f9ae2017-07-11 14:42:21 +0530312 if (!on) {
313 /* Send Display OFF hint to perf HAL */
314 perf_hint_enable(VENDOR_HINT_DISPLAY_OFF, 0);
315 } else {
316 /* Send Display ON hint to perf HAL */
317 perf_hint_enable(VENDOR_HINT_DISPLAY_ON, 0);
318 }
319
Zhao Wei Liew5a81c9a2016-06-26 21:29:34 +0800320 /**
321 * Ignore consecutive display-off hints
322 * Consecutive display-on hints are already handled
323 */
324 if (display_hint_sent && !on)
325 return;
326
327 display_hint_sent = !on;
328
Steve Kondika0e04952014-03-27 22:00:00 -0700329#ifdef SET_INTERACTIVE_EXT
330 power_set_interactive_ext(on);
331#endif
332
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700333 if (set_interactive_override(on) == HINT_HANDLED) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700334 return;
335 }
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700336
Anurag Singhb15323a2013-06-08 16:55:44 -0700337 ALOGI("Got set_interactive hint");
Anurag Singhfe93c1d2012-11-21 15:15:56 -0800338
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700339 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700340 ALOGE("Can't obtain scaling governor.");
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700341
342 return;
343 }
344
Anurag Singh6ec12062012-10-02 09:59:01 -0700345 if (!on) {
346 /* Display off. */
Michael Bestasfc62e7c2018-03-25 23:14:21 +0300347 if (is_ondemand_governor(governor)) {
Zhao Wei Liew28dff062016-06-26 11:45:11 +0800348 int resource_values[] = { MS_500, THREAD_MIGRATION_SYNC_OFF };
Anurag Singh10918c12012-11-09 17:35:20 -0800349
Zhao Wei Liew5a81c9a2016-06-26 21:29:34 +0800350 perform_hint_action(DISPLAY_STATE_HINT_ID,
351 resource_values, ARRAY_SIZE(resource_values));
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800352 } else if (is_interactive_governor(governor)) {
Dilip Gudlur2eae2662014-02-25 12:32:37 -0800353 int resource_values[] = {TR_MS_50, THREAD_MIGRATION_SYNC_OFF};
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700354
Zhao Wei Liew5a81c9a2016-06-26 21:29:34 +0800355 perform_hint_action(DISPLAY_STATE_HINT_ID,
356 resource_values, ARRAY_SIZE(resource_values));
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700357 }
Anurag Singh6ec12062012-10-02 09:59:01 -0700358 } else {
359 /* Display on. */
Michael Bestasfc62e7c2018-03-25 23:14:21 +0300360 if (is_ondemand_governor(governor)) {
Anurag Singh10918c12012-11-09 17:35:20 -0800361 undo_hint_action(DISPLAY_STATE_HINT_ID);
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800362 } else if (is_interactive_governor(governor)) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700363 undo_hint_action(DISPLAY_STATE_HINT_ID);
Anurag Singh6ec12062012-10-02 09:59:01 -0700364 }
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700365 }
Anurag Singh9cec85b2012-09-04 21:46:24 -0700366}
367
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700368void __attribute__((weak)) set_device_specific_feature(feature_t UNUSED(feature), int UNUSED(state))
Keith Mok72201a02015-11-13 09:46:14 -0800369{
370}
371
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700372void set_feature(feature_t feature, int state)
Steve Kondikcd8bfdc2015-10-19 14:43:39 -0700373{
374 switch (feature) {
375#ifdef TAP_TO_WAKE_NODE
376 case POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
377 sysfs_write(TAP_TO_WAKE_NODE, state ? "1" : "0");
378 break;
379#endif
380 default:
381 break;
382 }
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700383 set_device_specific_feature(feature, state);
Steve Kondikcd8bfdc2015-10-19 14:43:39 -0700384}
385
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200386#ifdef LEGACY_STATS
387static int extract_stats(uint64_t *list, char *file, const char**param_names,
388 unsigned int num_parameters, int isHex) {
389 FILE *fp;
390 ssize_t read;
391 size_t len;
392 size_t index = 0;
393 char *line;
394 int ret;
395
396 fp = fopen(file, "r");
397 if (fp == NULL) {
398 ret = -errno;
399 ALOGE("%s: failed to open: %s Error = %s", __func__, file, strerror(errno));
400 return ret;
401 }
402
403 for (line = NULL, len = 0;
404 ((read = getline(&line, &len, fp) != -1) && (index < num_parameters));
405 free(line), line = NULL, len = 0) {
406 uint64_t value;
407 char* offset;
408
409 size_t begin = strspn(line, " \t");
410 if (strncmp(line + begin, param_names[index], strlen(param_names[index]))) {
411 continue;
412 }
413
414 offset = memchr(line, ':', len);
415 if (!offset) {
416 continue;
417 }
418
419 if (isHex) {
420 sscanf(offset, ":%" SCNx64, &value);
421 } else {
422 sscanf(offset, ":%" SCNu64, &value);
423 }
424 list[index] = value;
425 index++;
426 }
427
428 free(line);
429 fclose(fp);
430
431 return 0;
432}
433
434int extract_platform_stats(uint64_t *list) {
435 int ret;
436 //Data is located in two files
437 ret = extract_stats(list, RPM_STAT, rpm_param_names, RPM_PARAM_COUNT, false);
438 if (ret) {
439 for (size_t i=0; i < RPM_PARAM_COUNT; i++)
440 list[i] = 0;
441 }
442 ret = extract_stats(list + RPM_PARAM_COUNT, RPM_MASTER_STAT,
443 rpm_master_param_names, PLATFORM_PARAM_COUNT - RPM_PARAM_COUNT, true);
444 if (ret) {
445 for (size_t i=RPM_PARAM_COUNT; i < PLATFORM_PARAM_COUNT; i++)
446 list[i] = 0;
447 }
448 return 0;
449}
450
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700451#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200452int extract_wlan_stats(uint64_t *list) {
453 int ret;
Rashed Abdel-Tawab34990dd2018-01-09 20:31:32 -0500454 ret = extract_stats(list, WLAN_POWER_STAT, wlan_param_names, WLAN_POWER_PARAMS_COUNT, false);
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200455 if (ret) {
Rashed Abdel-Tawab34990dd2018-01-09 20:31:32 -0500456 for (size_t i=0; i < WLAN_POWER_PARAMS_COUNT; i++)
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200457 list[i] = 0;
458 }
459 return 0;
460}
461#endif
462#else
463
Michael Bestas593b9d02018-03-26 01:00:20 +0300464static int parse_stats(const char **params, size_t params_size,
465 uint64_t *list, FILE *fp) {
466 ssize_t nread;
467 size_t len = LINE_SIZE;
468 char *line;
469 size_t params_read = 0;
470 size_t i;
471
472 line = malloc(len);
473 if (!line) {
474 ALOGE("%s: no memory to hold line", __func__);
475 return -ENOMEM;
476 }
477
478 while ((params_read < params_size) &&
479 (nread = getline(&line, &len, fp) > 0)) {
480 char *key = line + strspn(line, " \t");
481 char *value = strchr(key, ':');
482 if (!value || (value > (line + len)))
483 continue;
484 *value++ = '\0';
485
486 for (i = 0; i < params_size; i++) {
487 if (!strcmp(key, params[i])) {
488 list[i] = strtoull(value, NULL, 0);
489 params_read++;
490 break;
491 }
492 }
493 }
494 free(line);
495
496 return 0;
497}
498
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700499static int extract_stats(uint64_t *list, char *file,
500 struct stat_pair *map, size_t map_size) {
501 FILE *fp;
502 ssize_t read;
503 size_t len = LINE_SIZE;
504 char *line;
505 size_t i, stats_read = 0;
506 int ret = 0;
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200507
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700508 fp = fopen(file, "re");
509 if (fp == NULL) {
510 ALOGE("%s: failed to open: %s Error = %s", __func__, file, strerror(errno));
511 return -errno;
512 }
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200513
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700514 line = malloc(len);
515 if (!line) {
516 ALOGE("%s: no memory to hold line", __func__);
517 fclose(fp);
518 return -ENOMEM;
519 }
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200520
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700521 while ((stats_read < map_size) && (read = getline(&line, &len, fp) != -1)) {
522 size_t begin = strspn(line, " \t");
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200523
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700524 for (i = 0; i < map_size; i++) {
525 if (!strncmp(line + begin, map[i].label, strlen(map[i].label))) {
526 stats_read++;
527 break;
528 }
529 }
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200530
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700531 if (i == map_size)
532 continue;
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200533
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700534 ret = parse_stats(map[i].parameters, map[i].num_parameters,
535 &list[map[i].stat * MAX_RPM_PARAMS], fp);
536 if (ret < 0)
537 break;
538 }
539 free(line);
540 fclose(fp);
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200541
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700542 return ret;
543}
Anurag Singh9cec85b2012-09-04 21:46:24 -0700544
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200545int extract_platform_stats(uint64_t *list) {
546 return extract_stats(list, RPM_SYSTEM_STAT, rpm_stat_map, ARRAY_SIZE(rpm_stat_map));
547}
548
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700549#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700550int extract_wlan_stats(uint64_t *list) {
551 return extract_stats(list, WLAN_POWER_STAT, wlan_stat_map, ARRAY_SIZE(wlan_stat_map));
552}
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200553#endif
554#endif