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 (at) 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 45 Power::Power() { 46 power_init(); 47 } 48 49 // Methods from ::android::hardware::power::V1_0::IPower follow. 50 Return<void> Power::setInteractive(bool interactive) { 51 power_set_interactive(interactive ? 1 : 0); 52 return Void(); 53 } 54 55 Return<void> Power::powerHint(PowerHint hint, int32_t data) { 56 if (android::base::GetProperty("init.svc.vendor.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 64 Return<void> Power::setFeature(Feature /*feature*/, bool /*activate*/) { 65 return Void(); 66 } 67 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 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 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 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