summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei Wang <wvw@google.com>2020-03-27 03:02:46 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-03-27 03:02:46 +0000
commitcebc313870e23d23fa190a935a36720088c58b69 (patch)
treebdd978cd8833c599b0408aa1af86021cb621e7b1
parentb50af6e4d89a10398f7241b22d58ef5c52edf10e (diff)
parent3776b53e3735239f8418a48340bb042081ab3154 (diff)
downloadextras-cebc313870e23d23fa190a935a36720088c58b69.tar.gz
Merge "Move libperfmgr into hardware/google/pixel" into rvc-dev
-rw-r--r--libperfmgr/.clang-format11
-rw-r--r--libperfmgr/Android.bp77
-rw-r--r--libperfmgr/CPPLINT.cfg2
-rw-r--r--libperfmgr/FileNode.cc118
-rw-r--r--libperfmgr/HintManager.cc392
-rw-r--r--libperfmgr/Node.cc97
-rw-r--r--libperfmgr/NodeLooperThread.cc147
-rw-r--r--libperfmgr/OWNERS3
-rw-r--r--libperfmgr/PropertyNode.cc80
-rw-r--r--libperfmgr/RequestGroup.cc84
-rw-r--r--libperfmgr/config_schema.json126
-rw-r--r--libperfmgr/include/perfmgr/FileNode.h56
-rw-r--r--libperfmgr/include/perfmgr/HintManager.h98
-rw-r--r--libperfmgr/include/perfmgr/Node.h92
-rw-r--r--libperfmgr/include/perfmgr/NodeLooperThread.h104
-rw-r--r--libperfmgr/include/perfmgr/PropertyNode.h48
-rw-r--r--libperfmgr/include/perfmgr/RequestGroup.h67
-rw-r--r--libperfmgr/tests/FileNodeTest.cc234
-rw-r--r--libperfmgr/tests/HintManagerTest.cc575
-rw-r--r--libperfmgr/tests/NodeLooperThreadTest.cc195
-rw-r--r--libperfmgr/tests/PropertyNodeTest.cc222
-rw-r--r--libperfmgr/tests/RequestGroupTest.cc164
-rw-r--r--libperfmgr/tools/ConfigVerifier.cc177
23 files changed, 0 insertions, 3169 deletions
diff --git a/libperfmgr/.clang-format b/libperfmgr/.clang-format
deleted file mode 100644
index 181b743d..00000000
--- a/libperfmgr/.clang-format
+++ /dev/null
@@ -1,11 +0,0 @@
-BasedOnStyle: Google
-AccessModifierOffset: -2
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 80
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-IndentWidth: 4
-PointerAlignment: Left
-TabWidth: 4
-UseTab: Never
-PenaltyExcessCharacter: 32
diff --git a/libperfmgr/Android.bp b/libperfmgr/Android.bp
deleted file mode 100644
index 168fa2c4..00000000
--- a/libperfmgr/Android.bp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (C) 2017 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.
-//
-
-cc_defaults {
- name: "libperfmgr_defaults",
- local_include_dirs: ["include"],
- shared_libs: [
- "libbase",
- "libutils",
- ],
- static_libs: [
- "libjsoncpp",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- tidy: true,
- tidy_checks: [
- "android-*",
- "cert-*",
- "clang-analyzer-security*",
- ],
- tidy_flags: [
- "-warnings-as-errors=android-*,clang-analyzer-security*,cert-*"
- ],
-}
-
-cc_library {
- name: "libperfmgr",
- vendor_available: true,
- defaults: ["libperfmgr_defaults"],
- export_include_dirs: ["include"],
- srcs: [
- "RequestGroup.cc",
- "Node.cc",
- "FileNode.cc",
- "PropertyNode.cc",
- "NodeLooperThread.cc",
- "HintManager.cc",
- ]
-}
-
-cc_test {
- name: "libperfmgr_test",
- defaults: ["libperfmgr_defaults"],
- static_libs: ["libperfmgr"],
- srcs: [
- "tests/RequestGroupTest.cc",
- "tests/FileNodeTest.cc",
- "tests/PropertyNodeTest.cc",
- "tests/NodeLooperThreadTest.cc",
- "tests/HintManagerTest.cc",
- ]
-}
-
-cc_binary {
- name: "perfmgr_config_verifier",
- defaults: ["libperfmgr_defaults"],
- static_libs: ["libperfmgr"],
- srcs: [
- "tools/ConfigVerifier.cc",
- ]
-}
diff --git a/libperfmgr/CPPLINT.cfg b/libperfmgr/CPPLINT.cfg
deleted file mode 100644
index 25e55c66..00000000
--- a/libperfmgr/CPPLINT.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-filter=-build/c++11,-build/include_order,-build/namespaces,-build/header_guard,-whitespace/indent,-whitespace/line_length
diff --git a/libperfmgr/FileNode.cc b/libperfmgr/FileNode.cc
deleted file mode 100644
index 4133f0a8..00000000
--- a/libperfmgr/FileNode.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "libperfmgr"
-
-#include "perfmgr/FileNode.h"
-
-#include <android-base/chrono_utils.h>
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
-namespace android {
-namespace perfmgr {
-
-FileNode::FileNode(std::string name, std::string node_path,
- std::vector<RequestGroup> req_sorted,
- std::size_t default_val_index, bool reset_on_init,
- bool hold_fd)
- : Node(std::move(name), std::move(node_path), std::move(req_sorted),
- default_val_index, reset_on_init),
- hold_fd_(hold_fd),
- warn_timeout_(
- android::base::GetBoolProperty("ro.debuggable", false) ? 5ms : 50ms) {
-}
-
-std::chrono::milliseconds FileNode::Update(bool log_error) {
- std::size_t value_index = default_val_index_;
- std::chrono::milliseconds expire_time = std::chrono::milliseconds::max();
-
- // Find the highest outstanding request's expire time
- for (std::size_t i = 0; i < req_sorted_.size(); i++) {
- if (req_sorted_[i].GetExpireTime(&expire_time)) {
- value_index = i;
- break;
- }
- }
-
- // Update node only if request index changes
- if (value_index != current_val_index_ || reset_on_init_) {
- const std::string& req_value =
- req_sorted_[value_index].GetRequestValue();
-
- android::base::Timer t;
- fd_.reset(TEMP_FAILURE_RETRY(
- open(node_path_.c_str(), O_WRONLY | O_CLOEXEC | O_TRUNC)));
-
- if (fd_ == -1 || !android::base::WriteStringToFd(req_value, fd_)) {
- if (log_error) {
- LOG(WARNING) << "Failed to write to node: " << node_path_
- << " with value: " << req_value << ", fd: " << fd_;
- }
- // Retry in 500ms or sooner
- expire_time = std::min(expire_time, std::chrono::milliseconds(500));
- } else {
- // For regular file system, we need fsync
- fsync(fd_);
- // Some dev node requires file to remain open during the entire hint
- // duration e.g. /dev/cpu_dma_latency, so fd_ is intentionally kept
- // open during any requested value other than default one. If
- // request a default value, node will write the value and then
- // release the fd.
- if ((!hold_fd_) || value_index == default_val_index_) {
- fd_.reset();
- }
- auto duration = t.duration();
- if (duration > warn_timeout_) {
- LOG(WARNING) << "Slow writing to file: '" << node_path_
- << "' with value: '" << req_value
- << "' took: " << duration.count() << " ms";
- }
- // Update current index only when succeed
- current_val_index_ = value_index;
- reset_on_init_ = false;
- }
- }
- return expire_time;
-}
-
-bool FileNode::GetHoldFd() const {
- return hold_fd_;
-}
-
-void FileNode::DumpToFd(int fd) const {
- std::string node_value;
- if (!android::base::ReadFileToString(node_path_, &node_value)) {
- LOG(ERROR) << "Failed to read node path: " << node_path_;
- }
- node_value = android::base::Trim(node_value);
- std::string buf(android::base::StringPrintf(
- "%s\t%s\t%zu\t%s\n", name_.c_str(), node_path_.c_str(),
- current_val_index_, node_value.c_str()));
- if (!android::base::WriteStringToFd(buf, fd)) {
- LOG(ERROR) << "Failed to dump fd: " << fd;
- }
- for (std::size_t i = 0; i < req_sorted_.size(); i++) {
- req_sorted_[i].DumpToFd(
- fd, android::base::StringPrintf("\t\tReq%zu:\t", i));
- }
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/HintManager.cc b/libperfmgr/HintManager.cc
deleted file mode 100644
index 1b546ae6..00000000
--- a/libperfmgr/HintManager.cc
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "libperfmgr"
-
-#include "perfmgr/HintManager.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <json/reader.h>
-#include <json/value.h>
-
-#include <algorithm>
-#include <set>
-
-#include "perfmgr/FileNode.h"
-#include "perfmgr/PropertyNode.h"
-
-namespace android {
-namespace perfmgr {
-
-bool HintManager::ValidateHint(const std::string& hint_type) const {
- if (nm_.get() == nullptr) {
- LOG(ERROR) << "NodeLooperThread not present";
- return false;
- }
- return IsHintSupported(hint_type);
-}
-
-bool HintManager::IsHintSupported(const std::string& hint_type) const {
- if (actions_.find(hint_type) == actions_.end()) {
- LOG(INFO) << "Hint type not present in actions: " << hint_type;
- return false;
- }
- return true;
-}
-
-bool HintManager::DoHint(const std::string& hint_type) {
- LOG(VERBOSE) << "Do Powerhint: " << hint_type;
- return ValidateHint(hint_type)
- ? nm_->Request(actions_.at(hint_type), hint_type)
- : false;
-}
-
-bool HintManager::DoHint(const std::string& hint_type,
- std::chrono::milliseconds timeout_ms_override) {
- LOG(VERBOSE) << "Do Powerhint: " << hint_type << " for "
- << timeout_ms_override.count() << "ms";
- if (!ValidateHint(hint_type)) {
- return false;
- }
- std::vector<NodeAction> actions_override = actions_.at(hint_type);
- for (auto& action : actions_override) {
- action.timeout_ms = timeout_ms_override;
- }
- return nm_->Request(actions_override, hint_type);
-}
-
-bool HintManager::EndHint(const std::string& hint_type) {
- LOG(VERBOSE) << "End Powerhint: " << hint_type;
- return ValidateHint(hint_type)
- ? nm_->Cancel(actions_.at(hint_type), hint_type)
- : false;
-}
-
-bool HintManager::IsRunning() const {
- return (nm_.get() == nullptr) ? false : nm_->isRunning();
-}
-
-std::vector<std::string> HintManager::GetHints() const {
- std::vector<std::string> hints;
- for (auto const& action : actions_) {
- hints.push_back(action.first);
- }
- return hints;
-}
-
-void HintManager::DumpToFd(int fd) {
- std::string header(
- "========== Begin perfmgr nodes ==========\n"
- "Node Name\t"
- "Node Path\t"
- "Current Index\t"
- "Current Value\n");
- if (!android::base::WriteStringToFd(header, fd)) {
- LOG(ERROR) << "Failed to dump fd: " << fd;
- }
- nm_->DumpToFd(fd);
- std::string footer("========== End perfmgr nodes ==========\n");
- if (!android::base::WriteStringToFd(footer, fd)) {
- LOG(ERROR) << "Failed to dump fd: " << fd;
- }
- fsync(fd);
-}
-
-bool HintManager::Start() {
- return nm_->Start();
-}
-
-std::unique_ptr<HintManager> HintManager::GetFromJSON(
- const std::string& config_path, bool start) {
- std::string json_doc;
-
- if (!android::base::ReadFileToString(config_path, &json_doc)) {
- LOG(ERROR) << "Failed to read JSON config from " << config_path;
- return nullptr;
- }
-
- std::vector<std::unique_ptr<Node>> nodes = ParseNodes(json_doc);
- if (nodes.empty()) {
- LOG(ERROR) << "Failed to parse Nodes section from " << config_path;
- return nullptr;
- }
- std::map<std::string, std::vector<NodeAction>> actions =
- HintManager::ParseActions(json_doc, nodes);
-
- if (actions.empty()) {
- LOG(ERROR) << "Failed to parse Actions section from " << config_path;
- return nullptr;
- }
-
- sp<NodeLooperThread> nm = new NodeLooperThread(std::move(nodes));
- std::unique_ptr<HintManager> hm =
- std::make_unique<HintManager>(std::move(nm), actions);
-
- LOG(INFO) << "Initialized HintManager from JSON config: " << config_path;
-
- if (start) {
- hm->Start();
- }
- return hm;
-}
-
-std::vector<std::unique_ptr<Node>> HintManager::ParseNodes(
- const std::string& json_doc) {
- // function starts
- std::vector<std::unique_ptr<Node>> nodes_parsed;
- std::set<std::string> nodes_name_parsed;
- std::set<std::string> nodes_path_parsed;
- Json::Value root;
- Json::Reader reader;
-
- if (!reader.parse(json_doc, root)) {
- LOG(ERROR) << "Failed to parse JSON config";
- return nodes_parsed;
- }
-
- Json::Value nodes = root["Nodes"];
- for (Json::Value::ArrayIndex i = 0; i < nodes.size(); ++i) {
- std::string name = nodes[i]["Name"].asString();
- LOG(VERBOSE) << "Node[" << i << "]'s Name: " << name;
- if (name.empty()) {
- LOG(ERROR) << "Failed to read "
- << "Node[" << i << "]'s Name";
- nodes_parsed.clear();
- return nodes_parsed;
- }
-
- auto result = nodes_name_parsed.insert(name);
- if (!result.second) {
- LOG(ERROR) << "Duplicate Node[" << i << "]'s Name";
- nodes_parsed.clear();
- return nodes_parsed;
- }
-
- std::string path = nodes[i]["Path"].asString();
- LOG(VERBOSE) << "Node[" << i << "]'s Path: " << path;
- if (path.empty()) {
- LOG(ERROR) << "Failed to read "
- << "Node[" << i << "]'s Path";
- nodes_parsed.clear();
- return nodes_parsed;
- }
-
- result = nodes_path_parsed.insert(path);
- if (!result.second) {
- LOG(ERROR) << "Duplicate Node[" << i << "]'s Path";
- nodes_parsed.clear();
- return nodes_parsed;
- }
-
- bool is_file = true;
- std::string node_type = nodes[i]["Type"].asString();
- LOG(VERBOSE) << "Node[" << i << "]'s Type: " << node_type;
- if (node_type.empty()) {
- LOG(ERROR) << "Failed to read "
- << "Node[" << i << "]'s Type, set to 'File' as default";
- } else if (node_type == "File") {
- is_file = true;
- } else if (node_type == "Property") {
- is_file = false;
- } else {
- LOG(ERROR) << "Invalid Node[" << i
- << "]'s Type: only File and Property supported.";
- nodes_parsed.clear();
- return nodes_parsed;
- }
-
- std::vector<RequestGroup> values_parsed;
- std::set<std::string> values_set_parsed;
- Json::Value values = nodes[i]["Values"];
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- std::string value = values[j].asString();
- LOG(VERBOSE) << "Node[" << i << "]'s Value[" << j << "]: " << value;
- auto result = values_set_parsed.insert(value);
- if (!result.second) {
- LOG(ERROR) << "Duplicate value parsed in Node[" << i
- << "]'s Value[" << j << "]";
- nodes_parsed.clear();
- return nodes_parsed;
- }
- if (is_file && value.empty()) {
- LOG(ERROR) << "Failed to read Node[" << i << "]'s Value[" << j
- << "]";
- nodes_parsed.clear();
- return nodes_parsed;
- }
- values_parsed.emplace_back(value);
- }
- if (values_parsed.size() < 1) {
- LOG(ERROR) << "Failed to read Node[" << i << "]'s Values";
- nodes_parsed.clear();
- return nodes_parsed;
- }
-
- Json::UInt64 default_index = values_parsed.size() - 1;
- if (nodes[i]["DefaultIndex"].empty() ||
- !nodes[i]["DefaultIndex"].isUInt64()) {
- LOG(INFO) << "Failed to read Node[" << i
- << "]'s DefaultIndex, set to last index: "
- << default_index;
- } else {
- default_index = nodes[i]["DefaultIndex"].asUInt64();
- }
- if (default_index > values_parsed.size() - 1) {
- default_index = values_parsed.size() - 1;
- LOG(ERROR) << "Node[" << i
- << "]'s DefaultIndex out of bound, max value index: "
- << default_index;
- nodes_parsed.clear();
- return nodes_parsed;
- }
- LOG(VERBOSE) << "Node[" << i << "]'s DefaultIndex: " << default_index;
-
- bool reset = false;
- if (nodes[i]["ResetOnInit"].empty() ||
- !nodes[i]["ResetOnInit"].isBool()) {
- LOG(INFO) << "Failed to read Node[" << i
- << "]'s ResetOnInit, set to 'false'";
- } else {
- reset = nodes[i]["ResetOnInit"].asBool();
- }
- LOG(VERBOSE) << "Node[" << i << "]'s ResetOnInit: " << std::boolalpha
- << reset << std::noboolalpha;
-
- if (is_file) {
- bool hold_fd = false;
- if (nodes[i]["HoldFd"].empty() || !nodes[i]["HoldFd"].isBool()) {
- LOG(INFO) << "Failed to read Node[" << i
- << "]'s HoldFd, set to 'false'";
- } else {
- hold_fd = nodes[i]["HoldFd"].asBool();
- }
- LOG(VERBOSE) << "Node[" << i << "]'s HoldFd: " << std::boolalpha
- << hold_fd << std::noboolalpha;
-
- nodes_parsed.emplace_back(std::make_unique<FileNode>(
- name, path, values_parsed,
- static_cast<std::size_t>(default_index), reset, hold_fd));
- } else {
- nodes_parsed.emplace_back(std::make_unique<PropertyNode>(
- name, path, values_parsed,
- static_cast<std::size_t>(default_index), reset));
- }
- }
- LOG(INFO) << nodes_parsed.size() << " Nodes parsed successfully";
- return nodes_parsed;
-}
-
-std::map<std::string, std::vector<NodeAction>> HintManager::ParseActions(
- const std::string& json_doc,
- const std::vector<std::unique_ptr<Node>>& nodes) {
- // function starts
- std::map<std::string, std::vector<NodeAction>> actions_parsed;
- Json::Value root;
- Json::Reader reader;
-
- if (!reader.parse(json_doc, root)) {
- LOG(ERROR) << "Failed to parse JSON config";
- return actions_parsed;
- }
-
- Json::Value actions = root["Actions"];
- std::size_t total_parsed = 0;
-
- std::map<std::string, std::size_t> nodes_index;
- for (std::size_t i = 0; i < nodes.size(); ++i) {
- nodes_index[nodes[i]->GetName()] = i;
- }
-
- for (Json::Value::ArrayIndex i = 0; i < actions.size(); ++i) {
- const std::string& hint_type = actions[i]["PowerHint"].asString();
- LOG(VERBOSE) << "Action[" << i << "]'s PowerHint: " << hint_type;
- if (hint_type.empty()) {
- LOG(ERROR) << "Failed to read "
- << "Action[" << i << "]'s PowerHint";
- actions_parsed.clear();
- return actions_parsed;
- }
-
- std::string node_name = actions[i]["Node"].asString();
- LOG(VERBOSE) << "Action[" << i << "]'s Node: " << node_name;
- std::size_t node_index;
-
- if (nodes_index.find(node_name) == nodes_index.end()) {
- LOG(ERROR) << "Failed to find "
- << "Action[" << i << "]'s Node from Nodes section: ["
- << node_name << "]";
- actions_parsed.clear();
- return actions_parsed;
- }
- node_index = nodes_index[node_name];
-
- std::string value_name = actions[i]["Value"].asString();
- LOG(VERBOSE) << "Action[" << i << "]'s Value: " << value_name;
- std::size_t value_index = 0;
-
- if (!nodes[node_index]->GetValueIndex(value_name, &value_index)) {
- LOG(ERROR) << "Failed to read Action[" << i << "]'s Value";
- LOG(ERROR) << "Action[" << i << "]'s Value " << value_name
- << " is not defined in Node[" << node_name << "]";
- actions_parsed.clear();
- return actions_parsed;
- }
- LOG(VERBOSE) << "Action[" << i << "]'s ValueIndex: " << value_index;
-
- Json::UInt64 duration = 0;
- if (actions[i]["Duration"].empty() ||
- !actions[i]["Duration"].isUInt64()) {
- LOG(ERROR) << "Failed to read Action[" << i << "]'s Duration";
- actions_parsed.clear();
- return actions_parsed;
- } else {
- duration = actions[i]["Duration"].asUInt64();
- }
- LOG(VERBOSE) << "Action[" << i << "]'s Duration: " << duration;
-
- if (actions_parsed.find(hint_type) == actions_parsed.end()) {
- actions_parsed[hint_type] = std::vector<NodeAction>{
- {node_index, value_index, std::chrono::milliseconds(duration)}};
- } else {
- for (const auto& action : actions_parsed[hint_type]) {
- if (action.node_index == node_index) {
- LOG(ERROR)
- << "Action[" << i
- << "]'s NodeIndex is duplicated with another Action";
- actions_parsed.clear();
- return actions_parsed;
- }
- }
- actions_parsed[hint_type].emplace_back(
- node_index, value_index, std::chrono::milliseconds(duration));
- }
-
- ++total_parsed;
- }
-
- LOG(INFO) << total_parsed << " Actions parsed successfully";
-
- for (const auto& action : actions_parsed) {
- LOG(INFO) << "PowerHint " << action.first << " has "
- << action.second.size() << " actions parsed";
- }
-
- return actions_parsed;
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/Node.cc b/libperfmgr/Node.cc
deleted file mode 100644
index eb180e65..00000000
--- a/libperfmgr/Node.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "libperfmgr"
-
-#include "perfmgr/Node.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
-namespace android {
-namespace perfmgr {
-
-Node::Node(std::string name, std::string node_path,
- std::vector<RequestGroup> req_sorted, std::size_t default_val_index,
- bool reset_on_init)
- : name_(std::move(name)),
- node_path_(std::move(node_path)),
- req_sorted_(std::move(req_sorted)),
- default_val_index_(default_val_index),
- reset_on_init_(reset_on_init),
- current_val_index_(default_val_index) {}
-
-bool Node::AddRequest(std::size_t value_index, const std::string& hint_type,
- ReqTime end_time) {
- if (value_index >= req_sorted_.size()) {
- LOG(ERROR) << "Value index out of bound: " << value_index
- << " ,size: " << req_sorted_.size();
- return false;
- }
- // Add/Update request to the new end_time for the specific hint_type
- req_sorted_[value_index].AddRequest(hint_type, end_time);
- return true;
-}
-
-bool Node::RemoveRequest(const std::string& hint_type) {
- bool ret = false;
- // Remove all requests for the specific hint_type
- for (auto& value : req_sorted_) {
- ret = value.RemoveRequest(hint_type) || ret;
- }
- return ret;
-}
-
-const std::string& Node::GetName() const {
- return name_;
-}
-
-const std::string& Node::GetPath() const {
- return node_path_;
-}
-
-bool Node::GetValueIndex(const std::string& value, std::size_t* index) const {
- bool found = false;
- for (std::size_t i = 0; i < req_sorted_.size(); i++) {
- if (req_sorted_[i].GetRequestValue() == value) {
- *index = i;
- found = true;
- break;
- }
- }
- return found;
-}
-
-std::size_t Node::GetDefaultIndex() const {
- return default_val_index_;
-}
-
-bool Node::GetResetOnInit() const {
- return reset_on_init_;
-}
-
-std::vector<std::string> Node::GetValues() const {
- std::vector<std::string> values;
- for (const auto& value : req_sorted_) {
- values.emplace_back(value.GetRequestValue());
- }
- return values;
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/NodeLooperThread.cc b/libperfmgr/NodeLooperThread.cc
deleted file mode 100644
index 747cd319..00000000
--- a/libperfmgr/NodeLooperThread.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "libperfmgr"
-
-#include "perfmgr/NodeLooperThread.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-
-namespace android {
-namespace perfmgr {
-
-bool NodeLooperThread::Request(const std::vector<NodeAction>& actions,
- const std::string& hint_type) {
- if (::android::Thread::exitPending()) {
- LOG(WARNING) << "NodeLooperThread is exiting";
- return false;
- }
- if (!::android::Thread::isRunning()) {
- LOG(WARNING) << "NodeLooperThread is not running, request " << hint_type;
- }
-
- bool ret = true;
- ::android::AutoMutex _l(lock_);
- for (const auto& a : actions) {
- if (a.node_index >= nodes_.size()) {
- LOG(ERROR) << "Node index out of bound: " << a.node_index
- << " ,size: " << nodes_.size();
- ret = false;
- } else {
- // End time set to steady time point max
- ReqTime end_time = ReqTime::max();
- // Timeout is non-zero
- if (a.timeout_ms != std::chrono::milliseconds::zero()) {
- auto now = std::chrono::steady_clock::now();
- // Overflow protection in case timeout_ms is too big to overflow
- // time point which is unsigned integer
- if (std::chrono::duration_cast<std::chrono::milliseconds>(
- ReqTime::max() - now) > a.timeout_ms) {
- end_time = now + a.timeout_ms;
- }
- }
- ret = nodes_[a.node_index]->AddRequest(a.value_index, hint_type,
- end_time) &&
- ret;
- }
- }
- wake_cond_.signal();
- return ret;
-}
-
-bool NodeLooperThread::Cancel(const std::vector<NodeAction>& actions,
- const std::string& hint_type) {
- if (::android::Thread::exitPending()) {
- LOG(WARNING) << "NodeLooperThread is exiting";
- return false;
- }
- if (!::android::Thread::isRunning()) {
- LOG(WARNING) << "NodeLooperThread is not running, cancel " << hint_type;
- }
-
- bool ret = true;
- ::android::AutoMutex _l(lock_);
- for (const auto& a : actions) {
- if (a.node_index >= nodes_.size()) {
- LOG(ERROR) << "Node index out of bound: " << a.node_index
- << " ,size: " << nodes_.size();
- ret = false;
- } else {
- nodes_[a.node_index]->RemoveRequest(hint_type);
- }
- }
- wake_cond_.signal();
- return ret;
-}
-
-void NodeLooperThread::DumpToFd(int fd) {
- ::android::AutoMutex _l(lock_);
- for (auto& n : nodes_) {
- n->DumpToFd(fd);
- }
-}
-
-bool NodeLooperThread::threadLoop() {
- ::android::AutoMutex _l(lock_);
- std::chrono::milliseconds timeout_ms = kMaxUpdatePeriod;
-
- // Update 2 passes: some node may have dependency in other node
- // e.g. update cpufreq min to VAL while cpufreq max still set to
- // a value lower than VAL, is expected to fail in first pass
- for (auto& n : nodes_) {
- n->Update(false);
- }
- for (auto& n : nodes_) {
- timeout_ms = std::min(n->Update(true), timeout_ms);
- }
-
- nsecs_t sleep_timeout_ns = std::numeric_limits<nsecs_t>::max();
- if (timeout_ms.count() < sleep_timeout_ns / 1000 / 1000) {
- sleep_timeout_ns = timeout_ms.count() * 1000 * 1000;
- }
- // VERBOSE level won't print by default in user/userdebug build
- LOG(VERBOSE) << "NodeLooperThread will wait for " << sleep_timeout_ns
- << "ns";
- wake_cond_.waitRelative(lock_, sleep_timeout_ns);
- return true;
-}
-
-bool NodeLooperThread::Start() {
- auto ret = this->run("NodeLooperThread", PRIORITY_HIGHEST);
- if (ret != NO_ERROR) {
- LOG(ERROR) << "NodeLooperThread start failed: " << ret;
- } else {
- LOG(INFO) << "NodeLooperThread started";
- }
- return ret == NO_ERROR;
-}
-
-void NodeLooperThread::Stop() {
- if (::android::Thread::isRunning()) {
- LOG(INFO) << "NodeLooperThread stopping";
- {
- ::android::AutoMutex _l(lock_);
- wake_cond_.signal();
- ::android::Thread::requestExit();
- }
- ::android::Thread::join();
- LOG(INFO) << "NodeLooperThread stopped";
- }
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/OWNERS b/libperfmgr/OWNERS
deleted file mode 100644
index b21a9312..00000000
--- a/libperfmgr/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-wvw@google.com
-joaodias@google.com
-paillon@google.com
diff --git a/libperfmgr/PropertyNode.cc b/libperfmgr/PropertyNode.cc
deleted file mode 100644
index c8067117..00000000
--- a/libperfmgr/PropertyNode.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "libperfmgr"
-
-#include "perfmgr/PropertyNode.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
-namespace android {
-namespace perfmgr {
-
-PropertyNode::PropertyNode(std::string name, std::string node_path,
- std::vector<RequestGroup> req_sorted,
- std::size_t default_val_index, bool reset_on_init)
- : Node(std::move(name), std::move(node_path), std::move(req_sorted),
- default_val_index, reset_on_init) {}
-
-std::chrono::milliseconds PropertyNode::Update(bool) {
- std::size_t value_index = default_val_index_;
- std::chrono::milliseconds expire_time = std::chrono::milliseconds::max();
-
- // Find the highest outstanding request's expire time
- for (std::size_t i = 0; i < req_sorted_.size(); i++) {
- if (req_sorted_[i].GetExpireTime(&expire_time)) {
- value_index = i;
- break;
- }
- }
-
- // Update node only if request index changes
- if (value_index != current_val_index_ || reset_on_init_) {
- const std::string& req_value =
- req_sorted_[value_index].GetRequestValue();
-
- if (!android::base::SetProperty(node_path_, req_value)) {
- LOG(WARNING) << "Failed to set property to : " << node_path_
- << " with value: " << req_value;
- } else {
- // Update current index only when succeed
- current_val_index_ = value_index;
- reset_on_init_ = false;
- }
- }
- return expire_time;
-}
-
-void PropertyNode::DumpToFd(int fd) const {
- std::string node_value = android::base::GetProperty(node_path_, "");
- std::string buf(android::base::StringPrintf(
- "%s\t%s\t%zu\t%s\n", name_.c_str(), node_path_.c_str(),
- current_val_index_, node_value.c_str()));
- if (!android::base::WriteStringToFd(buf, fd)) {
- LOG(ERROR) << "Failed to dump fd: " << fd;
- }
- for (std::size_t i = 0; i < req_sorted_.size(); i++) {
- req_sorted_[i].DumpToFd(
- fd, android::base::StringPrintf("\t\tReq%zu:\t", i));
- }
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/RequestGroup.cc b/libperfmgr/RequestGroup.cc
deleted file mode 100644
index 4fedd33a..00000000
--- a/libperfmgr/RequestGroup.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "libperfmgr"
-
-#include "perfmgr/RequestGroup.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-
-#include <sstream>
-
-namespace android {
-namespace perfmgr {
-
-bool RequestGroup::AddRequest(const std::string& hint_type, ReqTime end_time) {
- if (request_map_.find(hint_type) == request_map_.end()) {
- request_map_.emplace(hint_type, end_time);
- return true;
- } else {
- if (request_map_[hint_type] < end_time) {
- request_map_[hint_type] = end_time;
- }
- return false;
- }
-}
-
-bool RequestGroup::RemoveRequest(const std::string& hint_type) {
- return request_map_.erase(hint_type);
-}
-
-const std::string& RequestGroup::GetRequestValue() const {
- return request_value_;
-}
-
-bool RequestGroup::GetExpireTime(std::chrono::milliseconds* expire_time) {
- ReqTime now = std::chrono::steady_clock::now();
- *expire_time = std::chrono::milliseconds::max();
-
- bool active = false;
- for (auto it = request_map_.begin(); it != request_map_.end();) {
- auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
- it->second - now);
- if (duration <= std::chrono::milliseconds::zero()) {
- it = request_map_.erase(it);
- } else {
- *expire_time = std::min(duration, *expire_time);
- active = true;
- ++it;
- }
- }
- return active;
-}
-
-void RequestGroup::DumpToFd(int fd, const std::string& prefix) const {
- std::ostringstream dump_buf;
- ReqTime now = std::chrono::steady_clock::now();
- for (auto it = request_map_.begin(); it != request_map_.end(); it++) {
- auto remaining_duration =
- std::chrono::duration_cast<std::chrono::milliseconds>(it->second -
- now);
- dump_buf << prefix << it->first << "\t" << remaining_duration.count()
- << "\t" << request_value_ << "\n";
- }
- if (!android::base::WriteStringToFd(dump_buf.str(), fd)) {
- LOG(ERROR) << "Failed to dump fd: " << fd;
- }
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/config_schema.json b/libperfmgr/config_schema.json
deleted file mode 100644
index 712af500..00000000
--- a/libperfmgr/config_schema.json
+++ /dev/null
@@ -1,126 +0,0 @@
-{
- "definitions": {},
- "$schema": "http://json-schema.org/draft-06/schema#",
- "type": "object",
- "id": "config_schema.json",
- "required": [
- "Nodes",
- "Actions"
- ],
- "properties": {
- "Nodes": {
- "type": "array",
- "id": "/properties/Nodes",
- "minItems": 1,
- "uniqueItems": true,
- "items": {
- "type": "object",
- "id": "/properties/Nodes/items",
- "required": [
- "Name",
- "Path",
- "Values"
- ],
- "properties": {
- "Name": {
- "type": "string",
- "id": "/properties/Nodes/items/properties/Name",
- "title": "The Name Schema.",
- "description": "The name of the node.",
- "minLength": 1
- },
- "Path": {
- "type": "string",
- "id": "/properties/Nodes/items/properties/Path",
- "title": "The Path Schema.",
- "description": "For File type node, it is filesystem path of the file; for Property type node, it is the key of the property.",
- "minLength": 1
- },
- "Values": {
- "type": "array",
- "id": "/properties/Nodes/items/properties/Values",
- "minItems": 1,
- "uniqueItems": true,
- "items": {
- "type": "string",
- "id": "/properties/Nodes/items/properties/Values/items",
- "title": "The Values Schema.",
- "description": "The Values array lists all possible values that can be set in the Actions section, and the list of values is sorted based on their priority, with the highest priority first."
- }
- },
- "DefaultIndex": {
- "type": "integer",
- "id": "/properties/Nodes/items/properties/DefaultIndex",
- "title": "The Default Index Schema.",
- "description": "The default index of the node, if not present, it will be set to max index of Values.",
- "minimum": 0
- },
- "ResetOnInit": {
- "type": "boolean",
- "id": "/properties/Nodes/items/properties/ResetOnInit",
- "title": "The Reset On Init Schema.",
- "description": "Flag if node will be set to default value on initialization; if not present, it will be set to false."
- },
- "Type": {
- "type": "string",
- "id": "/properties/Nodes/items/properties/Type",
- "title": "The type Schema.",
- "description": "Type of Node (File or Property), if not present, it will be set to File."
- },
- "HoldFd": {
- "type": "boolean",
- "id": "/properties/Nodes/items/properties/HoldFd",
- "title": "The Hold Fd Schema.",
- "description": "Flag if node will hold the file descriptor on non-default values; if not present, it will be set to false. This is only honoured for File type node."
- }
- }
- }
- },
- "Actions": {
- "type": "array",
- "id": "/properties/Actions",
- "minItems": 1,
- "uniqueItems": true,
- "items": {
- "type": "object",
- "id": "/properties/Actions/items",
- "required": [
- "PowerHint",
- "Node",
- "ValueIndex",
- "Duration"
- ],
- "properties": {
- "PowerHint": {
- "type": "string",
- "id": "/properties/Actions/items/properties/PowerHint",
- "title": "The PowerHint Schema.",
- "description": "The PowerHint name of the action.",
- "minLength": 1
- },
- "Node": {
- "type": "string",
- "id": "/properties/Actions/items/properties/Node",
- "title": "The Node Schema.",
- "description": "The Node name of the action, which is defined in Nodes.",
- "minLength": 1
- },
- "Value": {
- "type": "string",
- "id": "/properties/Actions/items/properties/Value",
- "title": "The Value Index Schema.",
- "description": "The value of action, which is defined in Nodes.",
- "minLength": 1
- },
- "Duration": {
- "type": "integer",
- "id": "/properties/Actions/items/properties/Duration",
- "title": "The Duration Schema.",
- "description": "The number of milliseconds that this action will be active (zero means forever).",
- "minimum": 0
- }
- }
- }
- }
- }
-}
diff --git a/libperfmgr/include/perfmgr/FileNode.h b/libperfmgr/include/perfmgr/FileNode.h
deleted file mode 100644
index b8f2db6e..00000000
--- a/libperfmgr/include/perfmgr/FileNode.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LIBPERFMGR_FILENODE_H_
-#define ANDROID_LIBPERFMGR_FILENODE_H_
-
-#include <android-base/unique_fd.h>
-
-#include <cstddef>
-#include <string>
-#include <vector>
-
-#include "perfmgr/Node.h"
-
-namespace android {
-namespace perfmgr {
-
-// FileNode represents file
-class FileNode : public Node {
- public:
- FileNode(std::string name, std::string node_path,
- std::vector<RequestGroup> req_sorted, std::size_t default_val_index,
- bool reset_on_init, bool hold_fd = false);
-
- std::chrono::milliseconds Update(bool log_error) override;
-
- bool GetHoldFd() const;
-
- void DumpToFd(int fd) const override;
-
- private:
- FileNode(const Node& other) = delete;
- FileNode& operator=(Node const&) = delete;
-
- const bool hold_fd_;
- const std::chrono::milliseconds warn_timeout_;
- android::base::unique_fd fd_;
-};
-
-} // namespace perfmgr
-} // namespace android
-
-#endif // ANDROID_LIBPERFMGR_FILENODE_H_
diff --git a/libperfmgr/include/perfmgr/HintManager.h b/libperfmgr/include/perfmgr/HintManager.h
deleted file mode 100644
index bfb96fde..00000000
--- a/libperfmgr/include/perfmgr/HintManager.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LIBPERFMGR_HINTMANAGER_H_
-#define ANDROID_LIBPERFMGR_HINTMANAGER_H_
-
-#include <cstddef>
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "perfmgr/NodeLooperThread.h"
-
-namespace android {
-namespace perfmgr {
-
-// HintManager is the external interface of the library to be used by PowerHAL
-// to do power hints with sysfs nodes. HintManager maintains a representation of
-// the actions that are parsed from the configuration file as a mapping from a
-// PowerHint to the set of actions that are performed for that PowerHint.
-class HintManager {
- public:
- HintManager(sp<NodeLooperThread> nm,
- const std::map<std::string, std::vector<NodeAction>>& actions)
- : nm_(std::move(nm)), actions_(actions) {}
- ~HintManager() {
- if (nm_.get() != nullptr) nm_->Stop();
- }
-
- // Return true if the sysfs manager thread is running.
- bool IsRunning() const;
-
- // Do hint based on hint_type which defined as PowerHint in the actions
- // section of the JSON config. Return true with valid hint_type and also
- // NodeLooperThread::Request succeeds; otherwise return false.
- bool DoHint(const std::string& hint_type);
-
- // Do hint with the override time for all actions defined for the given
- // hint_type. Return true with valid hint_type and also
- // NodeLooperThread::Request succeeds; otherwise return false.
- bool DoHint(const std::string& hint_type,
- std::chrono::milliseconds timeout_ms_override);
-
- // End hint early. Return true with valid hint_type and also
- // NodeLooperThread::Cancel succeeds; otherwise return false.
- bool EndHint(const std::string& hint_type);
-
- // Query if given hint supported.
- bool IsHintSupported(const std::string& hint_type) const;
-
- // Static method to construct HintManager from the JSON config file.
- static std::unique_ptr<HintManager> GetFromJSON(
- const std::string& config_path, bool start = true);
-
- // Return available hints managed by HintManager
- std::vector<std::string> GetHints() const;
-
- // Dump internal status to fd
- void DumpToFd(int fd);
-
- // Start thread loop
- bool Start();
-
- protected:
- static std::vector<std::unique_ptr<Node>> ParseNodes(
- const std::string& json_doc);
- static std::map<std::string, std::vector<NodeAction>> ParseActions(
- const std::string& json_doc,
- const std::vector<std::unique_ptr<Node>>& nodes);
-
- private:
- HintManager(HintManager const&) = delete;
- void operator=(HintManager const&) = delete;
- bool ValidateHint(const std::string& hint_type) const;
-
- sp<NodeLooperThread> nm_;
- const std::map<std::string, std::vector<NodeAction>> actions_;
-};
-
-} // namespace perfmgr
-} // namespace android
-
-#endif // ANDROID_LIBPERFMGR_HINTMANAGER_H_
diff --git a/libperfmgr/include/perfmgr/Node.h b/libperfmgr/include/perfmgr/Node.h
deleted file mode 100644
index e0db0777..00000000
--- a/libperfmgr/include/perfmgr/Node.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LIBPERFMGR_NODE_H_
-#define ANDROID_LIBPERFMGR_NODE_H_
-
-#include <android-base/unique_fd.h>
-
-#include <cstddef>
-#include <string>
-#include <vector>
-
-#include "perfmgr/RequestGroup.h"
-
-namespace android {
-namespace perfmgr {
-
-// The Node class provides an interface for adding and cancelling powerhint
-// requests, as well as checking the next time that an in-progress powerhint
-// request will expire. There are additional methods for getting the Node’s name
-// and the index of a value, which may be used for initialization, debugging,
-// and request management. The core of the Node class is a vector of
-// RequestGroups named req_sorted_, which is used to track the in-progress
-// requests on the node. Each entry in the vector corresponds to a possible
-// value for the node, in priority order. For example, the first entry in the
-// vector for the cpu0 cluster represents the in-progress requests to boost the
-// cluster’s frequency to the highest available value. The next entry represents
-// the in-progress requests to boost the cluster’s frequency to the next highest
-// value. For each value, there may be multiple requests because different
-// powerhints may request the same value, and the requests may have different
-// expiration times. All of the in-progress powerhints for a given value are
-// collected in a RequestGroup. Node class is not thread safe so it needs
-// protection from caller e.g. NodeLooperThread.
-class Node {
- public:
- virtual ~Node() {}
-
- // Return true if successfully add a request
- bool AddRequest(std::size_t value_index, const std::string& hint_type,
- ReqTime end_time);
-
- // Return true if successfully remove a request
- bool RemoveRequest(const std::string& hint_type);
-
- // Return the nearest expire time of active requests; return
- // std::chrono::milliseconds::max() if no active request on Node; update
- // node's controlled file node value and the current value index based on
- // active request.
- virtual std::chrono::milliseconds Update(bool log_error) = 0;
-
- const std::string& GetName() const;
- const std::string& GetPath() const;
- std::vector<std::string> GetValues() const;
- std::size_t GetDefaultIndex() const;
- bool GetResetOnInit() const;
- bool GetValueIndex(const std::string& value, std::size_t* index) const;
- virtual void DumpToFd(int fd) const = 0;
-
- protected:
- Node(std::string name, std::string node_path,
- std::vector<RequestGroup> req_sorted, std::size_t default_val_index,
- bool reset_on_init);
- Node(const Node& other) = delete;
- Node& operator=(Node const&) = delete;
-
- const std::string name_;
- const std::string node_path_;
- // request vector, one entry per possible value, sorted by priority.
- std::vector<RequestGroup> req_sorted_;
- const std::size_t default_val_index_;
- // node will be explicitly initialized when first time called Update().
- bool reset_on_init_;
- std::size_t current_val_index_;
-};
-
-} // namespace perfmgr
-} // namespace android
-
-#endif // ANDROID_LIBPERFMGR_NODE_H_
diff --git a/libperfmgr/include/perfmgr/NodeLooperThread.h b/libperfmgr/include/perfmgr/NodeLooperThread.h
deleted file mode 100644
index eba0fc7f..00000000
--- a/libperfmgr/include/perfmgr/NodeLooperThread.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_
-#define ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_
-
-#include <utils/Thread.h>
-
-#include <cstddef>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "perfmgr/Node.h"
-
-namespace android {
-namespace perfmgr {
-
-// The NodeAction specifies the sysfs node, the value to be assigned, and the
-// timeout for this action:
-struct NodeAction {
- NodeAction(std::size_t node_index, std::size_t value_index,
- std::chrono::milliseconds timeout_ms)
- : node_index(node_index),
- value_index(value_index),
- timeout_ms(timeout_ms) {}
- std::size_t node_index;
- std::size_t value_index;
- std::chrono::milliseconds timeout_ms; // 0ms for forever
-};
-
-// The NodeLooperThread is responsible for managing each of the sysfs nodes
-// specified in the configuration. At initialization, the NodeLooperThrea holds
-// a vector containing the nodes defined in the configuration. The NodeManager
-// gets powerhint requests and cancellations from the HintManager, maintains
-// state about the current set of powerhint requests on each sysfs node, and
-// decides how to apply the requests. The NodeLooperThread contains a ThreadLoop
-// to maintain the sysfs nodes, and that thread is woken up both to handle
-// powerhint requests and when the timeout expires for an in-progress powerhint.
-class NodeLooperThread : public ::android::Thread {
- public:
- explicit NodeLooperThread(std::vector<std::unique_ptr<Node>> nodes)
- : Thread(false), nodes_(std::move(nodes)) {}
- virtual ~NodeLooperThread() { Stop(); }
-
- // Need call Stop() as the threadloop will hold a strong pointer
- // itself and wait for Condition fired or timeout (60s) before
- // the out looper can call deconstructor to Stop() thread
- void Stop();
-
- // Return true when successfully adds request from actions for the hint_type
- // in each individual node. Return false if any of the actions has either
- // invalid node index or value index.
- bool Request(const std::vector<NodeAction>& actions,
- const std::string& hint_type);
- // Return when successfully cancels request from actions for the hint_type
- // in each individual node. Return false if any of the actions has invalid
- // node index.
- bool Cancel(const std::vector<NodeAction>& actions,
- const std::string& hint_type);
-
- // Dump all nodes to fd
- void DumpToFd(int fd);
-
- // Return true when successfully started the looper thread
- bool Start();
-
- private:
- NodeLooperThread(NodeLooperThread const&) = delete;
- void operator=(NodeLooperThread const&) = delete;
- bool threadLoop() override;
-
- static constexpr auto kMaxUpdatePeriod = std::chrono::milliseconds::max();
-
- std::vector<std::unique_ptr<Node>> nodes_; // parsed from Config
-
- // conditional variable from C++ standard library can be affected by wall
- // time change as it is using CLOCK_REAL (b/35756266). The component should
- // not be impacted by wall time, thus need use Android specific Condition
- // class for waking up threadloop.
- ::android::Condition wake_cond_;
-
- // lock to protect nodes_
- ::android::Mutex lock_;
-};
-
-} // namespace perfmgr
-} // namespace android
-
-#endif // ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_
diff --git a/libperfmgr/include/perfmgr/PropertyNode.h b/libperfmgr/include/perfmgr/PropertyNode.h
deleted file mode 100644
index feaf85fa..00000000
--- a/libperfmgr/include/perfmgr/PropertyNode.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LIBPERFMGR_PROPERTYNODE_H_
-#define ANDROID_LIBPERFMGR_PROPERTYNODE_H_
-
-#include <cstddef>
-#include <string>
-#include <vector>
-
-#include "perfmgr/Node.h"
-
-namespace android {
-namespace perfmgr {
-
-// PropertyNode represents managed system properties
-class PropertyNode : public Node {
- public:
- PropertyNode(std::string name, std::string node_path,
- std::vector<RequestGroup> req_sorted,
- std::size_t default_val_index, bool reset_on_init);
-
- std::chrono::milliseconds Update(bool log_error) override;
-
- void DumpToFd(int fd) const override;
-
- private:
- PropertyNode(const Node& other) = delete;
- PropertyNode& operator=(Node const&) = delete;
-};
-
-} // namespace perfmgr
-} // namespace android
-
-#endif // ANDROID_LIBPERFMGR_PROPERTYNODE_H_
diff --git a/libperfmgr/include/perfmgr/RequestGroup.h b/libperfmgr/include/perfmgr/RequestGroup.h
deleted file mode 100644
index 698a8216..00000000
--- a/libperfmgr/include/perfmgr/RequestGroup.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LIBPERFMGR_REQUESTGROUP_H_
-#define ANDROID_LIBPERFMGR_REQUESTGROUP_H_
-
-#include <chrono>
-#include <map>
-#include <string>
-#include <utility>
-
-namespace android {
-namespace perfmgr {
-
-using ReqTime = std::chrono::time_point<std::chrono::steady_clock>;
-
-// The RequestGroup type represents the set of requests for a given value on a
-// particular sysfs node, and the interface is simple: there is a function to
-// add requests, a function to remove requests, and a function to check for the
-// next expiration time if there is an outstanding request, and a function to
-// check the requested value. There may only be one request per PowerHint, so
-// the representation is simple: a map from PowerHint to the expiration time for
-// that hint.
-class RequestGroup {
- public:
- RequestGroup(std::string request_value) // NOLINT(runtime/explicit)
- : request_value_(std::move(request_value)) {}
-
- // Remove expired request in the map and return true when request_map_ is
- // not empty, false when request_map_ is empty; also update expire_time with
- // nearest timeout in request_map_ or std::chrono::milliseconds::max() when
- // request_map_ is empty.
- bool GetExpireTime(std::chrono::milliseconds* expire_time);
- // Return the request value.
- const std::string& GetRequestValue() const;
- // Return true for adding request, false for extending expire time of
- // existing active request on given hint_type.
- bool AddRequest(const std::string& hint_type, ReqTime end_time);
- // Return true for removing request, false if request is not active on given
- // hint_type. If request exits and the new end_time is less than the active
- // time, expire time will not be updated; also returns false.
- bool RemoveRequest(const std::string& hint_type);
- // Dump internal status to fd
- void DumpToFd(int fd, const std::string& prefix) const;
-
- private:
- const std::string request_value_;
- std::map<std::string, ReqTime> request_map_;
-};
-
-} // namespace perfmgr
-} // namespace android
-
-#endif // ANDROID_LIBPERFMGR_REQUESTGROUP_H_
diff --git a/libperfmgr/tests/FileNodeTest.cc b/libperfmgr/tests/FileNodeTest.cc
deleted file mode 100644
index d163be80..00000000
--- a/libperfmgr/tests/FileNodeTest.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <thread>
-
-#include "perfmgr/FileNode.h"
-
-namespace android {
-namespace perfmgr {
-
-using namespace std::chrono_literals;
-
-constexpr double kTIMING_TOLERANCE_MS = std::chrono::milliseconds(25).count();
-constexpr auto kSLEEP_TOLERANCE_MS = 2ms;
-
-static inline void _VerifyPathValue(const std::string& path,
- const std::string& value) {
- std::string s;
- EXPECT_TRUE(android::base::ReadFileToString(path, &s)) << strerror(errno);
- EXPECT_EQ(value, s);
-}
-
-// Test init with no default value
-TEST(FileNodeTest, NoInitDefaultTest) {
- TemporaryFile tf;
- FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1, false);
- t.Update(false);
- _VerifyPathValue(tf.path, "");
-}
-
-// Test init with default value
-TEST(FileNodeTest, InitDefaultTest) {
- TemporaryFile tf;
- FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1, true);
- t.Update(false);
- _VerifyPathValue(tf.path, "value1");
- TemporaryFile tf2;
- FileNode t2("t2", tf2.path, {{"value0"}, {"value1"}, {"value2"}}, 0, true);
- t2.Update(false);
- _VerifyPathValue(tf2.path, "value0");
-}
-
-// Test DumpToFd
-TEST(FileNodeTest, DumpToFdTest) {
- TemporaryFile tf;
- FileNode t("test_dump", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1,
- true);
- t.Update(false);
- TemporaryFile dumptf;
- t.DumpToFd(dumptf.fd);
- fsync(dumptf.fd);
- std::string buf(
- android::base::StringPrintf("test_dump\t%s\t1\tvalue1\n", tf.path));
- _VerifyPathValue(dumptf.path, buf);
-}
-
-// Test GetValueIndex
-TEST(FileNodeTest, GetValueIndexTest) {
- TemporaryFile tf;
- FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1, false);
- std::size_t index = 0;
- EXPECT_TRUE(t.GetValueIndex("value2", &index));
- EXPECT_EQ(2u, index);
- index = 1234;
- EXPECT_FALSE(t.GetValueIndex("NON_EXIST", &index));
- EXPECT_EQ(1234u, index);
-}
-
-// Test GetValues
-TEST(FileNodeTest, GetValuesTest) {
- TemporaryFile tf;
- FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1, false);
- std::vector values = t.GetValues();
- EXPECT_EQ(3u, values.size());
- EXPECT_EQ("value0", values[0]);
- EXPECT_EQ("value1", values[1]);
- EXPECT_EQ("value2", values[2]);
-}
-
-// Test get more properties
-TEST(FileNodeTest, GetPropertiesTest) {
- std::string test_name = "TESTREQ_1";
- std::string test_path = "TEST_PATH";
- FileNode t(test_name, test_path, {}, 0, false, true);
- EXPECT_EQ(test_name, t.GetName());
- EXPECT_EQ(test_path, t.GetPath());
- EXPECT_EQ(0u, t.GetValues().size());
- EXPECT_EQ(0u, t.GetDefaultIndex());
- EXPECT_FALSE(t.GetResetOnInit());
- EXPECT_TRUE(t.GetHoldFd());
-}
-
-// Test add request fail and retry
-TEST(FileNodeTest, AddRequestTestFail) {
- FileNode t("t", "/sys/android/nonexist_node_test",
- {{"value0"}, {"value1"}, {"value2"}}, 2, true);
- auto start = std::chrono::steady_clock::now();
- EXPECT_TRUE(t.AddRequest(1, "INTERACTION", start + 200ms));
- std::chrono::milliseconds expire_time = t.Update(true);
- // Add request @ value1
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 higher prio than value1
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 2000ms));
- expire_time = t.Update(true);
- // Retry in 500 ms
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
-}
-
-// Test add request
-TEST(FileNodeTest, AddRequestTest) {
- TemporaryFile tf;
- FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 2, true);
- auto start = std::chrono::steady_clock::now();
- EXPECT_TRUE(t.AddRequest(1, "INTERACTION", start + 500ms));
- std::chrono::milliseconds expire_time = t.Update(true);
- // Add request @ value1
- _VerifyPathValue(tf.path, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 higher prio than value1
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 200ms));
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Let high prio request timeout, now only request @ value1 active
- std::this_thread::sleep_for(expire_time + kSLEEP_TOLERANCE_MS);
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(300).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Let all requests timeout, now default value2
- std::this_thread::sleep_for(expire_time + kSLEEP_TOLERANCE_MS);
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value2");
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
-}
-
-// Test remove request
-TEST(FileNodeTest, RemoveRequestTest) {
- TemporaryFile tf;
- FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 2, true);
- auto start = std::chrono::steady_clock::now();
- EXPECT_TRUE(t.AddRequest(1, "INTERACTION", start + 500ms));
- std::chrono::milliseconds expire_time = t.Update(true);
- // Add request @ value1
- _VerifyPathValue(tf.path, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 higher prio than value1
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 200ms));
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove high prio request, now only request @ value1 active
- t.RemoveRequest("LAUNCH");
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove request, now default value2
- t.RemoveRequest("INTERACTION");
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value2");
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
-}
-
-// Test add request with holding fd
-TEST(FileNodeTest, AddRequestTestHoldFdOverride) {
- TemporaryFile tf;
- FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 2, true,
- true);
- EXPECT_TRUE(t.GetHoldFd());
- auto start = std::chrono::steady_clock::now();
- EXPECT_TRUE(t.AddRequest(1, "INTERACTION", start + 500ms));
- std::chrono::milliseconds expire_time = t.Update(true);
- // Add request @ value1
- _VerifyPathValue(tf.path, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 higher prio than value1
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 200ms));
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 shorter
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 100ms));
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 longer
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 300ms));
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(300).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove high prio request, now only request @ value1 active
- t.RemoveRequest("LAUNCH");
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove request, now default value2
- t.RemoveRequest("INTERACTION");
- expire_time = t.Update(true);
- _VerifyPathValue(tf.path, "value2");
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/tests/HintManagerTest.cc b/libperfmgr/tests/HintManagerTest.cc
deleted file mode 100644
index a4d31884..00000000
--- a/libperfmgr/tests/HintManagerTest.cc
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <thread>
-
-#include "perfmgr/FileNode.h"
-#include "perfmgr/HintManager.h"
-#include "perfmgr/PropertyNode.h"
-
-namespace android {
-namespace perfmgr {
-
-using namespace std::chrono_literals;
-
-constexpr auto kSLEEP_TOLERANCE_MS = 50ms;
-
-// JSON_CONFIG
-// {
-// "Nodes": [
-// {
-// "Name": "CPUCluster0MinFreq",
-// "Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq",
-// "Values": [
-// "1512000",
-// "1134000",
-// "384000"
-// ],
-// "DefaultIndex": 2,
-// "ResetOnInit": true
-// },
-// {
-// "Name": "CPUCluster1MinFreq",
-// "Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq",
-// "Values": [
-// "1512000",
-// "1134000",
-// "384000"
-// ],
-// "HoldFd": true
-// },
-// {
-// "Name": "ModeProperty",
-// "Path": "vendor.pwhal.mode",
-// "Values": [
-// "HIGH",
-// "LOW",
-// "NONE"
-// ],
-// "Type": "Property"
-// }
-// ],
-// "Actions": [
-// {
-// "PowerHint": "INTERACTION",
-// "Node": "CPUCluster1MinFreq",
-// "Value": "1134000",
-// "Duration": 800
-// },
-// {
-// "PowerHint": "INTERACTION",
-// "Node": "ModeProperty",
-// "Value": "LOW",
-// "Duration": 800
-// },
-// {
-// "PowerHint": "LAUNCH",
-// "Node": "CPUCluster0MinFreq",
-// "Value": "1134000",
-// "Duration": 500
-// },
-// {
-// "PowerHint": "LAUNCH",
-// "Node": "ModeProperty",
-// "Value": "HIGH",
-// "Duration": 500
-// },
-// {
-// "PowerHint": "LAUNCH",
-// "Node": "CPUCluster1MinFreq",
-// "Value": "1512000",
-// "Duration": 2000
-// }
-// ]
-// }
-constexpr char kJSON_RAW[] =
- "{\"Nodes\":[{\"Name\":\"CPUCluster0MinFreq\",\"Path\":\"/sys/devices/"
- "system/cpu/cpu0/cpufreq/"
- "scaling_min_freq\",\"Values\":[\"1512000\",\"1134000\",\"384000\"],"
- "\"DefaultIndex\":2,\"ResetOnInit\":true},{\"Name\":\"CPUCluster1MinFreq\","
- "\"Path\":\"/sys/devices/system/cpu/cpu4/cpufreq/"
- "scaling_min_freq\",\"Values\":[\"1512000\",\"1134000\",\"384000\"],"
- "\"HoldFd\":true},{\"Name\":\"ModeProperty\",\"Path\":\"vendor.pwhal."
- "mode\",\"Values\":[\"HIGH\",\"LOW\",\"NONE\"],\"Type\":\"Property\"}],"
- "\"Actions\":[{\"PowerHint\":\"INTERACTION\",\"Node\":"
- "\"CPUCluster1MinFreq\",\"Value\":\"1134000\",\"Duration\":800},{"
- "\"PowerHint\":\"INTERACTION\",\"Node\":\"ModeProperty\",\"Value\":\"LOW\","
- "\"Duration\":800},{\"PowerHint\":\"LAUNCH\",\"Node\":"
- "\"CPUCluster0MinFreq\",\"Value\":\"1134000\",\"Duration\":500},{"
- "\"PowerHint\":\"LAUNCH\",\"Node\":\"ModeProperty\",\"Value\":\"HIGH\","
- "\"Duration\":500},{\"PowerHint\":\"LAUNCH\",\"Node\":"
- "\"CPUCluster1MinFreq\",\"Value\":\"1512000\",\"Duration\":2000}]}";
-
-class HintManagerTest : public ::testing::Test, public HintManager {
- protected:
- HintManagerTest()
- : HintManager(nullptr,
- std::map<std::string, std::vector<NodeAction>>{}) {
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
- prop_ = "vendor.pwhal.mode";
- }
-
- virtual void SetUp() {
- // Set up 3 dummy nodes
- std::unique_ptr<TemporaryFile> tf = std::make_unique<TemporaryFile>();
- nodes_.emplace_back(new FileNode(
- "n0", tf->path, {{"n0_value0"}, {"n0_value1"}, {"n0_value2"}}, 2,
- false));
- files_.emplace_back(std::move(tf));
- tf = std::make_unique<TemporaryFile>();
- nodes_.emplace_back(new FileNode(
- "n1", tf->path, {{"n1_value0"}, {"n1_value1"}, {"n1_value2"}}, 2,
- true));
- files_.emplace_back(std::move(tf));
- nodes_.emplace_back(new PropertyNode(
- "n2", prop_, {{"n2_value0"}, {"n2_value1"}, {"n2_value2"}}, 2,
- true));
- nm_ = new NodeLooperThread(std::move(nodes_));
- // Set up dummy actions
- // "INTERACTION"
- // Node0, value1, 800ms
- // Node1, value1, forever
- // Node2, value1, 800ms
- // "LAUNCH"
- // Node0, value0, forever
- // Node1, value0, 400ms
- // Node2, value0, 400ms
- actions_ = std::map<std::string, std::vector<NodeAction>>{
- {"INTERACTION", {{0, 1, 800ms}, {1, 1, 0ms}, {2, 1, 800ms}}},
- {"LAUNCH", {{0, 0, 0ms}, {1, 0, 400ms}, {2, 0, 400ms}}}};
-
- // Prepare dummy files to replace the nodes' path in example json_doc
- files_.emplace_back(std::make_unique<TemporaryFile>());
- files_.emplace_back(std::make_unique<TemporaryFile>());
- // replace file path
- json_doc_ = kJSON_RAW;
- std::string from =
- "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), files_[0 + 2]->path);
- from = "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq";
- start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), files_[1 + 2]->path);
- EXPECT_TRUE(android::base::SetProperty(prop_, ""))
- << "failed to clear property";
- }
-
- virtual void TearDown() {
- actions_.clear();
- nodes_.clear();
- files_.clear();
- nm_ = nullptr;
- }
- sp<NodeLooperThread> nm_;
- std::map<std::string, std::vector<NodeAction>> actions_;
- std::vector<std::unique_ptr<Node>> nodes_;
- std::vector<std::unique_ptr<TemporaryFile>> files_;
- std::string json_doc_;
- std::string prop_;
-};
-
-static inline void _VerifyPropertyValue(const std::string& path,
- const std::string& value) {
- std::string s = android::base::GetProperty(path, "");
- EXPECT_EQ(value, s);
-}
-
-static inline void _VerifyPathValue(const std::string& path,
- const std::string& value) {
- std::string s;
- EXPECT_TRUE(android::base::ReadFileToString(path, &s)) << strerror(errno);
- EXPECT_EQ(value, s);
-}
-
-// Test GetHints
-TEST_F(HintManagerTest, GetHintsTest) {
- HintManager hm(nm_, actions_);
- EXPECT_TRUE(hm.Start());
- std::vector<std::string> hints = hm.GetHints();
- EXPECT_TRUE(hm.IsRunning());
- EXPECT_EQ(2u, hints.size());
- EXPECT_NE(std::find(hints.begin(), hints.end(), "INTERACTION"), hints.end());
- EXPECT_NE(std::find(hints.begin(), hints.end(), "LAUNCH"), hints.end());
-}
-
-// Test initialization of default values
-TEST_F(HintManagerTest, HintInitDefaultTest) {
- HintManager hm(nm_, actions_);
- EXPECT_TRUE(hm.Start());
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- EXPECT_TRUE(hm.IsRunning());
- _VerifyPathValue(files_[0]->path, "");
- _VerifyPathValue(files_[1]->path, "n1_value2");
- _VerifyPropertyValue(prop_, "n2_value2");
-}
-
-// Test IsHintSupported
-TEST_F(HintManagerTest, HintSupportedTest) {
- HintManager hm(nm_, actions_);
- EXPECT_TRUE(hm.IsHintSupported("INTERACTION"));
- EXPECT_TRUE(hm.IsHintSupported("LAUNCH"));
- EXPECT_FALSE(hm.IsHintSupported("NO_SUCH_HINT"));
-}
-
-// Test DumpToFd
-TEST_F(HintManagerTest, DumpToFdTest) {
- HintManager hm(nm_, actions_);
- TemporaryFile dumptf;
- hm.DumpToFd(dumptf.fd);
- fsync(dumptf.fd);
- std::ostringstream dump_buf;
- dump_buf << "========== Begin perfmgr nodes ==========\nNode Name\tNode "
- "Path\tCurrent Index\tCurrent Value\nn0\t"
- << files_[0]->path << "\t2\t\nn1\t" << files_[1]->path
- << "\t2\t\nn2\tvendor.pwhal.mode\t2\t\n========== End perfmgr "
- "nodes ==========\n";
- _VerifyPathValue(dumptf.path, dump_buf.str());
- TemporaryFile dumptf_started;
- EXPECT_TRUE(hm.Start());
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- EXPECT_TRUE(hm.IsRunning());
- hm.DumpToFd(dumptf_started.fd);
- fsync(dumptf_started.fd);
- dump_buf.str("");
- dump_buf.clear();
- dump_buf << "========== Begin perfmgr nodes ==========\nNode Name\tNode "
- "Path\tCurrent Index\tCurrent Value\nn0\t"
- << files_[0]->path << "\t2\t\nn1\t" << files_[1]->path
- << "\t2\tn1_value2\nn2\tvendor.pwhal.mode\t2\tn2_value2\n========="
- "= End perfmgr nodes ==========\n";
- _VerifyPathValue(dumptf_started.path, dump_buf.str());
-}
-
-// Test hint/cancel/expire with dummy actions
-TEST_F(HintManagerTest, HintTest) {
- HintManager hm(nm_, actions_);
- EXPECT_TRUE(hm.Start());
- EXPECT_TRUE(hm.IsRunning());
- EXPECT_TRUE(hm.DoHint("INTERACTION"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value1");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- _VerifyPropertyValue(prop_, "n2_value1");
- // this won't change the expire time of INTERACTION hint
- EXPECT_TRUE(hm.DoHint("INTERACTION", 200ms));
- // now place new hint
- EXPECT_TRUE(hm.DoHint("LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value0");
- _VerifyPropertyValue(prop_, "n2_value0");
- EXPECT_TRUE(hm.DoHint("LAUNCH", 500ms));
- // "LAUNCH" node1 not expired
- std::this_thread::sleep_for(400ms);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value0");
- _VerifyPropertyValue(prop_, "n2_value0");
- // "LAUNCH" node1 expired
- std::this_thread::sleep_for(100ms + kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- _VerifyPropertyValue(prop_, "n2_value1");
- EXPECT_TRUE(hm.EndHint("LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- // "LAUNCH" canceled
- _VerifyPathValue(files_[0]->path, "n0_value1");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- _VerifyPropertyValue(prop_, "n2_value1");
- std::this_thread::sleep_for(200ms);
- // "INTERACTION" node0 expired
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- _VerifyPropertyValue(prop_, "n2_value2");
- EXPECT_TRUE(hm.EndHint("INTERACTION"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- // "INTERACTION" canceled
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value2");
- _VerifyPropertyValue(prop_, "n2_value2");
-}
-
-// Test parsing nodes
-TEST_F(HintManagerTest, ParseNodesTest) {
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(3u, nodes.size());
- EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName());
- EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName());
- EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath());
- EXPECT_EQ(files_[1 + 2]->path, nodes[1]->GetPath());
- EXPECT_EQ("1512000", nodes[0]->GetValues()[0]);
- EXPECT_EQ("1134000", nodes[0]->GetValues()[1]);
- EXPECT_EQ("384000", nodes[0]->GetValues()[2]);
- EXPECT_EQ("1512000", nodes[1]->GetValues()[0]);
- EXPECT_EQ("1134000", nodes[1]->GetValues()[1]);
- EXPECT_EQ("384000", nodes[1]->GetValues()[2]);
- EXPECT_EQ(2u, nodes[0]->GetDefaultIndex());
- EXPECT_EQ(2u, nodes[1]->GetDefaultIndex());
- EXPECT_TRUE(nodes[0]->GetResetOnInit());
- EXPECT_FALSE(nodes[1]->GetResetOnInit());
- // no dynamic_cast intentionally in Android
- EXPECT_FALSE(reinterpret_cast<FileNode*>(nodes[0].get())->GetHoldFd());
- EXPECT_TRUE(reinterpret_cast<FileNode*>(nodes[1].get())->GetHoldFd());
- EXPECT_EQ("ModeProperty", nodes[2]->GetName());
- EXPECT_EQ(prop_, nodes[2]->GetPath());
- EXPECT_EQ("HIGH", nodes[2]->GetValues()[0]);
- EXPECT_EQ("LOW", nodes[2]->GetValues()[1]);
- EXPECT_EQ("NONE", nodes[2]->GetValues()[2]);
- EXPECT_EQ(2u, nodes[2]->GetDefaultIndex());
- EXPECT_FALSE(nodes[2]->GetResetOnInit());
-}
-
-// Test parsing nodes with duplicate name
-TEST_F(HintManagerTest, ParseNodesDuplicateNameTest) {
- std::string from = "CPUCluster0MinFreq";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), "CPUCluster1MinFreq");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(0u, nodes.size());
-}
-
-TEST_F(HintManagerTest, ParsePropertyNodesDuplicatNameTest) {
- std::string from = "ModeProperty";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), "CPUCluster1MinFreq");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(0u, nodes.size());
-}
-
-// Test parsing nodes with duplicate path
-TEST_F(HintManagerTest, ParseNodesDuplicatePathTest) {
- std::string from = files_[0 + 2]->path;
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), files_[1 + 2]->path);
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(0u, nodes.size());
-}
-
-// Test parsing file node with duplicate value
-TEST_F(HintManagerTest, ParseFileNodesDuplicateValueTest) {
- std::string from = "1512000";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), "1134000");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(0u, nodes.size());
-}
-
-// Test parsing property node with duplicate value
-TEST_F(HintManagerTest, ParsePropertyNodesDuplicateValueTest) {
- std::string from = "HIGH";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), "LOW");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(0u, nodes.size());
-}
-
-// Test parsing file node with empty value
-TEST_F(HintManagerTest, ParseFileNodesEmptyValueTest) {
- std::string from = "384000";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), "");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(0u, nodes.size());
-}
-
-// Test parsing property node with empty value
-TEST_F(HintManagerTest, ParsePropertyNodesEmptyValueTest) {
- std::string from = "LOW";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), "");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(3u, nodes.size());
- EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName());
- EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName());
- EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath());
- EXPECT_EQ(files_[1 + 2]->path, nodes[1]->GetPath());
- EXPECT_EQ("1512000", nodes[0]->GetValues()[0]);
- EXPECT_EQ("1134000", nodes[0]->GetValues()[1]);
- EXPECT_EQ("384000", nodes[0]->GetValues()[2]);
- EXPECT_EQ("1512000", nodes[1]->GetValues()[0]);
- EXPECT_EQ("1134000", nodes[1]->GetValues()[1]);
- EXPECT_EQ("384000", nodes[1]->GetValues()[2]);
- EXPECT_EQ(2u, nodes[0]->GetDefaultIndex());
- EXPECT_EQ(2u, nodes[1]->GetDefaultIndex());
- EXPECT_TRUE(nodes[0]->GetResetOnInit());
- EXPECT_FALSE(nodes[1]->GetResetOnInit());
- // no dynamic_cast intentionally in Android
- EXPECT_FALSE(reinterpret_cast<FileNode*>(nodes[0].get())->GetHoldFd());
- EXPECT_TRUE(reinterpret_cast<FileNode*>(nodes[1].get())->GetHoldFd());
- EXPECT_EQ("ModeProperty", nodes[2]->GetName());
- EXPECT_EQ(prop_, nodes[2]->GetPath());
- EXPECT_EQ("HIGH", nodes[2]->GetValues()[0]);
- EXPECT_EQ("", nodes[2]->GetValues()[1]);
- EXPECT_EQ("NONE", nodes[2]->GetValues()[2]);
- EXPECT_EQ(2u, nodes[2]->GetDefaultIndex());
- EXPECT_FALSE(nodes[2]->GetResetOnInit());
-}
-
-// Test parsing invalid json for nodes
-TEST_F(HintManagerTest, ParseBadFileNodesTest) {
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes("invalid json");
- EXPECT_EQ(0u, nodes.size());
- nodes = HintManager::ParseNodes(
- "{\"devices\":{\"15\":[\"armeabi-v7a\"],\"16\":[\"armeabi-v7a\"],"
- "\"26\":[\"armeabi-v7a\",\"arm64-v8a\",\"x86\",\"x86_64\"]}}");
- EXPECT_EQ(0u, nodes.size());
-}
-
-// Test parsing actions
-TEST_F(HintManagerTest, ParseActionsTest) {
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- std::map<std::string, std::vector<NodeAction>> actions =
- HintManager::ParseActions(json_doc_, nodes);
- EXPECT_EQ(2u, actions.size());
-
- EXPECT_EQ(2u, actions["INTERACTION"].size());
- EXPECT_EQ(1u, actions["INTERACTION"][0].node_index);
- EXPECT_EQ(1u, actions["INTERACTION"][0].value_index);
- EXPECT_EQ(std::chrono::milliseconds(800).count(),
- actions["INTERACTION"][0].timeout_ms.count());
-
- EXPECT_EQ(2u, actions["INTERACTION"][1].node_index);
- EXPECT_EQ(1u, actions["INTERACTION"][1].value_index);
- EXPECT_EQ(std::chrono::milliseconds(800).count(),
- actions["INTERACTION"][1].timeout_ms.count());
-
- EXPECT_EQ(3u, actions["LAUNCH"].size());
-
- EXPECT_EQ(0u, actions["LAUNCH"][0].node_index);
- EXPECT_EQ(1u, actions["LAUNCH"][0].value_index);
- EXPECT_EQ(std::chrono::milliseconds(500).count(),
- actions["LAUNCH"][0].timeout_ms.count());
-
- EXPECT_EQ(2u, actions["LAUNCH"][1].node_index);
- EXPECT_EQ(0u, actions["LAUNCH"][1].value_index);
- EXPECT_EQ(std::chrono::milliseconds(500).count(),
- actions["LAUNCH"][1].timeout_ms.count());
-
- EXPECT_EQ(1u, actions["LAUNCH"][2].node_index);
- EXPECT_EQ(0u, actions["LAUNCH"][2].value_index);
- EXPECT_EQ(std::chrono::milliseconds(2000).count(),
- actions["LAUNCH"][2].timeout_ms.count());
-}
-
-// Test parsing actions with duplicate File node
-TEST_F(HintManagerTest, ParseActionDuplicateFileNodeTest) {
- std::string from = "\"Node\":\"CPUCluster0MinFreq\"";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(),
- "\"Node\":\"CPUCluster1MinFreq\"");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(3u, nodes.size());
- std::map<std::string, std::vector<NodeAction>> actions =
- HintManager::ParseActions(json_doc_, nodes);
- EXPECT_EQ(0u, actions.size());
-}
-
-// Test parsing actions with duplicate Property node
-TEST_F(HintManagerTest, ParseActionDuplicatePropertyNodeTest) {
- std::string from = "\"Node\":\"CPUCluster0MinFreq\"";
- size_t start_pos = json_doc_.find(from);
- json_doc_.replace(start_pos, from.length(), "\"Node\":\"ModeProperty\"");
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- EXPECT_EQ(3u, nodes.size());
- std::map<std::string, std::vector<NodeAction>> actions =
- HintManager::ParseActions(json_doc_, nodes);
- EXPECT_EQ(0u, actions.size());
-}
-
-// Test parsing invalid json for actions
-TEST_F(HintManagerTest, ParseBadActionsTest) {
- std::vector<std::unique_ptr<Node>> nodes =
- HintManager::ParseNodes(json_doc_);
- std::map<std::string, std::vector<NodeAction>> actions =
- HintManager::ParseActions("invalid json", nodes);
- EXPECT_EQ(0u, actions.size());
- actions = HintManager::ParseActions(
- "{\"devices\":{\"15\":[\"armeabi-v7a\"],\"16\":[\"armeabi-v7a\"],"
- "\"26\":[\"armeabi-v7a\",\"arm64-v8a\",\"x86\",\"x86_64\"]}}",
- nodes);
- EXPECT_EQ(0u, actions.size());
-}
-
-// Test hint/cancel/expire with json config
-TEST_F(HintManagerTest, GetFromJSONTest) {
- TemporaryFile json_file;
- ASSERT_TRUE(android::base::WriteStringToFile(json_doc_, json_file.path))
- << strerror(errno);
- std::unique_ptr<HintManager> hm =
- HintManager::GetFromJSON(json_file.path, false);
- EXPECT_NE(nullptr, hm.get());
- EXPECT_FALSE(hm->IsRunning());
- EXPECT_TRUE(hm->Start());
- EXPECT_TRUE(hm->IsRunning());
- hm = HintManager::GetFromJSON(json_file.path);
- EXPECT_NE(nullptr, hm.get());
- EXPECT_TRUE(hm->IsRunning());
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- EXPECT_TRUE(hm->IsRunning());
- // Initial default value on Node0
- _VerifyPathValue(files_[0 + 2]->path, "384000");
- _VerifyPathValue(files_[1 + 2]->path, "");
- _VerifyPropertyValue(prop_, "");
- // Do INTERACTION
- EXPECT_TRUE(hm->DoHint("INTERACTION"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0 + 2]->path, "384000");
- _VerifyPathValue(files_[1 + 2]->path, "1134000");
- _VerifyPropertyValue(prop_, "LOW");
- // Do LAUNCH
- EXPECT_TRUE(hm->DoHint("LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0 + 2]->path, "1134000");
- _VerifyPathValue(files_[1 + 2]->path, "1512000");
- _VerifyPropertyValue(prop_, "HIGH");
- std::this_thread::sleep_for(500ms);
- // "LAUNCH" node0 expired
- _VerifyPathValue(files_[0 + 2]->path, "384000");
- _VerifyPathValue(files_[1 + 2]->path, "1512000");
- _VerifyPropertyValue(prop_, "LOW");
- EXPECT_TRUE(hm->EndHint("LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- // "LAUNCH" canceled
- _VerifyPathValue(files_[0 + 2]->path, "384000");
- _VerifyPathValue(files_[1 + 2]->path, "1134000");
- _VerifyPropertyValue(prop_, "LOW");
- std::this_thread::sleep_for(300ms);
- // "INTERACTION" node1 expired
- _VerifyPathValue(files_[0 + 2]->path, "384000");
- _VerifyPathValue(files_[1 + 2]->path, "384000");
- _VerifyPropertyValue(prop_, "NONE");
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/tests/NodeLooperThreadTest.cc b/libperfmgr/tests/NodeLooperThreadTest.cc
deleted file mode 100644
index 9283d9f9..00000000
--- a/libperfmgr/tests/NodeLooperThreadTest.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/file.h>
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <thread>
-
-#include "perfmgr/FileNode.h"
-#include "perfmgr/NodeLooperThread.h"
-
-namespace android {
-namespace perfmgr {
-
-using namespace std::chrono_literals;
-
-constexpr auto kSLEEP_TOLERANCE_MS = 50ms;
-
-class NodeLooperThreadTest : public ::testing::Test {
- protected:
- virtual void SetUp() {
- std::unique_ptr<TemporaryFile> tf = std::make_unique<TemporaryFile>();
- nodes_.emplace_back(new FileNode(
- "n0", tf->path, {{"n0_value0"}, {"n0_value1"}, {"n0_value2"}}, 2,
- false));
- files_.emplace_back(std::move(tf));
- tf = std::make_unique<TemporaryFile>();
- nodes_.emplace_back(new FileNode(
- "n1", tf->path, {{"n1_value0"}, {"n1_value1"}, {"n1_value2"}}, 2,
- true));
- files_.emplace_back(std::move(tf));
- }
-
- virtual void TearDown() {
- nodes_.clear();
- files_.clear();
- }
- std::vector<std::unique_ptr<Node>> nodes_;
- std::vector<std::unique_ptr<TemporaryFile>> files_;
-};
-
-static inline void _VerifyPathValue(const std::string& path,
- const std::string& value) {
- std::string s;
- EXPECT_TRUE(android::base::ReadFileToString(path, &s)) << strerror(errno);
- EXPECT_EQ(value, s);
-}
-
-// Test default value init
-TEST_F(NodeLooperThreadTest, InitRunTest) {
- sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
- EXPECT_TRUE(th->Start());
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- EXPECT_TRUE(th->isRunning());
- _VerifyPathValue(files_[0]->path, "");
- _VerifyPathValue(files_[1]->path, "n1_value2");
- th->Stop();
- EXPECT_FALSE(th->isRunning());
-}
-
-// Test add request
-TEST_F(NodeLooperThreadTest, AddRequest) {
- sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
- EXPECT_TRUE(th->Start());
- EXPECT_TRUE(th->isRunning());
- // Dummy LAUNCH boost actions:
- // Node0, value0, 200ms
- // Node1, value1, 400ms
- std::vector<NodeAction> actions{{0, 0, 200ms}, {1, 1, 400ms}};
- EXPECT_TRUE(th->Request(actions, "LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- std::this_thread::sleep_for(200ms);
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- std::this_thread::sleep_for(200ms);
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value2");
- th->Stop();
- EXPECT_FALSE(th->isRunning());
-}
-
-// Test request to override expire time
-TEST_F(NodeLooperThreadTest, AddRequestOverride) {
- sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
- EXPECT_TRUE(th->Start());
- EXPECT_TRUE(th->isRunning());
- // Dummy LAUNCH boost actions:
- // Node0, value0, 200ms
- // Node1, value1, 500ms
- std::vector<NodeAction> actions{{0, 0, 200ms}, {1, 1, 500ms}};
- EXPECT_TRUE(th->Request(actions, "LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- // Dummy LAUNCH boost actions:
- // Node0, value0, 300ms will extend
- // Node1, value1, 100ms will not extend
- actions = std::vector<NodeAction>{{0, 0, 300ms}, {1, 1, 100ms}};
- EXPECT_TRUE(th->Request(actions, "LAUNCH"));
- std::this_thread::sleep_for(200ms);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- std::this_thread::sleep_for(150ms);
- // Node0 value0 expired
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- std::this_thread::sleep_for(150ms);
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value2");
- th->Stop();
- EXPECT_FALSE(th->isRunning());
-}
-
-// Test cancel request
-TEST_F(NodeLooperThreadTest, CancelRequest) {
- sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
- EXPECT_TRUE(th->Start());
- EXPECT_TRUE(th->isRunning());
- // Dummy LAUNCH boost actions:
- // Node0, value0, forever
- // Node1, value1, forever
- std::vector<NodeAction> actions{{0, 0, 0ms}, {1, 1, 0ms}};
- EXPECT_TRUE(th->Request(actions, "LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- EXPECT_TRUE(th->Cancel(actions, "LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value2");
- th->Stop();
- EXPECT_FALSE(th->isRunning());
-}
-
-// Test multiple request
-TEST_F(NodeLooperThreadTest, MultipleRequest) {
- sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
- EXPECT_TRUE(th->Start());
- EXPECT_TRUE(th->isRunning());
- // Dummy LAUNCH boost actions:
- // Node0, value1, 800ms
- // Node1, value1, forever
- std::vector<NodeAction> actions_interaction{{0, 1, 800ms}, {1, 1, 0ms}};
- EXPECT_TRUE(th->Request(actions_interaction, "INTERACTION"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value1");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- // Dummy LAUNCH boost actions:
- // Node0, value0, forever
- // Node1, value0, 400ms
- std::vector<NodeAction> actions_launch{{0, 0, 0ms}, {1, 0, 400ms}};
- EXPECT_TRUE(th->Request(actions_launch, "LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value0");
- std::this_thread::sleep_for(400ms);
- // "LAUNCH" node1 expired
- _VerifyPathValue(files_[0]->path, "n0_value0");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- EXPECT_TRUE(th->Cancel(actions_launch, "LAUNCH"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- // "LAUNCH" canceled
- _VerifyPathValue(files_[0]->path, "n0_value1");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- std::this_thread::sleep_for(400ms);
- // "INTERACTION" node0 expired
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value1");
- EXPECT_TRUE(th->Cancel(actions_interaction, "INTERACTION"));
- std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
- // "INTERACTION" canceled
- _VerifyPathValue(files_[0]->path, "n0_value2");
- _VerifyPathValue(files_[1]->path, "n1_value2");
- th->Stop();
- EXPECT_FALSE(th->isRunning());
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/tests/PropertyNodeTest.cc b/libperfmgr/tests/PropertyNodeTest.cc
deleted file mode 100644
index 73f41c56..00000000
--- a/libperfmgr/tests/PropertyNodeTest.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/file.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <thread>
-
-#include "perfmgr/PropertyNode.h"
-
-namespace android {
-namespace perfmgr {
-
-using namespace std::chrono_literals;
-
-constexpr double kTIMING_TOLERANCE_MS = std::chrono::milliseconds(25).count();
-constexpr auto kSLEEP_TOLERANCE_MS = 2ms;
-
-static inline void _VerifyPropertyValue(const std::string& path,
- const std::string& value) {
- std::string s = android::base::GetProperty(path, "");
- EXPECT_EQ(value, s);
-}
-
-static inline const std::string _InitProperty(const std::string& path) {
- EXPECT_TRUE(android::base::SetProperty(path, ""))
- << "failed to clear property";
- return path;
-}
-
-// Test init with no default value
-TEST(PropertyNodeTest, NoInitDefaultTest) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 1, false);
- t.Update(false);
- _VerifyPropertyValue(key, "");
-}
-
-// Test init with default value
-TEST(PropertyNodeTest, InitDefaultTest) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 1, true);
- t.Update(false);
- _VerifyPropertyValue(key, "value1");
- std::string key2 = _InitProperty("test.libperfmgr.key2");
- PropertyNode t2("t2", key2, {{"value0"}, {"value1"}, {"value2"}}, 0, true);
- t2.Update(false);
- _VerifyPropertyValue(key2, "value0");
-}
-
-// Test DumpToFd
-TEST(PropertyNodeTest, DumpToFdTest) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("test_dump", key, {{"value0"}, {"value1"}, {"value2"}}, 1,
- true);
- t.Update(false);
- TemporaryFile dumptf;
- t.DumpToFd(dumptf.fd);
- fsync(dumptf.fd);
- std::string buf(
- android::base::StringPrintf("test_dump\t%s\t1\tvalue1\n", key.c_str()));
- std::string s;
- EXPECT_TRUE(android::base::ReadFileToString(dumptf.path, &s))
- << strerror(errno);
- EXPECT_EQ(buf, s);
-}
-
-// Test GetValueIndex
-TEST(PropertyNodeTest, GetValueIndexTest) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 1, false);
- std::size_t index = 0;
- EXPECT_TRUE(t.GetValueIndex("value2", &index));
- EXPECT_EQ(2u, index);
- index = 1234;
- EXPECT_FALSE(t.GetValueIndex("NON_EXIST", &index));
- EXPECT_EQ(1234u, index);
-}
-
-// Test GetValues
-TEST(PropertyNodeTest, GetValuesTest) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 1, false);
- std::vector values = t.GetValues();
- EXPECT_EQ(3u, values.size());
- EXPECT_EQ("value0", values[0]);
- EXPECT_EQ("value1", values[1]);
- EXPECT_EQ("value2", values[2]);
-}
-
-// Test get more properties
-TEST(PropertyNodeTest, GetPropertiesTest) {
- std::string test_name = "TESTREQ_1";
- std::string test_path = "TEST_PATH";
- PropertyNode t(test_name, test_path, {}, 0, false);
- EXPECT_EQ(test_name, t.GetName());
- EXPECT_EQ(test_path, t.GetPath());
- EXPECT_EQ(0u, t.GetValues().size());
- EXPECT_EQ(0u, t.GetDefaultIndex());
- EXPECT_FALSE(t.GetResetOnInit());
-}
-
-// Test add request
-TEST(PropertyNodeTest, AddRequestTest) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("t", key, {{"value0"}, {"value1"}, {""}}, 2, true);
- auto start = std::chrono::steady_clock::now();
- EXPECT_TRUE(t.AddRequest(1, "INTERACTION", start + 500ms));
- std::chrono::milliseconds expire_time = t.Update(true);
- // Add request @ value1
- _VerifyPropertyValue(key, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 higher prio than value1
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 200ms));
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Let high prio request timeout, now only request @ value1 active
- std::this_thread::sleep_for(expire_time + kSLEEP_TOLERANCE_MS);
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(300).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Let all requests timeout, now default value2
- std::this_thread::sleep_for(expire_time + kSLEEP_TOLERANCE_MS);
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "");
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
-}
-
-// Test remove request
-TEST(PropertyNodeTest, RemoveRequestTest) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 2, true);
- auto start = std::chrono::steady_clock::now();
- EXPECT_TRUE(t.AddRequest(1, "INTERACTION", start + 500ms));
- std::chrono::milliseconds expire_time = t.Update(true);
- // Add request @ value1
- _VerifyPropertyValue(key, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 higher prio than value1
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 200ms));
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove high prio request, now only request @ value1 active
- t.RemoveRequest("LAUNCH");
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove request, now default value2
- t.RemoveRequest("INTERACTION");
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value2");
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
-}
-
-// Test add request
-TEST(PropertyNodeTest, AddRequestTestOverride) {
- std::string key = _InitProperty("test.libperfmgr.key");
- PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 2, true);
- auto start = std::chrono::steady_clock::now();
- EXPECT_TRUE(t.AddRequest(1, "INTERACTION", start + 500ms));
- std::chrono::milliseconds expire_time = t.Update(true);
- // Add request @ value1
- _VerifyPropertyValue(key, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 higher prio than value1
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 200ms));
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 shorter
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 100ms));
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(200).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Add request @ value0 longer
- EXPECT_TRUE(t.AddRequest(0, "LAUNCH", start + 300ms));
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value0");
- EXPECT_NEAR(std::chrono::milliseconds(300).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove high prio request, now only request @ value1 active
- t.RemoveRequest("LAUNCH");
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value1");
- EXPECT_NEAR(std::chrono::milliseconds(500).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- // Remove request, now default value2
- t.RemoveRequest("INTERACTION");
- expire_time = t.Update(true);
- _VerifyPropertyValue(key, "value2");
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/tests/RequestGroupTest.cc b/libperfmgr/tests/RequestGroupTest.cc
deleted file mode 100644
index f3393c80..00000000
--- a/libperfmgr/tests/RequestGroupTest.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2017 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <thread>
-
-#include "perfmgr/RequestGroup.h"
-
-namespace android {
-namespace perfmgr {
-
-using namespace std::chrono_literals;
-
-constexpr double kTIMING_TOLERANCE_MS = std::chrono::milliseconds(25).count();
-
-// Test GetRequestValue()
-TEST(RequestGroupTest, GetRequestValueTest) {
- std::string test_str = "TESTREQ_1";
- RequestGroup req(test_str);
- EXPECT_EQ(test_str, req.GetRequestValue());
-}
-
-// Test AddRequest()
-TEST(RequestGroupTest, AddRequestTest) {
- RequestGroup req("");
- auto start = std::chrono::steady_clock::now();
- auto duration = 500ms;
- bool ret = req.AddRequest("INTERACTION", start + duration);
- EXPECT_EQ(true, ret);
- auto sleep_time = 200ms;
- std::this_thread::sleep_for(sleep_time);
- std::chrono::milliseconds expire_time;
- bool active = req.GetExpireTime(&expire_time);
- EXPECT_NEAR((duration - sleep_time).count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- EXPECT_EQ(true, active);
-}
-
-// Test AddRequest() with a huge expire time which could be done in some long
-// persist power hint such as VR_MODE
-TEST(RequestGroupTest, AddRequestNoExpireTest) {
- RequestGroup req("");
- bool ret = req.AddRequest("INTERACTION", ReqTime::max());
- EXPECT_EQ(true, ret);
- std::chrono::milliseconds expire_time;
- bool active = req.GetExpireTime(&expire_time);
- auto expect = std::chrono::duration_cast<std::chrono::milliseconds>(
- ReqTime::max() - std::chrono::steady_clock::now());
- EXPECT_NEAR(expect.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
- // expire time is greater than 1 year
- EXPECT_LE(365 * 24 * 60 * 60 * 1000, expire_time.count());
- EXPECT_EQ(true, active);
-}
-
-// Test AddRequest() and expires
-TEST(RequestGroupTest, AddRequestTestExpire) {
- RequestGroup req("");
- auto start = std::chrono::steady_clock::now();
- auto duration = 5ms;
- bool ret = req.AddRequest("INTERACTION", start + duration);
- EXPECT_EQ(true, ret);
- ret = req.AddRequest("INTERACTION", start + duration + 1ms);
- EXPECT_EQ(false, ret);
- std::this_thread::sleep_for(duration + 10ms);
- std::chrono::milliseconds expire_time;
- bool active = req.GetExpireTime(&expire_time);
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
- EXPECT_EQ(false, active);
-}
-
-// Test AddRequest() with new value
-TEST(RequestGroupTest, AddRequestNewValue) {
- RequestGroup req("");
- auto start = std::chrono::steady_clock::now();
- auto duration = 5000ms;
- bool ret = req.AddRequest("INTERACTION", start + duration);
- EXPECT_EQ(true, ret);
- std::chrono::milliseconds expire_time;
- bool active = req.GetExpireTime(&expire_time);
- EXPECT_NEAR(duration.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
- EXPECT_EQ(true, active);
- // Add a request shorter than the current outstanding one, expiration time
- // not changed
- auto shorter_duration = 100ms;
- ret = req.AddRequest("INTERACTION", start + shorter_duration);
- EXPECT_EQ(false, ret);
- active = req.GetExpireTime(&expire_time);
- EXPECT_NEAR(duration.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
- EXPECT_EQ(true, active);
- // Add a request longer than the current outstanding one, expiration time
- // changed
- duration = 10000ms;
- ret = req.AddRequest("INTERACTION", start + duration);
- EXPECT_EQ(false, ret);
- active = req.GetExpireTime(&expire_time);
- EXPECT_NEAR(duration.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
- EXPECT_EQ(true, active);
-}
-
-// Test multiple AddRequest() with different hint_type
-TEST(RequestGroupTest, AddRequestTestMutiple) {
- RequestGroup req("");
- auto start = std::chrono::steady_clock::now();
- auto duration_interact = 500ms;
- req.AddRequest("INTERACTION", start + duration_interact);
- auto duration_launch = 5000ms;
- req.AddRequest("LAUNCH", start + duration_launch);
- std::chrono::milliseconds expire_time;
- bool active = req.GetExpireTime(&expire_time);
- EXPECT_NEAR(std::min(duration_interact, duration_launch).count(),
- expire_time.count(), kTIMING_TOLERANCE_MS);
- EXPECT_EQ(true, active);
-}
-
-// Test RemoveRequest()
-TEST(RequestGroupTest, RemoveRequestTest) {
- RequestGroup req("");
- auto start = std::chrono::steady_clock::now();
- auto duration_interact = 500ms;
- req.AddRequest("INTERACTION", start + duration_interact);
- bool ret = req.RemoveRequest("INTERACTION");
- EXPECT_EQ(true, ret);
- std::chrono::milliseconds expire_time;
- bool active = req.GetExpireTime(&expire_time);
- EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
- EXPECT_EQ(false, active);
- // Test removing an already-removed request
- ret = req.RemoveRequest("INTERACTION");
- EXPECT_EQ(false, ret);
-}
-
-// Test multiple RemoveRequest() with different hint_type
-TEST(RequestGroupTest, RemoveRequestTestMutiple) {
- RequestGroup req("");
- auto start = std::chrono::steady_clock::now();
- auto duration_interact = 500ms;
- req.AddRequest("INTERACTION", start + duration_interact);
- auto duration_launch = 50000ms;
- req.AddRequest("LAUNCH", start + duration_launch);
- req.RemoveRequest("INTERACTION");
- std::chrono::milliseconds expire_time;
- bool active = req.GetExpireTime(&expire_time);
- EXPECT_NEAR(duration_launch.count(), expire_time.count(),
- kTIMING_TOLERANCE_MS);
- EXPECT_EQ(true, active);
-}
-
-} // namespace perfmgr
-} // namespace android
diff --git a/libperfmgr/tools/ConfigVerifier.cc b/libperfmgr/tools/ConfigVerifier.cc
deleted file mode 100644
index ad959102..00000000
--- a/libperfmgr/tools/ConfigVerifier.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2018 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 specic language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <thread>
-
-#include "perfmgr/HintManager.h"
-
-namespace android {
-namespace perfmgr {
-
-class NodeVerifier : public HintManager {
- public:
- static bool VerifyNodes(const std::string& config_path) {
- std::string json_doc;
-
- if (!android::base::ReadFileToString(config_path, &json_doc)) {
- LOG(ERROR) << "Failed to read JSON config from " << config_path;
- return false;
- }
-
- std::vector<std::unique_ptr<Node>> nodes = ParseNodes(json_doc);
- if (nodes.empty()) {
- LOG(ERROR) << "Failed to parse Nodes section from " << config_path;
- return false;
- }
-
- return true;
- }
-
- private:
- NodeVerifier(sp<NodeLooperThread> nm,
- const std::map<std::string, std::vector<NodeAction>>& actions)
- : HintManager(std::move(nm), actions) {}
-};
-
-} // namespace perfmgr
-} // namespace android
-
-static void printUsage(const char* exec_name) {
- std::string usage = exec_name;
- usage =
- usage +
- " is a command-line tool to verify Nodes in Json config are writable.\n"
- "Usages:\n"
- " [su system] " +
- exec_name +
- " [options]\n"
- "\n"
- "Options:\n"
- " --config, -c [PATH]\n"
- " path to Json config file\n\n"
- " --exec_hint, -e\n"
- " do hints in Json config\n\n"
- " --hint_name, -i\n"
- " do only the specific hint\n\n"
- " --hint_duration, -d [duration]\n"
- " duration in ms for each hint\n\n"
- " --help, -h\n"
- " print this message\n\n"
- " --verbose, -v\n"
- " print verbose log during execution\n\n";
-
- LOG(INFO) << usage;
-}
-
-static void execConfig(const std::string& json_file,
- const std::string& hint_name, uint64_t hint_duration) {
- std::unique_ptr<android::perfmgr::HintManager> hm =
- android::perfmgr::HintManager::GetFromJSON(json_file);
- if (!hm.get() || !hm->IsRunning()) {
- LOG(ERROR) << "Failed to Parse JSON config";
- }
- std::vector<std::string> hints = hm->GetHints();
- for (const auto& hint : hints) {
- if (!hint_name.empty() && hint_name != hint) continue;
- LOG(INFO) << "Do hint: " << hint;
- hm->DoHint(hint, std::chrono::milliseconds(hint_duration));
- std::this_thread::yield();
- std::this_thread::sleep_for(std::chrono::milliseconds(hint_duration));
- LOG(INFO) << "End hint: " << hint;
- hm->EndHint(hint);
- std::this_thread::yield();
- }
-}
-
-int main(int argc, char* argv[]) {
- android::base::InitLogging(argv, android::base::StdioLogger);
-
- if (getuid() == 0) {
- LOG(WARNING) << "Running as root might mask node permission";
- }
-
- std::string config_path;
- std::string hint_name;
- bool exec_hint = false;
- uint64_t hint_duration = 100;
-
- while (true) {
- static struct option opts[] = {
- {"config", required_argument, nullptr, 'c'},
- {"exec_hint", no_argument, nullptr, 'e'},
- {"hint_name", required_argument, nullptr, 'i'},
- {"hint_duration", required_argument, nullptr, 'd'},
- {"help", no_argument, nullptr, 'h'},
- {"verbose", no_argument, nullptr, 'v'},
- {0, 0, 0, 0} // termination of the option list
- };
-
- int option_index = 0;
- int c = getopt_long(argc, argv, "c:ei:d:hv", opts, &option_index);
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 'c':
- config_path = optarg;
- break;
- case 'e':
- exec_hint = true;
- break;
- case 'i':
- hint_name = optarg;
- break;
- case 'd':
- hint_duration = strtoul(optarg, NULL, 10);
- break;
- case 'v':
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
- break;
- case 'h':
- printUsage(argv[0]);
- return 0;
- default:
- // getopt already prints "invalid option -- %c" for us.
- return 1;
- }
- }
-
- if (config_path.empty()) {
- LOG(ERROR) << "Need specify JSON config";
- printUsage(argv[0]);
- return 1;
- }
-
- if (exec_hint) {
- execConfig(config_path, hint_name, hint_duration);
- return 0;
- }
-
- if (android::perfmgr::NodeVerifier::VerifyNodes(config_path)) {
- LOG(INFO) << "Verified writing to JSON config";
- return 0;
- } else {
- LOG(ERROR) << "Failed to verify nodes in JSON config";
- return 1;
- }
-}