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
19 #include <array>
20 #include <cstddef>
21 #include <cstdint>
22
23 #include "perfetto/ext/base/string_utils.h"
24 #include "perfetto/ext/base/string_view.h"
25 #include "perfetto/protozero/field.h"
26 #include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
27 #include "protos/perfetto/trace/ftrace/thermal_exynos.pbzero.h"
28 #include "src/trace_processor/importers/common/args_tracker.h"
29 #include "src/trace_processor/importers/common/event_tracker.h"
30 #include "src/trace_processor/importers/common/track_tracker.h"
31 #include "src/trace_processor/importers/common/tracks.h"
32 #include "src/trace_processor/importers/common/tracks_common.h"
33 #include "src/trace_processor/storage/stats.h"
34 #include "src/trace_processor/storage/trace_storage.h"
35 #include "src/trace_processor/types/variadic.h"
36
37 namespace perfetto::trace_processor {
38 namespace {
39
40 constexpr std::array<const char*, 7> kAcpmThermalZones = {
41 "BIG", "MID", "LITTLE", "GPU", "ISP", "TPU", "AUR",
42 };
43
44 constexpr char kThermalZoneIdKey[] = "thermal_zone_id";
45
46 constexpr auto kThermalZoneDimension =
47 tracks::StringDimensionBlueprint("thermal_zone");
48
49 constexpr auto kAcpmTemperatureTrackBlueprint = tracks::CounterBlueprint(
50 "acpm_thermal_temperature",
51 tracks::UnknownUnitBlueprint(),
52 tracks::DimensionBlueprints(kThermalZoneDimension),
__anonaecd97970202(base::StringView zone) 53 tracks::FnNameBlueprint([](base::StringView zone) {
54 return base::StackString<64>("%.*s Temperature",
55 static_cast<int>(zone.size()), zone.data());
56 }));
57
58 constexpr auto kAcpmCoolingTrackBlueprint = tracks::CounterBlueprint(
59 "acpm_cooling_device_counter",
60 tracks::UnknownUnitBlueprint(),
61 tracks::DimensionBlueprints(kThermalZoneDimension),
__anonaecd97970302(base::StringView zone) 62 tracks::FnNameBlueprint([](base::StringView zone) {
63 return base::StackString<64>("Tj-%.*s Cooling Device",
64 static_cast<int>(zone.size()), zone.data());
65 }));
66
67 } // namespace
68
ThermalTracker(TraceProcessorContext * context)69 ThermalTracker::ThermalTracker(TraceProcessorContext* context)
70 : context_(context) {}
71
ParseThermalTemperature(int64_t timestamp,protozero::ConstBytes blob)72 void ThermalTracker::ParseThermalTemperature(int64_t timestamp,
73 protozero::ConstBytes blob) {
74 protos::pbzero::ThermalTemperatureFtraceEvent::Decoder event(blob);
75 TrackId track = context_->track_tracker->InternTrack(
76 tracks::kThermalTemperatureBlueprint,
77 tracks::Dimensions(event.thermal_zone()));
78 context_->event_tracker->PushCounter(
79 timestamp, static_cast<double>(event.temp()), track);
80 }
81
ParseCdevUpdate(int64_t timestamp,protozero::ConstBytes blob)82 void ThermalTracker::ParseCdevUpdate(int64_t timestamp,
83 protozero::ConstBytes blob) {
84 protos::pbzero::CdevUpdateFtraceEvent::Decoder event(blob);
85 TrackId track = context_->track_tracker->InternTrack(
86 tracks::kCoolingDeviceCounterBlueprint, tracks::Dimensions(event.type()));
87 context_->event_tracker->PushCounter(
88 timestamp, static_cast<double>(event.target()), track);
89 }
90
ParseThermalExynosAcpmBulk(protozero::ConstBytes blob)91 void ThermalTracker::ParseThermalExynosAcpmBulk(protozero::ConstBytes blob) {
92 protos::pbzero::ThermalExynosAcpmBulkFtraceEvent::Decoder event(blob);
93 auto tz_id = static_cast<uint32_t>(event.tz_id());
94 if (tz_id >= kAcpmThermalZones.size()) {
95 context_->storage->IncrementStats(
96 stats::ftrace_thermal_exynos_acpm_unknown_tz_id);
97 return;
98 }
99 auto timestamp = static_cast<int64_t>(event.timestamp());
100 {
101 TrackId track = context_->track_tracker->InternTrack(
102 kAcpmTemperatureTrackBlueprint,
103 tracks::Dimensions(kAcpmThermalZones[tz_id]));
104 context_->event_tracker->PushCounter(
105 timestamp, static_cast<double>(event.current_temp()), track,
106 [this, tz_id](ArgsTracker::BoundInserter* inserter) {
107 StringId key = context_->storage->InternString(kThermalZoneIdKey);
108 inserter->AddArg(key, Variadic::Integer(tz_id));
109 });
110 }
111 {
112 TrackId track = context_->track_tracker->InternTrack(
113 kAcpmCoolingTrackBlueprint,
114 tracks::Dimensions(kAcpmThermalZones[tz_id]));
115 context_->event_tracker->PushCounter(
116 timestamp, static_cast<double>(event.cdev_state()), track,
117 [this, tz_id](ArgsTracker::BoundInserter* inserter) {
118 StringId key = context_->storage->InternString(kThermalZoneIdKey);
119 inserter->AddArg(key, Variadic::Integer(tz_id));
120 });
121 }
122 }
123
ParseThermalExynosAcpmHighOverhead(int64_t timestamp,protozero::ConstBytes blob)124 void ThermalTracker::ParseThermalExynosAcpmHighOverhead(
125 int64_t timestamp,
126 protozero::ConstBytes blob) {
127 protos::pbzero::ThermalExynosAcpmHighOverheadFtraceEvent::Decoder event(blob);
128 auto tz_id = static_cast<uint32_t>(event.tz_id());
129 if (tz_id >= kAcpmThermalZones.size()) {
130 context_->storage->IncrementStats(
131 stats::ftrace_thermal_exynos_acpm_unknown_tz_id);
132 return;
133 }
134 {
135 TrackId track = context_->track_tracker->InternTrack(
136 kAcpmTemperatureTrackBlueprint,
137 tracks::Dimensions(kAcpmThermalZones[tz_id]));
138 context_->event_tracker->PushCounter(
139 timestamp, static_cast<double>(event.current_temp()), track,
140 [this, tz_id](ArgsTracker::BoundInserter* inserter) {
141 StringId key = context_->storage->InternString(kThermalZoneIdKey);
142 inserter->AddArg(key, Variadic::Integer(tz_id));
143 });
144 }
145 {
146 TrackId track = context_->track_tracker->InternTrack(
147 kAcpmCoolingTrackBlueprint,
148 tracks::Dimensions(kAcpmThermalZones[tz_id]));
149 context_->event_tracker->PushCounter(
150 timestamp, static_cast<double>(event.cdev_state()), track,
151 [this, tz_id](ArgsTracker::BoundInserter* inserter) {
152 StringId key = context_->storage->InternString(kThermalZoneIdKey);
153 inserter->AddArg(key, Variadic::Integer(tz_id));
154 });
155 }
156 }
157
158 } // namespace perfetto::trace_processor
159