Home | History | Annotate | Download | only in external
      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