/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "easelstateresidency"
#include <android-base/logging.h>
#include <fstream>
#include "EaselStateResidencyDataProvider.h"
namespace android {
namespace device {
namespace google {
namespace wahoo {
namespace powerstats {
const uint32_t EASEL_SYNTHETIC_SLEEP_ID = 0;
EaselStateResidencyDataProvider::EaselStateResidencyDataProvider(uint32_t id) :
mPowerEntityId(id), mTotalOnSnapshotCount(0), mTotalNotOnSnapshotCount(0) {}
bool EaselStateResidencyDataProvider::getResults(
std::unordered_map<uint32_t, PowerEntityStateResidencyResult> &results) {
const std::string path = "/sys/devices/virtual/misc/mnh_sm/state";
enum easel_state {
EASEL_OFF = 0,
EASEL_ON,
EASEL_SUSPENDED,
NUM_EASEL_STATES
};
// Since we are storing stats locally but can have multiple parallel
// callers, locking is required to ensure stats are not corrupted.
std::lock_guard<std::mutex> lock(mLock);
std::ifstream inFile(path, std::ifstream::in);
if (!inFile.is_open()) {
PLOG(ERROR) << __func__ << ":Failed to open file " << path;
return false;
}
unsigned long currentState;
if(!(inFile >> currentState) || currentState >= NUM_EASEL_STATES) {
PLOG(ERROR) << __func__ << ":Failed to parse " << path;
return false;
}
// Update statistics for synthetic sleep state. We combine OFF and
// SUSPENDED to act as a composite "not on" state so the numbers will behave
// like a real sleep state.
if ((currentState == EASEL_OFF) || (currentState == EASEL_SUSPENDED)) {
mTotalNotOnSnapshotCount++;
} else {
mTotalOnSnapshotCount++;
}
// Update statistics for synthetic sleep state, where
// totalStateEntryCount = cumulative count of Easel state0 and state2
// (as seen by power.stats HAL)
// totalTimeInStateMs = cumulative count of Easel state1 (as seen by
// power.stats HAL)
PowerEntityStateResidencyResult result = {
.powerEntityId = mPowerEntityId,
.stateResidencyData = {{.powerEntityStateId = EASEL_SYNTHETIC_SLEEP_ID,
.totalStateEntryCount = mTotalOnSnapshotCount,
.totalTimeInStateMs = mTotalNotOnSnapshotCount,
.lastEntryTimestampMs = 0}}
};
results.emplace(std::make_pair(mPowerEntityId, result));
return true;
}
std::vector<PowerEntityStateSpace> EaselStateResidencyDataProvider::getStateSpaces() {
return {
{.powerEntityId = mPowerEntityId,
.states = {
{
.powerEntityStateId = EASEL_SYNTHETIC_SLEEP_ID,
.powerEntityStateName = "SyntheticSleep"
}
}
}
};
}
} // namespace powerstats
} // namespace wahoo
} // namespace google
} // namespace device
} // namespace android