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
generate(const proto::TransactionTraceFile & traceFile,const char * outputLayersTracePath,bool onlyLastEntry)43 bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile,
44 const char* outputLayersTracePath, bool onlyLastEntry) {
45 if (traceFile.entry_size() == 0) {
46 ALOGD("Trace file is empty");
47 return false;
48 }
49
50 TransactionProtoParser parser(std::make_unique<TransactionProtoParser::FlingerDataMapper>());
51
52 // frontend
53 frontend::LayerLifecycleManager lifecycleManager;
54 frontend::LayerHierarchyBuilder hierarchyBuilder{{}};
55 frontend::LayerSnapshotBuilder snapshotBuilder;
56 ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo> displayInfos;
57
58 renderengine::ShadowSettings globalShadowSettings{.ambientColor = {1, 1, 1, 1}};
59 char value[PROPERTY_VALUE_MAX];
60 property_get("ro.surface_flinger.supports_background_blur", value, "0");
61 bool supportsBlur = atoi(value);
62
63 LayerTracing layerTracing;
64 layerTracing.setTraceFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS);
65 // 10MB buffer size (large enough to hold a single entry)
66 layerTracing.setBufferSize(10 * 1024 * 1024);
67 layerTracing.enable();
68 layerTracing.writeToFile(outputLayersTracePath);
69 std::ofstream out(outputLayersTracePath, std::ios::binary | std::ios::app);
70
71 ALOGD("Generating %d transactions...", traceFile.entry_size());
72 for (int i = 0; i < traceFile.entry_size(); i++) {
73 // parse proto
74 proto::TransactionTraceEntry entry = traceFile.entry(i);
75 ALOGV(" Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
76 " layers +%d -%d handles -%d transactions=%d",
77 i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
78 entry.added_layers_size(), entry.destroyed_layers_size(),
79 entry.destroyed_layer_handles_size(), entry.transactions_size());
80
81 std::vector<std::unique_ptr<frontend::RequestedLayerState>> addedLayers;
82 addedLayers.reserve((size_t)entry.added_layers_size());
83 for (int j = 0; j < entry.added_layers_size(); j++) {
84 LayerCreationArgs args;
85 parser.fromProto(entry.added_layers(j), args);
86 ALOGV(" %s", args.getDebugString().c_str());
87 addedLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args));
88 }
89
90 std::vector<TransactionState> transactions;
91 transactions.reserve((size_t)entry.transactions_size());
92 for (int j = 0; j < entry.transactions_size(); j++) {
93 // apply transactions
94 TransactionState transaction = parser.fromProto(entry.transactions(j));
95 for (auto& resolvedComposerState : transaction.states) {
96 if (resolvedComposerState.state.what & layer_state_t::eInputInfoChanged) {
97 if (!resolvedComposerState.state.windowInfoHandle->getInfo()->inputConfig.test(
98 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
99 // create a fake token since the FE expects a valid token
100 resolvedComposerState.state.windowInfoHandle->editInfo()->token =
101 sp<BBinder>::make();
102 }
103 }
104 }
105 transactions.emplace_back(std::move(transaction));
106 }
107
108 for (int j = 0; j < entry.destroyed_layers_size(); j++) {
109 ALOGV(" destroyedHandles=%d", entry.destroyed_layers(j));
110 }
111
112 std::vector<uint32_t> destroyedHandles;
113 destroyedHandles.reserve((size_t)entry.destroyed_layer_handles_size());
114 for (int j = 0; j < entry.destroyed_layer_handles_size(); j++) {
115 ALOGV(" destroyedHandles=%d", entry.destroyed_layer_handles(j));
116 destroyedHandles.push_back(entry.destroyed_layer_handles(j));
117 }
118
119 bool displayChanged = entry.displays_changed();
120 if (displayChanged) {
121 parser.fromProto(entry.displays(), displayInfos);
122 }
123
124 // apply updates
125 lifecycleManager.addLayers(std::move(addedLayers));
126 lifecycleManager.applyTransactions(transactions, /*ignoreUnknownHandles=*/true);
127 lifecycleManager.onHandlesDestroyed(destroyedHandles, /*ignoreUnknownHandles=*/true);
128
129 if (lifecycleManager.getGlobalChanges().test(
130 frontend::RequestedLayerState::Changes::Hierarchy)) {
131 hierarchyBuilder.update(lifecycleManager.getLayers(),
132 lifecycleManager.getDestroyedLayers());
133 }
134
135 frontend::LayerSnapshotBuilder::Args args{.root = hierarchyBuilder.getHierarchy(),
136 .layerLifecycleManager = lifecycleManager,
137 .displays = displayInfos,
138 .displayChanges = displayChanged,
139 .globalShadowSettings = globalShadowSettings,
140 .supportsBlur = supportsBlur,
141 .forceFullDamage = false,
142 .supportedLayerGenericMetadata = {},
143 .genericLayerMetadataKeyMap = {}};
144 snapshotBuilder.update(args);
145
146 bool visibleRegionsDirty = lifecycleManager.getGlobalChanges().any(
147 frontend::RequestedLayerState::Changes::VisibleRegion |
148 frontend::RequestedLayerState::Changes::Hierarchy |
149 frontend::RequestedLayerState::Changes::Visibility);
150
151 ALOGV(" layers:%04zu snapshots:%04zu changes:%s", lifecycleManager.getLayers().size(),
152 snapshotBuilder.getSnapshots().size(),
153 lifecycleManager.getGlobalChanges().string().c_str());
154
155 lifecycleManager.commitChanges();
156
157 LayersProto layersProto = LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {},
158 layerTracing.getFlags())
159 .generate(hierarchyBuilder.getHierarchy());
160 auto displayProtos = LayerProtoHelper::writeDisplayInfoToProto(displayInfos);
161 if (!onlyLastEntry || (i == traceFile.entry_size() - 1)) {
162 layerTracing.notify(visibleRegionsDirty, entry.elapsed_realtime_nanos(),
163 entry.vsync_id(), &layersProto, {}, &displayProtos);
164 layerTracing.appendToStream(out);
165 }
166 }
167 layerTracing.disable("", /*writeToFile=*/false);
168 out.close();
169 ALOGD("End of generating trace file. File written to %s", outputLayersTracePath);
170 return true;
171 }
172
173 } // namespace android
174