android13/frameworks/native/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp

283 lines
12 KiB
C++

/*
* Copyright (C) 2022 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.
*/
#undef LOG_TAG
#define LOG_TAG "LayerTraceGenerator"
#include <TestableSurfaceFlinger.h>
#include <Tracing/TransactionProtoParser.h>
#include <binder/IPCThreadState.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gui/LayerState.h>
#include <log/log.h>
#include <mock/MockEventThread.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <utils/String16.h>
#include <string>
#include "LayerTraceGenerator.h"
namespace android {
class Factory final : public surfaceflinger::Factory {
public:
~Factory() = default;
std::unique_ptr<HWComposer> createHWComposer(const std::string&) override { return nullptr; }
std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(
Fps /*currentRefreshRate*/) override {
return std::make_unique<scheduler::FakePhaseOffsets>();
}
sp<SurfaceInterceptor> createSurfaceInterceptor() override {
return new android::impl::SurfaceInterceptor();
}
sp<StartPropertySetThread> createStartPropertySetThread(
bool /* timestampPropertyValue */) override {
return nullptr;
}
sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs& /* creationArgs */) override {
return nullptr;
}
sp<GraphicBuffer> createGraphicBuffer(uint32_t /* width */, uint32_t /* height */,
PixelFormat /* format */, uint32_t /* layerCount */,
uint64_t /* usage */,
std::string /* requestorName */) override {
return nullptr;
}
void createBufferQueue(sp<IGraphicBufferProducer>* /* outProducer */,
sp<IGraphicBufferConsumer>* /* outConsumer */,
bool /* consumerIsSurfaceFlinger */) override {}
sp<IGraphicBufferProducer> createMonitoredProducer(
const sp<IGraphicBufferProducer>& /* producer */,
const sp<SurfaceFlinger>& /* flinger */, const wp<Layer>& /* layer */) override {
return nullptr;
}
sp<BufferLayerConsumer> createBufferLayerConsumer(
const sp<IGraphicBufferConsumer>& /* consumer */,
renderengine::RenderEngine& /* renderEngine */, uint32_t /* textureName */,
Layer* /* layer */) override {
return nullptr;
}
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>& /* producer */) override {
return nullptr;
}
std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
return compositionengine::impl::createCompositionEngine();
}
sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) {
return sp<ContainerLayer>::make(args);
}
sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) {
return new BufferStateLayer(args);
}
sp<EffectLayer> createEffectLayer(const LayerCreationArgs& args) {
return new EffectLayer(args);
}
sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
return nullptr;
}
std::unique_ptr<FrameTracer> createFrameTracer() override {
return std::make_unique<testing::NiceMock<mock::FrameTracer>>();
}
std::unique_ptr<frametimeline::FrameTimeline> createFrameTimeline(
std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid = 0) override {
return std::make_unique<testing::NiceMock<mock::FrameTimeline>>(timeStats,
surfaceFlingerPid);
}
};
class MockSurfaceFlinger : public SurfaceFlinger {
public:
MockSurfaceFlinger(Factory& factory)
: SurfaceFlinger(factory, SurfaceFlinger::SkipInitialization) {}
std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
const BufferData& bufferData, const char* /* layerName */) const override {
return std::make_shared<renderengine::mock::FakeExternalTexture>(bufferData.getWidth(),
bufferData.getHeight(),
bufferData.getId(),
bufferData
.getPixelFormat(),
bufferData.getUsage());
};
// b/220017192 migrate from transact codes to ISurfaceComposer apis
void setLayerTracingFlags(int32_t flags) {
Parcel data;
Parcel reply;
data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
data.writeInt32(flags);
transact(1033, data, &reply, 0 /* flags */);
}
void startLayerTracing(int64_t traceStartTime) {
Parcel data;
Parcel reply;
data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
data.writeInt32(1);
data.writeInt64(traceStartTime);
transact(1025, data, &reply, 0 /* flags */);
}
void stopLayerTracing(const char* tracePath) {
Parcel data;
Parcel reply;
data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
data.writeInt32(2);
data.writeCString(tracePath);
transact(1025, data, &reply, 0 /* flags */);
}
};
class TraceGenFlingerDataMapper : public TransactionProtoParser::FlingerDataMapper {
public:
std::unordered_map<int32_t /*layerId*/, sp<IBinder> /* handle */> mLayerHandles;
sp<IBinder> getLayerHandle(int32_t layerId) const override {
if (layerId == -1) {
ALOGE("Error: Called with layer=%d", layerId);
return nullptr;
}
auto it = mLayerHandles.find(layerId);
if (it == mLayerHandles.end()) {
ALOGE("Error: Could not find handle for layer=%d", layerId);
return nullptr;
}
return it->second;
}
};
bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile,
const char* outputLayersTracePath) {
if (traceFile.entry_size() == 0) {
return false;
}
Factory mFactory;
sp<MockSurfaceFlinger> flinger = new MockSurfaceFlinger(mFactory);
TestableSurfaceFlinger mFlinger(flinger);
mFlinger.setupRenderEngine(
std::make_unique<testing::NiceMock<renderengine::mock::RenderEngine>>());
mock::VsyncController* mVsyncController = new testing::NiceMock<mock::VsyncController>();
mock::VSyncTracker* mVSyncTracker = new testing::NiceMock<mock::VSyncTracker>();
mock::EventThread* mEventThread = new testing::NiceMock<mock::EventThread>();
mock::EventThread* mSFEventThread = new testing::NiceMock<mock::EventThread>();
mFlinger.setupScheduler(std::unique_ptr<scheduler::VsyncController>(mVsyncController),
std::unique_ptr<scheduler::VSyncTracker>(mVSyncTracker),
std::unique_ptr<EventThread>(mEventThread),
std::unique_ptr<EventThread>(mSFEventThread),
TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
TestableSurfaceFlinger::kOneDisplayMode, true /* useNiceMock */);
Hwc2::mock::Composer* mComposer = new testing::NiceMock<Hwc2::mock::Composer>();
mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
mFlinger.mutableMaxRenderTargetSize() = 16384;
flinger->setLayerTracingFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS);
flinger->startLayerTracing(traceFile.entry(0).elapsed_realtime_nanos());
std::unique_ptr<TraceGenFlingerDataMapper> mapper =
std::make_unique<TraceGenFlingerDataMapper>();
TraceGenFlingerDataMapper* dataMapper = mapper.get();
TransactionProtoParser parser(std::move(mapper));
nsecs_t frameTime;
int64_t vsyncId;
ALOGD("Generating %d transactions...", traceFile.entry_size());
for (int i = 0; i < traceFile.entry_size(); i++) {
proto::TransactionTraceEntry entry = traceFile.entry(i);
ALOGV(" Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
" layers +%d -%d transactions=%d",
i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
entry.added_layers_size(), entry.removed_layers_size(), entry.transactions_size());
for (int j = 0; j < entry.added_layers_size(); j++) {
// create layers
TracingLayerCreationArgs tracingArgs;
parser.fromProto(entry.added_layers(j), tracingArgs);
sp<IBinder> outHandle;
int32_t outLayerId;
LayerCreationArgs args(mFlinger.flinger(), nullptr /* client */, tracingArgs.name,
tracingArgs.flags, LayerMetadata());
args.sequence = std::make_optional<int32_t>(tracingArgs.layerId);
if (tracingArgs.mirrorFromId == -1) {
sp<IBinder> parentHandle = nullptr;
if ((tracingArgs.parentId != -1) &&
(dataMapper->mLayerHandles.find(tracingArgs.parentId) ==
dataMapper->mLayerHandles.end())) {
args.addToRoot = false;
} else {
parentHandle = dataMapper->getLayerHandle(tracingArgs.parentId);
}
mFlinger.createLayer(args, &outHandle, parentHandle, &outLayerId,
nullptr /* parentLayer */, nullptr /* outTransformHint */);
} else {
sp<IBinder> mirrorFromHandle = dataMapper->getLayerHandle(tracingArgs.mirrorFromId);
mFlinger.mirrorLayer(args, mirrorFromHandle, &outHandle, &outLayerId);
}
LOG_ALWAYS_FATAL_IF(outLayerId != tracingArgs.layerId,
"Could not create layer expected:%d actual:%d", tracingArgs.layerId,
outLayerId);
dataMapper->mLayerHandles[tracingArgs.layerId] = outHandle;
}
for (int j = 0; j < entry.transactions_size(); j++) {
// apply transactions
TransactionState transaction = parser.fromProto(entry.transactions(j));
mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
transaction.displays, transaction.flags,
transaction.applyToken, transaction.inputWindowCommands,
transaction.desiredPresentTime,
transaction.isAutoTimestamp, {},
transaction.hasListenerCallbacks,
transaction.listenerCallbacks, transaction.id);
}
for (int j = 0; j < entry.removed_layer_handles_size(); j++) {
dataMapper->mLayerHandles.erase(entry.removed_layer_handles(j));
}
frameTime = entry.elapsed_realtime_nanos();
vsyncId = entry.vsync_id();
mFlinger.commit(frameTime, vsyncId);
}
flinger->stopLayerTracing(outputLayersTracePath);
ALOGD("End of generating trace file. File written to %s", outputLayersTracePath);
dataMapper->mLayerHandles.clear();
return true;
}
} // namespace android