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 
registerStatesUpdateCallback(std::function<void (const std::string &,const std::vector<State> & in_states)> statesUpdateCallback)110 void PixelStateResidencyDataProvider::registerStatesUpdateCallback(
111         std::function<void(const std::string &, const std::vector<State> &in_states)>
112                 statesUpdateCallback) {
113     mStatesUpdateCallback = statesUpdateCallback;
114 }
115 
registerCallbackByStates(const std::string & in_entityName,const std::shared_ptr<IPixelStateResidencyCallback> & in_cb,const std::vector<State> & in_states)116 ::ndk::ScopedAStatus PixelStateResidencyDataProvider::registerCallbackByStates(
117         const std::string &in_entityName,
118         const std::shared_ptr<IPixelStateResidencyCallback> &in_cb,
119         const std::vector<State> &in_states) {
120     std::lock_guard<std::mutex> lock(mLock);
121 
122     if (!in_cb) {
123         return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
124     }
125 
126     auto toRegister =
127             std::find_if(mEntries.begin(), mEntries.end(),
128                          [&in_entityName](const auto &it) { return it.mName == in_entityName; });
129 
130     if (toRegister == mEntries.end()) {
131         LOG(ERROR) << __func__ << " Invalid entityName: " << in_entityName;
132         return ::ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
133     }
134 
135     toRegister->mCallback = in_cb;
136 
137     if (!in_states.empty()) {
138         toRegister->mStates = in_states;
139         mStatesUpdateCallback(in_entityName, in_states);
140     }
141 
142     LOG(INFO) << __func__ << ": Registered " << in_entityName;
143     return ::ndk::ScopedAStatus::ok();
144 }
145 
registerCallback(const std::string & in_entityName,const std::shared_ptr<IPixelStateResidencyCallback> & in_cb)146 ::ndk::ScopedAStatus PixelStateResidencyDataProvider::registerCallback(
147         const std::string &in_entityName,
148         const std::shared_ptr<IPixelStateResidencyCallback> &in_cb) {
149     return registerCallbackByStates(in_entityName, in_cb, {});
150 }
151 
unregisterCallback(const std::shared_ptr<IPixelStateResidencyCallback> & in_cb)152 ::ndk::ScopedAStatus PixelStateResidencyDataProvider::unregisterCallback(
153         const std::shared_ptr<IPixelStateResidencyCallback> &in_cb) {
154     std::lock_guard<std::mutex> lock(mLock);
155 
156     if (!in_cb) {
157         return ndk::ScopedAStatus::fromStatus(STATUS_UNEXPECTED_NULL);
158     }
159 
160     auto toRemove = std::find_if(mEntries.begin(), mEntries.end(), [&in_cb](const auto &it) {
161         if (!it.mCallback) {
162             return false;
163         }
164         return it.mCallback->asBinder().get() == in_cb->asBinder().get();
165     });
166 
167     if (toRemove == mEntries.end()) {
168         return ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
169     }
170 
171     toRemove->mCallback = nullptr;
172 
173     return ::ndk::ScopedAStatus::ok();
174 }
175 
176 }  // namespace stats
177 }  // namespace power
178 }  // namespace hardware
179 }  // namespace android
180 }  // namespace aidl
181