traced_probes: Remove statsd exec backend
Change-Id: I8b17745662941d9f444938992e8ddda3a39da7b6
diff --git a/Android.bp b/Android.bp
index 97333b0..95248ff 100644
--- a/Android.bp
+++ b/Android.bp
@@ -10847,7 +10847,6 @@
srcs: [
"src/traced/probes/statsd_client/common.cc",
"src/traced/probes/statsd_client/statsd_binder_data_source.cc",
- "src/traced/probes/statsd_client/statsd_exec_data_source.cc",
],
}
diff --git a/BUILD b/BUILD
index 7754759..06c9dab 100644
--- a/BUILD
+++ b/BUILD
@@ -2481,8 +2481,6 @@
"src/traced/probes/statsd_client/common.h",
"src/traced/probes/statsd_client/statsd_binder_data_source.cc",
"src/traced/probes/statsd_client/statsd_binder_data_source.h",
- "src/traced/probes/statsd_client/statsd_exec_data_source.cc",
- "src/traced/probes/statsd_client/statsd_exec_data_source.h",
],
)
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index d80d021..c64f16f 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -49,7 +49,6 @@
#include "src/traced/probes/probes_data_source.h"
#include "src/traced/probes/ps/process_stats_data_source.h"
#include "src/traced/probes/statsd_client/statsd_binder_data_source.h"
-#include "src/traced/probes/statsd_client/statsd_exec_data_source.h"
#include "src/traced/probes/sys_stats/sys_stats_data_source.h"
#include "src/traced/probes/system_info/system_info_data_source.h"
@@ -179,17 +178,6 @@
template <>
std::unique_ptr<ProbesDataSource>
-ProbesProducer::CreateDSInstance<StatsdExecDataSource>(
- TracingSessionID session_id,
- const DataSourceConfig& config) {
- auto buffer_id = static_cast<BufferID>(config.target_buffer());
- return std::unique_ptr<StatsdExecDataSource>(new StatsdExecDataSource(
- task_runner_, session_id, endpoint_->CreateTraceWriter(buffer_id),
- config));
-}
-
-template <>
-std::unique_ptr<ProbesDataSource>
ProbesProducer::CreateDSInstance<StatsdBinderDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
@@ -339,8 +327,6 @@
Ds<ProcessStatsDataSource>(),
#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
Ds<StatsdBinderDataSource>(),
-#else
- Ds<StatsdExecDataSource>(),
#endif
Ds<SysStatsDataSource>(),
Ds<SystemInfoDataSource>(),
diff --git a/src/traced/probes/statsd_client/BUILD.gn b/src/traced/probes/statsd_client/BUILD.gn
index f36c993..0750576 100644
--- a/src/traced/probes/statsd_client/BUILD.gn
+++ b/src/traced/probes/statsd_client/BUILD.gn
@@ -37,8 +37,6 @@
"common.h",
"statsd_binder_data_source.cc",
"statsd_binder_data_source.h",
- "statsd_exec_data_source.cc",
- "statsd_exec_data_source.h",
]
}
diff --git a/src/traced/probes/statsd_client/statsd_exec_data_source.cc b/src/traced/probes/statsd_client/statsd_exec_data_source.cc
deleted file mode 100644
index 811370a..0000000
--- a/src/traced/probes/statsd_client/statsd_exec_data_source.cc
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2022 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/traced/probes/statsd_client/statsd_exec_data_source.h"
-
-#include <stdlib.h>
-
-#include "perfetto/base/task_runner.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/subprocess.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "src/traced/probes/statsd_client/common.h"
-
-#include "protos/perfetto/trace/statsd/statsd_atom.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace {
-
-static constexpr const size_t kHeaderSize = sizeof(size_t);
-
-} // namespace
-
-SizetPrefixedMessageReader::SizetPrefixedMessageReader()
- : RingBufferMessageReader() {}
-SizetPrefixedMessageReader::~SizetPrefixedMessageReader() {}
-
-SizetPrefixedMessageReader::Message SizetPrefixedMessageReader::TryReadMessage(
- const uint8_t* start,
- const uint8_t* end) {
- SizetPrefixedMessageReader::Message msg{};
- size_t available = static_cast<size_t>(end - start);
- if (kHeaderSize <= available) {
- size_t sz = 0;
- static_assert(sizeof(sz) == kHeaderSize, "kHeaderSize must match size_t");
- memcpy(&sz, start, kHeaderSize);
- // It is valid for sz to be zero here and we must ensure we return
- // a valid Message for this case.
- if (kHeaderSize + sz <= available) {
- PERFETTO_CHECK(kHeaderSize + sz > sz);
- msg.start = start + kHeaderSize;
- msg.len = static_cast<uint32_t>(sz);
- msg.field_id = 0;
- }
- }
- return msg;
-}
-
-// static
-const ProbesDataSource::Descriptor StatsdExecDataSource::descriptor = {
- /*name*/ "android.statsd",
- /*flags*/ Descriptor::kHandlesIncrementalState,
- /*fill_descriptor_func*/ nullptr,
-};
-
-// This datasource works by execing "cmd stats data-subscribe" and
-// read/write stdin/stdout. This is the only way to make this work when
-// side loading but for in tree builds this causes to many denials:
-// avc: denied { execute_no_trans } for comm="traced_probes"
-// path="/system/bin/cmd" dev="dm-0" ino=200 scontext=u:r:traced_probes:s0
-// tcontext=u:object_r:system_file:s0 tclass=file permissive=1 avc: denied {
-// call } for comm="cmd" scontext=u:r:traced_probes:s0 tcontext=u:r:statsd:s0
-// tclass=binder permissive=1 avc: denied { use } for comm="cmd"
-// path="pipe:[51149]" dev="pipefs" ino=51149 scontext=u:r:statsd:s0
-// tcontext=u:r:traced_probes:s0 tclass=fd permissive=1 avc: denied { read } for
-// comm="cmd" path="pipe:[51149]" dev="pipefs" ino=51149 scontext=u:r:statsd:s0
-// tcontext=u:r:traced_probes:s0 tclass=fifo_file permissive=1 avc: denied {
-// write } for comm="cmd" path="pipe:[51148]" dev="pipefs" ino=51148
-// scontext=u:r:statsd:s0 tcontext=u:r:traced_probes:s0 tclass=fifo_file
-// permissive=1 avc: denied { transfer } for comm="cmd"
-// scontext=u:r:traced_probes:s0 tcontext=u:r:statsd:s0 tclass=binder
-// permissive=1
-StatsdExecDataSource::StatsdExecDataSource(base::TaskRunner* task_runner,
- TracingSessionID session_id,
- std::unique_ptr<TraceWriter> writer,
- const DataSourceConfig& ds_config)
- : ProbesDataSource(session_id, &descriptor),
- task_runner_(task_runner),
- writer_(std::move(writer)),
- output_(base::Pipe::Create(base::Pipe::Flags::kRdNonBlock)),
- shell_subscription_(CreateStatsdShellConfig(ds_config)),
- weak_factory_(this) {}
-
-StatsdExecDataSource::~StatsdExecDataSource() {
- if (output_.rd) {
- task_runner_->RemoveFileDescriptorWatch(output_.rd.get());
- }
-}
-
-void StatsdExecDataSource::Start() {
- // Don't bother actually connecting to statsd if no pull/push atoms
- // were configured:
- if (shell_subscription_.empty()) {
- PERFETTO_LOG("Empty statsd config. Not connecting to statsd.");
- return;
- }
-
- // The binary protocol for talking to statsd is to write 'size_t'
- // followed by a proto encoded ShellConfig. For now we assume that
- // us and statsd are the same bitness & endianness.
- std::string body = shell_subscription_;
- size_t size = body.size();
- static_assert(sizeof(size) == kHeaderSize, "kHeaderSize must match size_t");
- std::string input(sizeof(size) + size, '\0');
- memcpy(&input[0], &size, sizeof(size));
- memcpy(&input[0] + sizeof(size), body.data(), size);
-
- subprocess_ =
- base::Subprocess({"/system/bin/cmd", "stats", "data-subscribe"});
- subprocess_.args.stdin_mode = base::Subprocess::InputMode::kBuffer;
- subprocess_.args.stdout_mode = base::Subprocess::OutputMode::kFd;
- subprocess_.args.stderr_mode = base::Subprocess::OutputMode::kInherit;
- subprocess_.args.input = std::move(input);
- subprocess_.args.out_fd = std::move(output_.wr);
- subprocess_.Start();
-
- // Have to Poll at least once so the subprocess has a chance to
- // consume the input.
- // TODO(hjd): Might not manage to push the whole stdin here in which
- // case we can be stuck here forever. We should re-posttask the Poll
- // until the whole stdin is consumed.
- subprocess_.Poll();
-
- // Watch is removed on destruction.
- auto weak_this = weak_factory_.GetWeakPtr();
- task_runner_->AddFileDescriptorWatch(output_.rd.get(), [weak_this] {
- if (weak_this) {
- weak_this->OnStatsdWakeup();
- }
- });
-}
-
-// Once the pipe is available to read we want to drain it but we need
-// to split the work across multiple tasks to avoid statsd ddos'ing us
-// and causing us to hit the timeout. At the same time we don't want
-// multiple OnStatsdWakeup to cause 'concurrent' read cycles (we're
-// single threaded so we can't actually race but we could still end up
-// in some confused state) so:
-// - The first wakeup triggers DoRead and sets read_in_progress_
-// - Subsequent wakeups are ignored due to read_in_progress_
-// - DoRead does a single read and either:
-// - No data = we're finished so unset read_in_progress_
-// - Some data so PostTask another DoRead.
-void StatsdExecDataSource::OnStatsdWakeup() {
- if (read_in_progress_) {
- return;
- }
- read_in_progress_ = true;
- DoRead();
-}
-
-// Do a single read. If there is potentially more data to read schedule
-// another DoRead.
-void StatsdExecDataSource::DoRead() {
- PERFETTO_CHECK(read_in_progress_);
-
- uint8_t data[4098];
- // Read into the static buffer
- ssize_t rd = PERFETTO_EINTR(read(output_.rd.get(), &data, sizeof(data)));
- if (rd < 0) {
- if (!base::IsAgain(errno)) {
- PERFETTO_PLOG("Failed to read statsd pipe (ret: %zd)", rd);
- }
- // EAGAIN or otherwise we're done so re-enable the fd watch.
- read_in_progress_ = false;
- return;
- } else if (rd == 0) {
- // EOF so clean everything up.
- read_in_progress_ = false;
- task_runner_->RemoveFileDescriptorWatch(output_.rd.get());
- subprocess_.KillAndWaitForTermination();
- }
-
- buffer_.Append(data, static_cast<size_t>(rd));
-
- TraceWriter::TracePacketHandle packet;
- for (;;) {
- SizetPrefixedMessageReader::Message msg = buffer_.ReadMessage();
- // The whole packet is not available so we're done.
- if (!msg.valid()) {
- break;
- }
-
- // A heart beat packet with no content
- if (msg.len == 0) {
- continue;
- }
-
- packet = writer_->NewTracePacket();
- // This is late. It's already been >=2 IPC hops since the client
- // code actually produced the atom however we don't get any time
- // stamp from statsd/the client so this is the best we can do:
- packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
- auto* atom = packet->set_statsd_atom();
- atom->AppendRawProtoBytes(msg.start, msg.len);
- packet->Finalize();
- }
-
- // Potentially more to read so repost:
- auto weak_this = weak_factory_.GetWeakPtr();
- task_runner_->PostTask([weak_this] {
- if (weak_this) {
- weak_this->DoRead();
- }
- });
-}
-
-void StatsdExecDataSource::Flush(FlushRequestID,
- std::function<void()> callback) {
- writer_->Flush(callback);
-}
-
-void StatsdExecDataSource::ClearIncrementalState() {}
-
-} // namespace perfetto
diff --git a/src/traced/probes/statsd_client/statsd_exec_data_source.h b/src/traced/probes/statsd_client/statsd_exec_data_source.h
deleted file mode 100644
index 8dc25f5..0000000
--- a/src/traced/probes/statsd_client/statsd_exec_data_source.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2022 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_TRACED_PROBES_STATSD_CLIENT_STATSD_EXEC_DATA_SOURCE_H_
-#define SRC_TRACED_PROBES_STATSD_CLIENT_STATSD_EXEC_DATA_SOURCE_H_
-
-#include <array>
-#include <limits>
-#include <memory>
-#include <set>
-#include <unordered_map>
-#include <vector>
-
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/subprocess.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/tracing/core/forward_decls.h"
-#include "src/protozero/proto_ring_buffer.h"
-#include "src/traced/probes/probes_data_source.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-} // namespace base
-
-namespace protos {
-namespace pbzero {
-class ProcessTree;
-class Statsd;
-class Statsd_Process;
-} // namespace pbzero
-} // namespace protos
-
-class SizetPrefixedMessageReader final
- : public protozero::RingBufferMessageReader {
- public:
- SizetPrefixedMessageReader();
- virtual ~SizetPrefixedMessageReader() override;
-
- protected:
- virtual SizetPrefixedMessageReader::Message TryReadMessage(
- const uint8_t* start,
- const uint8_t* end) override;
-};
-
-class StatsdExecDataSource : public ProbesDataSource {
- public:
- static const ProbesDataSource::Descriptor descriptor;
-
- StatsdExecDataSource(base::TaskRunner*,
- TracingSessionID,
- std::unique_ptr<TraceWriter> writer,
- const DataSourceConfig&);
- ~StatsdExecDataSource() override;
-
- // ProbesDataSource implementation.
- void Start() override;
- void Flush(FlushRequestID, std::function<void()> callback) override;
- void ClearIncrementalState() override;
-
- private:
- // Common functions.
- StatsdExecDataSource(const StatsdExecDataSource&) = delete;
- StatsdExecDataSource& operator=(const StatsdExecDataSource&) = delete;
-
- void OnStatsdWakeup();
- void DoRead();
-
- base::TaskRunner* const task_runner_;
- std::unique_ptr<TraceWriter> writer_;
- base::Pipe output_;
- base::Subprocess subprocess_;
- std::string shell_subscription_;
- bool read_in_progress_ = false;
- SizetPrefixedMessageReader buffer_;
-
- base::WeakPtrFactory<StatsdExecDataSource> weak_factory_; // Keep last.
-};
-
-} // namespace perfetto
-
-#endif // SRC_TRACED_PROBES_STATSD_CLIENT_STATSD_EXEC_DATA_SOURCE_H_