| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file provides a thin binary wrapper around the BattOr Agent | 5 // This file provides a thin binary wrapper around the BattOr Agent |
| 6 // library. This binary wrapper provides a means for non-C++ tracing | 6 // library. This binary wrapper provides a means for non-C++ tracing |
| 7 // controllers, such as Telemetry and Android Systrace, to issue high-level | 7 // controllers, such as Telemetry and Android Systrace, to issue high-level |
| 8 // tracing commands to the BattOr through an interactive shell. | 8 // tracing commands to the BattOr through an interactive shell. |
| 9 // | 9 // |
| 10 // Example usage of how an external trace controller might use this binary: | 10 // Example usage of how an external trace controller might use this binary: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 // sync end timestamp and sends the subprocess the StopTracing message via | 26 // sync end timestamp and sends the subprocess the StopTracing message via |
| 27 // STDIN | 27 // STDIN |
| 28 // 9) PowerTracingAgent continues to read trace output lines from STDOUT until | 28 // 9) PowerTracingAgent continues to read trace output lines from STDOUT until |
| 29 // the binary exits with an exit code of 1 (indicating failure) or the | 29 // the binary exits with an exit code of 1 (indicating failure) or the |
| 30 // 'Done.' line is printed to STDOUT, signaling the last line of the trace | 30 // 'Done.' line is printed to STDOUT, signaling the last line of the trace |
| 31 // 10) PowerTracingAgent returns the battery trace to the Telemetry trace | 31 // 10) PowerTracingAgent returns the battery trace to the Telemetry trace |
| 32 // controller | 32 // controller |
| 33 | 33 |
| 34 #include <stdint.h> | 34 #include <stdint.h> |
| 35 | 35 |
| 36 #include <fstream> |
| 36 #include <iostream> | 37 #include <iostream> |
| 37 | 38 |
| 38 #include "base/at_exit.h" | 39 #include "base/at_exit.h" |
| 39 #include "base/bind.h" | 40 #include "base/bind.h" |
| 40 #include "base/bind_helpers.h" | 41 #include "base/bind_helpers.h" |
| 41 #include "base/command_line.h" | 42 #include "base/command_line.h" |
| 42 #include "base/location.h" | 43 #include "base/location.h" |
| 43 #include "base/logging.h" | 44 #include "base/logging.h" |
| 44 #include "base/strings/string_tokenizer.h" | 45 #include "base/strings/string_tokenizer.h" |
| 45 #include "base/strings/utf_string_conversions.h" | 46 #include "base/strings/utf_string_conversions.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 62 "Start the battor_agent shell with:\n" | 63 "Start the battor_agent shell with:\n" |
| 63 "\n" | 64 "\n" |
| 64 " battor_agent <switches>\n" | 65 " battor_agent <switches>\n" |
| 65 "\n" | 66 "\n" |
| 66 "Switches: \n" | 67 "Switches: \n" |
| 67 " --battor-path=<path> Uses the specified BattOr path.\n" | 68 " --battor-path=<path> Uses the specified BattOr path.\n" |
| 68 "\n" | 69 "\n" |
| 69 "Once in the shell, you can issue the following commands:\n" | 70 "Once in the shell, you can issue the following commands:\n" |
| 70 "\n" | 71 "\n" |
| 71 " StartTracing\n" | 72 " StartTracing\n" |
| 72 " StopTracing\n" | 73 " StopTracing <optional file path>\n" |
| 73 " SupportsExplicitClockSync\n" | 74 " SupportsExplicitClockSync\n" |
| 74 " RecordClockSyncMarker <marker>\n" | 75 " RecordClockSyncMarker <marker>\n" |
| 75 " Exit\n" | 76 " Exit\n" |
| 76 " Help\n" | 77 " Help\n" |
| 77 "\n"; | 78 "\n"; |
| 78 | 79 |
| 79 void PrintSupportsExplicitClockSync() { | 80 void PrintSupportsExplicitClockSync() { |
| 80 std::cout << BattOrAgent::SupportsExplicitClockSync() << endl; | 81 std::cout << BattOrAgent::SupportsExplicitClockSync() << endl; |
| 81 } | 82 } |
| 82 | 83 |
| 83 // Logs the error and exits with an error code. | 84 // Logs the error and exits with an error code. |
| 84 void HandleError(battor::BattOrError error) { | 85 void HandleError(battor::BattOrError error) { |
| 85 if (error != BATTOR_ERROR_NONE) | 86 if (error != BATTOR_ERROR_NONE) |
| 86 LOG(FATAL) << "Fatal error when communicating with the BattOr: " | 87 LOG(FATAL) << "Fatal error when communicating with the BattOr: " |
| 87 << BattOrErrorToString(error); | 88 << BattOrErrorToString(error); |
| 88 } | 89 } |
| 89 | 90 |
| 90 // Prints an error message and exits due to a required thread failing to start. | 91 // Prints an error message and exits due to a required thread failing to start. |
| 91 void ExitFromThreadStartFailure(const std::string& thread_name) { | 92 void ExitFromThreadStartFailure(const std::string& thread_name) { |
| 92 LOG(FATAL) << "Failed to start " << thread_name; | 93 LOG(FATAL) << "Failed to start " << thread_name; |
| 93 } | 94 } |
| 94 | 95 |
| 96 std::vector<std::string> TokenizeString(std::string cmd) { |
| 97 base::StringTokenizer tokenizer(cmd, " "); |
| 98 std::vector<std::string> tokens; |
| 99 while (tokenizer.GetNext()) |
| 100 tokens.push_back(tokenizer.token()); |
| 101 return tokens; |
| 102 } |
| 103 |
| 95 } // namespace | 104 } // namespace |
| 96 | 105 |
| 97 // Wrapper class containing all state necessary for an independent binary to | 106 // Wrapper class containing all state necessary for an independent binary to |
| 98 // use a BattOrAgent to communicate with a BattOr. | 107 // use a BattOrAgent to communicate with a BattOr. |
| 99 class BattOrAgentBin : public BattOrAgent::Listener { | 108 class BattOrAgentBin : public BattOrAgent::Listener { |
| 100 public: | 109 public: |
| 101 BattOrAgentBin() | 110 BattOrAgentBin() |
| 102 : done_(false, false), | 111 : done_(false, false), |
| 103 io_thread_(kIoThreadName), | 112 io_thread_(kIoThreadName), |
| 104 file_thread_(kFileThreadName), | 113 file_thread_(kFileThreadName), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 117 } | 126 } |
| 118 | 127 |
| 119 SetUp(path); | 128 SetUp(path); |
| 120 | 129 |
| 121 std::string cmd; | 130 std::string cmd; |
| 122 for (;;) { | 131 for (;;) { |
| 123 std::getline(std::cin, cmd); | 132 std::getline(std::cin, cmd); |
| 124 | 133 |
| 125 if (cmd == "StartTracing") { | 134 if (cmd == "StartTracing") { |
| 126 StartTracing(); | 135 StartTracing(); |
| 127 } else if (cmd == "StopTracing") { | 136 } else if (cmd.find("StopTracing") != std::string::npos) { |
| 128 StopTracing(); | 137 std::vector<std::string> tokens = TokenizeString(cmd); |
| 138 if (tokens.size() == 1 && tokens[0] == "StopTracing") { |
| 139 // No path given. |
| 140 StopTracing(); |
| 141 } else if (tokens.size() == 2 && tokens[0] == "StopTracing") { |
| 142 // Path given. |
| 143 StopTracing(tokens[1]); |
| 144 } else { |
| 145 std::cout << "Invalid StopTracing command." << endl; |
| 146 std::cout << kUsage << endl; |
| 147 continue; |
| 148 } |
| 129 break; | 149 break; |
| 130 } else if (cmd == "SupportsExplicitClockSync") { | 150 } else if (cmd == "SupportsExplicitClockSync") { |
| 131 PrintSupportsExplicitClockSync(); | 151 PrintSupportsExplicitClockSync(); |
| 132 } else if (cmd.find("RecordClockSyncMarker") != std::string::npos) { | 152 } else if (cmd.find("RecordClockSyncMarker") != std::string::npos) { |
| 133 base::StringTokenizer tokenizer(cmd, " "); | 153 std::vector<std::string> tokens = TokenizeString(cmd); |
| 134 | |
| 135 std::vector<std::string> tokens; | |
| 136 while (tokenizer.GetNext()) | |
| 137 tokens.push_back(tokenizer.token()); | |
| 138 | |
| 139 if (tokens.size() != 2 || tokens[0] != "RecordClockSyncMarker") { | 154 if (tokens.size() != 2 || tokens[0] != "RecordClockSyncMarker") { |
| 140 std::cout << "Invalid RecordClockSyncMarker command." << endl; | 155 std::cout << "Invalid RecordClockSyncMarker command." << endl; |
| 141 std::cout << kUsage << endl; | 156 std::cout << kUsage << endl; |
| 142 continue; | 157 continue; |
| 143 } | 158 } |
| 144 | 159 |
| 145 RecordClockSyncMarker(tokens[1]); | 160 RecordClockSyncMarker(tokens[1]); |
| 146 } else if (cmd == "Exit") { | 161 } else if (cmd == "Exit") { |
| 147 break; | 162 break; |
| 148 } else { | 163 } else { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 | 202 |
| 188 void OnStartTracingComplete(BattOrError error) override { | 203 void OnStartTracingComplete(BattOrError error) override { |
| 189 if (error == BATTOR_ERROR_NONE) | 204 if (error == BATTOR_ERROR_NONE) |
| 190 std::cout << "Done." << endl; | 205 std::cout << "Done." << endl; |
| 191 else | 206 else |
| 192 HandleError(error); | 207 HandleError(error); |
| 193 | 208 |
| 194 done_.Signal(); | 209 done_.Signal(); |
| 195 } | 210 } |
| 196 | 211 |
| 197 void StopTracing() { | 212 void StopTracing(const std::string& path = "") { |
| 213 trace_output_file_ = path; |
| 198 io_thread_.task_runner()->PostTask( | 214 io_thread_.task_runner()->PostTask( |
| 199 FROM_HERE, | 215 FROM_HERE, |
| 200 base::Bind(&BattOrAgent::StopTracing, base::Unretained(agent_.get()))); | 216 base::Bind(&BattOrAgent::StopTracing, base::Unretained(agent_.get()))); |
| 201 done_.Wait(); | 217 done_.Wait(); |
| 218 trace_output_file_ = std::string(); |
| 202 } | 219 } |
| 203 | 220 |
| 204 void OnStopTracingComplete(const std::string& trace, | 221 void OnStopTracingComplete(const std::string& trace, |
| 205 BattOrError error) override { | 222 BattOrError error) override { |
| 206 if (error == BATTOR_ERROR_NONE) { | 223 if (error == BATTOR_ERROR_NONE) { |
| 207 std::cout << trace; | 224 if (trace_output_file_.empty()) { |
| 225 std::cout << trace; |
| 226 } |
| 227 else { |
| 228 std::ofstream trace_stream(trace_output_file_); |
| 229 if (!trace_stream.is_open()) { |
| 230 std::cout << "Tracing output file could not be opened." << endl; |
| 231 exit(1); |
| 232 } |
| 233 trace_stream << trace; |
| 234 trace_stream.close(); |
| 235 } |
| 208 std::cout << "Done." << endl; | 236 std::cout << "Done." << endl; |
| 209 } else { | 237 } else { |
| 210 HandleError(error); | 238 HandleError(error); |
| 211 } | 239 } |
| 212 | 240 |
| 213 done_.Signal(); | 241 done_.Signal(); |
| 214 } | 242 } |
| 215 | 243 |
| 216 void RecordClockSyncMarker(const std::string& marker) { | 244 void RecordClockSyncMarker(const std::string& marker) { |
| 217 io_thread_.task_runner()->PostTask( | 245 io_thread_.task_runner()->PostTask( |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 // Event signaled when an async task has finished executing. | 289 // Event signaled when an async task has finished executing. |
| 262 base::WaitableEvent done_; | 290 base::WaitableEvent done_; |
| 263 | 291 |
| 264 // Threads needed for serial communication. | 292 // Threads needed for serial communication. |
| 265 base::Thread io_thread_; | 293 base::Thread io_thread_; |
| 266 base::Thread file_thread_; | 294 base::Thread file_thread_; |
| 267 base::Thread ui_thread_; | 295 base::Thread ui_thread_; |
| 268 | 296 |
| 269 // The agent capable of asynchronously communicating with the BattOr. | 297 // The agent capable of asynchronously communicating with the BattOr. |
| 270 scoped_ptr<BattOrAgent> agent_; | 298 scoped_ptr<BattOrAgent> agent_; |
| 299 |
| 300 std::string trace_output_file_; |
| 301 |
| 271 }; | 302 }; |
| 272 | 303 |
| 273 } // namespace battor | 304 } // namespace battor |
| 274 | 305 |
| 275 int main(int argc, char* argv[]) { | 306 int main(int argc, char* argv[]) { |
| 276 base::AtExitManager exit_manager; | 307 base::AtExitManager exit_manager; |
| 277 base::CommandLine::Init(argc, argv); | 308 base::CommandLine::Init(argc, argv); |
| 278 battor::BattOrAgentBin bin; | 309 battor::BattOrAgentBin bin; |
| 279 return bin.Run(argc, argv); | 310 return bin.Run(argc, argv); |
| 280 } | 311 } |
| OLD | NEW |