1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "android.hardware.power@1.1-service.marlin"
18
19 #include <android/log.h>
20 #include <utils/Log.h>
21
22 #include <android-base/properties.h>
23
24 #include "Power.h"
25 #include "power-helper.h"
26
27 /* RPM runs at 19.2Mhz. Divide by 19200 for msec */
28 #define RPM_CLK 19200
29
30 namespace android {
31 namespace hardware {
32 namespace power {
33 namespace V1_1 {
34 namespace implementation {
35
36 using ::android::hardware::power::V1_0::Feature;
37 using ::android::hardware::power::V1_0::PowerHint;
38 using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
39 using ::android::hardware::power::V1_0::Status;
40 using ::android::hardware::power::V1_1::PowerStateSubsystem;
41 using ::android::hardware::hidl_vec;
42 using ::android::hardware::Return;
43 using ::android::hardware::Void;
44
Power()45 Power::Power() {
46 power_init();
47 }
48
49 // Methods from ::android::hardware::power::V1_0::IPower follow.
setInteractive(bool interactive)50 Return<void> Power::setInteractive(bool interactive) {
51 power_set_interactive(interactive ? 1 : 0);
52 return Void();
53 }
54
powerHint(PowerHint hint,int32_t data)55 Return<void> Power::powerHint(PowerHint hint, int32_t data) {
56 if (android::base::GetProperty("init.svc.perfd", "") != "running") {
57 ALOGW("perfd is not started");
58 return Void();
59 }
60 power_hint(static_cast<power_hint_t>(hint), data ? (&data) : NULL);
61 return Void();
62 }
63
setFeature(Feature,bool)64 Return<void> Power::setFeature(Feature /*feature*/, bool /*activate*/) {
65 return Void();
66 }
67
getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb)68 Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
69
70 hidl_vec<PowerStatePlatformSleepState> states;
71 uint64_t stats[platform_param_id::PLATFORM_PARAM_COUNT] = {0};
72 struct PowerStatePlatformSleepState *state;
73 int ret;
74
75 ret = extract_platform_stats(stats);
76 if (ret != 0) {
77 states.resize(0);
78 goto done;
79 }
80
81 states.resize(platform_mode_id::RPM_MODE_COUNT);
82
83 /* Update statistics for XO_shutdown */
84 state = &states[platform_mode_id::RPM_MODE_XO];
85 state->name = "XO_shutdown";
86
87 state->residencyInMsecSinceBoot = stats[platform_param_id::ACCUMULATED_VLOW_TIME];
88 state->totalTransitions = stats[platform_param_id::VLOW_COUNT];
89 state->supportedOnlyInSuspend = false;
90 state->voters.resize(XO_VOTERS);
91
92 /* Update statistics for APSS voter */
93 state->voters[0].name = "APSS";
94 state->voters[0].totalTimeInMsecVotedForSinceBoot =
95 stats[platform_param_id::XO_ACCUMULATED_DURATION_APSS] / RPM_CLK;
96 state->voters[0].totalNumberOfTimesVotedSinceBoot = stats[platform_param_id::XO_COUNT_APSS];
97
98 /* Update statistics for MPSS voter */
99 state->voters[1].name = "MPSS";
100 state->voters[1].totalTimeInMsecVotedForSinceBoot =
101 stats[platform_param_id::XO_ACCUMULATED_DURATION_MPSS] / RPM_CLK;
102 state->voters[1].totalNumberOfTimesVotedSinceBoot = stats[platform_param_id::XO_COUNT_MPSS];
103
104 /* Update statistics for ADSP voter */
105 state->voters[2].name = "ADSP";
106 state->voters[2].totalTimeInMsecVotedForSinceBoot =
107 stats[platform_param_id::XO_ACCUMULATED_DURATION_ADSP] / RPM_CLK;
108 state->voters[2].totalNumberOfTimesVotedSinceBoot = stats[platform_param_id::XO_COUNT_ADSP];
109
110 /* Update statistics for SLPI voter */
111 state->voters[3].name = "SLPI";
112 state->voters[3].totalTimeInMsecVotedForSinceBoot =
113 stats[platform_param_id::XO_ACCUMULATED_DURATION_SLPI] / RPM_CLK;
114 state->voters[3].totalNumberOfTimesVotedSinceBoot = stats[platform_param_id::XO_COUNT_SLPI];
115
116
117 /* Update statistics for VMIN state */
118 state = &states[platform_mode_id::RPM_MODE_VMIN];
119 state->name = "VMIN";
120
121 state->residencyInMsecSinceBoot = stats[platform_param_id::ACCUMULATED_VMIN_TIME];
122 state->totalTransitions = stats[platform_param_id::VMIN_COUNT];
123 state->supportedOnlyInSuspend = false;
124 state->voters.resize(VMIN_VOTERS);
125 //Note: No filling of state voters since VMIN_VOTERS = 0
126
127 done:
128 _hidl_cb(states, Status::SUCCESS);
129 return Void();
130 }
131
132
133 // Methods from ::android::hardware::power::V1_1::IPower follow.
134
get_wlan_low_power_stats(struct PowerStateSubsystem & subsystem)135 static int get_wlan_low_power_stats(struct PowerStateSubsystem &subsystem) {
136
137 uint64_t stats[WLAN_PARAM_COUNT] = {0};
138 struct PowerStateSubsystemSleepState *state;
139 int ret;
140
141 ret = extract_wlan_stats(stats);
142 if (ret)
143 return ret;
144
145 subsystem.name = "wlan";
146 subsystem.states.resize(WLAN_STATE_COUNT);
147
148 /* Update statistics for Active State */
149 state = &subsystem.states[WLAN_STATE_ACTIVE];
150 state->name = "Active";
151 state->residencyInMsecSinceBoot = stats[wlan_param_id::CUMULATIVE_TOTAL_ON_TIME_MS];
152 state->totalTransitions = stats[wlan_param_id::DEEP_SLEEP_ENTER_COUNTER];
153 state->lastEntryTimestampMs = 0; //FIXME need a new value from Qcom
154 state->supportedOnlyInSuspend = false;
155
156 /* Update statistics for Deep-Sleep state */
157 state = &subsystem.states[WLAN_STATE_DEEP_SLEEP];
158 state->name = "Deep-Sleep";
159 state->residencyInMsecSinceBoot = stats[wlan_param_id::CUMULATIVE_SLEEP_TIME_MS];
160 state->totalTransitions = stats[wlan_param_id::DEEP_SLEEP_ENTER_COUNTER];
161 state->lastEntryTimestampMs = stats[wlan_param_id::LAST_DEEP_SLEEP_ENTER_TSTAMP_MS];
162 state->supportedOnlyInSuspend = false;
163
164 return 0;
165 }
166
getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb)167 Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
168
169 hidl_vec<PowerStateSubsystem> subsystems;
170 int ret;
171
172 subsystems.resize(subsystem_type::SUBSYSTEM_COUNT);
173
174 //We currently have only one Subsystem for WLAN
175 ret = get_wlan_low_power_stats(subsystems[subsystem_type::SUBSYSTEM_WLAN]);
176 if (ret != 0) {
177 goto done;
178 }
179
180 //Add query for other subsystems here
181
182 done:
183 _hidl_cb(subsystems, Status::SUCCESS);
184 return Void();
185 }
186
powerHintAsync(PowerHint hint,int32_t data)187 Return<void> Power::powerHintAsync(PowerHint hint, int32_t data) {
188 // just call the normal power hint in this oneway function
189 return powerHint(hint, data);
190 }
191
192 } // namespace implementation
193 } // namespace V1_1
194 } // namespace power
195 } // namespace hardware
196 } // namespace android
197