blob: 2fc18a32e54adbe9ba9f930c921dbf746365f199 [file] [log] [blame]
Lalit Maganti79f2d7b2018-01-23 18:27:33 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "test/fake_producer.h"
18
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000019#include <mutex>
Lalit Maganti3f5705c2018-03-09 12:09:44 +000020
Lalit Maganti79f2d7b2018-01-23 18:27:33 +000021#include "perfetto/base/logging.h"
Eric Seckler83dcc8c2019-08-21 12:18:43 +010022#include "perfetto/base/time.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010023#include "perfetto/ext/base/utils.h"
24#include "perfetto/ext/traced/traced.h"
Primiano Tucci9c41ceb2020-04-14 13:23:01 +010025#include "perfetto/ext/tracing/core/commit_data_request.h"
Eric Seckler526921b2020-02-18 11:44:30 +000026#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010027#include "perfetto/ext/tracing/core/trace_packet.h"
28#include "perfetto/ext/tracing/core/trace_writer.h"
Primiano Tucci3b39fc72019-06-22 19:05:23 +010029#include "perfetto/tracing/core/data_source_config.h"
Primiano Tucci57dd66b2019-10-15 23:09:04 +010030
31#include "protos/perfetto/config/test_config.gen.h"
Primiano Tucci355b8c82019-08-29 08:37:51 +020032#include "protos/perfetto/trace/test_event.pbzero.h"
33#include "protos/perfetto/trace/trace_packet.pbzero.h"
Lalit Maganti79f2d7b2018-01-23 18:27:33 +000034
35namespace perfetto {
36
Eric Seckler526921b2020-02-18 11:44:30 +000037namespace {
38const MaybeUnboundBufferID kStartupTargetBufferReservationId = 1;
39} // namespace
40
41FakeProducer::FakeProducer(const std::string& name,
42 base::TaskRunner* task_runner)
43 : name_(name), task_runner_(task_runner) {}
Lalit Maganti79f2d7b2018-01-23 18:27:33 +000044FakeProducer::~FakeProducer() = default;
45
Eric Seckler326a3d32020-02-04 11:24:56 +000046void FakeProducer::Connect(const char* socket_name,
Primiano Tuccibbe68be2020-04-16 22:17:12 +010047 std::function<void()> on_connect,
Eric Seckler326a3d32020-02-04 11:24:56 +000048 std::function<void()> on_setup_data_source_instance,
49 std::function<void()> on_create_data_source_instance,
Eric Seckler526921b2020-02-18 11:44:30 +000050 std::unique_ptr<SharedMemory> shm,
51 std::unique_ptr<SharedMemoryArbiter> shm_arbiter) {
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000052 PERFETTO_DCHECK_THREAD(thread_checker_);
Isabelle Taylor86262cb2018-03-27 16:00:54 +010053 endpoint_ = ProducerIPCClient::Connect(
Eric Seckler526921b2020-02-18 11:44:30 +000054 socket_name, this, "android.perfetto.FakeProducer", task_runner_,
Eric Seckler326a3d32020-02-04 11:24:56 +000055 TracingService::ProducerSMBScrapingMode::kDefault,
56 /*shared_memory_size_hint_bytes=*/0,
Eric Seckler526921b2020-02-18 11:44:30 +000057 /*shared_memory_page_size_hint_bytes=*/base::kPageSize, std::move(shm),
58 std::move(shm_arbiter));
Primiano Tuccibbe68be2020-04-16 22:17:12 +010059 on_connect_ = std::move(on_connect);
Stephen Nuskoe8238112019-04-09 18:37:00 +010060 on_setup_data_source_instance_ = std::move(on_setup_data_source_instance);
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000061 on_create_data_source_instance_ = std::move(on_create_data_source_instance);
Lalit Maganti79f2d7b2018-01-23 18:27:33 +000062}
63
64void FakeProducer::OnConnect() {
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000065 PERFETTO_DCHECK_THREAD(thread_checker_);
Lalit Maganti79f2d7b2018-01-23 18:27:33 +000066 DataSourceDescriptor descriptor;
67 descriptor.set_name(name_);
Primiano Tucci9daa4832018-03-28 23:28:17 +010068 endpoint_->RegisterDataSource(descriptor);
Primiano Tuccibbe68be2020-04-16 22:17:12 +010069 auto on_connect_callback = std::move(on_connect_);
70 auto task_runner = task_runner_;
71 endpoint_->Sync([task_runner, on_connect_callback] {
72 task_runner->PostTask(on_connect_callback);
73 });
Lalit Maganti79f2d7b2018-01-23 18:27:33 +000074}
75
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000076void FakeProducer::OnDisconnect() {
77 PERFETTO_DCHECK_THREAD(thread_checker_);
Primiano Tucci008cdb92019-07-19 19:52:41 +010078 PERFETTO_FATAL("Producer unexpectedly disconnected from the service");
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000079}
Lalit Maganti79f2d7b2018-01-23 18:27:33 +000080
Primiano Tucci674076d2018-10-01 10:41:09 +010081void FakeProducer::SetupDataSource(DataSourceInstanceID,
Stephen Nuskoe8238112019-04-09 18:37:00 +010082 const DataSourceConfig&) {
83 task_runner_->PostTask(on_setup_data_source_instance_);
84}
Primiano Tucci674076d2018-10-01 10:41:09 +010085
Primiano Tucciafb72b52018-09-25 09:37:24 +010086void FakeProducer::StartDataSource(DataSourceInstanceID,
87 const DataSourceConfig& source_config) {
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000088 PERFETTO_DCHECK_THREAD(thread_checker_);
Eric Seckler526921b2020-02-18 11:44:30 +000089 if (trace_writer_) {
90 // Startup tracing was already active, just bind the target buffer.
91 endpoint_->MaybeSharedMemoryArbiter()->BindStartupTargetBuffer(
92 kStartupTargetBufferReservationId,
93 static_cast<BufferID>(source_config.target_buffer()));
94 } else {
95 // Common case: Start tracing now.
96 trace_writer_ = endpoint_->CreateTraceWriter(
97 static_cast<BufferID>(source_config.target_buffer()));
98 SetupFromConfig(source_config.for_testing());
99 }
Lalit Maganti36557d82018-04-11 14:36:17 +0100100 if (source_config.for_testing().send_batch_on_register()) {
101 ProduceEventBatch(on_create_data_source_instance_);
102 } else {
103 task_runner_->PostTask(on_create_data_source_instance_);
104 }
Lalit Maganti79f2d7b2018-01-23 18:27:33 +0000105}
106
Primiano Tucciafb72b52018-09-25 09:37:24 +0100107void FakeProducer::StopDataSource(DataSourceInstanceID) {
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000108 PERFETTO_DCHECK_THREAD(thread_checker_);
109 trace_writer_.reset();
110}
111
Lalit Maganti36557d82018-04-11 14:36:17 +0100112// Note: this can be called on a different thread.
Eric Seckler526921b2020-02-18 11:44:30 +0000113void FakeProducer::ProduceStartupEventBatch(
114 const protos::gen::TestConfig& config,
115 SharedMemoryArbiter* arbiter,
116 std::function<void()> callback) {
117 task_runner_->PostTask([this, config, arbiter, callback] {
118 SetupFromConfig(config);
Lalit Maganti131b6e52018-03-29 18:29:31 +0100119
Eric Seckler526921b2020-02-18 11:44:30 +0000120 PERFETTO_CHECK(!trace_writer_);
121 trace_writer_ =
122 arbiter->CreateStartupTraceWriter(kStartupTargetBufferReservationId);
Lalit Maganti131b6e52018-03-29 18:29:31 +0100123
Eric Seckler526921b2020-02-18 11:44:30 +0000124 EmitEventBatchOnTaskRunner({});
Lalit Maganti131b6e52018-03-29 18:29:31 +0100125
Eric Seckler526921b2020-02-18 11:44:30 +0000126 // Issue callback right after writing - cannot wait for flush yet because
127 // we're not connected yet.
128 callback();
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000129 });
130}
Primiano Tucci9c41ceb2020-04-14 13:23:01 +0100131
Eric Seckler526921b2020-02-18 11:44:30 +0000132// Note: this can be called on a different thread.
133void FakeProducer::ProduceEventBatch(std::function<void()> callback) {
134 task_runner_->PostTask(
135 [this, callback] { EmitEventBatchOnTaskRunner(callback); });
136}
Lalit Maganti79f2d7b2018-01-23 18:27:33 +0000137
Primiano Tucci9c41ceb2020-04-14 13:23:01 +0100138void FakeProducer::RegisterDataSource(const DataSourceDescriptor& desc) {
139 task_runner_->PostTask([this, desc] { endpoint_->RegisterDataSource(desc); });
140}
141
142void FakeProducer::CommitData(const CommitDataRequest& req,
143 std::function<void()> callback) {
144 task_runner_->PostTask(
145 [this, req, callback] { endpoint_->CommitData(req, callback); });
146}
147
Primiano Tuccibbe68be2020-04-16 22:17:12 +0100148void FakeProducer::Sync(std::function<void()> callback) {
149 task_runner_->PostTask([this, callback] { endpoint_->Sync(callback); });
150}
151
Primiano Tuccidca727d2018-04-04 11:31:55 +0200152void FakeProducer::OnTracingSetup() {}
Isabelle Taylor69faa902018-03-21 15:42:03 +0000153
Primiano Tuccid52e6272018-04-06 19:06:53 +0200154void FakeProducer::Flush(FlushRequestID flush_request_id,
155 const DataSourceInstanceID*,
156 size_t num_data_sources) {
157 PERFETTO_DCHECK(num_data_sources > 0);
158 if (trace_writer_)
159 trace_writer_->Flush();
160 endpoint_->NotifyFlushComplete(flush_request_id);
161}
162
Eric Seckler526921b2020-02-18 11:44:30 +0000163void FakeProducer::SetupFromConfig(const protos::gen::TestConfig& config) {
164 rnd_engine_ = std::minstd_rand0(config.seed());
165 message_count_ = config.message_count();
166 message_size_ = config.message_size();
167 max_messages_per_second_ = config.max_messages_per_second();
168}
169
170void FakeProducer::EmitEventBatchOnTaskRunner(std::function<void()> callback) {
171 PERFETTO_CHECK(trace_writer_);
172 PERFETTO_CHECK(message_size_ > 1);
173 std::unique_ptr<char, base::FreeDeleter> payload(
174 static_cast<char*>(malloc(message_size_)));
175 memset(payload.get(), '.', message_size_);
176 payload.get()[message_size_ - 1] = 0;
177
178 base::TimeMillis start = base::GetWallTimeMs();
179 int64_t iterations = 0;
180 uint32_t messages_to_emit = message_count_;
181 while (messages_to_emit > 0) {
182 uint32_t messages_in_minibatch =
183 max_messages_per_second_ == 0
184 ? messages_to_emit
185 : std::min(max_messages_per_second_, messages_to_emit);
186 PERFETTO_DCHECK(messages_to_emit >= messages_in_minibatch);
187
188 for (uint32_t i = 0; i < messages_in_minibatch; i++) {
189 auto handle = trace_writer_->NewTracePacket();
190 handle->set_for_testing()->set_seq_value(
191 static_cast<uint32_t>(rnd_engine_()));
192 handle->set_for_testing()->set_str(payload.get(), message_size_);
193 }
194 messages_to_emit -= messages_in_minibatch;
195 iterations++;
196
197 // Pause until the second boundary to make sure that we are adhering to
198 // the speed limitation.
199 if (max_messages_per_second_ > 0) {
200 int64_t expected_time_taken = iterations * 1000;
201 base::TimeMillis time_taken = base::GetWallTimeMs() - start;
202 while (time_taken.count() < expected_time_taken) {
203 usleep(static_cast<useconds_t>(
204 (expected_time_taken - time_taken.count()) * 1000));
205 time_taken = base::GetWallTimeMs() - start;
206 }
207 }
208 trace_writer_->Flush(messages_to_emit > 0 ? [] {} : callback);
209 }
210}
211
Lalit Maganti79f2d7b2018-01-23 18:27:33 +0000212} // namespace perfetto