1 /*
2  * Copyright (C) 2022 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 #undef LOG_TAG
18 #define LOG_TAG "LayerTraceGenerator"
19 //#define LOG_NDEBUG 0
20 
21 #include <Tracing/TransactionProtoParser.h>
22 #include <gui/LayerState.h>
23 #include <log/log.h>
24 #include <renderengine/ExternalTexture.h>
25 #include <utils/String16.h>
26 #include <filesystem>
27 #include <fstream>
28 #include <ios>
29 #include <string>
30 #include <vector>
31 #include "FrontEnd/LayerCreationArgs.h"
32 #include "FrontEnd/RequestedLayerState.h"
33 #include "LayerProtoHelper.h"
34 #include "Tracing/LayerTracing.h"
35 #include "TransactionState.h"
36 #include "cutils/properties.h"
37 
38 #include "LayerTraceGenerator.h"
39 
40 namespace android {
41 using namespace ftl::flag_operators;
42 
43 namespace {
44 class ScopedTraceDisabler {
45 public:
ScopedTraceDisabler()46     ScopedTraceDisabler() { TransactionTraceWriter::getInstance().disable(); }
~ScopedTraceDisabler()47     ~ScopedTraceDisabler() { TransactionTraceWriter::getInstance().enable(); }
48 };
49 } // namespace
50 
generate(const perfetto::protos::TransactionTraceFile & traceFile,std::uint32_t traceFlags,LayerTracing & layerTracing,bool onlyLastEntry)51 bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& traceFile,
52                                    std::uint32_t traceFlags, LayerTracing& layerTracing,
53                                    bool onlyLastEntry) {
54     // We are generating the layers trace by replaying back a set of transactions. If the
55     // transactions have unexpected states, we may generate a transaction trace to debug
56     // the unexpected state. This is silly. So we disable it by poking the
57     // TransactionTraceWriter. This is really a hack since we should manage our depenecies a
58     // little better.
59     ScopedTraceDisabler fatalErrorTraceDisabler;
60 
61     if (traceFile.entry_size() == 0) {
62         ALOGD("Trace file is empty");
63         return false;
64     }
65 
66     TransactionProtoParser parser(std::make_unique<TransactionProtoParser::FlingerDataMapper>());
67 
68     // frontend
69     frontend::LayerLifecycleManager lifecycleManager;
70     frontend::LayerHierarchyBuilder hierarchyBuilder;
71     frontend::LayerSnapshotBuilder snapshotBuilder;
72     ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo> displayInfos;
73 
74     ShadowSettings globalShadowSettings{.ambientColor = {1, 1, 1, 1}};
75     char value[PROPERTY_VALUE_MAX];
76     property_get("ro.surface_flinger.supports_background_blur", value, "0");
77     bool supportsBlur = atoi(value);
78 
79     ALOGD("Generating %d transactions...", traceFile.entry_size());
80     for (int i = 0; i < traceFile.entry_size(); i++) {
81         // parse proto
82         perfetto::protos::TransactionTraceEntry entry = traceFile.entry(i);
83         ALOGV("    Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
84               " layers +%d -%d handles -%d transactions=%d",
85               i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
86               entry.added_layers_size(), entry.destroyed_layers_size(),
87               entry.destroyed_layer_handles_size(), entry.transactions_size());
88 
89         std::vector<std::unique_ptr<frontend::RequestedLayerState>> addedLayers;
90         addedLayers.reserve((size_t)entry.added_layers_size());
91         for (int j = 0; j < entry.added_layers_size(); j++) {
92             LayerCreationArgs args;
93             parser.fromProto(entry.added_layers(j), args);
94             ALOGV("       %s", args.getDebugString().c_str());
95             addedLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args));
96         }
97 
98         std::vector<TransactionState> transactions;
99         transactions.reserve((size_t)entry.transactions_size());
100         for (int j = 0; j < entry.transactions_size(); j++) {
101             // apply transactions
102             TransactionState transaction = parser.fromProto(entry.transactions(j));
103             for (auto& resolvedComposerState : transaction.states) {
104                 if (resolvedComposerState.state.what & layer_state_t::eInputInfoChanged) {
105                     if (!resolvedComposerState.state.windowInfoHandle->getInfo()->inputConfig.test(
106                                 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
107                         // create a fake token since the FE expects a valid token
108                         resolvedComposerState.state.windowInfoHandle->editInfo()->token =
109                                 sp<BBinder>::make();
110                     }
111                 }
112             }
113             transactions.emplace_back(std::move(transaction));
114         }
115 
116         for (int j = 0; j < entry.destroyed_layers_size(); j++) {
117             ALOGV("       destroyedHandles=%d", entry.destroyed_layers(j));
118         }
119 
120         std::vector<std::pair<uint32_t, std::string>> destroyedHandles;
121         destroyedHandles.reserve((size_t)entry.destroyed_layer_handles_size());
122         for (int j = 0; j < entry.destroyed_layer_handles_size(); j++) {
123             ALOGV("       destroyedHandles=%d", entry.destroyed_layer_handles(j));
124             destroyedHandles.push_back({entry.destroyed_layer_handles(j), ""});
125         }
126 
127         bool displayChanged = entry.displays_changed();
128         if (displayChanged) {
129             parser.fromProto(entry.displays(), displayInfos);
130         }
131 
132         // apply updates
133         lifecycleManager.addLayers(std::move(addedLayers));
134         lifecycleManager.applyTransactions(transactions, /*ignoreUnknownHandles=*/true);
135         lifecycleManager.onHandlesDestroyed(destroyedHandles, /*ignoreUnknownHandles=*/true);
136 
137         // update hierarchy
138         hierarchyBuilder.update(lifecycleManager);
139 
140         // update snapshots
141         frontend::LayerSnapshotBuilder::Args args{.root = hierarchyBuilder.getHierarchy(),
142                                                   .layerLifecycleManager = lifecycleManager,
143                                                   .displays = displayInfos,
144                                                   .displayChanges = displayChanged,
145                                                   .globalShadowSettings = globalShadowSettings,
146                                                   .supportsBlur = supportsBlur,
147                                                   .forceFullDamage = false,
148                                                   .supportedLayerGenericMetadata = {},
149                                                   .genericLayerMetadataKeyMap = {}};
150         snapshotBuilder.update(args);
151 
152         bool visibleRegionsDirty = lifecycleManager.getGlobalChanges().any(
153                 frontend::RequestedLayerState::Changes::VisibleRegion |
154                 frontend::RequestedLayerState::Changes::Hierarchy |
155                 frontend::RequestedLayerState::Changes::Visibility);
156 
157         ALOGV("    layers:%04zu snapshots:%04zu changes:%s", lifecycleManager.getLayers().size(),
158               snapshotBuilder.getSnapshots().size(),
159               lifecycleManager.getGlobalChanges().string().c_str());
160 
161         lifecycleManager.commitChanges();
162 
163         auto layersProto =
164                 LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {}, traceFlags)
165                         .generate(hierarchyBuilder.getHierarchy());
166         auto displayProtos = LayerProtoHelper::writeDisplayInfoToProto(displayInfos);
167         if (!onlyLastEntry || (i == traceFile.entry_size() - 1)) {
168             perfetto::protos::LayersSnapshotProto snapshotProto{};
169             snapshotProto.set_vsync_id(entry.vsync_id());
170             snapshotProto.set_elapsed_realtime_nanos(entry.elapsed_realtime_nanos());
171             snapshotProto.set_where(visibleRegionsDirty ? "visibleRegionsDirty" : "bufferLatched");
172             *snapshotProto.mutable_layers() = std::move(layersProto);
173             if ((traceFlags & LayerTracing::TRACE_COMPOSITION) == 0) {
174                 snapshotProto.set_excludes_composition_state(true);
175             }
176             *snapshotProto.mutable_displays() = std::move(displayProtos);
177 
178             layerTracing.addProtoSnapshotToOstream(std::move(snapshotProto),
179                                                    LayerTracing::Mode::MODE_GENERATED);
180         }
181     }
182     ALOGD("End of generating trace file");
183     return true;
184 }
185 
186 } // namespace android
187