Chromium Code Reviews| 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.. | 8 // tracing commands to the BattOr through an interactive shell. |
| 9 | 9 |
| 10 #include <stdint.h> | 10 #include <stdint.h> |
| 11 | 11 |
| 12 #include <iostream> | 12 #include <iostream> |
| 13 | 13 |
| 14 #include "base/at_exit.h" | 14 #include "base/at_exit.h" |
| 15 #include "base/bind.h" | 15 #include "base/bind.h" |
| 16 #include "base/bind_helpers.h" | 16 #include "base/bind_helpers.h" |
| 17 #include "base/command_line.h" | 17 #include "base/command_line.h" |
| 18 #include "base/location.h" | 18 #include "base/location.h" |
| 19 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
| 22 #include "tools/battor_agent/battor_agent.h" | 22 #include "tools/battor_agent/battor_agent.h" |
| 23 #include "tools/battor_agent/battor_error.h" | 23 #include "tools/battor_agent/battor_error.h" |
| 24 #include "tools/battor_agent/battor_finder.h" | 24 #include "tools/battor_agent/battor_finder.h" |
| 25 | 25 |
| 26 using std::cout; | |
| 27 using std::endl; | 26 using std::endl; |
| 28 | 27 |
| 29 namespace { | 28 namespace { |
| 30 | 29 |
| 31 const char kIoThreadName[] = "BattOr IO Thread"; | 30 const char kIoThreadName[] = "BattOr IO Thread"; |
| 32 const char kFileThreadName[] = "BattOr File Thread"; | 31 const char kFileThreadName[] = "BattOr File Thread"; |
| 33 const char kUiThreadName[] = "BattOr UI Thread"; | 32 const char kUiThreadName[] = "BattOr UI Thread"; |
| 34 const int32_t kBattOrCommandTimeoutSeconds = 10; | 33 const int32_t kBattOrCommandTimeoutSeconds = 10; |
| 35 | 34 |
| 36 void PrintUsage() { | 35 void PrintUsage() { |
| 37 cout << "Usage: battor_agent <command> <arguments> <switches>" << endl | 36 std::cout << "Start the battor_agent shell with:" << endl |
| 38 << endl | 37 << endl |
| 39 << "Commands:" << endl | 38 << " battor_agent <switches>" << endl |
| 39 << endl | |
| 40 << "Switches: " << endl | |
| 41 << " --battor-path=<path> Uses the specified BattOr path." << endl | |
| 42 << endl | |
| 43 << "Once in the shell, you can issue the following commands:" << endl | |
| 40 << endl | 44 << endl |
| 41 << " StartTracing" << endl | 45 << " StartTracing" << endl |
| 42 << " StopTracing" << endl | 46 << " StopTracing" << endl |
| 43 << " SupportsExplicitClockSync" << endl | 47 << " SupportsExplicitClockSync" << endl |
| 44 << " RecordClockSyncMarker <marker>" << endl | 48 << " RecordClockSyncMarker <marker>" << endl |
| 45 << " IssueClockSyncMarker" << endl | 49 << " Exit" << endl |
| 46 << " Help" << endl | 50 << " Help" << endl; |
| 47 << endl | |
| 48 << "Switches:" << endl | |
| 49 << endl | |
| 50 << " --battor-path=<path> Uses the specified BattOr path." << endl; | |
| 51 } | 51 } |
| 52 | 52 |
| 53 void PrintSupportsExplicitClockSync() { | 53 void PrintSupportsExplicitClockSync() { |
| 54 cout << battor::BattOrAgent::SupportsExplicitClockSync() << endl; | 54 std::cout << battor::BattOrAgent::SupportsExplicitClockSync() << endl; |
| 55 } | |
| 56 | |
| 57 // Retrieves argument argnum from the argument list, or an empty string if the | |
| 58 // argument doesn't exist. | |
| 59 std::string GetArg(size_t argnum, base::CommandLine::StringVector args) { | |
| 60 if (argnum >= args.size()) { | |
| 61 return std::string(); | |
| 62 } | |
| 63 | |
| 64 #if defined(OS_WIN) | |
| 65 return base::WideToUTF8(args[argnum]); | |
| 66 #else | |
| 67 return args[argnum]; | |
| 68 #endif | |
| 69 } | 55 } |
| 70 | 56 |
| 71 // Checks if an error occurred and, if it did, prints the error and exits | 57 // Checks if an error occurred and, if it did, prints the error and exits |
| 72 // with an error code. | 58 // with an error code. |
| 73 void CheckError(battor::BattOrError error) { | 59 void CheckError(battor::BattOrError error) { |
| 74 if (error != battor::BATTOR_ERROR_NONE) | 60 if (error != battor::BATTOR_ERROR_NONE) |
| 75 LOG(FATAL) << "Fatal error when communicating with the BattOr: " << error; | 61 LOG(FATAL) << "Fatal error when communicating with the BattOr: " << error; |
| 76 } | 62 } |
| 77 | 63 |
| 78 // Prints an error message and exits due to a required thread failing to start. | 64 // Prints an error message and exits due to a required thread failing to start. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 89 class BattOrAgentBin : public BattOrAgent::Listener { | 75 class BattOrAgentBin : public BattOrAgent::Listener { |
| 90 public: | 76 public: |
| 91 BattOrAgentBin() | 77 BattOrAgentBin() |
| 92 : done_(false, false), | 78 : done_(false, false), |
| 93 io_thread_(kIoThreadName), | 79 io_thread_(kIoThreadName), |
| 94 file_thread_(kFileThreadName), | 80 file_thread_(kFileThreadName), |
| 95 ui_thread_(kUiThreadName) {} | 81 ui_thread_(kUiThreadName) {} |
| 96 | 82 |
| 97 ~BattOrAgentBin() { DCHECK(!agent_); } | 83 ~BattOrAgentBin() { DCHECK(!agent_); } |
| 98 | 84 |
| 99 // Runs the BattOr binary and returns the exit code. | 85 // Starts the interactive BattOr agent shell and eventually returns an exit |
| 86 // code. | |
| 100 int Run(int argc, char* argv[]) { | 87 int Run(int argc, char* argv[]) { |
| 101 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | |
| 102 std::string cmd = GetArg(0, command_line->GetArgs()); | |
| 103 if (cmd.empty()) { | |
| 104 PrintUsage(); | |
| 105 exit(1); | |
| 106 } | |
| 107 | |
| 108 // SupportsExplicitClockSync doesn't need to use the serial connection, so | |
| 109 // handle it separately. | |
| 110 if (cmd == "SupportsExplicitClockSync") { | |
| 111 PrintSupportsExplicitClockSync(); | |
| 112 return 0; | |
| 113 } | |
| 114 | |
| 115 // If we don't have any BattOr to use, exit. | 88 // If we don't have any BattOr to use, exit. |
| 116 std::string path = BattOrFinder::FindBattOr(); | 89 std::string path = BattOrFinder::FindBattOr(); |
|
alexandermont
2016/02/24 22:01:48
Where is the "battor-path" switch actually read? I
Zhen Wang
2016/02/24 22:35:45
Yes, it is done in FindBattOr. base::CommandLine::
| |
| 117 if (path.empty()) { | 90 if (path.empty()) { |
| 118 cout << "Unable to find a BattOr." << endl; | 91 std::cout << "Unable to find a BattOr." << endl; |
| 119 exit(1); | 92 exit(1); |
| 120 } | 93 } |
| 121 | 94 |
| 122 SetUp(path); | 95 SetUp(path); |
| 123 | 96 |
| 124 if (cmd == "StartTracing") { | 97 std::string cmd; |
| 125 StartTracing(); | 98 for (;;) { |
|
alexandermont
2016/02/24 22:01:47
maybe while(true) instead?
| |
| 126 } else if (cmd == "StopTracing") { | 99 std::getline(std::cin, cmd); |
| 127 StopTracing(); | 100 |
| 128 } else if (cmd == "RecordClockSyncMarker") { | 101 if (cmd == "StartTracing") { |
| 129 // TODO(charliea): Write RecordClockSyncMarker. | 102 StartTracing(); |
| 130 } else if (cmd == "IssueClockSyncMarker") { | 103 } else if (cmd == "StopTracing") { |
|
alexandermont
2016/02/24 22:01:48
documentation should mention that StopTracing make
| |
| 131 // TODO(charliea): Write IssueClockSyncMarker. | 104 StopTracing(); |
| 132 } else { | 105 break; |
| 133 TearDown(); | 106 } else if (cmd == "SupportsExplicitClockSync") { |
| 134 PrintUsage(); | 107 PrintSupportsExplicitClockSync(); |
| 135 return 1; | 108 } else if (cmd == "RecordClockSyncMarker") { |
| 109 // TODO(charliea): Write RecordClockSyncMarker. | |
| 110 } else if (cmd == "Exit") { | |
| 111 break; | |
| 112 } else { | |
| 113 PrintUsage(); | |
| 114 } | |
| 136 } | 115 } |
| 137 | 116 |
| 138 TearDown(); | 117 TearDown(); |
| 139 return 0; | 118 return 0; |
| 140 } | 119 } |
| 141 | 120 |
| 142 // Performs any setup necessary for the BattOr binary to run. | 121 // Performs any setup necessary for the BattOr binary to run. |
| 143 void SetUp(const std::string& path) { | 122 void SetUp(const std::string& path) { |
| 144 // TODO(charliea): Investigate whether it's possible to replace this | 123 // TODO(charliea): Investigate whether it's possible to replace this |
| 145 // separate thread with a combination of MessageLoopForIO and RunLoop. | 124 // separate thread with a combination of MessageLoopForIO and RunLoop. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 165 | 144 |
| 166 void StartTracing() { | 145 void StartTracing() { |
| 167 io_thread_.task_runner()->PostTask( | 146 io_thread_.task_runner()->PostTask( |
| 168 FROM_HERE, | 147 FROM_HERE, |
| 169 base::Bind(&BattOrAgent::StartTracing, base::Unretained(agent_.get()))); | 148 base::Bind(&BattOrAgent::StartTracing, base::Unretained(agent_.get()))); |
| 170 CheckError(AwaitResult()); | 149 CheckError(AwaitResult()); |
| 171 } | 150 } |
| 172 | 151 |
| 173 void OnStartTracingComplete(BattOrError error) override { | 152 void OnStartTracingComplete(BattOrError error) override { |
| 174 error_ = error; | 153 error_ = error; |
| 154 std::cout << "Done." << endl; | |
| 175 done_.Signal(); | 155 done_.Signal(); |
| 176 } | 156 } |
| 177 | 157 |
| 178 void StopTracing() { | 158 void StopTracing() { |
| 179 io_thread_.task_runner()->PostTask( | 159 io_thread_.task_runner()->PostTask( |
| 180 FROM_HERE, | 160 FROM_HERE, |
| 181 base::Bind(&BattOrAgent::StopTracing, base::Unretained(agent_.get()))); | 161 base::Bind(&BattOrAgent::StopTracing, base::Unretained(agent_.get()))); |
| 182 CheckError(AwaitResult()); | 162 CheckError(AwaitResult()); |
| 183 } | 163 } |
| 184 | 164 |
| 185 void OnStopTracingComplete(const std::string& trace, | 165 void OnStopTracingComplete(const std::string& trace, |
| 186 BattOrError error) override { | 166 BattOrError error) override { |
| 187 error_ = error; | 167 error_ = error; |
| 188 | 168 |
| 189 if (error == BATTOR_ERROR_NONE) | 169 if (error == BATTOR_ERROR_NONE) |
| 190 cout << trace << endl; | 170 std::cout << trace; |
| 191 | 171 |
| 192 done_.Signal(); | 172 done_.Signal(); |
| 193 } | 173 } |
| 194 | 174 |
| 195 void OnRecordClockSyncMarkerComplete(BattOrError error) override { | 175 void OnRecordClockSyncMarkerComplete(BattOrError error) override { |
| 196 // TODO(charliea): Implement RecordClockSyncMarker for this binary. This | 176 // TODO(charliea): Implement RecordClockSyncMarker for this binary. This |
| 197 // will probably involve reading an external file for the actual sample | 177 // will probably involve reading an external file for the actual sample |
| 198 // number to clock sync ID map. | 178 // number to clock sync ID map. |
| 199 NOTREACHED(); | 179 NOTREACHED(); |
| 200 } | 180 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 255 }; | 235 }; |
| 256 | 236 |
| 257 } // namespace battor | 237 } // namespace battor |
| 258 | 238 |
| 259 int main(int argc, char* argv[]) { | 239 int main(int argc, char* argv[]) { |
| 260 base::AtExitManager exit_manager; | 240 base::AtExitManager exit_manager; |
| 261 base::CommandLine::Init(argc, argv); | 241 base::CommandLine::Init(argc, argv); |
| 262 battor::BattOrAgentBin bin; | 242 battor::BattOrAgentBin bin; |
| 263 return bin.Run(argc, argv); | 243 return bin.Run(argc, argv); |
| 264 } | 244 } |
| OLD | NEW |