Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: chrome/browser/chromeos/arc/trace/arc_trace_reader.cc

Issue 2400163003: arc: enable Android tracing in verified-boot mode (Closed)
Patch Set: Fix some nits Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/arc/trace/arc_trace_reader.h"
6
7 #include <errno.h>
8 #include <string.h>
9 #include <sys/select.h>
10
11 #include <memory>
12 #include <sstream>
13 #include <utility>
14 #include <vector>
15
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
20 #include "base/values.h"
21 #include "content/public/browser/browser_thread.h"
22
23 namespace arc {
24
25 namespace {
26
27 #define ARC_TRACE_MESSAGE_LENGTH (1024 + 512)
Luis Héctor Chávez 2017/02/10 17:43:54 constexpr size_t kArcTraceMessageLength = 1024 + 5
Earl Ou 2017/03/22 11:38:26 Done in Android side.
28
29 // Maximum data to be stored in the buffer.
30 constexpr int kTraceBufferByteSize = 16 * 1024 * 1024; // 16MB
31
32 } // namespace
33
34 ArcTraceReader::ArcTraceReader()
35 : is_recording_(false), input_fd_(-1), recording_thread_(nullptr) {}
Luis Héctor Chávez 2017/02/10 17:43:55 these three can be set in the .h, that way you can
Earl Ou 2017/03/22 11:38:26 Done in Android side.
36
37 void ArcTraceReader::Run() {
38 if (input_fd_.get() == -1) {
39 LOG(WARNING) << "No input FD is set before starting recording.";
40 return;
41 }
42
43 int ret;
44 fd_set fds;
45 timeval tv;
46 char buf[ARC_TRACE_MESSAGE_LENGTH];
47
48 while (is_recording_) {
49 FD_ZERO(&fds);
50 FD_SET(input_fd_.get(), &fds);
51
52 // Wait up to 1 second.
53 tv.tv_sec = 1;
54 tv.tv_usec = 0;
55
56 ret = TEMP_FAILURE_RETRY(
57 select(input_fd_.get() + 1, &fds, nullptr, nullptr, &tv));
58 if (ret < 0) {
59 LOG(ERROR) << "Unexpected error while recording ARC trace: "
60 << strerror(errno);
61 break;
62 }
63 if (!ret) // No data available.
64 continue;
65
66 ret = TEMP_FAILURE_RETRY(read(input_fd_.get(), buf, sizeof(buf) - 1));
Luis Héctor Chávez 2017/02/10 23:16:51 in any case, you should try to limit the amount of
Earl Ou 2017/03/22 11:38:26 This is moved to the Android side.
67 if (ret < 0) {
68 LOG(ERROR) << "Unexpected error while reading ARC trace: "
69 << strerror(errno);
70 break;
71 }
72 if (ret == 0) { // EOF
73 LOG(WARNING) << "EOF while recording ARC trace.";
74 break;
75 }
76 buf[ret] = 0; // Make sure the string is null terminated.
77 ParseAndSaveData(buf);
78 }
79 }
80
81 void ArcTraceReader::SetInputFD(base::ScopedFD fd) {
82 input_fd_ = std::move(fd);
83 }
84
85 void ArcTraceReader::StartRecord() {
86 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
87
88 if (is_recording_) {
89 LOG(WARNING) << "ARC trace reader already started.";
90 return;
91 }
92 is_recording_ = true;
93 current_data_size_ = 0;
94 trace_buffer_ = std::queue<std::string>(); // clean the queue.
95
96 recording_thread_.reset(
Luis Héctor Chávez 2017/02/10 17:43:54 How about using base::FileDescriptorWatcher::Watch
Luis Héctor Chávez 2017/02/10 23:16:51 You can also use something similar to https://cs.c
Earl Ou 2017/03/22 11:38:26 Done in arc_tracing_agent.cc
97 new base::DelegateSimpleThread(this, "ArcTraceReader"));
98 recording_thread_->Start();
99 }
100
101 void ArcTraceReader::StopRecord(const StopTracingCallback& callback) {
102 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
103
104 if (!is_recording_) {
105 LOG(WARNING) << "ARC trace reader was not started.";
106 callback.Run("");
107 return;
108 }
109 is_recording_ = false;
110 recording_thread_->Join();
111 recording_thread_.reset(nullptr);
Luis Héctor Chávez 2017/02/10 17:43:54 nit: recording_thread_.reset();
Earl Ou 2017/03/22 11:38:26 No reading thread now as suggested.
112
113 // TODO(shunshingou): run the following in a separated thread to avoid long
Luis Héctor Chávez 2017/02/10 17:43:55 This must be done in this CL, unfortunately. Worst
Luis Héctor Chávez 2017/02/10 17:48:03 D'Oh, this is a socket, not a pipe. Ignore the SIG
Earl Ou 2017/02/16 09:56:45 The comment here is for the processing of stringst
Earl Ou 2017/03/22 11:38:26 Now this is running in IO thread with WatchReadabl
114 // processing in UI thread.
115 std::stringstream ss;
116 bool is_first = true;
117 while (!trace_buffer_.empty()) {
118 if (!is_first)
119 ss << ",";
120 is_first = false;
121 ss << trace_buffer_.front();
122 trace_buffer_.pop();
123 }
124 callback.Run(ss.str());
125 }
126
127 void ArcTraceReader::WriteTraceEvent(char ph,
128 int pid,
129 int tid,
130 uint64_t ts,
131 uint64_t tts,
132 const std::string* name,
133 const int* count,
134 const int* id) {
135 base::DictionaryValue event;
136 event.SetString("cat", "android");
137 event.SetString("ph", std::string(1, ph));
138 event.SetInteger("pid", pid);
139 event.SetInteger("tid", tid);
140 event.SetDouble("ts", ts);
141 event.SetDouble("tts", tts);
142 if (name)
143 event.SetString("name", *name);
144
145 if (count)
146 event.SetInteger("args.count", *count);
147
148 if (id)
149 event.SetInteger("id", *id);
150
151 std::string json;
152 if (!base::JSONWriter::Write(event, &json)) {
153 // Bad data, shouldn't happen as the data is prepared by ourself.
Luis Héctor Chávez 2017/02/10 17:43:54 nit: ourselves.
Earl Ou 2017/03/22 11:38:26 Done on the Android side.
154 // Skip and return.
155 return;
156 }
157
158 current_data_size_ += json.size();
Luis Héctor Chávez 2017/02/10 17:43:54 Why do you still need this? Why can't you just sen
Luis Héctor Chávez 2017/02/10 23:16:51 Ignore the above comment, since it's the way the A
Earl Ou 2017/02/16 09:56:45 trace_buffer seems to be designed for Chrome traci
Earl Ou 2017/03/22 11:38:26 I'm using TraceBuffer in the new patch now.
159 trace_buffer_.emplace(std::move(json));
160
161 while (current_data_size_ > kTraceBufferByteSize) {
162 current_data_size_ -= trace_buffer_.front().size();
163 trace_buffer_.pop();
164 }
165 }
166
167 void ArcTraceReader::ParseAndSaveData(std::string data) {
Luis Héctor Chávez 2017/02/10 17:43:54 This might fail since |data| might contain multipl
Earl Ou 2017/02/16 09:56:46 The data would only have one trace event since we'
168 const std::vector<std::string> tokens =
169 base::SplitString(data, "|", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
170
171 // ph|pid|tid|ts|tts
172 if (tokens.size() < 5 || tokens[0].size() != 1) // bad data, skip.
173 return;
174
175 char ph = tokens[0][0];
176 int pid, tid;
177 uint64_t ts, tts;
178
179 if (!base::StringToInt(tokens[1], &pid) ||
180 !base::StringToInt(tokens[2], &tid) ||
181 !base::StringToUint64(tokens[3], &ts) ||
182 !base::StringToUint64(tokens[4], &tts)) {
183 return; // bad data, skip.
184 }
185
186 switch (ph) {
187 case 'B':
188 // B|pid|tid|ts|tts|name
189 if (tokens.size() != 6)
190 return; // bad data, skip.
191 WriteTraceEvent(ph, pid, tid, ts, tts, &tokens[5]);
192 break;
193 case 'E':
194 // E|pid|tid|ts|tts
195 WriteTraceEvent(ph, pid, tid, ts, tts);
196 break;
197 case 'F':
198 case 'S':
199 // F|pid|tid|ts|tts|name|value
200 int id;
201 if (tokens.size() != 7 || !base::StringToInt(tokens[6], &id))
202 return; // bad data, skip.
203 WriteTraceEvent(ph, pid, tid, ts, tts, &tokens[5], nullptr, &id);
204 break;
205 case 'C':
206 // C|pid|tid|ts|tts|name|value
207 int count;
208 if (tokens.size() != 7 || !base::StringToInt(tokens[6], &count))
209 return; // bad data, skip.
210 WriteTraceEvent(ph, pid, tid, ts, tts, &tokens[5], &count);
211 break;
212 }
213 }
214
215 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698