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

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

Issue 2400163003: arc: enable Android tracing in verified-boot mode (Closed)
Patch Set: Address comments Created 3 years, 8 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>
Luis Héctor Chávez 2017/04/13 21:37:52 do you still need this?
Earl Ou 2017/04/15 20:05:51 Done.
8 #include <sys/socket.h>
Luis Héctor Chávez 2017/04/13 21:37:52 Do you still need this?
Earl Ou 2017/04/15 20:05:51 Done.
9
10 #include <memory>
7 #include <string> 11 #include <string>
12 #include <utility>
13 #include <vector>
8 14
9 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/bind_helpers.h"
17 #include "base/files/file.h"
18 #include "base/files/file_descriptor_watcher_posix.h"
10 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/memory/ptr_util.h"
11 #include "base/memory/singleton.h" 21 #include "base/memory/singleton.h"
12 #include "base/threading/thread_checker.h" 22 #include "base/memory/weak_ptr.h"
23 #include "base/posix/unix_domain_socket_linux.h"
24 #include "base/threading/sequenced_task_runner_handle.h"
13 #include "base/threading/thread_task_runner_handle.h" 25 #include "base/threading/thread_task_runner_handle.h"
26 #include "base/time/time.h"
27 #include "cc/base/ring_buffer.h"
28 #include "content/public/browser/browser_thread.h"
14 29
15 namespace content { 30 namespace content {
16 31
17 namespace { 32 namespace {
18 33
34 // The maximum size used to store one trace event. The ad hoc trace format for
35 // atrace is 1024 bytes. Here we add additional size as we're using JSON and
36 // have additional data field.
37 constexpr size_t kArcTraceMessageLength = 1024 + 512;
38
19 constexpr char kArcTracingAgentName[] = "arc"; 39 constexpr char kArcTracingAgentName[] = "arc";
20 constexpr char kArcTraceLabel[] = "ArcTraceEvents"; 40 constexpr char kArcTraceLabel[] = "ArcTraceEvents";
21 41
22 void OnStopTracing(bool success) { 42 // Number of events for the ring buffer.
23 DLOG_IF(WARNING, !success) << "Failed to stop ARC tracing."; 43 constexpr size_t kTraceEventBufferSize = 64000;
24 } 44
45 // A helper class for reading trace data from the client side. We separate this
46 // from |ArcTracingAgentImpl| to isolate logics that runs on browser's IO
Luis Héctor Chávez 2017/04/13 21:37:52 nit: s/logics/the logic/
Earl Ou 2017/04/15 20:05:51 Done.
47 // thread. All the functions in this class except for constructor, destructor,
48 // and |GetWeakPtr| are expected to be run on browser's IO thread.
49 class ArcTracingReader {
50 public:
51 using StopTracingCallback =
52 base::Callback<void(const scoped_refptr<base::RefCountedString>&)>;
53
54 ArcTracingReader() : weak_ptr_factory_(this) {}
55
56 void StartTracing(base::ScopedFD read_fd) {
57 DCHECK_CURRENTLY_ON(BrowserThread::IO);
58 read_fd_ = std::move(read_fd);
59 // We don't use the weak pointer returned by |GetWeakPtr| to avoid using it
60 // on different task runner. Instead, we use |base::Unretained| here as
61 // fd_watcher_ is always destructed before |this| got destructed.
Luis Héctor Chávez 2017/04/13 21:37:52 nit: |fd_watcher_|. s/got destructed/is destroyed/
62 fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
63 read_fd_.get(), base::Bind(&ArcTracingReader::OnTraceDataAvailable,
64 base::Unretained(this)));
65 }
66
67 void OnTraceDataAvailable() {
68 DCHECK_CURRENTLY_ON(BrowserThread::IO);
69
70 char buf[kArcTraceMessageLength];
71 std::vector<base::ScopedFD> unused_fds;
72 ssize_t n = base::UnixDomainSocket::RecvMsg(
73 read_fd_.get(), buf, kArcTraceMessageLength, &unused_fds);
74 // When EOF, return and do nothing. The clean up is done in StopTracing.
75 if (n == 0)
76 return;
77
78 if (n < 0) {
79 DPLOG(WARNING) << "Unexpected error while reading trace from client.";
80 // Do nothing here as StopTracing will do the clean up and the existing
81 // trace logs will be returned.
82 return;
83 }
84
85 if (n > static_cast<ssize_t>(kArcTraceMessageLength)) {
86 DLOG(WARNING) << "Unexpected data size when reading trace from client.";
87 return;
88 }
89 ring_buffer_.SaveToBuffer(std::string(buf, n));
90 }
91
92 void StopTracing(const StopTracingCallback& callback) {
93 DCHECK_CURRENTLY_ON(BrowserThread::IO);
94 fd_watcher_.reset();
95 read_fd_.reset();
96
97 bool append_comma = false;
98 std::string data;
99 for (auto it = ring_buffer_.Begin(); it; ++it) {
100 if (append_comma)
101 data.append(",");
102 else
103 append_comma = true;
104 data.append(**it);
105 }
106 ring_buffer_.Clear();
107
108 BrowserThread::PostTask(
109 BrowserThread::IO, FROM_HERE,
110 base::Bind(callback, base::RefCountedString::TakeString(&data)));
111 }
112
113 base::WeakPtr<ArcTracingReader> GetWeakPtr() {
114 return weak_ptr_factory_.GetWeakPtr();
115 }
116
117 private:
118 base::ScopedFD read_fd_;
119 std::unique_ptr<base::FileDescriptorWatcher::Controller> fd_watcher_;
120 cc::RingBuffer<std::string, kTraceEventBufferSize> ring_buffer_;
121 // NOTE: Weak pointers must be invalidated before all other member variables
122 // so it must be the last member.
123 base::WeakPtrFactory<ArcTracingReader> weak_ptr_factory_;
124
125 DISALLOW_COPY_AND_ASSIGN(ArcTracingReader);
126 };
25 127
26 class ArcTracingAgentImpl : public ArcTracingAgent { 128 class ArcTracingAgentImpl : public ArcTracingAgent {
27 public: 129 public:
28 // base::trace_event::TracingAgent overrides: 130 // base::trace_event::TracingAgent overrides:
29 std::string GetTracingAgentName() override { return kArcTracingAgentName; } 131 std::string GetTracingAgentName() override { return kArcTracingAgentName; }
30 132
31 std::string GetTraceEventLabel() override { return kArcTraceLabel; } 133 std::string GetTraceEventLabel() override { return kArcTraceLabel; }
32 134
33 void StartAgentTracing(const base::trace_event::TraceConfig& trace_config, 135 void StartAgentTracing(const base::trace_event::TraceConfig& trace_config,
34 const StartAgentTracingCallback& callback) override { 136 const StartAgentTracingCallback& callback) override {
35 DCHECK(thread_checker_.CalledOnValidThread()); 137 DCHECK_CURRENTLY_ON(BrowserThread::UI);
138
36 // delegate_ may be nullptr if ARC is not enabled on the system. In such 139 // delegate_ may be nullptr if ARC is not enabled on the system. In such
37 // case, simply do nothing. 140 // case, simply do nothing.
38 if (!delegate_) { 141 bool success = (delegate_ != nullptr);
142
143 base::ScopedFD write_fd, read_fd;
144 success = success && CreateSocketPair(&read_fd, &write_fd);
145
146 if (!success) {
39 // Use PostTask as the convention of TracingAgent. The caller expects 147 // Use PostTask as the convention of TracingAgent. The caller expects
40 // callback to be called after this function returns. 148 // callback to be called after this function returns.
41 base::ThreadTaskRunnerHandle::Get()->PostTask( 149 base::ThreadTaskRunnerHandle::Get()->PostTask(
42 FROM_HERE, base::Bind(callback, GetTracingAgentName(), false)); 150 FROM_HERE, base::Bind(callback, GetTracingAgentName(), false));
43 return; 151 return;
44 } 152 }
45 153
46 delegate_->StartTracing(trace_config, 154 BrowserThread::PostTask(
155 BrowserThread::IO, FROM_HERE,
156 base::Bind(&ArcTracingReader::StartTracing, reader_.GetWeakPtr(),
157 base::Passed(&read_fd)));
158
159 delegate_->StartTracing(trace_config, std::move(write_fd),
47 base::Bind(callback, GetTracingAgentName())); 160 base::Bind(callback, GetTracingAgentName()));
48 } 161 }
49 162
50 void StopAgentTracing(const StopAgentTracingCallback& callback) override { 163 void StopAgentTracing(const StopAgentTracingCallback& callback) override {
51 DCHECK(thread_checker_.CalledOnValidThread()); 164 DCHECK_CURRENTLY_ON(BrowserThread::UI);
52 if (delegate_)
53 delegate_->StopTracing(base::Bind(OnStopTracing));
54 165
55 // Trace data is collect via systrace (debugd) in dev-mode. Simply 166 if (is_stopping_) {
56 // return empty data here. 167 DLOG(WARNING) << "Already working on stopping ArcTracingAgent.";
57 std::string no_data; 168 return;
58 base::ThreadTaskRunnerHandle::Get()->PostTask( 169 }
59 FROM_HERE, 170 is_stopping_ = true;
60 base::Bind(callback, GetTracingAgentName(), GetTraceEventLabel(), 171 if (delegate_) {
61 base::RefCountedString::TakeString(&no_data))); 172 delegate_->StopTracing(
173 base::Bind(&ArcTracingAgentImpl::OnArcTracingStopped,
174 weak_ptr_factory_.GetWeakPtr(), callback));
175 }
62 } 176 }
63 177
64 // ArcTracingAgent overrides: 178 // ArcTracingAgent overrides:
65 void SetDelegate(Delegate* delegate) override { 179 void SetDelegate(Delegate* delegate) override {
66 DCHECK(thread_checker_.CalledOnValidThread()); 180 DCHECK_CURRENTLY_ON(BrowserThread::UI);
67 delegate_ = delegate; 181 delegate_ = delegate;
68 } 182 }
69 183
70 static ArcTracingAgentImpl* GetInstance() { 184 static ArcTracingAgentImpl* GetInstance() {
71 return base::Singleton<ArcTracingAgentImpl>::get(); 185 return base::Singleton<ArcTracingAgentImpl>::get();
72 } 186 }
73 187
74 private: 188 private:
75 // This allows constructor and destructor to be private and usable only 189 // This allows constructor and destructor to be private and usable only
76 // by the Singleton class. 190 // by the Singleton class.
77 friend struct base::DefaultSingletonTraits<ArcTracingAgentImpl>; 191 friend struct base::DefaultSingletonTraits<ArcTracingAgentImpl>;
78 192
79 ArcTracingAgentImpl() = default; 193 ArcTracingAgentImpl() : weak_ptr_factory_(this) {}
194
80 ~ArcTracingAgentImpl() override = default; 195 ~ArcTracingAgentImpl() override = default;
81 196
197 void OnArcTracingStopped(const StopAgentTracingCallback& callback,
198 bool success) {
199 DCHECK_CURRENTLY_ON(BrowserThread::UI);
200 if (!success) {
201 DLOG(WARNING) << "Failed to stop ARC tracing.";
202 callback.Run(GetTracingAgentName(), GetTraceEventLabel(),
203 new base::RefCountedString());
204 is_stopping_ = false;
205 return;
206 }
207 BrowserThread::PostTask(
208 BrowserThread::IO, FROM_HERE,
209 base::Bind(&ArcTracingReader::StopTracing, reader_.GetWeakPtr(),
210 base::Bind(&ArcTracingAgentImpl::OnTracingReaderStopped,
211 weak_ptr_factory_.GetWeakPtr(), callback)));
212 }
213
214 void OnTracingReaderStopped(
215 const StopAgentTracingCallback& callback,
216 const scoped_refptr<base::RefCountedString>& data) {
217 DCHECK_CURRENTLY_ON(BrowserThread::UI);
218 callback.Run(GetTracingAgentName(), GetTraceEventLabel(), data);
219 is_stopping_ = false;
220 }
221
82 Delegate* delegate_ = nullptr; // Owned by ArcServiceLauncher. 222 Delegate* delegate_ = nullptr; // Owned by ArcServiceLauncher.
83 base::ThreadChecker thread_checker_; 223 // We use |reader_.GetWeakPtr()| when binding callbacks with its functions.
224 // Notes that the weak pointer returned by it can only be deferenced or
225 // invalided in the same task runner to avoid racing condition. The
226 // destruction of |reader_| is also a source of invalidation. However, we're
227 // lucky as we're using |ArcTracingAgentImpl| as a singleton, the
228 // destruction is always performed after all messageloop destructed, and thus
Luis Héctor Chávez 2017/04/13 21:37:52 nit: all MessageLoops are destructed.
Earl Ou 2017/04/15 20:05:51 Done.
229 // no racing condition in such situation.
Luis Héctor Chávez 2017/04/13 21:37:52 nit: "and thus there are no race conditions in suc
Earl Ou 2017/04/15 20:05:51 Done.
230 ArcTracingReader reader_;
231 bool is_stopping_ = false;
232 // NOTE: Weak pointers must be invalidated before all other member variables
233 // so it must be the last member.
234 base::WeakPtrFactory<ArcTracingAgentImpl> weak_ptr_factory_;
84 235
85 DISALLOW_COPY_AND_ASSIGN(ArcTracingAgentImpl); 236 DISALLOW_COPY_AND_ASSIGN(ArcTracingAgentImpl);
86 }; 237 };
87 238
88 } // namespace 239 } // namespace
89 240
90 // static 241 // static
91 ArcTracingAgent* ArcTracingAgent::GetInstance() { 242 ArcTracingAgent* ArcTracingAgent::GetInstance() {
92 return ArcTracingAgentImpl::GetInstance(); 243 return ArcTracingAgentImpl::GetInstance();
93 } 244 }
94 245
95 ArcTracingAgent::ArcTracingAgent() = default; 246 ArcTracingAgent::ArcTracingAgent() = default;
96 ArcTracingAgent::~ArcTracingAgent() = default; 247 ArcTracingAgent::~ArcTracingAgent() = default;
97 248
98 ArcTracingAgent::Delegate::~Delegate() = default; 249 ArcTracingAgent::Delegate::~Delegate() = default;
99 250
100 } // namespace content 251 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698