/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include "LayerTraceGenerator.h" namespace android { class Factory final : public surfaceflinger::Factory { public: ~Factory() = default; std::unique_ptr createHWComposer(const std::string&) override { return nullptr; } std::unique_ptr createVsyncConfiguration( Fps /*currentRefreshRate*/) override { return std::make_unique(); } sp createSurfaceInterceptor() override { return new android::impl::SurfaceInterceptor(); } sp createStartPropertySetThread( bool /* timestampPropertyValue */) override { return nullptr; } sp createDisplayDevice(DisplayDeviceCreationArgs& /* creationArgs */) override { return nullptr; } sp createGraphicBuffer(uint32_t /* width */, uint32_t /* height */, PixelFormat /* format */, uint32_t /* layerCount */, uint64_t /* usage */, std::string /* requestorName */) override { return nullptr; } void createBufferQueue(sp* /* outProducer */, sp* /* outConsumer */, bool /* consumerIsSurfaceFlinger */) override {} sp createMonitoredProducer( const sp& /* producer */, const sp& /* flinger */, const wp& /* layer */) override { return nullptr; } sp createBufferLayerConsumer( const sp& /* consumer */, renderengine::RenderEngine& /* renderEngine */, uint32_t /* textureName */, Layer* /* layer */) override { return nullptr; } std::unique_ptr createNativeWindowSurface( const sp& /* producer */) override { return nullptr; } std::unique_ptr createCompositionEngine() override { return compositionengine::impl::createCompositionEngine(); } sp createContainerLayer(const LayerCreationArgs& args) { return sp::make(args); } sp createBufferStateLayer(const LayerCreationArgs& args) { return new BufferStateLayer(args); } sp createEffectLayer(const LayerCreationArgs& args) { return new EffectLayer(args); } sp createBufferQueueLayer(const LayerCreationArgs&) override { return nullptr; } std::unique_ptr createFrameTracer() override { return std::make_unique>(); } std::unique_ptr createFrameTimeline( std::shared_ptr timeStats, pid_t surfaceFlingerPid = 0) override { return std::make_unique>(timeStats, surfaceFlingerPid); } }; class MockSurfaceFlinger : public SurfaceFlinger { public: MockSurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SurfaceFlinger::SkipInitialization) {} std::shared_ptr getExternalTextureFromBufferData( const BufferData& bufferData, const char* /* layerName */) const override { return std::make_shared(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 /* handle */> mLayerHandles; sp 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 flinger = new MockSurfaceFlinger(mFactory); TestableSurfaceFlinger mFlinger(flinger); mFlinger.setupRenderEngine( std::make_unique>()); mock::VsyncController* mVsyncController = new testing::NiceMock(); mock::VSyncTracker* mVSyncTracker = new testing::NiceMock(); mock::EventThread* mEventThread = new testing::NiceMock(); mock::EventThread* mSFEventThread = new testing::NiceMock(); mFlinger.setupScheduler(std::unique_ptr(mVsyncController), std::unique_ptr(mVSyncTracker), std::unique_ptr(mEventThread), std::unique_ptr(mSFEventThread), TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp, TestableSurfaceFlinger::kOneDisplayMode, true /* useNiceMock */); Hwc2::mock::Composer* mComposer = new testing::NiceMock(); mFlinger.setupComposer(std::unique_ptr(mComposer)); mFlinger.mutableMaxRenderTargetSize() = 16384; flinger->setLayerTracingFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS); flinger->startLayerTracing(traceFile.entry(0).elapsed_realtime_nanos()); std::unique_ptr mapper = std::make_unique(); 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 outHandle; int32_t outLayerId; LayerCreationArgs args(mFlinger.flinger(), nullptr /* client */, tracingArgs.name, tracingArgs.flags, LayerMetadata()); args.sequence = std::make_optional(tracingArgs.layerId); if (tracingArgs.mirrorFromId == -1) { sp 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 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