1 /*
2 * Copyright (C) 2018 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 "easelstateresidency"
18
19 #include <android-base/logging.h>
20 #include <fstream>
21 #include "EaselStateResidencyDataProvider.h"
22
23 namespace android {
24 namespace device {
25 namespace google {
26 namespace wahoo {
27 namespace powerstats {
28
29 const uint32_t EASEL_SYNTHETIC_SLEEP_ID = 0;
30
EaselStateResidencyDataProvider(uint32_t id)31 EaselStateResidencyDataProvider::EaselStateResidencyDataProvider(uint32_t id) :
32 mPowerEntityId(id), mTotalOnSnapshotCount(0), mTotalNotOnSnapshotCount(0) {}
33
getResults(std::unordered_map<uint32_t,PowerEntityStateResidencyResult> & results)34 bool EaselStateResidencyDataProvider::getResults(
35 std::unordered_map<uint32_t, PowerEntityStateResidencyResult> &results) {
36 const std::string path = "/sys/devices/virtual/misc/mnh_sm/state";
37
38 enum easel_state {
39 EASEL_OFF = 0,
40 EASEL_ON,
41 EASEL_SUSPENDED,
42 NUM_EASEL_STATES
43 };
44
45 // Since we are storing stats locally but can have multiple parallel
46 // callers, locking is required to ensure stats are not corrupted.
47 std::lock_guard<std::mutex> lock(mLock);
48
49 std::ifstream inFile(path, std::ifstream::in);
50 if (!inFile.is_open()) {
51 PLOG(ERROR) << __func__ << ":Failed to open file " << path;
52 return false;
53 }
54
55 unsigned long currentState;
56 if(!(inFile >> currentState) || currentState >= NUM_EASEL_STATES) {
57 PLOG(ERROR) << __func__ << ":Failed to parse " << path;
58 return false;
59 }
60
61 // Update statistics for synthetic sleep state. We combine OFF and
62 // SUSPENDED to act as a composite "not on" state so the numbers will behave
63 // like a real sleep state.
64 if ((currentState == EASEL_OFF) || (currentState == EASEL_SUSPENDED)) {
65 mTotalNotOnSnapshotCount++;
66 } else {
67 mTotalOnSnapshotCount++;
68 }
69
70 // Update statistics for synthetic sleep state, where
71 // totalStateEntryCount = cumulative count of Easel state0 and state2
72 // (as seen by power.stats HAL)
73 // totalTimeInStateMs = cumulative count of Easel state1 (as seen by
74 // power.stats HAL)
75 PowerEntityStateResidencyResult result = {
76 .powerEntityId = mPowerEntityId,
77 .stateResidencyData = {{.powerEntityStateId = EASEL_SYNTHETIC_SLEEP_ID,
78 .totalStateEntryCount = mTotalOnSnapshotCount,
79 .totalTimeInStateMs = mTotalNotOnSnapshotCount,
80 .lastEntryTimestampMs = 0}}
81 };
82
83 results.emplace(std::make_pair(mPowerEntityId, result));
84 return true;
85 }
86
87
getStateSpaces()88 std::vector<PowerEntityStateSpace> EaselStateResidencyDataProvider::getStateSpaces() {
89 return {
90 {.powerEntityId = mPowerEntityId,
91 .states = {
92 {
93 .powerEntityStateId = EASEL_SYNTHETIC_SLEEP_ID,
94 .powerEntityStateName = "SyntheticSleep"
95 }
96 }
97 }
98 };
99 }
100
101 } // namespace powerstats
102 } // namespace wahoo
103 } // namespace google
104 } // namespace device
105 } // namespace android