tracing_service_impl: Use virtual interface for clock
So that we can mock it in tests.
Change-Id: If9eefdf9315ac60970928daf72e054fea935fa03
diff --git a/Android.bp b/Android.bp
index 0b974a1..8e9dace 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14895,6 +14895,7 @@
filegroup {
name: "perfetto_src_tracing_service_service",
srcs: [
+ "src/tracing/service/clock.cc",
"src/tracing/service/metatrace_writer.cc",
"src/tracing/service/packet_stream_validator.cc",
"src/tracing/service/trace_buffer.cc",
diff --git a/BUILD b/BUILD
index bbd999c..84cd949 100644
--- a/BUILD
+++ b/BUILD
@@ -3930,6 +3930,9 @@
perfetto_filegroup(
name = "src_tracing_service_service",
srcs = [
+ "src/tracing/service/clock.cc",
+ "src/tracing/service/clock.h",
+ "src/tracing/service/dependencies.h",
"src/tracing/service/histogram.h",
"src/tracing/service/metatrace_writer.cc",
"src/tracing/service/metatrace_writer.h",
diff --git a/src/tracing/service/BUILD.gn b/src/tracing/service/BUILD.gn
index f2eaa0e..b6c8750 100644
--- a/src/tracing/service/BUILD.gn
+++ b/src/tracing/service/BUILD.gn
@@ -38,6 +38,9 @@
"../core",
]
sources = [
+ "clock.cc",
+ "clock.h",
+ "dependencies.h",
"histogram.h",
"metatrace_writer.cc",
"metatrace_writer.h",
diff --git a/src/tracing/service/clock.cc b/src/tracing/service/clock.cc
new file mode 100644
index 0000000..350115a
--- /dev/null
+++ b/src/tracing/service/clock.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/tracing/service/clock.h"
+
+namespace perfetto::tracing_service {
+
+Clock::~Clock() = default;
+
+ClockImpl::~ClockImpl() = default;
+
+base::TimeNanos ClockImpl::GetBootTimeNs() {
+ return base::GetBootTimeNs();
+}
+
+base::TimeNanos ClockImpl::GetWallTimeNs() {
+ return base::GetWallTimeNs();
+}
+
+} // namespace perfetto::tracing_service
diff --git a/src/tracing/service/clock.h b/src/tracing/service/clock.h
new file mode 100644
index 0000000..9fc9ef4
--- /dev/null
+++ b/src/tracing/service/clock.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACING_SERVICE_CLOCK_H_
+#define SRC_TRACING_SERVICE_CLOCK_H_
+
+#include "perfetto/base/time.h"
+
+namespace perfetto::tracing_service {
+
+class Clock {
+ public:
+ virtual ~Clock();
+ virtual base::TimeNanos GetBootTimeNs() = 0;
+ virtual base::TimeNanos GetWallTimeNs() = 0;
+
+ base::TimeMillis GetBootTimeMs() {
+ return std::chrono::duration_cast<base::TimeMillis>(GetBootTimeNs());
+ }
+ base::TimeMillis GetWallTimeMs() {
+ return std::chrono::duration_cast<base::TimeMillis>(GetWallTimeNs());
+ }
+
+ base::TimeSeconds GetBootTimeS() {
+ return std::chrono::duration_cast<base::TimeSeconds>(GetBootTimeNs());
+ }
+ base::TimeSeconds GetWallTimeS() {
+ return std::chrono::duration_cast<base::TimeSeconds>(GetWallTimeNs());
+ }
+};
+
+class ClockImpl : public Clock {
+ public:
+ ~ClockImpl() override;
+ base::TimeNanos GetBootTimeNs() override;
+ base::TimeNanos GetWallTimeNs() override;
+};
+
+} // namespace perfetto::tracing_service
+
+#endif // SRC_TRACING_SERVICE_CLOCK_H_
diff --git a/src/tracing/service/dependencies.h b/src/tracing/service/dependencies.h
new file mode 100644
index 0000000..cb2475c
--- /dev/null
+++ b/src/tracing/service/dependencies.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACING_SERVICE_DEPENDENCIES_H_
+#define SRC_TRACING_SERVICE_DEPENDENCIES_H_
+
+#include <memory>
+
+#include "src/tracing/service/clock.h"
+
+namespace perfetto::tracing_service {
+
+// Dependencies of TracingServiceImpl. Can point to real implementations or to
+// mocks in tests.
+struct Dependencies {
+ std::unique_ptr<Clock> clock;
+};
+
+} // namespace perfetto::tracing_service
+
+#endif // SRC_TRACING_SERVICE_DEPENDENCIES_H_
diff --git a/src/tracing/service/tracing_service_impl.cc b/src/tracing/service/tracing_service_impl.cc
index b01ec8b..487a34d 100644
--- a/src/tracing/service/tracing_service_impl.cc
+++ b/src/tracing/service/tracing_service_impl.cc
@@ -19,6 +19,7 @@
#include <limits.h>
#include <string.h>
+#include <algorithm>
#include <cinttypes>
#include <cstdint>
#include <limits>
@@ -26,10 +27,6 @@
#include <string>
#include <unordered_set>
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/clock_snapshots.h"
-#include "perfetto/ext/tracing/core/client_identity.h"
-
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
!PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
#include <sys/uio.h>
@@ -50,12 +47,11 @@
#include <sys/stat.h>
#endif
-#include <algorithm>
-
#include "perfetto/base/build_config.h"
#include "perfetto/base/status.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/base/android_utils.h"
+#include "perfetto/ext/base/clock_snapshots.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
#include "perfetto/ext/base/string_utils.h"
@@ -66,6 +62,7 @@
#include "perfetto/ext/base/version.h"
#include "perfetto/ext/base/watchdog.h"
#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ext/tracing/core/client_identity.h"
#include "perfetto/ext/tracing/core/consumer.h"
#include "perfetto/ext/tracing/core/observable_events.h"
#include "perfetto/ext/tracing/core/producer.h"
@@ -336,21 +333,25 @@
std::unique_ptr<SharedMemory::Factory> shm_factory,
base::TaskRunner* task_runner,
InitOpts init_opts) {
- return std::unique_ptr<TracingService>(
- new TracingServiceImpl(std::move(shm_factory), task_runner, init_opts));
+ tracing_service::Dependencies deps;
+ deps.clock = std::make_unique<tracing_service::ClockImpl>();
+ return std::unique_ptr<TracingService>(new TracingServiceImpl(
+ std::move(shm_factory), task_runner, std::move(deps), init_opts));
}
TracingServiceImpl::TracingServiceImpl(
std::unique_ptr<SharedMemory::Factory> shm_factory,
base::TaskRunner* task_runner,
+ tracing_service::Dependencies deps,
InitOpts init_opts)
: task_runner_(task_runner),
+ clock_(std::move(deps.clock)),
init_opts_(init_opts),
shm_factory_(std::move(shm_factory)),
uid_(base::GetCurrentUserId()),
buffer_ids_(kMaxTraceBufferID),
trigger_probability_rand_(
- static_cast<uint32_t>(base::GetWallTimeNs().count())),
+ static_cast<uint32_t>(clock_->GetWallTimeMs().count())),
weak_ptr_factory_(this) {
PERFETTO_DCHECK(task_runner_);
}
@@ -835,7 +836,7 @@
if (cfg.enable_extra_guardrails()) {
// unique_session_name can be empty
const std::string& name = cfg.unique_session_name();
- int64_t now_s = base::GetBootTimeS().count();
+ int64_t now_s = clock_->GetBootTimeS().count();
// Remove any entries where the time limit has passed so this map doesn't
// grow indefinitely:
@@ -1254,6 +1255,14 @@
}
}
+uint32_t TracingServiceImpl::DelayToNextWritePeriodMs(
+ const TracingSession& session) {
+ PERFETTO_DCHECK(session.write_period_ms > 0);
+ return session.write_period_ms -
+ static_cast<uint32_t>(clock_->GetWallTimeMs().count() %
+ session.write_period_ms);
+}
+
void TracingServiceImpl::StartTracing(TracingSessionID tsid) {
PERFETTO_DCHECK_THREAD(thread_checker_);
@@ -1343,7 +1352,7 @@
if (weak_this)
weak_this->ReadBuffersIntoFile(tsid);
},
- tracing_session->delay_to_next_write_period_ms());
+ DelayToNextWritePeriodMs(*tracing_session));
}
// Start the periodic flush tasks if the config specified a flush period.
@@ -1561,7 +1570,7 @@
return;
}
- int64_t timestamp = base::GetBootTimeNs().count();
+ int64_t timestamp = clock_->GetBootTimeNs().count();
protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
packet->set_timestamp(static_cast<uint64_t>(timestamp));
@@ -1671,7 +1680,7 @@
auto* producer = GetProducer(producer_id);
PERFETTO_DCHECK(producer);
- int64_t now_ns = base::GetBootTimeNs().count();
+ int64_t now_ns = clock_->GetBootTimeNs().count();
for (const auto& trigger_name : triggers) {
PERFETTO_DLOG("Received ActivateTriggers request for \"%s\"",
trigger_name.c_str());
@@ -2023,7 +2032,7 @@
if ((flush_flags.reason() == FlushFlags::Reason::kTraceClone ||
flush_flags.reason() == FlushFlags::Reason::kTraceStop) &&
!success) {
- int64_t timestamp = base::GetBootTimeNs().count();
+ int64_t timestamp = clock_->GetBootTimeNs().count();
protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
packet->set_timestamp(static_cast<uint64_t>(timestamp));
@@ -2252,7 +2261,7 @@
if (weak_this)
weak_this->PeriodicFlushTask(tsid, /*post_next_only=*/false);
},
- flush_period_ms - static_cast<uint32_t>(base::GetWallTimeMs().count() %
+ flush_period_ms - static_cast<uint32_t>(clock_->GetWallTimeMs().count() %
flush_period_ms));
if (post_next_only)
@@ -2286,7 +2295,7 @@
weak_this->PeriodicClearIncrementalStateTask(
tsid, /*post_next_only=*/false);
},
- clear_period_ms - static_cast<uint32_t>(base::GetWallTimeMs().count() %
+ clear_period_ms - static_cast<uint32_t>(clock_->GetWallTimeMs().count() %
clear_period_ms));
if (post_next_only)
@@ -2422,7 +2431,7 @@
if (weak_this)
weak_this->ReadBuffersIntoFile(tsid);
},
- tracing_session->delay_to_next_write_period_ms());
+ DelayToNextWritePeriodMs(*tracing_session));
return true;
}
@@ -2650,7 +2659,7 @@
// by the earlier call to SetFilterRoot() in EnableTracing().
PERFETTO_DCHECK(trace_filter.config().root_msg_index() != 0);
std::vector<protozero::MessageFilter::InputSlice> filter_input;
- auto start = base::GetWallTimeNs();
+ auto start = clock_->GetWallTimeNs();
for (TracePacket& packet : *packets) {
const auto& packet_slices = packet.slices();
const size_t input_packet_size = packet.size();
@@ -2690,7 +2699,7 @@
filtered_packet.size, kMaxTracePacketSliceSize,
&packet);
}
- auto end = base::GetWallTimeNs();
+ auto end = clock_->GetWallTimeNs();
tracing_session->filter_time_taken_ns +=
static_cast<uint64_t>((end - start).count());
}
@@ -3449,7 +3458,7 @@
event->timestamps.erase_front(1 + event->timestamps.size() -
event->max_size);
}
- event->timestamps.emplace_back(base::GetBootTimeNs().count());
+ event->timestamps.emplace_back(clock_->GetBootTimeNs().count());
}
void TracingServiceImpl::MaybeSnapshotClocksIntoRingBuffer(
diff --git a/src/tracing/service/tracing_service_impl.h b/src/tracing/service/tracing_service_impl.h
index 51cad75..346f6de 100644
--- a/src/tracing/service/tracing_service_impl.h
+++ b/src/tracing/service/tracing_service_impl.h
@@ -49,6 +49,8 @@
#include "perfetto/tracing/core/trace_config.h"
#include "src/android_stats/perfetto_atoms.h"
#include "src/tracing/core/id_allocator.h"
+#include "src/tracing/service/clock.h"
+#include "src/tracing/service/dependencies.h"
namespace protozero {
class MessageFilter;
@@ -312,6 +314,7 @@
explicit TracingServiceImpl(std::unique_ptr<SharedMemory::Factory>,
base::TaskRunner*,
+ tracing_service::Dependencies,
InitOpts = {});
~TracingServiceImpl() override;
@@ -511,13 +514,6 @@
size_t num_buffers() const { return buffers_index.size(); }
- uint32_t delay_to_next_write_period_ms() const {
- PERFETTO_DCHECK(write_period_ms > 0);
- return write_period_ms -
- static_cast<uint32_t>(base::GetWallTimeMs().count() %
- write_period_ms);
- }
-
uint32_t flush_timeout_ms() {
uint32_t timeout_ms = config.flush_timeout_ms();
return timeout_ms ? timeout_ms : kDefaultFlushTimeoutMs;
@@ -783,6 +779,7 @@
// shared memory and trace buffers.
void UpdateMemoryGuardrail();
+ uint32_t DelayToNextWritePeriodMs(const TracingSession&);
void StartDataSourceInstance(ProducerEndpointImpl*,
TracingSession*,
DataSourceInstance*);
@@ -887,6 +884,7 @@
TracingSessionID);
base::TaskRunner* const task_runner_;
+ std::unique_ptr<tracing_service::Clock> clock_;
const InitOpts init_opts_;
std::unique_ptr<SharedMemory::Factory> shm_factory_;
ProducerID last_producer_id_ = 0;