• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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