blob: 071e16dda8879dee6ca13423bd467151443eeb91 [file] [log] [blame]
Benjamin Schwartza45b98e2020-08-25 14:50:39 -07001/*
2 * Copyright (C) 2020 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 */
Benjamin Schwartz23a51cc2020-09-11 14:27:47 -070016// TODO(b/167628903): Delete this file
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070017#define LOG_TAG "libpixelpowerstats"
18
19#include <android-base/chrono_utils.h>
20#include <android-base/logging.h>
21#include <android-base/properties.h>
22
23#include <pixelpowerstats/DisplayStateResidencyDataProvider.h>
24#include <pixelpowerstats/PowerStatsUtils.h>
25
26#include <chrono>
27#include <cstdio>
28#include <cstring>
29
30namespace android {
31namespace hardware {
32namespace google {
33namespace pixel {
34namespace powerstats {
35
36DisplayStateResidencyDataProvider::DisplayStateResidencyDataProvider(
37 uint32_t id, std::string path, std::vector<std::string> states)
Benjamin Schwartz249ba882021-03-16 11:55:41 -070038 : mPath(std::move(path)),
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070039 mPowerEntityId(id),
40 mStates(states),
41 mCurState(-1),
42 mLooper(new Looper(true)) {
43 // Construct mResidencies
Benjamin Schwartz249ba882021-03-16 11:55:41 -070044 mResidencies.reserve(mStates.size());
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070045 for (uint32_t i = 0; i < mStates.size(); ++i) {
46 PowerEntityStateResidencyData p = {.powerEntityStateId = i};
47 mResidencies.emplace_back(p);
48 }
49
50 // Open display state file descriptor
51 LOG(VERBOSE) << "Opening " << mPath;
52 mFd = open(mPath.c_str(), O_RDONLY | O_NONBLOCK);
53 if (mFd < 0) {
54 PLOG(ERROR) << ":Failed to open file " << mPath;
55 return;
56 }
57
58 // Add display state file descriptor to be polled by the looper
59 mLooper->addFd(mFd, 0, Looper::EVENT_ERROR, nullptr, nullptr);
60
61 // Run the thread that will poll for changes to display state
62 LOG(VERBOSE) << "Starting DisplayStateWatcherThread";
Benjamin Schwartz249ba882021-03-16 11:55:41 -070063 mThread = std::thread(&DisplayStateResidencyDataProvider::pollLoop, this);
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070064}
65
66DisplayStateResidencyDataProvider::~DisplayStateResidencyDataProvider() {
67 if (mFd > 0) {
68 close(mFd);
69 }
70}
71
72bool DisplayStateResidencyDataProvider::getResults(
73 std::unordered_map<uint32_t, PowerEntityStateResidencyResult> &results) {
74 std::scoped_lock lk(mLock);
75
76 // Get current time since boot in milliseconds
Benjamin Schwartz249ba882021-03-16 11:55:41 -070077 uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
78 ::android::base::boot_clock::now().time_since_epoch())
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070079 .count();
80
81 // Construct residency result based on current residency data
Benjamin Schwartz249ba882021-03-16 11:55:41 -070082 PowerEntityStateResidencyResult result = {.powerEntityId = mPowerEntityId,
83 .stateResidencyData = mResidencies};
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070084
Benjamin Schwartz249ba882021-03-16 11:55:41 -070085 if (mCurState > -1) {
86 result.stateResidencyData[mCurState].totalTimeInStateMs +=
87 now - result.stateResidencyData[mCurState].lastEntryTimestampMs;
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070088 }
Benjamin Schwartz249ba882021-03-16 11:55:41 -070089
Benjamin Schwartza45b98e2020-08-25 14:50:39 -070090 results.emplace(mPowerEntityId, result);
91 return true;
92}
93
94std::vector<PowerEntityStateSpace> DisplayStateResidencyDataProvider::getStateSpaces() {
95 PowerEntityStateSpace s = {.powerEntityId = mPowerEntityId};
96 s.states.resize(mStates.size());
97 for (uint32_t i = 0; i < mStates.size(); ++i) {
98 s.states[i] = {.powerEntityStateId = i, .powerEntityStateName = mStates[i]};
99 }
100
101 return {s};
102}
103
104// Called when there is new data to be read from
105// display state file descriptor indicating a state change
106void DisplayStateResidencyDataProvider::updateStats() {
107 char data[32];
108
109 // Get current time since boot in milliseconds
Benjamin Schwartz249ba882021-03-16 11:55:41 -0700110 uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
111 ::android::base::boot_clock::now().time_since_epoch())
Benjamin Schwartza45b98e2020-08-25 14:50:39 -0700112 .count();
Benjamin Schwartza45b98e2020-08-25 14:50:39 -0700113 // Read display state
114 ssize_t ret = pread(mFd, data, sizeof(data) - 1, 0);
115 if (ret < 0) {
Benjamin Schwartz60027eb2021-04-01 14:16:04 -0700116 PLOG(WARNING) << "Failed to read display state";
Benjamin Schwartza45b98e2020-08-25 14:50:39 -0700117 return;
118 }
119 data[ret] = '\0';
120
121 LOG(VERBOSE) << "display state: " << data;
122
123 // Update residency stats based on state read
124 { // acquire lock
125 std::scoped_lock lk(mLock);
126 for (uint32_t i = 0; i < mStates.size(); ++i) {
127 if (strstr(data, mStates[i].c_str())) {
128 // Update total time of the previous state
129 if (mCurState > -1) {
130 mResidencies[mCurState].totalTimeInStateMs +=
131 now - mResidencies[mCurState].lastEntryTimestampMs;
132 }
133
134 // Set current state
135 mCurState = i;
136 mResidencies[i].totalStateEntryCount++;
137 mResidencies[i].lastEntryTimestampMs = now;
138 break;
139 }
140 }
141 } // release lock
142}
143
Benjamin Schwartz249ba882021-03-16 11:55:41 -0700144void DisplayStateResidencyDataProvider::pollLoop() {
Benjamin Schwartza45b98e2020-08-25 14:50:39 -0700145 LOG(VERBOSE) << "DisplayStateResidencyDataProvider polling...";
Benjamin Schwartz249ba882021-03-16 11:55:41 -0700146 while (true) {
147 // Poll for display state changes. Timeout set to poll indefinitely
148 if (mLooper->pollOnce(-1) >= 0) {
149 updateStats();
150 }
Benjamin Schwartza45b98e2020-08-25 14:50:39 -0700151 }
Benjamin Schwartza45b98e2020-08-25 14:50:39 -0700152}
Benjamin Schwartz249ba882021-03-16 11:55:41 -0700153
Benjamin Schwartza45b98e2020-08-25 14:50:39 -0700154} // namespace powerstats
155} // namespace pixel
156} // namespace google
157} // namespace hardware
158} // namespace android