Home | History | Annotate | Download | only in power
      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.wahoo"
     18 
     19 #include <android/log.h>
     20 #include <android-base/file.h>
     21 #include <android-base/properties.h>
     22 #include <android-base/strings.h>
     23 #include <utils/Log.h>
     24 #include "Power.h"
     25 #include "power-common.h"
     26 #include "power-helper.h"
     27 
     28 /* RPM runs at 19.2Mhz. Divide by 19200 for msec */
     29 #define RPM_CLK 19200
     30 
     31 extern struct stat_pair rpm_stat_map[];
     32 
     33 namespace android {
     34 namespace hardware {
     35 namespace power {
     36 namespace V1_1 {
     37 namespace implementation {
     38 
     39 using ::android::hardware::power::V1_0::Feature;
     40 using ::android::hardware::power::V1_0::PowerHint;
     41 using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
     42 using ::android::hardware::power::V1_0::Status;
     43 using ::android::hardware::power::V1_1::PowerStateSubsystem;
     44 using ::android::hardware::hidl_vec;
     45 using ::android::hardware::Return;
     46 using ::android::hardware::Void;
     47 
     48 Power::Power() {
     49     power_init();
     50     mInteractionHandler.Init();
     51 }
     52 
     53 // Methods from ::android::hardware::power::V1_0::IPower follow.
     54 Return<void> Power::setInteractive(bool interactive)  {
     55     if (!isSupportedGovernor()) {
     56         return Void();
     57     }
     58     power_set_interactive(interactive ? 1 : 0);
     59     return Void();
     60 }
     61 
     62 Return<void> Power::powerHint(PowerHint hint, int32_t data) {
     63     if (android::base::GetProperty("init.svc.perfd", "") != "running") {
     64         ALOGW("perfd is not started");
     65         return Void();
     66     }
     67 
     68     power_hint_t h = static_cast<power_hint_t>(hint);
     69     if (!isSupportedGovernor()) {
     70         return Void();
     71     }
     72     if (h == POWER_HINT_INTERACTION) {
     73         mInteractionHandler.Acquire(data);
     74         return Void();
     75     }
     76     power_hint(h, data ? &data : NULL);
     77     return Void();
     78 }
     79 
     80 Return<void> Power::setFeature(Feature /*feature*/, bool /*activate*/)  {
     81     //Nothing to do
     82     return Void();
     83 }
     84 
     85 Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
     86 
     87     hidl_vec<PowerStatePlatformSleepState> states;
     88     uint64_t stats[MAX_PLATFORM_STATS * MAX_RPM_PARAMS] = {0};
     89     uint64_t *values;
     90     struct PowerStatePlatformSleepState *state;
     91     int ret;
     92 
     93     states.resize(PLATFORM_SLEEP_MODES_COUNT);
     94 
     95     ret = extract_platform_stats(stats);
     96     if (ret != 0) {
     97         states.resize(0);
     98         goto done;
     99     }
    100 
    101     /* Update statistics for XO_shutdown */
    102     state = &states[RPM_MODE_XO];
    103     state->name = "XO_shutdown";
    104     values = stats + (RPM_MODE_XO * MAX_RPM_PARAMS);
    105 
    106     state->residencyInMsecSinceBoot = values[1];
    107     state->totalTransitions = values[0];
    108     state->supportedOnlyInSuspend = false;
    109     state->voters.resize(XO_VOTERS);
    110     for(size_t i = 0; i < XO_VOTERS; i++) {
    111         int voter = static_cast<int>(i + XO_VOTERS_START);
    112         state->voters[i].name = rpm_stat_map[voter].label;
    113         values = stats + (voter * MAX_RPM_PARAMS);
    114         state->voters[i].totalTimeInMsecVotedForSinceBoot = values[0] / RPM_CLK;
    115         state->voters[i].totalNumberOfTimesVotedSinceBoot = values[1];
    116     }
    117 
    118     /* Update statistics for VMIN state */
    119     state = &states[RPM_MODE_VMIN];
    120     state->name = "VMIN";
    121     values = stats + (RPM_MODE_VMIN * MAX_RPM_PARAMS);
    122 
    123     state->residencyInMsecSinceBoot = values[1];
    124     state->totalTransitions = values[0];
    125     state->supportedOnlyInSuspend = false;
    126     state->voters.resize(VMIN_VOTERS);
    127     //Note: No filling of state voters since VMIN_VOTERS = 0
    128 
    129 done:
    130     _hidl_cb(states, Status::SUCCESS);
    131     return Void();
    132 }
    133 
    134 static int get_wlan_low_power_stats(struct PowerStateSubsystem &subsystem) {
    135 
    136     uint64_t stats[WLAN_POWER_PARAMS_COUNT] = {0};
    137     struct PowerStateSubsystemSleepState *state;
    138     int ret;
    139 
    140     ret = extract_wlan_stats(stats);
    141     if (ret)
    142         return ret;
    143 
    144     subsystem.name = "wlan";
    145     subsystem.states.resize(WLAN_STATES_COUNT);
    146 
    147     /* Update statistics for Active State */
    148     state = &subsystem.states[WLAN_STATE_ACTIVE];
    149     state->name = "Active";
    150     state->residencyInMsecSinceBoot = stats[CUMULATIVE_TOTAL_ON_TIME_MS];
    151     state->totalTransitions = stats[DEEP_SLEEP_ENTER_COUNTER];
    152     state->lastEntryTimestampMs = 0; //FIXME need a new value from Qcom
    153     state->supportedOnlyInSuspend = false;
    154 
    155     /* Update statistics for Deep-Sleep state */
    156     state = &subsystem.states[WLAN_STATE_DEEP_SLEEP];
    157     state->name = "Deep-Sleep";
    158     state->residencyInMsecSinceBoot = stats[CUMULATIVE_SLEEP_TIME_MS];
    159     state->totalTransitions = stats[DEEP_SLEEP_ENTER_COUNTER];
    160     state->lastEntryTimestampMs = stats[LAST_DEEP_SLEEP_ENTER_TSTAMP_MS];
    161     state->supportedOnlyInSuspend = false;
    162 
    163     return 0;
    164 }
    165 
    166 // Methods from ::android::hardware::power::V1_1::IPower follow.
    167 Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
    168 
    169     hidl_vec<PowerStateSubsystem> subsystems;
    170     int ret;
    171 
    172     subsystems.resize(SUBSYSTEM_COUNT);
    173 
    174     //We currently have only one Subsystem for WLAN
    175     ret = get_wlan_low_power_stats(subsystems[SUBSYSTEM_WLAN]);
    176     if (ret != 0)
    177         goto done;
    178 
    179     //Add query for other subsystems here
    180 
    181 done:
    182     _hidl_cb(subsystems, Status::SUCCESS);
    183     return Void();
    184 }
    185 
    186 bool Power::isSupportedGovernor() {
    187     std::string buf;
    188     if (android::base::ReadFileToString(SCALING_GOVERNOR_PATH, &buf)) {
    189         buf = android::base::Trim(buf);
    190     }
    191     // Only support EAS 1.2, legacy EAS and HMP
    192     if (buf == SCHEDUTIL_GOVERNOR || buf == SCHED_GOVERNOR || buf == INTERACTIVE_GOVERNOR) {
    193         return true;
    194     } else {
    195         ALOGE("Governor not supported by powerHAL, skipping");
    196         return false;
    197     }
    198 }
    199 
    200 Return<void> Power::powerHintAsync(PowerHint hint, int32_t data) {
    201     // just call the normal power hint in this oneway function
    202     return powerHint(hint, data);
    203 }
    204 
    205 }  // namespace implementation
    206 }  // namespace V1_1
    207 }  // namespace power
    208 }  // namespace hardware
    209 }  // namespace android
    210