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

Side by Side Diff: content/browser/tracing/arc_tracing_agent.cc

Issue 2400163003: arc: enable Android tracing in verified-boot mode (Closed)
Patch Set: Rebase to crrev.com/2699833003 as it is merged Created 3 years, 9 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
1 // Copyright 2017 The Chromium Authors. All rights reserved. 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 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 #include "content/browser/tracing/arc_tracing_agent.h" 5 #include "content/browser/tracing/arc_tracing_agent.h"
6 6
7 #include <string.h>
8 #include <sys/socket.h>
9
10 #include <memory>
7 #include <string> 11 #include <string>
12 #include <utility>
8 13
9 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/files/file.h"
16 #include "base/files/file_descriptor_watcher_posix.h"
10 #include "base/logging.h" 17 #include "base/logging.h"
11 #include "base/memory/singleton.h" 18 #include "base/memory/singleton.h"
12 #include "base/threading/thread_checker.h" 19 #include "base/memory/weak_ptr.h"
20 #include "base/threading/sequenced_task_runner_handle.h"
13 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
22 #include "base/time/time.h"
23 #include "base/trace_event/trace_buffer.h"
24 #include "content/public/browser/browser_thread.h"
25
26 using base::trace_event::TraceEvent;
27 using base::trace_event::TraceBuffer;
28 using base::trace_event::TraceBufferChunk;
14 29
15 namespace content { 30 namespace content {
16 31
17 namespace { 32 namespace {
18 33
34 constexpr int kArcTraceMessageLength = 1024 + 512;
Luis Héctor Chávez 2017/03/22 17:04:58 nit: size_t
shunhsingou 2017/03/28 13:54:15 Done.
19 constexpr char kArcTracingAgentName[] = "arc"; 35 constexpr char kArcTracingAgentName[] = "arc";
20 constexpr char kArcTraceLabel[] = "ArcTraceEvents"; 36 constexpr char kArcTraceLabel[] = "ArcTraceEvents";
21 37
22 void OnStopTracing(bool success) { 38 // Number of chunks for the ring buffer.
23 DLOG_IF(WARNING, !success) << "Failed to stop ARC tracing."; 39 constexpr int kTraceEventChunks =
Luis Héctor Chávez 2017/03/22 17:04:57 nit: size_t
shunhsingou 2017/03/28 13:54:14 Done.
40 64000 / TraceBufferChunk::kTraceBufferChunkSize;
41
42 bool CreateSocketPair(base::ScopedFD* one, base::ScopedFD* two) {
Luis Héctor Chávez 2017/03/22 17:04:57 I see that you copied this from base/posix/unix_do
shunhsingou 2017/03/28 13:54:14 Done.
43 int raw_socks[2];
44 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks) == -1)
45 return false;
46 one->reset(raw_socks[0]);
47 two->reset(raw_socks[1]);
48 return true;
24 } 49 }
25 50
26 class ArcTracingAgentImpl : public ArcTracingAgent { 51 class ArcTracingAgentImpl : public ArcTracingAgent {
27 public: 52 public:
28 // base::trace_event::TracingAgent overrides: 53 // base::trace_event::TracingAgent overrides:
29 std::string GetTracingAgentName() override { return kArcTracingAgentName; } 54 std::string GetTracingAgentName() override { return kArcTracingAgentName; }
30 55
31 std::string GetTraceEventLabel() override { return kArcTraceLabel; } 56 std::string GetTraceEventLabel() override { return kArcTraceLabel; }
32 57
33 void StartAgentTracing(const base::trace_event::TraceConfig& trace_config, 58 void StartAgentTracing(const base::trace_event::TraceConfig& trace_config,
34 const StartAgentTracingCallback& callback) override { 59 const StartAgentTracingCallback& callback) override {
35 DCHECK(thread_checker_.CalledOnValidThread()); 60 DCHECK_CURRENTLY_ON(BrowserThread::UI);
36 // delegate_ may be nullptr if ARC is not enabled on the system. In such 61 // delegate_ may be nullptr if ARC is not enabled on the system. In such
37 // case, simply do nothing. 62 // case, simply do nothing.
38 if (!delegate_) { 63 if (!delegate_) {
39 // Use PostTask as the convention of TracingAgent. The caller expects 64 // Use PostTask as the convention of TracingAgent. The caller expects
40 // callback to be called after this function returns. 65 // callback to be called after this function returns.
41 base::ThreadTaskRunnerHandle::Get()->PostTask( 66 base::ThreadTaskRunnerHandle::Get()->PostTask(
42 FROM_HERE, base::Bind(callback, GetTracingAgentName(), false)); 67 FROM_HERE, base::Bind(callback, GetTracingAgentName(), false));
43 return; 68 return;
44 } 69 }
45 70 base::ScopedFD write_fd, read_fd;
46 delegate_->StartTracing(trace_config, 71 CreateSocketPair(&read_fd, &write_fd);
Luis Héctor Chávez 2017/03/22 17:04:58 Make this fail if CreateSocketPair() returns false
shunhsingou 2017/03/28 13:54:15 Done.
72 data_file_.reset(new base::File(read_fd.release()));
Luis Héctor Chávez 2017/03/22 17:04:57 nit: data_file_ = base::MakeUnique<base::File>(rea
shunhsingou 2017/03/28 13:54:14 This data member is removed.
73 CreateBuffer();
74 BrowserThread::PostTask(
75 BrowserThread::IO, FROM_HERE,
76 base::Bind(&ArcTracingAgentImpl::InitFileDescriptorWatcher,
77 weak_ptr_factory_.GetWeakPtr(),
78 data_file_->GetPlatformFile()));
79 delegate_->StartTracing(trace_config, std::move(write_fd),
47 base::Bind(callback, GetTracingAgentName())); 80 base::Bind(callback, GetTracingAgentName()));
48 } 81 }
49 82
50 void StopAgentTracing(const StopAgentTracingCallback& callback) override { 83 void StopAgentTracing(const StopAgentTracingCallback& callback) override {
51 DCHECK(thread_checker_.CalledOnValidThread()); 84 DCHECK_CURRENTLY_ON(BrowserThread::UI);
85
86 if (!callback_.is_null()) {
87 DLOG(WARNING) << "Already working on stopping ArcTracingAgent.";
88 return;
89 }
90 callback_ = callback;
Luis Héctor Chávez 2017/03/22 17:04:57 You don't need to do this. You can instead do del
shunhsingou 2017/03/28 13:54:14 Done. My original thought is that we still need an
52 if (delegate_) 91 if (delegate_)
Luis Héctor Chávez 2017/03/22 17:04:58 nit: you cannot elide braces since the body spans
shunhsingou 2017/03/28 13:54:15 Done.
53 delegate_->StopTracing(base::Bind(OnStopTracing)); 92 delegate_->StopTracing(
54 93 base::Bind(&ArcTracingAgentImpl::OnArcTracingStopped,
55 // Trace data is collect via systrace (debugd) in dev-mode. Simply 94 weak_ptr_factory_.GetWeakPtr()));
56 // return empty data here.
57 std::string no_data;
58 base::ThreadTaskRunnerHandle::Get()->PostTask(
59 FROM_HERE,
60 base::Bind(callback, GetTracingAgentName(), GetTraceEventLabel(),
61 base::RefCountedString::TakeString(&no_data)));
62 } 95 }
63 96
64 // ArcTracingAgent overrides: 97 // ArcTracingAgent overrides:
65 void SetDelegate(Delegate* delegate) override { 98 void SetDelegate(Delegate* delegate) override {
66 DCHECK(thread_checker_.CalledOnValidThread()); 99 DCHECK_CURRENTLY_ON(BrowserThread::UI);
67 delegate_ = delegate; 100 delegate_ = delegate;
68 } 101 }
69 102
70 static ArcTracingAgentImpl* GetInstance() { 103 static ArcTracingAgentImpl* GetInstance() {
71 return base::Singleton<ArcTracingAgentImpl>::get(); 104 return base::Singleton<ArcTracingAgentImpl>::get();
72 } 105 }
73 106
74 private: 107 private:
75 // This allows constructor and destructor to be private and usable only 108 // This allows constructor and destructor to be private and usable only
76 // by the Singleton class. 109 // by the Singleton class.
77 friend struct base::DefaultSingletonTraits<ArcTracingAgentImpl>; 110 friend struct base::DefaultSingletonTraits<ArcTracingAgentImpl>;
78 111
79 ArcTracingAgentImpl() = default; 112 ArcTracingAgentImpl() : weak_ptr_factory_(this) {}
113
80 ~ArcTracingAgentImpl() override = default; 114 ~ArcTracingAgentImpl() override = default;
81 115
116 void CreateBuffer() {
117 trace_buffer_.reset(
118 TraceBuffer::CreateTraceBufferRingBuffer(kTraceEventChunks));
119 chunk_.reset(nullptr);
Luis Héctor Chávez 2017/03/22 17:04:58 nit: chunk_.reset();
shunhsingou 2017/03/28 13:54:14 Done.
120 chunk_index_ = 0;
121 }
122
123 void OnTraceDataAvailable() {
Luis Héctor Chávez 2017/03/22 17:04:58 Can you move all the buffer-related stuff to anoth
shunhsingou 2017/03/28 13:54:14 Done.
124 DCHECK_CURRENTLY_ON(BrowserThread::IO);
125 char buf[kArcTraceMessageLength + 1];
126 int n =
127 data_file_->ReadAtCurrentPosNoBestEffort(buf, kArcTraceMessageLength);
Luis Héctor Chávez 2017/03/22 17:04:58 I'm a bit worried that we might need to use recv()
shunhsingou 2017/03/28 13:54:14 Done.
128 if (n == 0)
Luis Héctor Chávez 2017/03/22 17:04:58 What about errors?
shunhsingou 2017/03/28 13:54:15 Done.
129 return;
130
131 buf[n] = 0;
132 char* data = new char[n + 1];
Luis Héctor Chávez 2017/03/22 17:04:57 you're leaking this :(
shunhsingou 2017/03/28 13:54:14 Done. It's now free in StopTracing.
133 memcpy(data, buf, n + 1);
Luis Héctor Chávez 2017/03/22 18:23:04 You need to add if (n > kArcTraceMessageLength) {
shunhsingou 2017/03/28 13:54:14 Done.
134
135 // Save data into trace buffer.
136 if (!chunk_)
137 chunk_ = trace_buffer_->GetChunk(&chunk_index_);
138 size_t event_index;
139 TraceEvent* event = chunk_->AddTraceEvent(&event_index);
140
141 // Here we don't actually parse the data, which should already be a valid
Luis Héctor Chávez 2017/03/22 17:04:57 This is a dangerous assumption :( What happens if
shunhsingou 2017/03/28 13:54:15 Done add a validation check here.
142 // trace JSON object. We only use |TraceEvent| for saving data in
143 // |TraceBuffer| and |TraceBufferChunk|. So we can just put everything in
144 // |name|, and only fetch the |name| field after finishing tracing to
145 // avoid unnecessary deserialize and serialize from/to JSON.
146 event->Initialize(0, base::TimeTicks(), base::ThreadTicks(), 0, nullptr,
147 data, nullptr, 0, 0, 0, nullptr, nullptr, nullptr,
148 nullptr, 0);
149
150 if (chunk_->IsFull()) {
151 trace_buffer_->ReturnChunk(chunk_index_, std::move(chunk_));
152 chunk_ = trace_buffer_->GetChunk(&chunk_index_);
153 }
154 }
155
156 void InitFileDescriptorWatcher(int fd) {
157 DCHECK_CURRENTLY_ON(BrowserThread::IO);
158 fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
159 fd, base::Bind(&ArcTracingAgentImpl::OnTraceDataAvailable,
160 weak_ptr_factory_.GetWeakPtr()));
161 }
162
163 void OnArcTracingStopped(bool success) {
164 if (!success) {
165 DLOG(WARNING) << "Failed to stop ARC tracing.";
166 std::string no_data;
167 base::ResetAndReturn(&callback_)
168 .Run(GetTracingAgentName(), GetTraceEventLabel(),
169 base::RefCountedString::TakeString(&no_data));
170 return;
171 }
172 BrowserThread::PostTask(
173 BrowserThread::IO, FROM_HERE,
174 base::Bind(&ArcTracingAgentImpl::StopTracingInIOThread,
175 weak_ptr_factory_.GetWeakPtr()));
176 }
177
178 void StopTracingInIOThread() {
179 DCHECK_CURRENTLY_ON(BrowserThread::IO);
180 close(read_fd_.release());
Luis Héctor Chávez 2017/03/22 18:09:34 nit: read_fd_.reset();
shunhsingou 2017/03/28 13:54:15 Done.
181 // Stop fd_watcher_.
182 fd_watcher_.reset(nullptr);
Luis Héctor Chávez 2017/03/22 18:09:34 nit: fd_watcher_.reset();
shunhsingou 2017/03/28 13:54:14 Done.
183 if (chunk_)
184 trace_buffer_->ReturnChunk(chunk_index_, std::move(chunk_));
185
186 bool append_comma = false;
187 std::string data;
188 while (const TraceBufferChunk* chunk = trace_buffer_->NextChunk()) {
189 for (size_t i = 0; i < chunk->size(); ++i) {
190 const TraceEvent* event = chunk->GetEventAt(i);
191 if (append_comma)
192 data.append(",");
193 // See comment in |OnTraceDataAvailable|. We put the whole valid JSON
194 // object in |name|.
195 data.append(event->name());
196 append_comma = true;
197 }
198 }
199 base::ResetAndReturn(&callback_)
200 .Run(GetTracingAgentName(), GetTraceEventLabel(),
201 base::RefCountedString::TakeString(&data));
202 }
203
82 Delegate* delegate_ = nullptr; // Owned by ArcServiceLauncher. 204 Delegate* delegate_ = nullptr; // Owned by ArcServiceLauncher.
83 base::ThreadChecker thread_checker_; 205 base::ScopedFD read_fd_;
206 std::unique_ptr<base::File> data_file_;
207 std::unique_ptr<base::FileDescriptorWatcher::Controller> fd_watcher_;
208 std::unique_ptr<TraceBuffer> trace_buffer_;
209 std::unique_ptr<TraceBufferChunk> chunk_;
210 size_t chunk_index_;
211 StopAgentTracingCallback callback_;
212
213 // NOTE: Weak pointers must be invalidated before all other member variables
214 // so it must be the last member.
215 base::WeakPtrFactory<ArcTracingAgentImpl> weak_ptr_factory_;
84 216
85 DISALLOW_COPY_AND_ASSIGN(ArcTracingAgentImpl); 217 DISALLOW_COPY_AND_ASSIGN(ArcTracingAgentImpl);
86 }; 218 };
87 219
88 } // namespace 220 } // namespace
89 221
90 // static 222 // static
91 ArcTracingAgent* ArcTracingAgent::GetInstance() { 223 ArcTracingAgent* ArcTracingAgent::GetInstance() {
92 return ArcTracingAgentImpl::GetInstance(); 224 return ArcTracingAgentImpl::GetInstance();
93 } 225 }
94 226
95 ArcTracingAgent::ArcTracingAgent() = default; 227 ArcTracingAgent::ArcTracingAgent() = default;
96 ArcTracingAgent::~ArcTracingAgent() = default; 228 ArcTracingAgent::~ArcTracingAgent() = default;
97 229
98 ArcTracingAgent::Delegate::~Delegate() = default; 230 ArcTracingAgent::Delegate::~Delegate() = default;
99 231
100 } // namespace content 232 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/tracing/arc_tracing_agent.h ('k') | content/browser/tracing/tracing_controller_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698