diff --git a/powerstats/AocTimedStateResidencyDataProvider.cpp b/powerstats/AocTimedStateResidencyDataProvider.cpp new file mode 100644 index 0000000..ca427f6 --- /dev/null +++ b/powerstats/AocTimedStateResidencyDataProvider.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2022 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. + */ + +#include "AocTimedStateResidencyDataProvider.h" + +#include +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +AocTimedStateResidencyDataProvider::AocTimedStateResidencyDataProvider( + std::vector> ids, + std::vector> states, + const uint64_t timeoutMillis) + : AocStateResidencyDataProvider(ids, states) { + static const uint64_t DEFAULT_MAX_TIME_PER_STATE_MILLIS = 120; + + mTimeoutMillis = + timeoutMillis == 0 ? DEFAULT_MAX_TIME_PER_STATE_MILLIS * states.size() : timeoutMillis; + + mAsyncThread = std::thread(&AocTimedStateResidencyDataProvider::getStateResidenciesAsync, this); +} + +bool AocTimedStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { + bool ret = true; + std::unique_lock statusLock(mStatusMutex); + + if (mAsyncStatus != COMPLETED) { + LOG(ERROR) << "The async thread is not ready: " << mAsyncStatus; + return false; + } + + mStateResidencies.clear(); + + mAsyncStatus = RUN; + mRunCond.notify_one(); + + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(mTimeoutMillis); + auto isCompleted = + mCompletedCond.wait_until(statusLock, timeout, [this]{ return mAsyncStatus == COMPLETED; }); + + if (isCompleted) { + for (const auto &residency : mStateResidencies) { + residencies->emplace(residency.first, residency.second); + } + } else { + LOG(ERROR) << __func__ << " for AoC timed out: " << mTimeoutMillis << " ms"; + ret = false; + } + + return ret; +} + +void AocTimedStateResidencyDataProvider::getStateResidenciesAsync() { + std::unique_lock statusLock(mStatusMutex); + + mAsyncStatus = COMPLETED; + + while (1) { + mRunCond.wait(statusLock, [this]{ return mAsyncStatus == RUN; }); + + mAsyncStatus = RUNNING; + statusLock.unlock(); + + // States from the same power entity are merged. + for (const auto &providerList : mProviders) { + int32_t stateId = 0; + std::string curEntity = providerList.first; + std::vector stateResidencies; + + // Iterate over each provider in the providerList, appending each of the states + for (const auto &provider : providerList.second) { + std::unordered_map> residency; + provider->getStateResidencies(&residency); + + // Each provider should only return data for curEntity but checking anyway + if (residency.find(curEntity) != residency.end()) { + for (auto &r : residency.at(curEntity)) { + /* + * Modifying stateId here because we are stitching together infos from + * multiple GenericStateResidencyDataProviders. stateId must be modified + * to maintain uniqueness for a given entity + */ + r.id = stateId++; + stateResidencies.push_back(r); + } + } + } + mStateResidencies.emplace(curEntity, stateResidencies); + } + + statusLock.lock(); + mAsyncStatus = COMPLETED; + mCompletedCond.notify_one(); + } // while loop +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h index 5008912..f02b911 100644 --- a/powerstats/include/AocStateResidencyDataProvider.h +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -33,7 +33,7 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv std::unordered_map> *residencies) override; std::unordered_map> getInfo() override; - private: + protected: std::unordered_map> /* providers */> mProviders; }; @@ -42,4 +42,4 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv } // namespace power } // namespace hardware } // namespace android -} // namespace aidl \ No newline at end of file +} // namespace aidl diff --git a/powerstats/include/AocTimedStateResidencyDataProvider.h b/powerstats/include/AocTimedStateResidencyDataProvider.h new file mode 100644 index 0000000..98724b2 --- /dev/null +++ b/powerstats/include/AocTimedStateResidencyDataProvider.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 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. + */ +#pragma once + +#include "AocStateResidencyDataProvider.h" + +#include +#include +#include +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +enum AsyncStatus { + COMPLETED, + RUN, + RUNNING +}; + +class AocTimedStateResidencyDataProvider : public AocStateResidencyDataProvider { + public: + AocTimedStateResidencyDataProvider( + std::vector> ids, + std::vector> states, + const uint64_t timeoutMillis); + ~AocTimedStateResidencyDataProvider() = default; + + bool getStateResidencies( + std::unordered_map> *residencies) override; + + private: + void getStateResidenciesAsync(); + + uint64_t mTimeoutMillis; + std::thread mAsyncThread; + std::mutex mStatusMutex; + std::condition_variable mRunCond; + std::condition_variable mCompletedCond; + std::unordered_map> mStateResidencies; + AsyncStatus mAsyncStatus; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl