blob: 0765378f8d904b22c62f2e652c9925780ddf854b [file] [log] [blame]
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
dianlujitao5ec37732018-01-18 21:24:30 +08003 * Copyright (C) 2017-2018 The LineageOS Project
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -07004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +020018#define LOG_TAG "android.hardware.power@1.1-service-qti"
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070019
dianlujitao5ec37732018-01-18 21:24:30 +080020// #define LOG_NDEBUG 0
21
Ethan Chena42f4a82018-03-01 21:31:15 -080022#include <log/log.h>
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070023#include "Power.h"
24#include "power-common.h"
25#include "power-helper.h"
26
27/* RPM runs at 19.2Mhz. Divide by 19200 for msec */
28#define RPM_CLK 19200
29
30extern struct stat_pair rpm_stat_map[];
31
32namespace android {
33namespace hardware {
34namespace power {
35namespace V1_1 {
36namespace implementation {
37
38using ::android::hardware::power::V1_0::Feature;
39using ::android::hardware::power::V1_0::PowerHint;
40using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
41using ::android::hardware::power::V1_0::Status;
42using ::android::hardware::power::V1_1::PowerStateSubsystem;
43using ::android::hardware::hidl_vec;
44using ::android::hardware::Return;
45using ::android::hardware::Void;
46
47Power::Power() {
48 power_init();
49}
50
51// Methods from ::android::hardware::power::V1_0::IPower follow.
52Return<void> Power::setInteractive(bool interactive) {
53 power_set_interactive(interactive ? 1 : 0);
54 return Void();
55}
56
57Return<void> Power::powerHint(PowerHint hint, int32_t data) {
dianlujitao8780cb72019-02-23 20:24:57 +080058 power_hint(static_cast<power_hint_t>(hint), data ? (&data) : NULL);
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070059 return Void();
60}
61
62Return<void> Power::setFeature(Feature feature, bool activate) {
63 set_feature(static_cast<feature_t>(feature), activate ? 1 : 0);
64 return Void();
65}
66
67Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070068 hidl_vec<PowerStatePlatformSleepState> states;
Michael Bestas64de35f2018-07-03 21:29:54 +030069#ifdef NO_STATS
70 states.resize(0);
71 _hidl_cb(states, Status::SUCCESS);
72 return Void();
73#else
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070074 uint64_t stats[MAX_PLATFORM_STATS * MAX_RPM_PARAMS] = {0};
Michael Bestas593b9d02018-03-26 01:00:20 +030075#ifndef LEGACY_STATS
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070076 uint64_t *values;
Michael Bestas593b9d02018-03-26 01:00:20 +030077#endif
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070078 struct PowerStatePlatformSleepState *state;
79 int ret;
80
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -070081 ret = extract_platform_stats(stats);
82 if (ret != 0) {
83 states.resize(0);
84 goto done;
85 }
86
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +020087#ifdef LEGACY_STATS
88 states.resize(RPM_MODE_MAX);
89
90 /* Update statistics for XO_shutdown */
91 state = &states[RPM_MODE_XO];
92 state->name = "XO_shutdown";
93
94 state->residencyInMsecSinceBoot = stats[ACCUMULATED_VLOW_TIME];
95 state->totalTransitions = stats[VLOW_COUNT];
96 state->supportedOnlyInSuspend = false;
97 state->voters.resize(XO_VOTERS);
98
99 /* Update statistics for APSS voter */
100 state->voters[0].name = "APSS";
101 state->voters[0].totalTimeInMsecVotedForSinceBoot =
102 stats[XO_ACCUMULATED_DURATION_APSS] / RPM_CLK;
103 state->voters[0].totalNumberOfTimesVotedSinceBoot = stats[XO_COUNT_APSS];
104
105 /* Update statistics for MPSS voter */
106 state->voters[1].name = "MPSS";
107 state->voters[1].totalTimeInMsecVotedForSinceBoot =
108 stats[XO_ACCUMULATED_DURATION_MPSS] / RPM_CLK;
109 state->voters[1].totalNumberOfTimesVotedSinceBoot = stats[XO_COUNT_MPSS];
110
111 /* Update statistics for ADSP voter */
112 state->voters[2].name = "ADSP";
113 state->voters[2].totalTimeInMsecVotedForSinceBoot =
114 stats[XO_ACCUMULATED_DURATION_ADSP] / RPM_CLK;
115 state->voters[2].totalNumberOfTimesVotedSinceBoot = stats[XO_COUNT_ADSP];
116
117 /* Update statistics for SLPI voter */
118 state->voters[3].name = "SLPI";
119 state->voters[3].totalTimeInMsecVotedForSinceBoot =
120 stats[XO_ACCUMULATED_DURATION_SLPI] / RPM_CLK;
121 state->voters[3].totalNumberOfTimesVotedSinceBoot = stats[XO_COUNT_SLPI];
122
123 /* Update statistics for VMIN state */
124 state = &states[RPM_MODE_VMIN];
125
126 state->name = "VMIN";
127 state->residencyInMsecSinceBoot = stats[ACCUMULATED_VMIN_TIME];
128 state->totalTransitions = stats[VMIN_COUNT];
129 state->supportedOnlyInSuspend = false;
130 state->voters.resize(VMIN_VOTERS);
131 //Note: No filling of state voters since VMIN_VOTERS = 0
132#else
133 states.resize(PLATFORM_SLEEP_MODES_COUNT);
134
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700135 /* Update statistics for XO_shutdown */
136 state = &states[RPM_MODE_XO];
137 state->name = "XO_shutdown";
138 values = stats + (RPM_MODE_XO * MAX_RPM_PARAMS);
139
140 state->residencyInMsecSinceBoot = values[1];
141 state->totalTransitions = values[0];
142 state->supportedOnlyInSuspend = false;
143 state->voters.resize(XO_VOTERS);
144 for(size_t i = 0; i < XO_VOTERS; i++) {
145 int voter = i + XO_VOTERS_START;
146 state->voters[i].name = rpm_stat_map[voter].label;
147 values = stats + (voter * MAX_RPM_PARAMS);
148 state->voters[i].totalTimeInMsecVotedForSinceBoot = values[0] / RPM_CLK;
149 state->voters[i].totalNumberOfTimesVotedSinceBoot = values[1];
150 }
151
152 /* Update statistics for VMIN state */
153 state = &states[RPM_MODE_VMIN];
154 state->name = "VMIN";
155 values = stats + (RPM_MODE_VMIN * MAX_RPM_PARAMS);
156
157 state->residencyInMsecSinceBoot = values[1];
158 state->totalTransitions = values[0];
159 state->supportedOnlyInSuspend = false;
160 state->voters.resize(VMIN_VOTERS);
161 //Note: No filling of state voters since VMIN_VOTERS = 0
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200162#endif
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700163done:
164 _hidl_cb(states, Status::SUCCESS);
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700165 return Void();
Michael Bestas64de35f2018-07-03 21:29:54 +0300166#endif
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700167}
168
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200169// Methods from ::android::hardware::power::V1_1::IPower follow.
170
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700171#ifndef NO_WLAN_STATS
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700172static int get_wlan_low_power_stats(struct PowerStateSubsystem &subsystem) {
173
174 uint64_t stats[WLAN_POWER_PARAMS_COUNT] = {0};
175 struct PowerStateSubsystemSleepState *state;
176 int ret;
177
178 ret = extract_wlan_stats(stats);
179 if (ret)
180 return ret;
181
182 subsystem.name = "wlan";
183 subsystem.states.resize(WLAN_STATES_COUNT);
184
185 /* Update statistics for Active State */
186 state = &subsystem.states[WLAN_STATE_ACTIVE];
187 state->name = "Active";
188 state->residencyInMsecSinceBoot = stats[CUMULATIVE_TOTAL_ON_TIME_MS];
189 state->totalTransitions = stats[DEEP_SLEEP_ENTER_COUNTER];
190 state->lastEntryTimestampMs = 0; //FIXME need a new value from Qcom
191 state->supportedOnlyInSuspend = false;
192
193 /* Update statistics for Deep-Sleep state */
194 state = &subsystem.states[WLAN_STATE_DEEP_SLEEP];
195 state->name = "Deep-Sleep";
196 state->residencyInMsecSinceBoot = stats[CUMULATIVE_SLEEP_TIME_MS];
197 state->totalTransitions = stats[DEEP_SLEEP_ENTER_COUNTER];
198 state->lastEntryTimestampMs = stats[LAST_DEEP_SLEEP_ENTER_TSTAMP_MS];
199 state->supportedOnlyInSuspend = false;
200
201 return 0;
202}
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700203#endif
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700204
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700205Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700206 hidl_vec<PowerStateSubsystem> subsystems;
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700207#ifdef NO_WLAN_STATS
208 subsystems.resize(0);
209 _hidl_cb(subsystems, Status::SUCCESS);
210 return Void();
211#else
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700212 int ret;
213
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200214 subsystems.resize(subsystem_type::SUBSYSTEM_COUNT);
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700215
216 //We currently have only one Subsystem for WLAN
Rashed Abdel-Tawab067a9072017-12-30 00:41:49 +0200217 ret = get_wlan_low_power_stats(subsystems[subsystem_type::SUBSYSTEM_WLAN]);
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700218 if (ret != 0)
219 goto done;
220
221 //Add query for other subsystems here
222
223done:
224 _hidl_cb(subsystems, Status::SUCCESS);
225 return Void();
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700226#endif
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700227}
228
Philip Cuadrac1f872c2017-07-11 14:50:25 -0700229Return<void> Power::powerHintAsync(PowerHint hint, int32_t data) {
230 // just call the normal power hint in this oneway function
231 return powerHint(hint, data);
232}
233
dianlujitao5ec37732018-01-18 21:24:30 +0800234Return<int32_t> Power::getFeature(LineageFeature feature) {
235 if (feature == LineageFeature::SUPPORTED_PROFILES) {
236 return get_number_of_profiles();
237 }
238 return -1;
239}
240
241status_t Power::registerAsSystemService() {
242 status_t ret = 0;
243
244 ret = IPower::registerAsService();
245 if (ret != 0) {
246 ALOGE("Failed to register IPower (%d)", ret);
247 goto fail;
248 } else {
249 ALOGI("Successfully registered IPower");
250 }
251
252 ret = ILineagePower::registerAsService();
253 if (ret != 0) {
254 ALOGE("Failed to register ILineagePower (%d)", ret);
255 goto fail;
256 } else {
257 ALOGI("Successfully registered ILineagePower");
258 }
259
260fail:
261 return ret;
262}
263
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700264} // namespace implementation
Rashed Abdel-Tawabbd767ce2018-09-17 12:14:16 -0700265} // namespace V1_1
Rashed Abdel-Tawab00b21852017-11-03 12:44:16 -0700266} // namespace power
267} // namespace hardware
268} // namespace android