/* * 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 #include #include #include #include #include #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> nodes = ParseNodes(json_doc); if (nodes.empty()) { LOG(ERROR) << "Failed to parse Nodes section from " << config_path; return false; } for (const auto& node : nodes) { std::vector values = node->GetValues(); std::string default_value = values[node->GetDefaultIndex()]; // Always set to default first values.insert(values.begin(), default_value); // And reset to default after test values.push_back(default_value); for (const auto& value : values) { if (!android::base::WriteStringToFile(value, node->GetPath())) { LOG(ERROR) << "Failed to write to node: " << node->GetPath() << " with value: " << value; return false; } LOG(VERBOSE) << "Wrote to node: " << node->GetPath() << " with value: " << value; } } return true; } private: NodeVerifier(sp nm, const std::map>& actions) : HintManager(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 [PATH], -c\n" " path to Json config file\n\n" " --exec_hint, -e\n" " do hints in Json config\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) { std::unique_ptr hm = android::perfmgr::HintManager::GetFromJSON(json_file); if (!hm.get() || !hm->IsRunning()) { LOG(ERROR) << "Failed to Parse JSON config"; } std::vector hints = hm->GetHints(); for (const auto& hint : hints) { LOG(INFO) << "Do hint: " << hint; hm->DoHint(hint); std::this_thread::yield(); std::this_thread::sleep_for(std::chrono::milliseconds(50)); LOG(INFO) << "End hint: " << hint; hm->EndHint(hint); std::this_thread::yield(); std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } int main(int argc, char* argv[]) { android::base::InitLogging(argv, android::base::StderrLogger); if (getuid() == 0) { LOG(WARNING) << "Running as root might mask node permission"; } std::string config_path; bool exec_hint = false; while (true) { static struct option opts[] = { {"config", required_argument, nullptr, 'c'}, {"exec_hint", no_argument, nullptr, 'e'}, {"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:ehv", opts, &option_index); if (c == -1) { break; } switch (c) { case 'c': config_path = optarg; break; case 'e': exec_hint = true; 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); 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; } }