1 /*
2  * Copyright (C) 2021 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 #include <dataproviders/PixelStateResidencyDataProvider.h>
18 
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21 #include <android/binder_status.h>
22 
23 namespace aidl {
24 namespace android {
25 namespace hardware {
26 namespace power {
27 namespace stats {
28 
PixelStateResidencyDataProvider()29 PixelStateResidencyDataProvider::PixelStateResidencyDataProvider()
30     : mProviderService(ndk::SharedRefBase::make<ProviderService>(this)) {}
31 
addEntity(std::string name,std::vector<State> states)32 void PixelStateResidencyDataProvider::addEntity(std::string name, std::vector<State> states) {
33     std::lock_guard<std::mutex> lock(mLock);
34 
35     mEntries.emplace_back(name, states);
36 }
37 
start()38 void PixelStateResidencyDataProvider::start() {
39     binder_status_t status =
40             AServiceManager_addService(mProviderService->asBinder().get(), kInstance.c_str());
41     if (status != STATUS_OK) {
42         LOG(ERROR) << "Failed to start " << kInstance;
43     }
44 }
45 
getStateResidenciesTimed(const Entry & entry,std::vector<StateResidency> * residency)46 ::ndk::ScopedAStatus PixelStateResidencyDataProvider::getStateResidenciesTimed(
47         const Entry &entry, std::vector<StateResidency> *residency) {
48     const uint64_t MAX_LATENCY_US = 2000;
49 
50     if (!entry.mCallback) {
51         LOG(ERROR) << "callback for " << entry.mName << " is not registered";
52         return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
53     }
54 
55     struct timespec then;
56     struct timespec now;
57 
58     clock_gettime(CLOCK_BOOTTIME, &then);
59     ::ndk::ScopedAStatus status = entry.mCallback->getStateResidency(residency);
60     clock_gettime(CLOCK_BOOTTIME, &now);
61 
62     uint64_t timeElapsedUs =
63             ((now.tv_sec - then.tv_sec) * 1000000) + ((now.tv_nsec - then.tv_nsec) / 1000);
64     if (timeElapsedUs > MAX_LATENCY_US) {
65         LOG(WARNING) << "getStateResidency latency for " << entry.mName
66                      << " exceeded time allowed: " << timeElapsedUs << "us";
67     }
68 
69     return status;
70 }
71 
getStateResidencies(std::unordered_map<std::string,std::vector<StateResidency>> * residencies)72 bool PixelStateResidencyDataProvider::getStateResidencies(
73         std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
74     std::lock_guard<std::mutex> lock(mLock);
75 
76     size_t numResultsFound = 0;
77     size_t numResults = mEntries.size();
78     for (auto &entry : mEntries) {
79         std::vector<StateResidency> residency;
80         ::ndk::ScopedAStatus status = getStateResidenciesTimed(entry, &residency);
81 
82         if (!status.isOk()) {
83             LOG(ERROR) << "getStateResidency for " << entry.mName << " failed";
84 
85             if (status.getStatus() == STATUS_DEAD_OBJECT) {
86                 LOG(ERROR) << "Unregistering dead callback for " << entry.mName;
87                 entry.mCallback = nullptr;
88             }
89         }
90         if (!residency.empty()) {
91             residencies->emplace(entry.mName, residency);
92             numResultsFound++;
93         }
94     }
95 
96     return (numResultsFound == numResults);
97 }
98 
getInfo()99 std::unordered_map<std::string, std::vector<State>> PixelStateResidencyDataProvider::getInfo() {
100     std::lock_guard<std::mutex> lock(mLock);
101 
102     std::unordered_map<std::string, std::vector<State>> ret;
103     for (const auto &entry : mEntries) {
104         ret.emplace(entry.mName, entry.mStates);
105     }
106 
107     return ret;
108 }
109 
registerCallback(const std::string & in_entityName,const std::shared_ptr<IPixelStateResidencyCallback> & in_cb)110 ::ndk::ScopedAStatus PixelStateResidencyDataProvider::registerCallback(
111         const std::string &in_entityName,
112         const std::shared_ptr<IPixelStateResidencyCallback> &in_cb) {
113     std::lock_guard<std::mutex> lock(mLock);
114 
115     if (!in_cb) {
116         return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
117     }
118 
119     auto toRegister =
120             std::find_if(mEntries.begin(), mEntries.end(),
121                          [&in_entityName](const auto &it) { return it.mName == in_entityName; });
122 
123     if (toRegister == mEntries.end()) {
124         LOG(ERROR) << __func__ << " Invalid entityName: " << in_entityName;
125         return ::ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
126     }
127 
128     toRegister->mCallback = in_cb;
129 
130     LOG(INFO) << __func__ << ": Registered " << in_entityName;
131     return ::ndk::ScopedAStatus::ok();
132 }
133 
unregisterCallback(const std::shared_ptr<IPixelStateResidencyCallback> & in_cb)134 ::ndk::ScopedAStatus PixelStateResidencyDataProvider::unregisterCallback(
135         const std::shared_ptr<IPixelStateResidencyCallback> &in_cb) {
136     std::lock_guard<std::mutex> lock(mLock);
137 
138     if (!in_cb) {
139         return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
140     }
141 
142     auto toRemove = std::find_if(mEntries.begin(), mEntries.end(), [&in_cb](const auto &it) {
143         return it.mCallback->asBinder().get() == in_cb->asBinder().get();
144     });
145 
146     if (toRemove == mEntries.end()) {
147         return ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
148     }
149 
150     toRemove->mCallback = nullptr;
151 
152     return ::ndk::ScopedAStatus::ok();
153 }
154 
155 }  // namespace stats
156 }  // namespace power
157 }  // namespace hardware
158 }  // namespace android
159 }  // namespace aidl
160