blob: 59f3ab7b5815b920a890675fce1b37c4a3b2981d [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-Tawabe52ce102017-12-30 00:41:49 +02003 * Copyright (C) 2017 The Android Open Source Project
dianlujitao8df56d62018-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-Tawabe52ce102017-12-30 00:41:49 +020040#include <inttypes.h>
Anurag Singh9cec85b2012-09-04 21:46:24 -070041#include <stdlib.h>
Rashed Abdel-Tawab42eb1ee2017-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-Tawab42eb1ee2017-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 Mok964d2552015-11-13 09:46:14 -080053#include "power-feature.h"
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -070054#include "power-helper.h"
55
Rashed Abdel-Tawabe52ce102017-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-Tawab53320c12018-09-17 12:14:16 -070078#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -070079#ifndef WLAN_POWER_STAT
80#define WLAN_POWER_STAT "/d/wlan0/power_stats"
81#endif
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +020082#endif
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -070083
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -070084#define LINE_SIZE 128
85
Rashed Abdel-Tawabe52ce102017-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-Tawab031a2bc2018-01-09 20:31:32 -0500105
Rashed Abdel-Tawab53320c12018-09-17 12:14:16 -0700106#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab031a2bc2018-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 Bestas87dd9ad2018-03-26 01:00:20 +0300113#endif
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200114#else
Rashed Abdel-Tawab031a2bc2018-01-09 20:31:32 -0500115/* Use these stats on nougat kernels and forward */
Rashed Abdel-Tawabe52ce102017-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 Bestasc29ae842018-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-Tawabe52ce102017-12-30 00:41:49 +0200137};
138#endif
139
Rashed Abdel-Tawab53320c12018-09-17 12:14:16 -0700140#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab711a28d2017-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-Tawabe52ce102017-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-Tawab711a28d2017-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 Bestase701b2d2018-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 Liewa72f7772016-06-26 11:37:59 +0800195 resource_values, ARRAY_SIZE(resource_values));
Ethan Chened4628c2018-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 Liewa72f7772016-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 Bestase701b2d2018-03-25 23:14:21 +0300203 if (is_ondemand_governor(governor)) {
Paul Keith2d3df8b2016-07-31 19:22:50 -0700204 undo_hint_action(video_decode_metadata.hint_id);
Ethan Chened4628c2018-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 Bestase701b2d2018-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 Liewa72f7772016-06-26 11:37:59 +0800242 resource_values, ARRAY_SIZE(resource_values));
Ethan Chened4628c2018-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 Liewa72f7772016-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 Bestase701b2d2018-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 Chened4628c2018-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-Tawab711a28d2017-11-03 12:44:16 -0700259int __attribute__ ((weak)) power_hint_override(power_hint_t UNUSED(hint),
Adrian Salidoa60e94b2017-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-Tawab711a28d2017-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-Tawab711a28d2017-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 Keith4f2dadb2017-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 Keith4f2dadb2017-12-31 02:17:32 +0100279 break;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700280 case POWER_HINT_INTERACTION:
Vince Leung699c1bc2013-08-14 17:40:36 -0700281 {
282 int resources[] = {0x702, 0x20F, 0x30F};
283 int duration = 3000;
284
285 interaction(duration, sizeof(resources)/sizeof(resources[0]), resources);
286 }
Anurag Singh9cec85b2012-09-04 21:46:24 -0700287 break;
288 case POWER_HINT_VIDEO_ENCODE:
289 process_video_encode_hint(data);
290 break;
Anurag Singh6ec12062012-10-02 09:59:01 -0700291 case POWER_HINT_VIDEO_DECODE:
292 process_video_decode_hint(data);
293 break;
dianlujitao8df56d62018-01-18 21:24:30 +0800294 case POWER_HINT_SET_PROFILE:
295 ALOGI("set profile power hint not handled in power_hint_override");
296 break;
Paul Keith4f2dadb2017-12-31 02:17:32 +0100297 default:
298 break;
Anurag Singh9cec85b2012-09-04 21:46:24 -0700299 }
300}
301
dianlujitao8df56d62018-01-18 21:24:30 +0800302int get_number_of_profiles()
303{
304 return 0;
305}
306
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700307int __attribute__ ((weak)) set_interactive_override(int UNUSED(on))
Anurag Singh6ec12062012-10-02 09:59:01 -0700308{
Anurag Singh057806b2013-04-16 16:53:45 -0700309 return HINT_NONE;
Anurag Singh6ec12062012-10-02 09:59:01 -0700310}
311
Steve Kondik11a84642014-03-27 22:00:00 -0700312#ifdef SET_INTERACTIVE_EXT
313extern void power_set_interactive_ext(int on);
314#endif
315
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700316void power_set_interactive(int on)
Anurag Singh9cec85b2012-09-04 21:46:24 -0700317{
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700318 char governor[80];
Anurag Singh6ec12062012-10-02 09:59:01 -0700319
Balamurugan Thanikachalam930f9ae2017-07-11 14:42:21 +0530320 if (!on) {
321 /* Send Display OFF hint to perf HAL */
322 perf_hint_enable(VENDOR_HINT_DISPLAY_OFF, 0);
323 } else {
324 /* Send Display ON hint to perf HAL */
325 perf_hint_enable(VENDOR_HINT_DISPLAY_ON, 0);
326 }
327
Zhao Wei Liew1e863522016-06-26 21:29:34 +0800328 /**
329 * Ignore consecutive display-off hints
330 * Consecutive display-on hints are already handled
331 */
332 if (display_hint_sent && !on)
333 return;
334
335 display_hint_sent = !on;
336
Steve Kondik11a84642014-03-27 22:00:00 -0700337#ifdef SET_INTERACTIVE_EXT
338 power_set_interactive_ext(on);
339#endif
340
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700341 if (set_interactive_override(on) == HINT_HANDLED) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700342 return;
343 }
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700344
Anurag Singhb15323a2013-06-08 16:55:44 -0700345 ALOGI("Got set_interactive hint");
Anurag Singhfe93c1d2012-11-21 15:15:56 -0800346
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700347 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700348 ALOGE("Can't obtain scaling governor.");
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700349
350 return;
351 }
352
Anurag Singh6ec12062012-10-02 09:59:01 -0700353 if (!on) {
354 /* Display off. */
Michael Bestase701b2d2018-03-25 23:14:21 +0300355 if (is_ondemand_governor(governor)) {
Zhao Wei Liew40ec34d2016-06-26 11:45:11 +0800356 int resource_values[] = { MS_500, THREAD_MIGRATION_SYNC_OFF };
Anurag Singh10918c12012-11-09 17:35:20 -0800357
Zhao Wei Liew1e863522016-06-26 21:29:34 +0800358 perform_hint_action(DISPLAY_STATE_HINT_ID,
359 resource_values, ARRAY_SIZE(resource_values));
Ethan Chened4628c2018-03-01 21:41:04 -0800360 } else if (is_interactive_governor(governor)) {
Dilip Gudlur2eae2662014-02-25 12:32:37 -0800361 int resource_values[] = {TR_MS_50, THREAD_MIGRATION_SYNC_OFF};
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700362
Zhao Wei Liew1e863522016-06-26 21:29:34 +0800363 perform_hint_action(DISPLAY_STATE_HINT_ID,
364 resource_values, ARRAY_SIZE(resource_values));
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700365 }
Anurag Singh6ec12062012-10-02 09:59:01 -0700366 } else {
367 /* Display on. */
Michael Bestase701b2d2018-03-25 23:14:21 +0300368 if (is_ondemand_governor(governor)) {
Anurag Singh10918c12012-11-09 17:35:20 -0800369 undo_hint_action(DISPLAY_STATE_HINT_ID);
Ethan Chened4628c2018-03-01 21:41:04 -0800370 } else if (is_interactive_governor(governor)) {
Anurag Singh6ec12062012-10-02 09:59:01 -0700371 undo_hint_action(DISPLAY_STATE_HINT_ID);
Anurag Singh6ec12062012-10-02 09:59:01 -0700372 }
Anurag Singh6f64e9f2012-10-09 16:08:38 -0700373 }
Anurag Singh9cec85b2012-09-04 21:46:24 -0700374}
375
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700376void __attribute__((weak)) set_device_specific_feature(feature_t UNUSED(feature), int UNUSED(state))
Keith Mok964d2552015-11-13 09:46:14 -0800377{
378}
379
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700380void set_feature(feature_t feature, int state)
Steve Kondike4f15bd2015-10-19 14:43:39 -0700381{
382 switch (feature) {
383#ifdef TAP_TO_WAKE_NODE
384 case POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
385 sysfs_write(TAP_TO_WAKE_NODE, state ? "1" : "0");
386 break;
387#endif
388 default:
389 break;
390 }
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700391 set_device_specific_feature(feature, state);
Steve Kondike4f15bd2015-10-19 14:43:39 -0700392}
393
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200394#ifdef LEGACY_STATS
395static int extract_stats(uint64_t *list, char *file, const char**param_names,
396 unsigned int num_parameters, int isHex) {
397 FILE *fp;
398 ssize_t read;
399 size_t len;
400 size_t index = 0;
401 char *line;
402 int ret;
403
404 fp = fopen(file, "r");
405 if (fp == NULL) {
406 ret = -errno;
407 ALOGE("%s: failed to open: %s Error = %s", __func__, file, strerror(errno));
408 return ret;
409 }
410
411 for (line = NULL, len = 0;
412 ((read = getline(&line, &len, fp) != -1) && (index < num_parameters));
413 free(line), line = NULL, len = 0) {
414 uint64_t value;
415 char* offset;
416
417 size_t begin = strspn(line, " \t");
418 if (strncmp(line + begin, param_names[index], strlen(param_names[index]))) {
419 continue;
420 }
421
422 offset = memchr(line, ':', len);
423 if (!offset) {
424 continue;
425 }
426
427 if (isHex) {
428 sscanf(offset, ":%" SCNx64, &value);
429 } else {
430 sscanf(offset, ":%" SCNu64, &value);
431 }
432 list[index] = value;
433 index++;
434 }
435
436 free(line);
437 fclose(fp);
438
439 return 0;
440}
441
442int extract_platform_stats(uint64_t *list) {
443 int ret;
444 //Data is located in two files
445 ret = extract_stats(list, RPM_STAT, rpm_param_names, RPM_PARAM_COUNT, false);
446 if (ret) {
447 for (size_t i=0; i < RPM_PARAM_COUNT; i++)
448 list[i] = 0;
449 }
450 ret = extract_stats(list + RPM_PARAM_COUNT, RPM_MASTER_STAT,
451 rpm_master_param_names, PLATFORM_PARAM_COUNT - RPM_PARAM_COUNT, true);
452 if (ret) {
453 for (size_t i=RPM_PARAM_COUNT; i < PLATFORM_PARAM_COUNT; i++)
454 list[i] = 0;
455 }
456 return 0;
457}
458
Rashed Abdel-Tawab53320c12018-09-17 12:14:16 -0700459#ifndef NO_WLAN_STATS
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200460int extract_wlan_stats(uint64_t *list) {
461 int ret;
Rashed Abdel-Tawab031a2bc2018-01-09 20:31:32 -0500462 ret = extract_stats(list, WLAN_POWER_STAT, wlan_param_names, WLAN_POWER_PARAMS_COUNT, false);
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200463 if (ret) {
Rashed Abdel-Tawab031a2bc2018-01-09 20:31:32 -0500464 for (size_t i=0; i < WLAN_POWER_PARAMS_COUNT; i++)
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200465 list[i] = 0;
466 }
467 return 0;
468}
469#endif
470#else
471
Michael Bestas87dd9ad2018-03-26 01:00:20 +0300472static int parse_stats(const char **params, size_t params_size,
473 uint64_t *list, FILE *fp) {
474 ssize_t nread;
475 size_t len = LINE_SIZE;
476 char *line;
477 size_t params_read = 0;
478 size_t i;
479
480 line = malloc(len);
481 if (!line) {
482 ALOGE("%s: no memory to hold line", __func__);
483 return -ENOMEM;
484 }
485
486 while ((params_read < params_size) &&
487 (nread = getline(&line, &len, fp) > 0)) {
488 char *key = line + strspn(line, " \t");
489 char *value = strchr(key, ':');
490 if (!value || (value > (line + len)))
491 continue;
492 *value++ = '\0';
493
494 for (i = 0; i < params_size; i++) {
495 if (!strcmp(key, params[i])) {
496 list[i] = strtoull(value, NULL, 0);
497 params_read++;
498 break;
499 }
500 }
501 }
502 free(line);
503
504 return 0;
505}
506
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700507static int extract_stats(uint64_t *list, char *file,
508 struct stat_pair *map, size_t map_size) {
509 FILE *fp;
510 ssize_t read;
511 size_t len = LINE_SIZE;
512 char *line;
513 size_t i, stats_read = 0;
514 int ret = 0;
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200515
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700516 fp = fopen(file, "re");
517 if (fp == NULL) {
518 ALOGE("%s: failed to open: %s Error = %s", __func__, file, strerror(errno));
519 return -errno;
520 }
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200521
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700522 line = malloc(len);
523 if (!line) {
524 ALOGE("%s: no memory to hold line", __func__);
525 fclose(fp);
526 return -ENOMEM;
527 }
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200528
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700529 while ((stats_read < map_size) && (read = getline(&line, &len, fp) != -1)) {
530 size_t begin = strspn(line, " \t");
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200531
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700532 for (i = 0; i < map_size; i++) {
533 if (!strncmp(line + begin, map[i].label, strlen(map[i].label))) {
534 stats_read++;
535 break;
536 }
537 }
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200538
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700539 if (i == map_size)
540 continue;
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200541
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700542 ret = parse_stats(map[i].parameters, map[i].num_parameters,
543 &list[map[i].stat * MAX_RPM_PARAMS], fp);
544 if (ret < 0)
545 break;
546 }
547 free(line);
548 fclose(fp);
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200549
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700550 return ret;
551}
Anurag Singh9cec85b2012-09-04 21:46:24 -0700552
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200553int extract_platform_stats(uint64_t *list) {
554 return extract_stats(list, RPM_SYSTEM_STAT, rpm_stat_map, ARRAY_SIZE(rpm_stat_map));
555}
556
Rashed Abdel-Tawab53320c12018-09-17 12:14:16 -0700557#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab711a28d2017-11-03 12:44:16 -0700558int extract_wlan_stats(uint64_t *list) {
559 return extract_stats(list, WLAN_POWER_STAT, wlan_stat_map, ARRAY_SIZE(wlan_stat_map));
560}
Rashed Abdel-Tawabe52ce102017-12-30 00:41:49 +0200561#endif
562#endif