1 /*
2 * Copyright (C) 2024 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 "src/trace_processor/importers/ftrace/thermal_tracker.h"
18 #include "perfetto/ext/base/string_utils.h"
19 #include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
20 #include "protos/perfetto/trace/ftrace/thermal_exynos.pbzero.h"
21 #include "src/trace_processor/importers/common/event_tracker.h"
22 #include "src/trace_processor/importers/common/track_tracker.h"
23
24 namespace perfetto {
25 namespace trace_processor {
26
27 constexpr const char* kTemperatureSuffix = "Temperature";
28 constexpr const char* kCoolingDeviceSuffix = "Cooling Device";
29
ThermalTracker(TraceProcessorContext * context)30 ThermalTracker::ThermalTracker(TraceProcessorContext* context)
31 : context_(context) {
32 const std::array<const char*, kAcpmThermalZones> acpm_thermal_zones = {
33 "BIG", "MID", "LITTLE", "GPU", "ISP", "TPU", "AUR",
34 };
35 for (size_t i = 0; i < kAcpmThermalZones; i++) {
36 base::StackString<32> temperature_counter("%s %s", acpm_thermal_zones[i],
37 kTemperatureSuffix);
38 acpm_temperature_counters_[i] =
39 context_->storage->InternString(temperature_counter.string_view());
40 base::StackString<32> cooling_device_counter(
41 "Tj-%s %s", acpm_thermal_zones[i], kCoolingDeviceSuffix);
42 acpm_cooling_device_counters_[i] =
43 context_->storage->InternString(cooling_device_counter.string_view());
44 }
45 }
46
ParseThermalTemperature(int64_t timestamp,protozero::ConstBytes blob)47 void ThermalTracker::ParseThermalTemperature(int64_t timestamp,
48 protozero::ConstBytes blob) {
49 protos::pbzero::ThermalTemperatureFtraceEvent::Decoder event(blob);
50 base::StringView tz = event.thermal_zone();
51 base::StackString<255> counter_name("%.*s %s", static_cast<int>(tz.size()),
52 tz.data(), kTemperatureSuffix);
53 StringId counter_id =
54 context_->storage->InternString(counter_name.string_view());
55 PushCounter(timestamp, counter_id, static_cast<double>(event.temp()));
56 }
57
ParseCdevUpdate(int64_t timestamp,protozero::ConstBytes blob)58 void ThermalTracker::ParseCdevUpdate(int64_t timestamp,
59 protozero::ConstBytes blob) {
60 protos::pbzero::CdevUpdateFtraceEvent::Decoder event(blob);
61 base::StringView cdev = event.type();
62 base::StackString<255> counter_name("%.*s %s", static_cast<int>(cdev.size()),
63 cdev.data(), kCoolingDeviceSuffix);
64 StringId counter_id =
65 context_->storage->InternString(counter_name.string_view());
66 PushCounter(timestamp, counter_id, static_cast<double>(event.target()));
67 }
68
ParseThermalExynosAcpmBulk(protozero::ConstBytes blob)69 void ThermalTracker::ParseThermalExynosAcpmBulk(protozero::ConstBytes blob) {
70 protos::pbzero::ThermalExynosAcpmBulkFtraceEvent::Decoder event(blob);
71 auto tz_id = static_cast<size_t>(event.tz_id());
72 if (tz_id >= kAcpmThermalZones) {
73 context_->storage->IncrementStats(
74 stats::ftrace_thermal_exynos_acpm_unknown_tz_id);
75 return;
76 }
77 auto timestamp = static_cast<int64_t>(event.timestamp());
78 // Record acpm tz's temperature.
79 PushCounter(timestamp, acpm_temperature_counters_[tz_id],
80 static_cast<double>(event.current_temp()));
81 // Record cdev target of acpm tz's cooling device.
82 PushCounter(timestamp, acpm_cooling_device_counters_[tz_id],
83 static_cast<double>(event.cdev_state()));
84 }
85
ParseThermalExynosAcpmHighOverhead(int64_t timestamp,protozero::ConstBytes blob)86 void ThermalTracker::ParseThermalExynosAcpmHighOverhead(
87 int64_t timestamp,
88 protozero::ConstBytes blob) {
89 protos::pbzero::ThermalExynosAcpmHighOverheadFtraceEvent::Decoder event(blob);
90 auto tz_id = static_cast<size_t>(event.tz_id());
91 if (tz_id >= kAcpmThermalZones) {
92 context_->storage->IncrementStats(
93 stats::ftrace_thermal_exynos_acpm_unknown_tz_id);
94 return;
95 }
96 // Record acpm tz's temperature.
97 PushCounter(timestamp, acpm_temperature_counters_[tz_id],
98 static_cast<double>(event.current_temp()));
99 // Record cdev target of acpm tz's cooling device.
100 PushCounter(timestamp, acpm_cooling_device_counters_[tz_id],
101 static_cast<double>(event.cdev_state()));
102 }
103
PushCounter(int64_t timestamp,StringId counter_id,double value)104 void ThermalTracker::PushCounter(int64_t timestamp,
105 StringId counter_id,
106 double value) {
107 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
108 TrackTracker::Group::kThermals, counter_id);
109 context_->event_tracker->PushCounter(timestamp, value, track);
110 }
111
112 } // namespace trace_processor
113 } // namespace perfetto
114