From 40d29fac894bfe2e157881be9a06b565a45ead0a Mon Sep 17 00:00:00 2001 From: mincheli Date: Wed, 22 Dec 2021 16:35:24 +0800 Subject: [PATCH 1/9] Adds pregrant permissions for TalkBack Approved by b/204048166, cl/410296191 updates the pregant list for TalkBack "android.permission.READ_PHONE_STATE" "android.permission.BLUETOOTH_CONNECT", "android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_ADVERTISE", Bug: 192521587 Test: manual Change-Id: Ib21e56fa2038c9368b1be9318639dce03f510691 --- default-talkback-permissions.xml | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 default-talkback-permissions.xml diff --git a/default-talkback-permissions.xml b/default-talkback-permissions.xml new file mode 100644 index 0000000..ca8b5dd --- /dev/null +++ b/default-talkback-permissions.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + +        + + + + + + + +    + + + From 9135d780227270039f47f24808a50525b42c4ac4 Mon Sep 17 00:00:00 2001 From: Cyan_Hsieh Date: Wed, 22 Dec 2021 16:42:08 +0800 Subject: [PATCH 2/9] Initialize device makefile in gs common add default-talkback-permissions.xml to default-permissions Bug: 211723080 Change-Id: Id661d801bed78403024abc3e4998408f5470c5c5 --- device.mk | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 device.mk diff --git a/device.mk b/device.mk new file mode 100644 index 0000000..d9ee5e0 --- /dev/null +++ b/device.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2021 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. +# + +PRODUCT_COPY_FILES += \ + device/google/gs-common/default-talkback-permissions.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/default-permissions/default-talkback-permissions.xml From 673d3b0ab7e0e7614487ac2c879417e2e450a5e7 Mon Sep 17 00:00:00 2001 From: Darren Hsu Date: Tue, 28 Dec 2021 21:31:24 +0800 Subject: [PATCH 3/9] powerstats: add common data providers in gs common Bug: 206576142 Test: dumpsys android.hardware.power.stats.IPowerStats/default Change-Id: Iee66356150a8bdfcd1e0b3fe8b8d5ec9f601f543 Signed-off-by: Darren Hsu --- device.mk | 3 + powerstats/Android.bp | 24 +++ powerstats/AocStateResidencyDataProvider.cpp | 128 +++++++++++++++ .../DevfreqStateResidencyDataProvider.cpp | 111 +++++++++++++ powerstats/DvfsStateResidencyDataProvider.cpp | 149 ++++++++++++++++++ powerstats/UfsStateResidencyDataProvider.cpp | 82 ++++++++++ .../include/AocStateResidencyDataProvider.h | 45 ++++++ .../DevfreqStateResidencyDataProvider.h | 53 +++++++ .../include/DvfsStateResidencyDataProvider.h | 68 ++++++++ .../include/UfsStateResidencyDataProvider.h | 52 ++++++ 10 files changed, 715 insertions(+) create mode 100644 powerstats/Android.bp create mode 100644 powerstats/AocStateResidencyDataProvider.cpp create mode 100644 powerstats/DevfreqStateResidencyDataProvider.cpp create mode 100644 powerstats/DvfsStateResidencyDataProvider.cpp create mode 100644 powerstats/UfsStateResidencyDataProvider.cpp create mode 100644 powerstats/include/AocStateResidencyDataProvider.h create mode 100644 powerstats/include/DevfreqStateResidencyDataProvider.h create mode 100644 powerstats/include/DvfsStateResidencyDataProvider.h create mode 100644 powerstats/include/UfsStateResidencyDataProvider.h diff --git a/device.mk b/device.mk index d9ee5e0..d6a156c 100644 --- a/device.mk +++ b/device.mk @@ -16,3 +16,6 @@ PRODUCT_COPY_FILES += \ device/google/gs-common/default-talkback-permissions.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/default-permissions/default-talkback-permissions.xml + +PRODUCT_SOONG_NAMESPACES += \ + device/google/gs-common/powerstats diff --git a/powerstats/Android.bp b/powerstats/Android.bp new file mode 100644 index 0000000..74935c7 --- /dev/null +++ b/powerstats/Android.bp @@ -0,0 +1,24 @@ +soong_namespace { + imports: [ + "hardware/google/pixel", + ], +} + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "android.hardware.power.stats-impl.gs-common", + vendor_available: true, + export_include_dirs: ["include"], + defaults: ["powerstats_pixel_defaults"], + + srcs: [ + "*.cpp", + ], + + shared_libs: [ + "android.hardware.power.stats-impl.pixel", + ], +} diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp new file mode 100644 index 0000000..c64496d --- /dev/null +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 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 "AocStateResidencyDataProvider.h" + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> ids, std::vector> states) { + // AoC stats are reported in ticks of 244.140625ns. The transform + // function converts ticks to milliseconds. + // 1000000 / 244.140625 = 4096. + static const uint64_t AOC_CLK = 4096; + std::function aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; + GenericStateResidencyDataProvider::StateResidencyConfig config = { + .entryCountSupported = true, + .entryCountPrefix = "Counter:", + .totalTimeSupported = true, + .totalTimePrefix = "Cumulative time:", + .totalTimeTransform = aocTickToMs, + .lastEntrySupported = true, + .lastEntryPrefix = "Time last entered:", + .lastEntryTransform = aocTickToMs, + }; + for (const auto &id : ids) { + for (const auto &state : states) { + std::vector> aocStateHeaders = { + std::make_pair(state.first, ""), + }; + std::vector cfgs; + cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders), + id.first, ""); + std::unique_ptr sdp( + new GenericStateResidencyDataProvider(id.second + state.second, cfgs)); + mProviders[id.first].push_back(std::move(sdp)); + } + } +} + +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { + // States from the same power entity are merged. + bool ret = true; + 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; + ret &= 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); + } + } + } + + residencies->emplace(curEntity, stateResidencies); + } + return ret; +} + +std::unordered_map> AocStateResidencyDataProvider::getInfo() { + // States from the same power entity are merged + std::unordered_map> infos; + for (const auto &providerList : mProviders) { + int32_t stateId = 0; + std::string curEntity = providerList.first; + std::vector stateInfos; + + // Iterate over each provider in the providerList, appending each of the states + for (const auto &provider : providerList.second) { + std::unordered_map> info = provider->getInfo(); + + // Each provider should only return data for curEntity but checking anyway + if (info.find(curEntity) != info.end()) { + for (auto &i : info.at(curEntity)) { + /* + * Modifying stateId because we are stitching together infos from + * multiple GenericStateResidencyDataProviders. stateId must be modified + * to maintain uniqueness for a given entity + */ + i.id = stateId++; + stateInfos.push_back(i); + } + } + } + + infos.emplace(curEntity, stateInfos); + } + + return infos; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/DevfreqStateResidencyDataProvider.cpp b/powerstats/DevfreqStateResidencyDataProvider.cpp new file mode 100644 index 0000000..d59e1e5 --- /dev/null +++ b/powerstats/DevfreqStateResidencyDataProvider.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2021 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 "DevfreqStateResidencyDataProvider.h" + +#include + +static const std::string nameSuffix = "-DVFS"; +static const std::string pathSuffix = "/time_in_state"; + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +DevfreqStateResidencyDataProvider::DevfreqStateResidencyDataProvider(const std::string& name, + const std::string& path) : mName(name + nameSuffix), mPath(path + pathSuffix) {} + +bool DevfreqStateResidencyDataProvider::extractNum(const char *str, char **str_end, int base, + int64_t* num) { + // errno can be set to any non-zero value by a library function call + // regardless of whether there was an error, so it needs to be cleared + // in order to check the error set by strtoll + errno = 0; + *num = std::strtoll(str, str_end, base); + return (errno != ERANGE); +} + +std::vector> DevfreqStateResidencyDataProvider::parseTimeInState() { + // Using FILE* instead of std::ifstream for performance reasons + std::unique_ptr fp(fopen(mPath.c_str(), "r"), fclose); + if (!fp) { + PLOG(ERROR) << "Failed to open file " << mPath; + return {}; + } + + std::vector> timeInState; + + char *line = nullptr; + size_t len = 0; + while (getline(&line, &len, fp.get()) != -1) { + char* pEnd; + int64_t frequencyHz, totalTimeMs; + if (!extractNum(line, &pEnd, 10, &frequencyHz) || + !extractNum(pEnd, &pEnd, 10, &totalTimeMs)) { + PLOG(ERROR) << "Failed to parse " << mPath; + free(line); + return {}; + } + + timeInState.push_back({frequencyHz, totalTimeMs}); + } + + free(line); + return timeInState; +} + +bool DevfreqStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { + std::vector> timeInState = parseTimeInState(); + + if (timeInState.empty()) { + return false; + } + + int32_t id = 0; + std::vector stateResidencies; + for (const auto[frequencyHz, totalTimeMs] : timeInState) { + StateResidency s = {.id = id++, .totalTimeInStateMs = totalTimeMs}; + stateResidencies.push_back(s); + } + + residencies->emplace(mName, stateResidencies); + return true; +} + +std::unordered_map> DevfreqStateResidencyDataProvider::getInfo() { + std::vector> timeInState = parseTimeInState(); + + if (timeInState.empty()) { + return {}; + } + + int32_t id = 0; + std::vector states; + for (const auto[frequencyHz, totalTimeMs] : timeInState) { + State s = {.id = id++, .name = std::to_string(frequencyHz / 1000) + "MHz"}; + states.push_back(s); + } + + return {{mName, states}}; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/DvfsStateResidencyDataProvider.cpp b/powerstats/DvfsStateResidencyDataProvider.cpp new file mode 100644 index 0000000..511159e --- /dev/null +++ b/powerstats/DvfsStateResidencyDataProvider.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2020 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 "DvfsStateResidencyDataProvider.h" + +#include +#include +#include + +#include +#include + +using android::base::ParseUint; +using android::base::Split; +using android::base::StartsWith; +using android::base::Trim; + +static const std::string nameSuffix = "-DVFS"; + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +DvfsStateResidencyDataProvider::DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, + std::vector cfgs) + : mPath(std::move(path)), mClockRate(clockRate), mPowerEntities(std::move(cfgs)) {} + +int32_t DvfsStateResidencyDataProvider::matchEntity(char const *line) { + for (int32_t i = 0; i < mPowerEntities.size(); i++) { + if (mPowerEntities[i].powerEntityName == Trim(std::string(line))) { + return i; + } + } + return -1; +} + +int32_t DvfsStateResidencyDataProvider::matchState(char const *line, const Config& powerEntity) { + for (int32_t i = 0; i < powerEntity.states.size(); i++) { + if (StartsWith(Trim(std::string(line)), powerEntity.states[i].second)) { + return i; + } + } + return -1; +} + +bool DvfsStateResidencyDataProvider::parseState(char const *line, uint64_t *duration, + uint64_t *count) { + std::vector parts = Split(line, " "); + if (parts.size() != 7) { + return false; + } + if (!ParseUint(Trim(parts[3]), count)) { + return false; + } + if (!ParseUint(Trim(parts[6]), duration)) { + return false; + } + return true; +} + +bool DvfsStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { + std::unique_ptr fp(fopen(mPath.c_str(), "r"), fclose); + if (!fp) { + PLOG(ERROR) << __func__ << ":Failed to open file " << mPath; + return false; + } + + for (const Config &powerEntity : mPowerEntities) { + std::vector stateResidency(powerEntity.states.size()); + for (int32_t i = 0; i < stateResidency.size(); i++) { + stateResidency[i].id = i; + } + residencies->emplace(powerEntity.powerEntityName + nameSuffix, stateResidency); + } + + size_t len = 0; + char *line = nullptr; + + int32_t temp, powerEntityIndex, stateId = -1; + uint64_t duration, count; + auto it = residencies->end(); + + while (getline(&line, &len, fp.get()) != -1) { + temp = matchEntity(line); + // Assign new index only when a new valid entity is encountered. + if (temp >= 0) { + powerEntityIndex = temp; + it = residencies->find(mPowerEntities[powerEntityIndex].powerEntityName + nameSuffix); + } + + if (it != residencies->end()) { + stateId = matchState(line, mPowerEntities[powerEntityIndex]); + + if (stateId >= 0) { + if (parseState(line, &duration, &count)) { + it->second[stateId].totalTimeInStateMs = + duration / mClockRate; + it->second[stateId].totalStateEntryCount = count; + } else { + LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line) + << "]"; + return false; + } + } + } + } + + free(line); + + return true; +} + +std::unordered_map> DvfsStateResidencyDataProvider::getInfo() { + std::unordered_map> info; + for (auto const &entity : mPowerEntities) { + std::vector stateInfo(entity.states.size()); + int32_t stateId = 0; + for (auto const &state : entity.states) { + stateInfo[stateId] = State{ + .id = stateId, + .name = state.first + }; + stateId++; + } + info.emplace(entity.powerEntityName + nameSuffix, stateInfo); + } + return info; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/UfsStateResidencyDataProvider.cpp b/powerstats/UfsStateResidencyDataProvider.cpp new file mode 100644 index 0000000..aec7724 --- /dev/null +++ b/powerstats/UfsStateResidencyDataProvider.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2021 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 "UfsStateResidencyDataProvider.h" + +#include +#include +#include + +#include +#include + +using android::base::ParseInt; +using android::base::Split; +using android::base::StartsWith; +using android::base::Trim; + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +const int32_t HIBERNATE_STATE_ID = 0; +const std::string UFS_NAME = "UFS"; + +UfsStateResidencyDataProvider::UfsStateResidencyDataProvider(std::string prefix) : kPrefix(prefix) {} + +bool UfsStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { + StateResidency residency; + residency.id = HIBERNATE_STATE_ID; + + // The transform function converts microseconds to milliseconds. + std::function usecToMs = [](uint64_t a) { return a / 1000; }; + + residency.totalTimeInStateMs = usecToMs(readStat(kPrefix + "hibern8_total_us")); + residency.totalStateEntryCount = readStat(kPrefix + "hibern8_exit_cnt"); + residency.lastEntryTimestampMs = usecToMs(readStat(kPrefix + "last_hibern8_enter_time")); + + residencies->emplace(UFS_NAME, std::vector{residency}); + return true; +} + +std::unordered_map> UfsStateResidencyDataProvider::getInfo() { + return {{UFS_NAME, std::vector{{HIBERNATE_STATE_ID, "HIBERN8"}} }}; +} + +int64_t UfsStateResidencyDataProvider::readStat(std::string path) { + std::unique_ptr fp(fopen(path.c_str(), "r"), fclose); + if (!fp) { + PLOG(ERROR) << __func__ << ":Failed to open file " << path + << " Error = " << strerror(errno); + return 0; + } + const size_t size = 20; + char buf[size]; + (void)fread(&buf, sizeof(char), size, fp.get()); + int64_t ret; + if (!ParseInt(Trim(std::string(buf)), &ret)) { + LOG(ERROR) << "Failed to parse int64 from [" << std::string(buf) << "]"; + } + return ret; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h new file mode 100644 index 0000000..5008912 --- /dev/null +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 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 +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + AocStateResidencyDataProvider(std::vector> ids, + std::vector> states); + ~AocStateResidencyDataProvider() = default; + bool getStateResidencies( + std::unordered_map> *residencies) override; + std::unordered_map> getInfo() override; + + private: + std::unordered_map> /* providers */> mProviders; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl \ No newline at end of file diff --git a/powerstats/include/DevfreqStateResidencyDataProvider.h b/powerstats/include/DevfreqStateResidencyDataProvider.h new file mode 100644 index 0000000..8341b43 --- /dev/null +++ b/powerstats/include/DevfreqStateResidencyDataProvider.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 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 + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class DevfreqStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + DevfreqStateResidencyDataProvider(const std::string& name, const std::string& path); + ~DevfreqStateResidencyDataProvider() = default; + + /* + * See IStateResidencyDataProvider::getStateResidencies + */ + bool getStateResidencies( + std::unordered_map> *residencies) override; + + /* + * See IStateResidencyDataProvider::getInfo + */ + std::unordered_map> getInfo() override; + + private: + bool extractNum(const char *str, char **str_end, int base, int64_t* num); + std::vector> parseTimeInState(); + const std::string mName; + const std::string mPath; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/include/DvfsStateResidencyDataProvider.h b/powerstats/include/DvfsStateResidencyDataProvider.h new file mode 100644 index 0000000..ca8ab22 --- /dev/null +++ b/powerstats/include/DvfsStateResidencyDataProvider.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 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 + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class DvfsStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + class Config { + public: + // Power entity name to parse. + std::string powerEntityName; + + // List of state pairs (name to display, name to parse). + std::vector> states; + }; + /* + * path - path to dvfs sysfs node. + * clockRate - clock rate in KHz. + */ + DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, std::vector cfgs); + ~DvfsStateResidencyDataProvider() = default; + + /* + * See IStateResidencyDataProvider::getStateResidencies + */ + bool getStateResidencies( + std::unordered_map> *residencies) override; + + /* + * See IStateResidencyDataProvider::getInfo + */ + std::unordered_map> getInfo() override; + + private: + int32_t matchEntity(char const *line); + int32_t matchState(char const *line, const Config& powerEntity); + bool parseState(char const *line, uint64_t *duration, uint64_t *count); + + const std::string mPath; + const uint64_t mClockRate; + std::vector mPowerEntities; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/include/UfsStateResidencyDataProvider.h b/powerstats/include/UfsStateResidencyDataProvider.h new file mode 100644 index 0000000..f4ef268 --- /dev/null +++ b/powerstats/include/UfsStateResidencyDataProvider.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 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 + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class UfsStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + UfsStateResidencyDataProvider(std::string prefix); + ~UfsStateResidencyDataProvider() = default; + + /* + * See IStateResidencyDataProvider::getStateResidencies + */ + bool getStateResidencies( + std::unordered_map> *residencies) override; + + /* + * See IStateResidencyDataProvider::getInfo + */ + std::unordered_map> getInfo() override; + + private: + int64_t readStat(std::string path); + + const std::string kPrefix; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl From 088607751dd0921fd4d6209cdc4bbd4181448c13 Mon Sep 17 00:00:00 2001 From: mincheli Date: Wed, 26 Jan 2022 15:28:32 +0800 Subject: [PATCH 4/9] Reverts default-talkback-permissions.xml in gs-common ag/16646190 has fulfilled the permission pregrant for TalkBack. So we revert the old change. Bug: 192521587 Test: manual test Change-Id: I2f702597fbcafc361a7d383915433af4da735509 --- default-talkback-permissions.xml | 56 -------------------------------- device.mk | 3 -- 2 files changed, 59 deletions(-) delete mode 100644 default-talkback-permissions.xml diff --git a/default-talkback-permissions.xml b/default-talkback-permissions.xml deleted file mode 100644 index ca8b5dd..0000000 --- a/default-talkback-permissions.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - -        - - - - - - - -    - - - diff --git a/device.mk b/device.mk index d6a156c..80aae9f 100644 --- a/device.mk +++ b/device.mk @@ -14,8 +14,5 @@ # limitations under the License. # -PRODUCT_COPY_FILES += \ - device/google/gs-common/default-talkback-permissions.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/default-permissions/default-talkback-permissions.xml - PRODUCT_SOONG_NAMESPACES += \ device/google/gs-common/powerstats From aee3d1a322d14c4d573d247dac3181d66b346f0f Mon Sep 17 00:00:00 2001 From: Darren Hsu Date: Mon, 28 Mar 2022 14:26:25 +0800 Subject: [PATCH 5/9] powerstats: timeout mechanism for AoC data provider Bug: 219630658 Test: dumpsys android.hardware.power.stats.IPowerStats/default Change-Id: Ib70000580f9515b3cb73968dd190f99ae8af178f Signed-off-by: Darren Hsu --- powerstats/AocStateResidencyDataProvider.cpp | 95 +++++++++++++++++-- .../include/AocStateResidencyDataProvider.h | 7 +- 2 files changed, 93 insertions(+), 9 deletions(-) diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp index c64496d..b8d40ea 100644 --- a/powerstats/AocStateResidencyDataProvider.cpp +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -17,6 +17,8 @@ #include "AocStateResidencyDataProvider.h" #include +#include +#include namespace aidl { namespace android { @@ -24,12 +26,22 @@ namespace hardware { namespace power { namespace stats { +struct async_data_t { + pthread_cond_t *cond; + pthread_mutex_t *lock; + std::unordered_map> *residencies; + std::unordered_map>> *providers; +}; + AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> ids, std::vector> states) { + std::string>> ids, std::vector> states, + const uint64_t timeoutMillis) { // AoC stats are reported in ticks of 244.140625ns. The transform // function converts ticks to milliseconds. // 1000000 / 244.140625 = 4096. static const uint64_t AOC_CLK = 4096; + static const uint64_t TIMEOUT_MILLIS = 120; std::function aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; GenericStateResidencyDataProvider::StateResidencyConfig config = { .entryCountSupported = true, @@ -54,13 +66,16 @@ AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> *residencies) { +void *getStateResidenciesAsync(void *arg) { + struct async_data_t *async = (struct async_data_t*)arg; + const auto *originalContainer = async->residencies; + // States from the same power entity are merged. - bool ret = true; - for (const auto &providerList : mProviders) { + for (const auto &providerList : *async->providers) { int32_t stateId = 0; std::string curEntity = providerList.first; std::vector stateResidencies; @@ -68,7 +83,7 @@ bool AocStateResidencyDataProvider::getStateResidencies( // Iterate over each provider in the providerList, appending each of the states for (const auto &provider : providerList.second) { std::unordered_map> residency; - ret &= provider->getStateResidencies(&residency); + provider->getStateResidencies(&residency); // Each provider should only return data for curEntity but checking anyway if (residency.find(curEntity) != residency.end()) { @@ -84,8 +99,74 @@ bool AocStateResidencyDataProvider::getStateResidencies( } } - residencies->emplace(curEntity, stateResidencies); + if (async->residencies != originalContainer) { + /* + * When provider->gretStateResidencies() exceeds timeout expiration, the main thread + * stops waiting and continue, then the original residency pointer is erased in the + * main thread when AocStateResidencyDataProvider::getStateResidencies() ends, and new + * container will be created in the async thread later. In this situation, we ignore + * delayed residency data and end the async thread. + */ + return 0; + } + + async->residencies->emplace(curEntity, stateResidencies); } + + pthread_mutex_lock(async->lock); + pthread_cond_signal(async->cond); + pthread_mutex_unlock(async->lock); + + return 0; +} + +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { + bool ret = true; + int condResult = 0; + pthread_t tid; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + std::unordered_map> stateResidencies; + struct timespec start, timeout; + struct async_data_t async = { + .cond = &cond, + .lock = &lock, + .residencies = &stateResidencies, + .providers = &mProviders + }; + + pthread_create(&tid, NULL, &getStateResidenciesAsync, (void*)&async); + + clock_gettime(CLOCK_REALTIME, &start); + + uint64_t expirationMillis = mTimeoutMillis * mStateCount; + timeout.tv_sec = start.tv_sec + expirationMillis / 1000; + uint64_t nsec = start.tv_nsec + (expirationMillis % 1000) * 1000000; + if (nsec < 1000000000) { + timeout.tv_nsec = nsec; + } else { + timeout.tv_sec += 1; + timeout.tv_nsec = nsec - 1000000000; + } + + pthread_mutex_lock(&lock); + condResult = pthread_cond_timedwait(&cond, &lock, &timeout); + pthread_mutex_unlock(&lock); + + if (condResult != 0) { + if (condResult == ETIMEDOUT) { + LOG(WARNING) << __func__ << " latency for AoC timeout: " << expirationMillis << " ms"; + } else { + LOG(ERROR) << "Failed to wait for the condition variable: " << condResult; + } + ret = false; + } else { + for (const auto &residency : stateResidencies) { + residencies->emplace(residency.first, residency.second); + } + } + return ret; } diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h index 5008912..150f335 100644 --- a/powerstats/include/AocStateResidencyDataProvider.h +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -27,7 +27,8 @@ namespace stats { class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { public: AocStateResidencyDataProvider(std::vector> ids, - std::vector> states); + std::vector> states, + const uint64_t timeoutMillis); ~AocStateResidencyDataProvider() = default; bool getStateResidencies( std::unordered_map> *residencies) override; @@ -36,10 +37,12 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv private: std::unordered_map> /* providers */> mProviders; + int32_t mStateCount; + uint64_t mTimeoutMillis; }; } // namespace stats } // namespace power } // namespace hardware } // namespace android -} // namespace aidl \ No newline at end of file +} // namespace aidl From e8484562270d90072073c7dea377077dfb8d85af Mon Sep 17 00:00:00 2001 From: Sungtak Lee Date: Wed, 30 Mar 2022 15:11:05 -0700 Subject: [PATCH 6/9] Disable OMX Bug: 222649162 Test: make Change-Id: Iaf1046c610804c5bdb3b0f591e9907539534ea06 --- device.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/device.mk b/device.mk index 80aae9f..7defec0 100644 --- a/device.mk +++ b/device.mk @@ -16,3 +16,7 @@ PRODUCT_SOONG_NAMESPACES += \ device/google/gs-common/powerstats + +# Disable OMX +PRODUCT_PROPERTY_OVERRIDES += \ + vendor.media.omx=0 From 2433fcf62ed5239d89d442062688902cce41a6a3 Mon Sep 17 00:00:00 2001 From: Kelly Rossmoyer Date: Fri, 1 Apr 2022 20:28:24 +0000 Subject: [PATCH 7/9] Revert "powerstats: timeout mechanism for AoC data provider" Revert submission 17442015-powerstats-aoc-timeout Reason for revert: Causes PowerStatsHAL crashes (b/227578192) Reverted Changes: I9a9eb27fa:powerstats: set time limit as timeout for AoC Ib70000580:powerstats: timeout mechanism for AoC data provide... Ied599054c:Revert "powerstats: disable AoC power stats report... Iaf5af43eb:powerstats: set time limit as timeout for AoC Change-Id: I53e280871197aaf003d9ef3e5e0cb4c79f486cc8 --- powerstats/AocStateResidencyDataProvider.cpp | 95 ++----------------- .../include/AocStateResidencyDataProvider.h | 7 +- 2 files changed, 9 insertions(+), 93 deletions(-) diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp index b8d40ea..c64496d 100644 --- a/powerstats/AocStateResidencyDataProvider.cpp +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -17,8 +17,6 @@ #include "AocStateResidencyDataProvider.h" #include -#include -#include namespace aidl { namespace android { @@ -26,22 +24,12 @@ namespace hardware { namespace power { namespace stats { -struct async_data_t { - pthread_cond_t *cond; - pthread_mutex_t *lock; - std::unordered_map> *residencies; - std::unordered_map>> *providers; -}; - AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> ids, std::vector> states, - const uint64_t timeoutMillis) { + std::string>> ids, std::vector> states) { // AoC stats are reported in ticks of 244.140625ns. The transform // function converts ticks to milliseconds. // 1000000 / 244.140625 = 4096. static const uint64_t AOC_CLK = 4096; - static const uint64_t TIMEOUT_MILLIS = 120; std::function aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; GenericStateResidencyDataProvider::StateResidencyConfig config = { .entryCountSupported = true, @@ -66,16 +54,13 @@ AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vectorresidencies; - +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { // States from the same power entity are merged. - for (const auto &providerList : *async->providers) { + bool ret = true; + for (const auto &providerList : mProviders) { int32_t stateId = 0; std::string curEntity = providerList.first; std::vector stateResidencies; @@ -83,7 +68,7 @@ void *getStateResidenciesAsync(void *arg) { // 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); + ret &= provider->getStateResidencies(&residency); // Each provider should only return data for curEntity but checking anyway if (residency.find(curEntity) != residency.end()) { @@ -99,74 +84,8 @@ void *getStateResidenciesAsync(void *arg) { } } - if (async->residencies != originalContainer) { - /* - * When provider->gretStateResidencies() exceeds timeout expiration, the main thread - * stops waiting and continue, then the original residency pointer is erased in the - * main thread when AocStateResidencyDataProvider::getStateResidencies() ends, and new - * container will be created in the async thread later. In this situation, we ignore - * delayed residency data and end the async thread. - */ - return 0; - } - - async->residencies->emplace(curEntity, stateResidencies); + residencies->emplace(curEntity, stateResidencies); } - - pthread_mutex_lock(async->lock); - pthread_cond_signal(async->cond); - pthread_mutex_unlock(async->lock); - - return 0; -} - -bool AocStateResidencyDataProvider::getStateResidencies( - std::unordered_map> *residencies) { - bool ret = true; - int condResult = 0; - pthread_t tid; - pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - std::unordered_map> stateResidencies; - struct timespec start, timeout; - struct async_data_t async = { - .cond = &cond, - .lock = &lock, - .residencies = &stateResidencies, - .providers = &mProviders - }; - - pthread_create(&tid, NULL, &getStateResidenciesAsync, (void*)&async); - - clock_gettime(CLOCK_REALTIME, &start); - - uint64_t expirationMillis = mTimeoutMillis * mStateCount; - timeout.tv_sec = start.tv_sec + expirationMillis / 1000; - uint64_t nsec = start.tv_nsec + (expirationMillis % 1000) * 1000000; - if (nsec < 1000000000) { - timeout.tv_nsec = nsec; - } else { - timeout.tv_sec += 1; - timeout.tv_nsec = nsec - 1000000000; - } - - pthread_mutex_lock(&lock); - condResult = pthread_cond_timedwait(&cond, &lock, &timeout); - pthread_mutex_unlock(&lock); - - if (condResult != 0) { - if (condResult == ETIMEDOUT) { - LOG(WARNING) << __func__ << " latency for AoC timeout: " << expirationMillis << " ms"; - } else { - LOG(ERROR) << "Failed to wait for the condition variable: " << condResult; - } - ret = false; - } else { - for (const auto &residency : stateResidencies) { - residencies->emplace(residency.first, residency.second); - } - } - return ret; } diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h index 150f335..5008912 100644 --- a/powerstats/include/AocStateResidencyDataProvider.h +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -27,8 +27,7 @@ namespace stats { class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { public: AocStateResidencyDataProvider(std::vector> ids, - std::vector> states, - const uint64_t timeoutMillis); + std::vector> states); ~AocStateResidencyDataProvider() = default; bool getStateResidencies( std::unordered_map> *residencies) override; @@ -37,12 +36,10 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv private: std::unordered_map> /* providers */> mProviders; - int32_t mStateCount; - uint64_t mTimeoutMillis; }; } // namespace stats } // namespace power } // namespace hardware } // namespace android -} // namespace aidl +} // namespace aidl \ No newline at end of file From df08a31b762c00220673003b1f46b4b4746637e1 Mon Sep 17 00:00:00 2001 From: Darren Hsu Date: Tue, 19 Apr 2022 08:40:05 +0800 Subject: [PATCH 8/9] powerstats: timeout mechanism for AoC data provider Reading data from an AoC sysfs node by getline takes 1 second. In total there are 17 AoC sysfs nodes that must be read. The worst case is taking 17 seconds long that is greater than dumpsys timeout. Therefore, we need the timeout mechanism to ignore the AoC power stats reporting when AoC latency exceeds the allowed time. Bug: 219630658 Test: dumpsys android.hardware.power.stats.IPowerStats/default Change-Id: I71a9e681780471f31141599c53bb516aef445add Signed-off-by: Darren Hsu --- powerstats/AocStateResidencyDataProvider.cpp | 98 +++++++++++++++++-- .../include/AocStateResidencyDataProvider.h | 7 +- 2 files changed, 96 insertions(+), 9 deletions(-) diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp index c64496d..574a23d 100644 --- a/powerstats/AocStateResidencyDataProvider.cpp +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -17,6 +17,8 @@ #include "AocStateResidencyDataProvider.h" #include +#include +#include namespace aidl { namespace android { @@ -24,12 +26,23 @@ namespace hardware { namespace power { namespace stats { +struct async_data_t { + pthread_cond_t *cond; + pthread_mutex_t *lock; + uint64_t timeoutMillis; + std::unordered_map> *residencies; + std::unordered_map>> *providers; +}; + AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> ids, std::vector> states) { + std::string>> ids, std::vector> states, + const uint64_t timeoutMillis) { // AoC stats are reported in ticks of 244.140625ns. The transform // function converts ticks to milliseconds. // 1000000 / 244.140625 = 4096. static const uint64_t AOC_CLK = 4096; + static const uint64_t TIMEOUT_MILLIS = 120; std::function aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; GenericStateResidencyDataProvider::StateResidencyConfig config = { .entryCountSupported = true, @@ -54,13 +67,17 @@ AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> *residencies) { +void *getStateResidenciesAsync(void *arg) { + struct timespec start, end; + struct async_data_t *async = (struct async_data_t*)arg; + uint64_t timeoutUs = async->timeoutMillis * 1000; + // States from the same power entity are merged. - bool ret = true; - for (const auto &providerList : mProviders) { + for (const auto &providerList : *async->providers) { int32_t stateId = 0; std::string curEntity = providerList.first; std::vector stateResidencies; @@ -68,7 +85,18 @@ bool AocStateResidencyDataProvider::getStateResidencies( // Iterate over each provider in the providerList, appending each of the states for (const auto &provider : providerList.second) { std::unordered_map> residency; - ret &= provider->getStateResidencies(&residency); + + clock_gettime(CLOCK_REALTIME, &start); + provider->getStateResidencies(&residency); + clock_gettime(CLOCK_REALTIME, &end); + uint64_t elapsedUs = + ((end.tv_sec - start.tv_sec) * 1000000) + ((end.tv_nsec - start.tv_nsec) / 1000); + + if (elapsedUs >= timeoutUs) { + LOG(WARNING) << "getStateResidencies latency for " << curEntity + << " exceeds time allowed: " << elapsedUs << " us"; + return 0; + } // Each provider should only return data for curEntity but checking anyway if (residency.find(curEntity) != residency.end()) { @@ -84,8 +112,64 @@ bool AocStateResidencyDataProvider::getStateResidencies( } } - residencies->emplace(curEntity, stateResidencies); + async->residencies->emplace(curEntity, stateResidencies); } + + pthread_mutex_lock(async->lock); + pthread_cond_signal(async->cond); + pthread_mutex_unlock(async->lock); + + return 0; +} + +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { + bool ret = true; + int condResult = 0; + pthread_t tid; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + std::unordered_map> stateResidencies; + struct timespec start, timeout; + struct async_data_t async = { + .cond = &cond, + .lock = &lock, + .timeoutMillis = mTimeoutMillis, + .residencies = &stateResidencies, + .providers = &mProviders + }; + + pthread_create(&tid, NULL, &getStateResidenciesAsync, (void*)&async); + + clock_gettime(CLOCK_REALTIME, &start); + + uint64_t expirationMillis = mTimeoutMillis * mStateCount; + timeout.tv_sec = start.tv_sec + expirationMillis / 1000; + uint64_t nsec = start.tv_nsec + (expirationMillis % 1000) * 1000000; + if (nsec < 1000000000) { + timeout.tv_nsec = nsec; + } else { + timeout.tv_sec += 1; + timeout.tv_nsec = nsec - 1000000000; + } + + pthread_mutex_lock(&lock); + condResult = pthread_cond_timedwait(&cond, &lock, &timeout); + pthread_mutex_unlock(&lock); + + if (condResult != 0) { + if (condResult == ETIMEDOUT) { + LOG(WARNING) << __func__ << " latency for AoC timeout: " << expirationMillis << " ms"; + } else { + LOG(ERROR) << "Failed to wait for the condition variable: " << condResult; + } + ret = false; + } else { + for (const auto &residency : stateResidencies) { + residencies->emplace(residency.first, residency.second); + } + } + return ret; } diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h index 5008912..150f335 100644 --- a/powerstats/include/AocStateResidencyDataProvider.h +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -27,7 +27,8 @@ namespace stats { class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { public: AocStateResidencyDataProvider(std::vector> ids, - std::vector> states); + std::vector> states, + const uint64_t timeoutMillis); ~AocStateResidencyDataProvider() = default; bool getStateResidencies( std::unordered_map> *residencies) override; @@ -36,10 +37,12 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv private: std::unordered_map> /* providers */> mProviders; + int32_t mStateCount; + uint64_t mTimeoutMillis; }; } // namespace stats } // namespace power } // namespace hardware } // namespace android -} // namespace aidl \ No newline at end of file +} // namespace aidl From 20b039192d90f6dcbce3905cfe108c5ba8205440 Mon Sep 17 00:00:00 2001 From: Kelly Rossmoyer Date: Sun, 24 Apr 2022 23:22:49 +0000 Subject: [PATCH 9/9] Revert "powerstats: timeout mechanism for AoC data provider" Revert submission 17800080-power-stats-aoc-timeout Reason for revert: Causing crashes due to improper thread sync Reverted Changes: I71a9e6817:powerstats: timeout mechanism for AoC data provide... I725c00745:powerstats: set time limit as timeout for AoC I5b290a53d:powerstats: set time limit as timeout for AoC Change-Id: I6844a141739f93154d10debc29c7565f92349d25 --- powerstats/AocStateResidencyDataProvider.cpp | 98 ++----------------- .../include/AocStateResidencyDataProvider.h | 7 +- 2 files changed, 9 insertions(+), 96 deletions(-) diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp index 574a23d..c64496d 100644 --- a/powerstats/AocStateResidencyDataProvider.cpp +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -17,8 +17,6 @@ #include "AocStateResidencyDataProvider.h" #include -#include -#include namespace aidl { namespace android { @@ -26,23 +24,12 @@ namespace hardware { namespace power { namespace stats { -struct async_data_t { - pthread_cond_t *cond; - pthread_mutex_t *lock; - uint64_t timeoutMillis; - std::unordered_map> *residencies; - std::unordered_map>> *providers; -}; - AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> ids, std::vector> states, - const uint64_t timeoutMillis) { + std::string>> ids, std::vector> states) { // AoC stats are reported in ticks of 244.140625ns. The transform // function converts ticks to milliseconds. // 1000000 / 244.140625 = 4096. static const uint64_t AOC_CLK = 4096; - static const uint64_t TIMEOUT_MILLIS = 120; std::function aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; GenericStateResidencyDataProvider::StateResidencyConfig config = { .entryCountSupported = true, @@ -67,17 +54,13 @@ AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vectortimeoutMillis * 1000; - +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { // States from the same power entity are merged. - for (const auto &providerList : *async->providers) { + bool ret = true; + for (const auto &providerList : mProviders) { int32_t stateId = 0; std::string curEntity = providerList.first; std::vector stateResidencies; @@ -85,18 +68,7 @@ void *getStateResidenciesAsync(void *arg) { // Iterate over each provider in the providerList, appending each of the states for (const auto &provider : providerList.second) { std::unordered_map> residency; - - clock_gettime(CLOCK_REALTIME, &start); - provider->getStateResidencies(&residency); - clock_gettime(CLOCK_REALTIME, &end); - uint64_t elapsedUs = - ((end.tv_sec - start.tv_sec) * 1000000) + ((end.tv_nsec - start.tv_nsec) / 1000); - - if (elapsedUs >= timeoutUs) { - LOG(WARNING) << "getStateResidencies latency for " << curEntity - << " exceeds time allowed: " << elapsedUs << " us"; - return 0; - } + ret &= provider->getStateResidencies(&residency); // Each provider should only return data for curEntity but checking anyway if (residency.find(curEntity) != residency.end()) { @@ -112,64 +84,8 @@ void *getStateResidenciesAsync(void *arg) { } } - async->residencies->emplace(curEntity, stateResidencies); + residencies->emplace(curEntity, stateResidencies); } - - pthread_mutex_lock(async->lock); - pthread_cond_signal(async->cond); - pthread_mutex_unlock(async->lock); - - return 0; -} - -bool AocStateResidencyDataProvider::getStateResidencies( - std::unordered_map> *residencies) { - bool ret = true; - int condResult = 0; - pthread_t tid; - pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - std::unordered_map> stateResidencies; - struct timespec start, timeout; - struct async_data_t async = { - .cond = &cond, - .lock = &lock, - .timeoutMillis = mTimeoutMillis, - .residencies = &stateResidencies, - .providers = &mProviders - }; - - pthread_create(&tid, NULL, &getStateResidenciesAsync, (void*)&async); - - clock_gettime(CLOCK_REALTIME, &start); - - uint64_t expirationMillis = mTimeoutMillis * mStateCount; - timeout.tv_sec = start.tv_sec + expirationMillis / 1000; - uint64_t nsec = start.tv_nsec + (expirationMillis % 1000) * 1000000; - if (nsec < 1000000000) { - timeout.tv_nsec = nsec; - } else { - timeout.tv_sec += 1; - timeout.tv_nsec = nsec - 1000000000; - } - - pthread_mutex_lock(&lock); - condResult = pthread_cond_timedwait(&cond, &lock, &timeout); - pthread_mutex_unlock(&lock); - - if (condResult != 0) { - if (condResult == ETIMEDOUT) { - LOG(WARNING) << __func__ << " latency for AoC timeout: " << expirationMillis << " ms"; - } else { - LOG(ERROR) << "Failed to wait for the condition variable: " << condResult; - } - ret = false; - } else { - for (const auto &residency : stateResidencies) { - residencies->emplace(residency.first, residency.second); - } - } - return ret; } diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h index 150f335..5008912 100644 --- a/powerstats/include/AocStateResidencyDataProvider.h +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -27,8 +27,7 @@ namespace stats { class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { public: AocStateResidencyDataProvider(std::vector> ids, - std::vector> states, - const uint64_t timeoutMillis); + std::vector> states); ~AocStateResidencyDataProvider() = default; bool getStateResidencies( std::unordered_map> *residencies) override; @@ -37,12 +36,10 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv private: std::unordered_map> /* providers */> mProviders; - int32_t mStateCount; - uint64_t mTimeoutMillis; }; } // namespace stats } // namespace power } // namespace hardware } // namespace android -} // namespace aidl +} // namespace aidl \ No newline at end of file