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 DEBUG false // STOPSHIP if true 18 #include "Log.h" 19 20 #include <android/hardware/power/1.0/IPower.h> 21 #include <android/hardware/power/1.1/IPower.h> 22 #include <android/hardware/power/stats/1.0/IPowerStats.h> 23 24 #include <fcntl.h> 25 #include <hardware/power.h> 26 #include <hardware_legacy/power.h> 27 #include <inttypes.h> 28 #include <semaphore.h> 29 #include <stddef.h> 30 #include <stdio.h> 31 #include <string.h> 32 #include <sys/stat.h> 33 #include <sys/types.h> 34 #include <unistd.h> 35 #include "external/SubsystemSleepStatePuller.h" 36 #include "external/StatsPuller.h" 37 38 #include "SubsystemSleepStatePuller.h" 39 #include "logd/LogEvent.h" 40 #include "statslog.h" 41 #include "stats_log_util.h" 42 43 using android::hardware::hidl_vec; 44 using android::hardware::power::V1_0::IPower; 45 using android::hardware::power::V1_0::PowerStatePlatformSleepState; 46 using android::hardware::power::V1_0::PowerStateVoter; 47 using android::hardware::power::V1_1::PowerStateSubsystem; 48 using android::hardware::power::V1_1::PowerStateSubsystemSleepState; 49 using android::hardware::power::stats::V1_0::PowerEntityInfo; 50 using android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult; 51 using android::hardware::power::stats::V1_0::PowerEntityStateSpace; 52 53 using android::hardware::Return; 54 using android::hardware::Void; 55 56 using std::make_shared; 57 using std::shared_ptr; 58 59 namespace android { 60 namespace os { 61 namespace statsd { 62 63 static std::function<bool(vector<shared_ptr<LogEvent>>* data)> gPuller = {}; 64 65 static sp<android::hardware::power::V1_0::IPower> gPowerHalV1_0 = nullptr; 66 static sp<android::hardware::power::V1_1::IPower> gPowerHalV1_1 = nullptr; 67 static sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHalV1_0 = nullptr; 68 69 static std::unordered_map<uint32_t, std::string> gEntityNames = {}; 70 static std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> gStateNames = {}; 71 72 static std::mutex gPowerHalMutex; 73 74 // The caller must be holding gPowerHalMutex. 75 static void deinitPowerStatsLocked() { 76 gPowerHalV1_0 = nullptr; 77 gPowerHalV1_1 = nullptr; 78 gPowerStatsHalV1_0 = nullptr; 79 } 80 81 struct SubsystemSleepStatePullerDeathRecipient : virtual public hardware::hidl_death_recipient { 82 virtual void serviceDied(uint64_t cookie, 83 const wp<android::hidl::base::V1_0::IBase>& who) override { 84 85 // The HAL just died. Reset all handles to HAL services. 86 std::lock_guard<std::mutex> lock(gPowerHalMutex); 87 deinitPowerStatsLocked(); 88 } 89 }; 90 91 static sp<SubsystemSleepStatePullerDeathRecipient> gDeathRecipient = 92 new SubsystemSleepStatePullerDeathRecipient(); 93 94 SubsystemSleepStatePuller::SubsystemSleepStatePuller() : 95 StatsPuller(android::util::SUBSYSTEM_SLEEP_STATE) { 96 } 97 98 // The caller must be holding gPowerHalMutex. 99 static bool checkResultLocked(const Return<void> &ret, const char* function) { 100 if (!ret.isOk()) { 101 ALOGE("%s failed: requested HAL service not available. Description: %s", 102 function, ret.description().c_str()); 103 if (ret.isDeadObject()) { 104 deinitPowerStatsLocked(); 105 } 106 return false; 107 } 108 return true; 109 } 110 111 // The caller must be holding gPowerHalMutex. 112 // gPowerStatsHalV1_0 must not be null 113 static bool initializePowerStats() { 114 using android::hardware::power::stats::V1_0::Status; 115 116 // Clear out previous content if we are re-initializing 117 gEntityNames.clear(); 118 gStateNames.clear(); 119 120 Return<void> ret; 121 ret = gPowerStatsHalV1_0->getPowerEntityInfo([](auto infos, auto status) { 122 if (status != Status::SUCCESS) { 123 ALOGE("Error getting power entity info"); 124 return; 125 } 126 127 // construct lookup table of powerEntityId to power entity name 128 for (auto info : infos) { 129 gEntityNames.emplace(info.powerEntityId, info.powerEntityName); 130 } 131 }); 132 if (!checkResultLocked(ret, __func__)) { 133 return false; 134 } 135 136 ret = gPowerStatsHalV1_0->getPowerEntityStateInfo({}, [](auto stateSpaces, auto status) { 137 if (status != Status::SUCCESS) { 138 ALOGE("Error getting state info"); 139 return; 140 } 141 142 // construct lookup table of powerEntityId, powerEntityStateId to power entity state name 143 for (auto stateSpace : stateSpaces) { 144 std::unordered_map<uint32_t, std::string> stateNames = {}; 145 for (auto state : stateSpace.states) { 146 stateNames.emplace(state.powerEntityStateId, 147 state.powerEntityStateName); 148 } 149 gStateNames.emplace(stateSpace.powerEntityId, stateNames); 150 } 151 }); 152 if (!checkResultLocked(ret, __func__)) { 153 return false; 154 } 155 156 return (!gEntityNames.empty()) && (!gStateNames.empty()); 157 } 158 159 // The caller must be holding gPowerHalMutex. 160 static bool getPowerStatsHalLocked() { 161 if(gPowerStatsHalV1_0 == nullptr) { 162 gPowerStatsHalV1_0 = android::hardware::power::stats::V1_0::IPowerStats::getService(); 163 if (gPowerStatsHalV1_0 == nullptr) { 164 ALOGE("Unable to get power.stats HAL service."); 165 return false; 166 } 167 168 // Link death recipient to power.stats service handle 169 hardware::Return<bool> linked = gPowerStatsHalV1_0->linkToDeath(gDeathRecipient, 0); 170 if (!linked.isOk()) { 171 ALOGE("Transaction error in linking to power.stats HAL death: %s", 172 linked.description().c_str()); 173 deinitPowerStatsLocked(); 174 return false; 175 } else if (!linked) { 176 ALOGW("Unable to link to power.stats HAL death notifications"); 177 // We should still continue even though linking failed 178 } 179 return initializePowerStats(); 180 } 181 return true; 182 } 183 184 // The caller must be holding gPowerHalMutex. 185 static bool getIPowerStatsDataLocked(vector<shared_ptr<LogEvent>>* data) { 186 using android::hardware::power::stats::V1_0::Status; 187 188 if(!getPowerStatsHalLocked()) { 189 return false; 190 } 191 192 int64_t wallClockTimestampNs = getWallClockNs(); 193 int64_t elapsedTimestampNs = getElapsedRealtimeNs(); 194 195 // Get power entity state residency data 196 bool success = false; 197 Return<void> ret = gPowerStatsHalV1_0->getPowerEntityStateResidencyData({}, 198 [&data, &success, wallClockTimestampNs, elapsedTimestampNs] 199 (auto results, auto status) { 200 if (status == Status::NOT_SUPPORTED) { 201 ALOGW("getPowerEntityStateResidencyData is not supported"); 202 success = false; 203 return; 204 } 205 206 for(auto result : results) { 207 for(auto stateResidency : result.stateResidencyData) { 208 auto statePtr = make_shared<LogEvent>( 209 android::util::SUBSYSTEM_SLEEP_STATE, 210 wallClockTimestampNs, elapsedTimestampNs); 211 statePtr->write(gEntityNames.at(result.powerEntityId)); 212 statePtr->write(gStateNames.at(result.powerEntityId) 213 .at(stateResidency.powerEntityStateId)); 214 statePtr->write(stateResidency.totalStateEntryCount); 215 statePtr->write(stateResidency.totalTimeInStateMs); 216 statePtr->init(); 217 data->emplace_back(statePtr); 218 } 219 } 220 success = true; 221 }); 222 // Intentionally not returning early here. 223 // bool success determines if this succeeded or not. 224 checkResultLocked(ret, __func__); 225 226 return success; 227 } 228 229 // The caller must be holding gPowerHalMutex. 230 static bool getPowerHalLocked() { 231 if(gPowerHalV1_0 == nullptr) { 232 gPowerHalV1_0 = android::hardware::power::V1_0::IPower::getService(); 233 if(gPowerHalV1_0 == nullptr) { 234 ALOGE("Unable to get power HAL service."); 235 return false; 236 } 237 gPowerHalV1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0); 238 239 // Link death recipient to power service handle 240 hardware::Return<bool> linked = gPowerHalV1_0->linkToDeath(gDeathRecipient, 0); 241 if (!linked.isOk()) { 242 ALOGE("Transaction error in linking to power HAL death: %s", 243 linked.description().c_str()); 244 gPowerHalV1_0 = nullptr; 245 return false; 246 } else if (!linked) { 247 ALOGW("Unable to link to power. death notifications"); 248 // We should still continue even though linking failed 249 } 250 } 251 return true; 252 } 253 254 // The caller must be holding gPowerHalMutex. 255 static bool getIPowerDataLocked(vector<shared_ptr<LogEvent>>* data) { 256 using android::hardware::power::V1_0::Status; 257 258 if(!getPowerHalLocked()) { 259 return false; 260 } 261 262 int64_t wallClockTimestampNs = getWallClockNs(); 263 int64_t elapsedTimestampNs = getElapsedRealtimeNs(); 264 Return<void> ret; 265 ret = gPowerHalV1_0->getPlatformLowPowerStats( 266 [&data, wallClockTimestampNs, elapsedTimestampNs] 267 (hidl_vec<PowerStatePlatformSleepState> states, Status status) { 268 if (status != Status::SUCCESS) return; 269 270 for (size_t i = 0; i < states.size(); i++) { 271 const PowerStatePlatformSleepState& state = states[i]; 272 273 auto statePtr = make_shared<LogEvent>( 274 android::util::SUBSYSTEM_SLEEP_STATE, 275 wallClockTimestampNs, elapsedTimestampNs); 276 statePtr->write(state.name); 277 statePtr->write(""); 278 statePtr->write(state.totalTransitions); 279 statePtr->write(state.residencyInMsecSinceBoot); 280 statePtr->init(); 281 data->push_back(statePtr); 282 VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(), 283 (long long)state.residencyInMsecSinceBoot, 284 (long long)state.totalTransitions, 285 state.supportedOnlyInSuspend ? 1 : 0); 286 for (const auto& voter : state.voters) { 287 auto voterPtr = make_shared<LogEvent>( 288 android::util::SUBSYSTEM_SLEEP_STATE, 289 wallClockTimestampNs, elapsedTimestampNs); 290 voterPtr->write(state.name); 291 voterPtr->write(voter.name); 292 voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot); 293 voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot); 294 voterPtr->init(); 295 data->push_back(voterPtr); 296 VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(), 297 voter.name.c_str(), 298 (long long)voter.totalTimeInMsecVotedForSinceBoot, 299 (long long)voter.totalNumberOfTimesVotedSinceBoot); 300 } 301 } 302 }); 303 if (!checkResultLocked(ret, __func__)) { 304 return false; 305 } 306 307 // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1 308 sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 = 309 android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0); 310 if (gPowerHal_1_1 != nullptr) { 311 ret = gPowerHal_1_1->getSubsystemLowPowerStats( 312 [&data, wallClockTimestampNs, elapsedTimestampNs] 313 (hidl_vec<PowerStateSubsystem> subsystems, Status status) { 314 if (status != Status::SUCCESS) return; 315 316 if (subsystems.size() > 0) { 317 for (size_t i = 0; i < subsystems.size(); i++) { 318 const PowerStateSubsystem& subsystem = subsystems[i]; 319 for (size_t j = 0; j < subsystem.states.size(); j++) { 320 const PowerStateSubsystemSleepState& state = 321 subsystem.states[j]; 322 auto subsystemStatePtr = make_shared<LogEvent>( 323 android::util::SUBSYSTEM_SLEEP_STATE, 324 wallClockTimestampNs, elapsedTimestampNs); 325 subsystemStatePtr->write(subsystem.name); 326 subsystemStatePtr->write(state.name); 327 subsystemStatePtr->write(state.totalTransitions); 328 subsystemStatePtr->write(state.residencyInMsecSinceBoot); 329 subsystemStatePtr->init(); 330 data->push_back(subsystemStatePtr); 331 VLOG("subsystemstate: %s, %s, %lld, %lld, %lld", 332 subsystem.name.c_str(), state.name.c_str(), 333 (long long)state.residencyInMsecSinceBoot, 334 (long long)state.totalTransitions, 335 (long long)state.lastEntryTimestampMs); 336 } 337 } 338 } 339 }); 340 } 341 return true; 342 } 343 344 // The caller must be holding gPowerHalMutex. 345 std::function<bool(vector<shared_ptr<LogEvent>>* data)> getPullerLocked() { 346 std::function<bool(vector<shared_ptr<LogEvent>>* data)> ret = {}; 347 348 // First see if power.stats HAL is available. Fall back to power HAL if 349 // power.stats HAL is unavailable. 350 if(android::hardware::power::stats::V1_0::IPowerStats::getService() != nullptr) { 351 ALOGI("Using power.stats HAL"); 352 ret = getIPowerStatsDataLocked; 353 } else if(android::hardware::power::V1_0::IPower::getService() != nullptr) { 354 ALOGI("Using power HAL"); 355 ret = getIPowerDataLocked; 356 } 357 358 return ret; 359 } 360 361 bool SubsystemSleepStatePuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { 362 std::lock_guard<std::mutex> lock(gPowerHalMutex); 363 364 if(!gPuller) { 365 gPuller = getPullerLocked(); 366 } 367 368 if(gPuller) { 369 return gPuller(data); 370 } 371 372 ALOGE("Unable to load Power Hal or power.stats HAL"); 373 return false; 374 } 375 376 } // namespace statsd 377 } // namespace os 378 } // namespace android 379