diff options
6 files changed, 62 insertions, 136 deletions
diff --git a/power-libperfmgr/libperfmgr/HintManager.cc b/power-libperfmgr/libperfmgr/HintManager.cc index 73ebc43..8c84c68 100644 --- a/power-libperfmgr/libperfmgr/HintManager.cc +++ b/power-libperfmgr/libperfmgr/HintManager.cc @@ -125,6 +125,11 @@ void HintManager::EndHintStatus(const std::string &hint_type) { void HintManager::DoHintAction(const std::string &hint_type) { for (auto &action : actions_.at(hint_type).hint_actions) { + if (!action.enable_property.empty() && + !android::base::GetBoolProperty(action.enable_property, true)) { + // Disabled action based on its control property + continue; + } switch (action.type) { case HintActionType::DoHint: DoHint(action.value); @@ -537,6 +542,7 @@ std::unordered_map<std::string, Hint> HintManager::ParseActions( HintActionType action_type = HintActionType::Node; std::string type_string = actions[i]["Type"].asString(); + std::string enable_property = actions[i]["EnableProperty"].asString(); LOG(VERBOSE) << "Action[" << i << "]'s Type: " << type_string; if (type_string.empty()) { LOG(VERBOSE) << "Failed to read " @@ -599,7 +605,7 @@ std::unordered_map<std::string, Hint> HintManager::ParseActions( } } actions_parsed[hint_type].node_actions.emplace_back( - node_index, value_index, std::chrono::milliseconds(duration)); + node_index, value_index, std::chrono::milliseconds(duration), enable_property); } else { const std::string &hint_value = actions[i]["Value"].asString(); @@ -610,7 +616,8 @@ std::unordered_map<std::string, Hint> HintManager::ParseActions( actions_parsed.clear(); return actions_parsed; } - actions_parsed[hint_type].hint_actions.emplace_back(action_type, hint_value); + actions_parsed[hint_type].hint_actions.emplace_back(action_type, hint_value, + enable_property); } ++total_parsed; diff --git a/power-libperfmgr/libperfmgr/NodeLooperThread.cc b/power-libperfmgr/libperfmgr/NodeLooperThread.cc index 39ffc2e..d38501d 100644 --- a/power-libperfmgr/libperfmgr/NodeLooperThread.cc +++ b/power-libperfmgr/libperfmgr/NodeLooperThread.cc @@ -21,6 +21,7 @@ #include <android-base/file.h> #include <android-base/logging.h> +#include <android-base/properties.h> #include <utils/Trace.h> namespace android { @@ -39,6 +40,11 @@ bool NodeLooperThread::Request(const std::vector<NodeAction>& actions, bool ret = true; ::android::AutoMutex _l(lock_); for (const auto& a : actions) { + if (!a.enable_property.empty() && + !android::base::GetBoolProperty(a.enable_property, true)) { + // Disabled action based on its control property + continue; + } if (a.node_index >= nodes_.size()) { LOG(ERROR) << "Node index out of bound: " << a.node_index << " ,size: " << nodes_.size(); diff --git a/power-libperfmgr/libperfmgr/config_schema.json b/power-libperfmgr/libperfmgr/config_schema.json deleted file mode 100644 index 712af50..0000000 --- a/power-libperfmgr/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/power-libperfmgr/libperfmgr/include/perfmgr/HintManager.h b/power-libperfmgr/libperfmgr/include/perfmgr/HintManager.h index d360fea..13211a1 100644 --- a/power-libperfmgr/libperfmgr/include/perfmgr/HintManager.h +++ b/power-libperfmgr/libperfmgr/include/perfmgr/HintManager.h @@ -61,9 +61,11 @@ struct HintStatus { enum class HintActionType { Node, DoHint, EndHint, MaskHint }; struct HintAction { - HintAction(HintActionType t, const std::string &v) : type(t), value(v) {} + HintAction(HintActionType t, const std::string &v, const std::string &p) + : type(t), value(v), enable_property(p) {} HintActionType type; std::string value; + std::string enable_property; }; struct Hint { diff --git a/power-libperfmgr/libperfmgr/include/perfmgr/NodeLooperThread.h b/power-libperfmgr/libperfmgr/include/perfmgr/NodeLooperThread.h index eba0fc7..bad233c 100644 --- a/power-libperfmgr/libperfmgr/include/perfmgr/NodeLooperThread.h +++ b/power-libperfmgr/libperfmgr/include/perfmgr/NodeLooperThread.h @@ -34,13 +34,15 @@ namespace perfmgr { // timeout for this action: struct NodeAction { NodeAction(std::size_t node_index, std::size_t value_index, - std::chrono::milliseconds timeout_ms) + std::chrono::milliseconds timeout_ms, const std::string &enable_property = "") : node_index(node_index), value_index(value_index), - timeout_ms(timeout_ms) {} + timeout_ms(timeout_ms), + enable_property(enable_property) {} std::size_t node_index; std::size_t value_index; std::chrono::milliseconds timeout_ms; // 0ms for forever + std::string enable_property; // boolean property to control action on/off. }; // The NodeLooperThread is responsible for managing each of the sysfs nodes diff --git a/power-libperfmgr/libperfmgr/tests/HintManagerTest.cc b/power-libperfmgr/libperfmgr/tests/HintManagerTest.cc index 48a8494..979e7dc 100644 --- a/power-libperfmgr/libperfmgr/tests/HintManagerTest.cc +++ b/power-libperfmgr/libperfmgr/tests/HintManagerTest.cc @@ -68,6 +68,16 @@ constexpr char kJSON_RAW[] = R"( "NONE" ], "Type": "Property" + }, + { + "Name": "TestEnableProperty", + "Path": "vendor.pwhal.enable.test", + "Values": [ + "0", + "1" + ], + "Type": "Property", + "ResetOnInit": true } ], "Actions": [ @@ -87,6 +97,7 @@ constexpr char kJSON_RAW[] = R"( "PowerHint": "LAUNCH", "Node": "CPUCluster0MinFreq", "Value": "1134000", + "EnableProperty": "vendor.pwhal.enable.no_exist", "Duration": 500 }, { @@ -99,9 +110,16 @@ constexpr char kJSON_RAW[] = R"( "PowerHint": "LAUNCH", "Node": "CPUCluster1MinFreq", "Value": "1512000", + "EnableProperty": "vendor.pwhal.enable.test", "Duration": 2000 }, { + "PowerHint": "DISABLE_LAUNCH_ACT2", + "Node": "TestEnableProperty", + "Value": "0", + "Duration": 0 + }, + { "PowerHint": "MASK_LAUNCH_MODE", "Type": "MaskHint", "Value": "LAUNCH" @@ -410,7 +428,7 @@ TEST_F(HintManagerTest, HintStatsTest) { TEST_F(HintManagerTest, ParseNodesTest) { std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_); - EXPECT_EQ(3u, nodes.size()); + EXPECT_EQ(4u, nodes.size()); EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName()); EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName()); EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath()); @@ -503,7 +521,7 @@ TEST_F(HintManagerTest, ParsePropertyNodesEmptyValueTest) { 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(4u, nodes.size()); EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName()); EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName()); EXPECT_EQ(files_[0 + 2]->path, nodes[0]->GetPath()); @@ -546,7 +564,7 @@ TEST_F(HintManagerTest, ParseActionsTest) { std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_); std::unordered_map<std::string, Hint> actions = HintManager::ParseActions(json_doc_, nodes); - EXPECT_EQ(6u, actions.size()); + EXPECT_EQ(7u, actions.size()); EXPECT_EQ(2u, actions["INTERACTION"].node_actions.size()); EXPECT_EQ(1u, actions["INTERACTION"].node_actions[0].node_index); @@ -575,6 +593,7 @@ TEST_F(HintManagerTest, ParseActionsTest) { EXPECT_EQ(0u, actions["LAUNCH"].node_actions[2].value_index); EXPECT_EQ(std::chrono::milliseconds(2000).count(), actions["LAUNCH"].node_actions[2].timeout_ms.count()); + EXPECT_EQ("vendor.pwhal.enable.test", actions["LAUNCH"].node_actions[2].enable_property); EXPECT_EQ(1u, actions["MASK_LAUNCH_MODE"].hint_actions.size()); EXPECT_EQ(HintActionType::MaskHint, actions["MASK_LAUNCH_MODE"].hint_actions[0].type); @@ -604,7 +623,7 @@ TEST_F(HintManagerTest, ParseActionDuplicateFileNodeTest) { json_doc_.replace(start_pos, from.length(), R"("Node": "CPUCluster1MinFreq")"); std::vector<std::unique_ptr<Node>> nodes = HintManager::ParseNodes(json_doc_); - EXPECT_EQ(3u, nodes.size()); + EXPECT_EQ(4u, nodes.size()); auto actions = HintManager::ParseActions(json_doc_, nodes); EXPECT_EQ(0u, actions.size()); } @@ -615,7 +634,7 @@ TEST_F(HintManagerTest, ParseActionDuplicatePropertyNodeTest) { size_t start_pos = json_doc_.find(from); json_doc_.replace(start_pos, from.length(), R"("Node": "ModeProperty")"); auto nodes = HintManager::ParseNodes(json_doc_); - EXPECT_EQ(3u, nodes.size()); + EXPECT_EQ(4u, nodes.size()); auto actions = HintManager::ParseActions(json_doc_, nodes); EXPECT_EQ(0u, actions.size()); } @@ -660,6 +679,7 @@ TEST_F(HintManagerTest, GetFromJSONTest) { _VerifyPathValue(files_[1 + 2]->path, "1134000"); _VerifyPropertyValue(prop_, "LOW"); // Do LAUNCH + _VerifyPropertyValue("vendor.pwhal.enable.test", "1"); EXPECT_TRUE(hm->DoHint("LAUNCH")); std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS); _VerifyPathValue(files_[0 + 2]->path, "1134000"); @@ -682,6 +702,21 @@ TEST_F(HintManagerTest, GetFromJSONTest) { _VerifyPathValue(files_[1 + 2]->path, "384000"); _VerifyPropertyValue(prop_, "NONE"); + // Disable action[2] of LAUNCH + EXPECT_TRUE(hm->EndHint("LAUNCH")); + _VerifyPropertyValue("vendor.pwhal.enable.test", "1"); + EXPECT_TRUE(hm->DoHint("DISABLE_LAUNCH_ACT2")); + std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS); + _VerifyPropertyValue("vendor.pwhal.enable.test", "0"); + EXPECT_TRUE(hm->DoHint("LAUNCH")); + std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS); + _VerifyPathValue(files_[0 + 2]->path, "1134000"); + // action[2] have no effect. + _VerifyPathValue(files_[1 + 2]->path, "384000"); + _VerifyPropertyValue(prop_, "HIGH"); + EXPECT_TRUE(hm->EndHint("LAUNCH")); + EXPECT_TRUE(hm->EndHint("DISABLE_LAUNCH_ACT2")); + // Mask LAUNCH and do LAUNCH EXPECT_TRUE(hm->DoHint("MASK_LAUNCH_MODE")); EXPECT_FALSE(hm->DoHint("LAUNCH")); // should fail |