thermal: perfetto/ftrace: Parse thermal_exynos temp and cdev
Add support to parse ThermalExynosAcpmBulk and
ThermalExynosAcpmHighOverhead ftrace events and extract temperature and
cdev target of acpm thermal_zones
For ThermalExynosAcpmBulk extract timestamp from within the event
instead of relying on ftrace timestamp.
Move all thermal related events into one common file.
Bug: 257482511
Test: run ui/run-dev-server
Change-Id: I1ed41715fdade307ee359a9c763fade5c4f9ff52
diff --git a/Android.bp b/Android.bp
index 51e8609..9ca083d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12111,6 +12111,7 @@
"src/trace_processor/importers/ftrace/mali_gpu_event_tracker.cc",
"src/trace_processor/importers/ftrace/pkvm_hyp_cpu_tracker.cc",
"src/trace_processor/importers/ftrace/rss_stat_tracker.cc",
+ "src/trace_processor/importers/ftrace/thermal_tracker.cc",
"src/trace_processor/importers/ftrace/v4l2_tracker.cc",
"src/trace_processor/importers/ftrace/virtio_gpu_tracker.cc",
"src/trace_processor/importers/ftrace/virtio_video_tracker.cc",
diff --git a/BUILD b/BUILD
index 1f39840..19c6276 100644
--- a/BUILD
+++ b/BUILD
@@ -1588,6 +1588,8 @@
"src/trace_processor/importers/ftrace/pkvm_hyp_cpu_tracker.h",
"src/trace_processor/importers/ftrace/rss_stat_tracker.cc",
"src/trace_processor/importers/ftrace/rss_stat_tracker.h",
+ "src/trace_processor/importers/ftrace/thermal_tracker.cc",
+ "src/trace_processor/importers/ftrace/thermal_tracker.h",
"src/trace_processor/importers/ftrace/v4l2_tracker.cc",
"src/trace_processor/importers/ftrace/v4l2_tracker.h",
"src/trace_processor/importers/ftrace/virtio_gpu_tracker.cc",
diff --git a/src/trace_processor/importers/ftrace/BUILD.gn b/src/trace_processor/importers/ftrace/BUILD.gn
index 3a533d1..19354a7 100644
--- a/src/trace_processor/importers/ftrace/BUILD.gn
+++ b/src/trace_processor/importers/ftrace/BUILD.gn
@@ -51,6 +51,8 @@
"pkvm_hyp_cpu_tracker.h",
"rss_stat_tracker.cc",
"rss_stat_tracker.h",
+ "thermal_tracker.cc",
+ "thermal_tracker.h",
"v4l2_tracker.cc",
"v4l2_tracker.h",
"virtio_gpu_tracker.cc",
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index ba8a259..a46002f 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -85,7 +85,6 @@
#include "protos/perfetto/trace/ftrace/systrace.pbzero.h"
#include "protos/perfetto/trace/ftrace/task.pbzero.h"
#include "protos/perfetto/trace/ftrace/tcp.pbzero.h"
-#include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
#include "protos/perfetto/trace/ftrace/trusty.pbzero.h"
#include "protos/perfetto/trace/ftrace/ufs.pbzero.h"
#include "protos/perfetto/trace/ftrace/vmscan.pbzero.h"
@@ -244,6 +243,7 @@
mali_gpu_event_tracker_(context),
pkvm_hyp_cpu_tracker_(context),
gpu_work_period_tracker_(context),
+ thermal_tracker_(context),
sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
sched_waking_name_id_(context->storage->InternString("sched_waking")),
cpu_id_(context->storage->InternString("cpu")),
@@ -874,11 +874,20 @@
break;
}
case FtraceEvent::kThermalTemperatureFieldNumber: {
- ParseThermalTemperature(ts, fld_bytes);
+ thermal_tracker_.ParseThermalTemperature(ts, fld_bytes);
+ break;
+ }
+ case FtraceEvent::kThermalExynosAcpmBulkFieldNumber: {
+ thermal_tracker_.ParseThermalExynosAcpmBulk(fld_bytes);
+ break;
+ }
+ case FtraceEvent::kThermalExynosAcpmHighOverheadFieldNumber: {
+ thermal_tracker_.ParseThermalExynosAcpmHighOverhead(
+ ts, fld_bytes);
break;
}
case FtraceEvent::kCdevUpdateFieldNumber: {
- ParseCdevUpdate(ts, fld_bytes);
+ thermal_tracker_.ParseCdevUpdate(ts, fld_bytes);
break;
}
case FtraceEvent::kSchedBlockedReasonFieldNumber: {
@@ -2381,32 +2390,6 @@
timestamp, static_cast<double>(gpu_mem_total.size()), track);
}
-void FtraceParser::ParseThermalTemperature(int64_t timestamp,
- protozero::ConstBytes blob) {
- protos::pbzero::ThermalTemperatureFtraceEvent::Decoder event(blob.data,
- blob.size);
- base::StringView thermal_zone = event.thermal_zone();
- base::StackString<255> counter_name(
- "%.*s Temperature", int(thermal_zone.size()), thermal_zone.data());
- StringId name = context_->storage->InternString(counter_name.string_view());
- TrackId track = context_->track_tracker->InternGlobalCounterTrack(
- TrackTracker::Group::kThermals, name);
- context_->event_tracker->PushCounter(timestamp, event.temp(), track);
-}
-
-void FtraceParser::ParseCdevUpdate(int64_t timestamp,
- protozero::ConstBytes blob) {
- protos::pbzero::CdevUpdateFtraceEvent::Decoder event(blob.data, blob.size);
- base::StringView type = event.type();
- base::StackString<255> counter_name("%.*s Cooling Device", int(type.size()),
- type.data());
- StringId name = context_->storage->InternString(counter_name.string_view());
- TrackId track = context_->track_tracker->InternGlobalCounterTrack(
- TrackTracker::Group::kThermals, name);
- context_->event_tracker->PushCounter(
- timestamp, static_cast<double>(event.target()), track);
-}
-
void FtraceParser::ParseSchedBlockedReason(
protozero::ConstBytes blob,
PacketSequenceStateGeneration* seq_state) {
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 619b8d4..86c7114 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -35,6 +35,7 @@
#include "src/trace_processor/importers/ftrace/mali_gpu_event_tracker.h"
#include "src/trace_processor/importers/ftrace/pkvm_hyp_cpu_tracker.h"
#include "src/trace_processor/importers/ftrace/rss_stat_tracker.h"
+#include "src/trace_processor/importers/ftrace/thermal_tracker.h"
#include "src/trace_processor/importers/ftrace/virtio_gpu_tracker.h"
#include "src/trace_processor/types/trace_processor_context.h"
@@ -201,8 +202,6 @@
protozero::ConstBytes);
void ParseSoftIrqExit(uint32_t cpu, int64_t timestamp, protozero::ConstBytes);
void ParseGpuMemTotal(int64_t timestamp, protozero::ConstBytes);
- void ParseThermalTemperature(int64_t timestamp, protozero::ConstBytes);
- void ParseCdevUpdate(int64_t timestamp, protozero::ConstBytes);
void ParseSchedBlockedReason(protozero::ConstBytes,
PacketSequenceStateGeneration*);
void ParseFastRpcDmaStat(int64_t timestamp,
@@ -312,6 +311,7 @@
MaliGpuEventTracker mali_gpu_event_tracker_;
PkvmHypervisorCpuTracker pkvm_hyp_cpu_tracker_;
GpuWorkPeriodTracker gpu_work_period_tracker_;
+ ThermalTracker thermal_tracker_;
const StringId sched_wakeup_name_id_;
const StringId sched_waking_name_id_;
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
index 00656fa..0220986 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
@@ -34,6 +34,7 @@
#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
#include "protos/perfetto/trace/ftrace/power.pbzero.h"
+#include "protos/perfetto/trace/ftrace/thermal_exynos.pbzero.h"
namespace perfetto {
namespace trace_processor {
@@ -265,7 +266,12 @@
if (PERFETTO_UNLIKELY(
event_id == protos::pbzero::FtraceEvent::kGpuWorkPeriodFieldNumber)) {
- TokenizeFtraceGpuWorkPeriod(cpu, std::move(event), state);
+ TokenizeFtraceGpuWorkPeriod(cpu, std::move(event), std::move(state));
+ return;
+ } else if (PERFETTO_UNLIKELY(event_id ==
+ protos::pbzero::FtraceEvent::
+ kThermalExynosAcpmBulkFieldNumber)) {
+ TokenizeFtraceThermalExynosAcpmBulk(cpu, std::move(event), std::move(state));
return;
}
@@ -468,5 +474,33 @@
std::move(state), context_->machine_id());
}
+void FtraceTokenizer::TokenizeFtraceThermalExynosAcpmBulk(
+ uint32_t cpu, TraceBlobView event,
+ RefPtr<PacketSequenceStateGeneration> state) {
+ // Special handling of valid thermal_exynos_acpm_bulk tracepoint events which
+ // contains the right timestamp value nested inside the event data.
+ const uint8_t* data = event.data();
+ const size_t length = event.length();
+
+ ProtoDecoder decoder(data, length);
+ auto ts_field = decoder.FindField(
+ protos::pbzero::FtraceEvent::kThermalExynosAcpmBulkFieldNumber);
+ if (!ts_field.valid()) {
+ context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
+ return;
+ }
+
+ protos::pbzero::ThermalExynosAcpmBulkFtraceEvent::Decoder
+ thermal_exynos_acpm_bulk_event(ts_field.data(), ts_field.size());
+ if (!thermal_exynos_acpm_bulk_event.has_timestamp()) {
+ context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
+ return;
+ }
+ int64_t timestamp =
+ static_cast<int64_t>(thermal_exynos_acpm_bulk_event.timestamp());
+ context_->sorter->PushFtraceEvent(cpu, timestamp, std::move(event),
+ std::move(state), context_->machine_id());
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
index d53504e..e0b4f7c 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
@@ -64,6 +64,9 @@
void TokenizeFtraceGpuWorkPeriod(uint32_t cpu,
TraceBlobView event,
RefPtr<PacketSequenceStateGeneration> state);
+ void TokenizeFtraceThermalExynosAcpmBulk(uint32_t cpu,
+ TraceBlobView event,
+ RefPtr<PacketSequenceStateGeneration> state);
void DlogWithLimit(const base::Status& status) {
static std::atomic<uint32_t> dlog_count(0);
diff --git a/src/trace_processor/importers/ftrace/thermal_tracker.cc b/src/trace_processor/importers/ftrace/thermal_tracker.cc
new file mode 100644
index 0000000..4e1e367
--- /dev/null
+++ b/src/trace_processor/importers/ftrace/thermal_tracker.cc
@@ -0,0 +1,111 @@
+/*
+ * 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 "perfetto/ext/base/string_utils.h"
+#include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
+#include "protos/perfetto/trace/ftrace/thermal_exynos.pbzero.h"
+#include "src/trace_processor/importers/common/event_tracker.h"
+#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/importers/ftrace/thermal_tracker.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+constexpr const char* kTemperatureSuffix = "Temperature";
+constexpr const char* kCoolingDeviceSuffix = "Cooling Device";
+
+ThermalTracker::ThermalTracker(TraceProcessorContext* context)
+ : context_(context) {
+ const std::array<const char*, kAcpmThermalZones> acpm_thermal_zones = {
+ "BIG", "MID", "LITTLE", "GPU", "ISP", "TPU", "AUR",
+ };
+ for (size_t i = 0; i < kAcpmThermalZones; i++) {
+ base::StackString<32> temperature_counter("%s %s", acpm_thermal_zones[i],
+ kTemperatureSuffix);
+ acpm_temperature_counters_[i] =
+ context_->storage->InternString(temperature_counter.string_view());
+ base::StackString<32> cooling_device_counter(
+ "Tj-%s %s", acpm_thermal_zones[i], kCoolingDeviceSuffix);
+ acpm_cooling_device_counters_[i] =
+ context_->storage->InternString(cooling_device_counter.string_view());
+ }
+}
+
+void ThermalTracker::ParseThermalTemperature(int64_t timestamp,
+ protozero::ConstBytes blob) {
+ protos::pbzero::ThermalTemperatureFtraceEvent::Decoder event(blob);
+ base::StringView tz = event.thermal_zone();
+ base::StackString<255> counter_name("%.*s %s", static_cast<int>(tz.size()),
+ tz.data(), kTemperatureSuffix);
+ StringId counter_id =
+ context_->storage->InternString(counter_name.string_view());
+ PushCounter(timestamp, counter_id, static_cast<double>(event.temp()));
+}
+
+void ThermalTracker::ParseCdevUpdate(int64_t timestamp,
+ protozero::ConstBytes blob) {
+ protos::pbzero::CdevUpdateFtraceEvent::Decoder event(blob);
+ base::StringView cdev = event.type();
+ base::StackString<255> counter_name("%.*s %s", static_cast<int>(cdev.size()),
+ cdev.data(), kCoolingDeviceSuffix);
+ StringId counter_id =
+ context_->storage->InternString(counter_name.string_view());
+ PushCounter(timestamp, counter_id, static_cast<double>(event.target()));
+}
+
+void ThermalTracker::ParseThermalExynosAcpmBulk(protozero::ConstBytes blob) {
+ protos::pbzero::ThermalExynosAcpmBulkFtraceEvent::Decoder event(blob);
+ auto tz_id = static_cast<size_t>(event.tz_id());
+ if (tz_id >= kAcpmThermalZones) {
+ context_->storage->IncrementStats(
+ stats::ftrace_thermal_exynos_acpm_unknown_tz_id);
+ return;
+ }
+ auto timestamp = static_cast<int64_t>(event.timestamp());
+ // Record acpm tz's temperature.
+ PushCounter(timestamp, acpm_temperature_counters_[tz_id],
+ static_cast<double>(event.current_temp()));
+ // Record cdev target of acpm tz's cooling device.
+ PushCounter(timestamp, acpm_cooling_device_counters_[tz_id],
+ static_cast<double>(event.cdev_state()));
+}
+
+void ThermalTracker::ParseThermalExynosAcpmHighOverhead(
+ int64_t timestamp, protozero::ConstBytes blob) {
+ protos::pbzero::ThermalExynosAcpmHighOverheadFtraceEvent::Decoder event(blob);
+ auto tz_id = static_cast<size_t>(event.tz_id());
+ if (tz_id >= kAcpmThermalZones) {
+ context_->storage->IncrementStats(
+ stats::ftrace_thermal_exynos_acpm_unknown_tz_id);
+ return;
+ }
+ // Record acpm tz's temperature.
+ PushCounter(timestamp, acpm_temperature_counters_[tz_id],
+ static_cast<double>(event.current_temp()));
+ // Record cdev target of acpm tz's cooling device.
+ PushCounter(timestamp, acpm_cooling_device_counters_[tz_id],
+ static_cast<double>(event.cdev_state()));
+}
+
+void ThermalTracker::PushCounter(int64_t timestamp, StringId counter_id,
+ double value) {
+ TrackId track = context_->track_tracker->InternGlobalCounterTrack(
+ TrackTracker::Group::kThermals, counter_id);
+ context_->event_tracker->PushCounter(timestamp, value, track);
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/thermal_tracker.h b/src/trace_processor/importers/ftrace/thermal_tracker.h
new file mode 100644
index 0000000..ff04f6e
--- /dev/null
+++ b/src/trace_processor/importers/ftrace/thermal_tracker.h
@@ -0,0 +1,53 @@
+/*
+ * 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_TRACE_PROCESSOR_IMPORTERS_FTRACE_THERMAL_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_THERMAL_TRACKER_H_
+
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/util/descriptors.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+class ThermalTracker {
+ public:
+ explicit ThermalTracker(TraceProcessorContext*);
+ void ParseThermalTemperature(int64_t timestamp, protozero::ConstBytes blob);
+ void ParseCdevUpdate(int64_t timestamp, protozero::ConstBytes);
+ void ParseThermalExynosAcpmBulk(protozero::ConstBytes blob);
+ void ParseThermalExynosAcpmHighOverhead(int64_t timestamp,
+ protozero::ConstBytes blob);
+
+ private:
+ static constexpr size_t kAcpmThermalZones = 7;
+
+ TraceProcessorContext* context_;
+
+ // Maintain mapping of acpm tz_id's to their corresponding temperature and
+ // cooling device counter ids.
+ std::array<StringId, kAcpmThermalZones> acpm_temperature_counters_;
+ std::array<StringId, kAcpmThermalZones> acpm_cooling_device_counters_;
+
+ void PushCounter(int64_t timestamp, StringId counter_name, double value);
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_THERMAL_TRACKER_H_
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index 0584d84..9067b09 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -74,6 +74,8 @@
"enable. See ftrace_setup_errors in the metadata table for details."), \
F(ftrace_abi_errors_skipped_zero_data_length, \
kSingle, kInfo, kAnalysis, ""), \
+ F(ftrace_thermal_exynos_acpm_unknown_tz_id, \
+ kSingle, kError, kAnalysis, ""), \
F(fuchsia_non_numeric_counters, kSingle, kError, kAnalysis, ""), \
F(fuchsia_timestamp_overflow, kSingle, kError, kAnalysis, ""), \
F(fuchsia_invalid_event, kSingle, kError, kAnalysis, ""), \
@@ -362,7 +364,7 @@
// being reflected in the stats table.
kTrace,
- // The counter is genrated when importing / processing the trace in the trace
+ // The counter is generated when importing / processing the trace in the trace
// processor.
kAnalysis
};