diff options
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 48 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 4 | ||||
-rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 6 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 3 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 3 | ||||
-rw-r--r-- | libs/ui/GraphicBuffer.cpp | 4 | ||||
-rw-r--r-- | services/inputflinger/InputReader.cpp | 33 | ||||
-rw-r--r-- | services/inputflinger/InputReader.h | 14 | ||||
-rw-r--r-- | services/surfaceflinger/BufferLayer.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 81 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceTracing.cpp | 46 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceTracing.h | 9 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp | 3 |
14 files changed, 205 insertions, 52 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index e22bc708c9..d2d27e8239 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -332,6 +332,34 @@ public: return result; } + virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to transact: %d", result); + return result; + } + result = reply.readInt32(); + if (result == NO_ERROR) { + result = reply.read(*outViewport); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to read: %d", result); + return result; + } + } + return result; + } + virtual int getActiveConfig(const sp<IBinder>& display) { Parcel data, reply; @@ -724,6 +752,26 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } + case GET_DISPLAY_VIEWPORT: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + Rect outViewport; + sp<IBinder> display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to readStrongBinder: %d", result); + return result; + } + result = getDisplayViewport(display, &outViewport); + result = reply->writeInt32(result); + if (result == NO_ERROR) { + result = reply->write(outViewport); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to write: %d", result); + return result; + } + } + return NO_ERROR; + } case GET_ACTIVE_CONFIG: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 63560c4b89..f3c6fd2f87 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -718,6 +718,10 @@ status_t SurfaceComposerClient::getDisplayInfo(const sp<IBinder>& display, return NO_ERROR; } +status_t SurfaceComposerClient::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) { + return ComposerService::getComposerService()->getDisplayViewport(display, outViewport); +} + int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) { return ComposerService::getComposerService()->getActiveConfig(display); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e40157206d..99a3a75502 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -157,6 +157,9 @@ public: virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) = 0; + /* returns display viewport information of the given display */ + virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) = 0; + /* indicates which of the configurations returned by getDisplayInfo is * currently active */ virtual int getActiveConfig(const sp<IBinder>& display) = 0; @@ -250,7 +253,8 @@ public: ENABLE_VSYNC_INJECTIONS, INJECT_VSYNC, GET_LAYER_DEBUG_INFO, - CREATE_SCOPED_CONNECTION + CREATE_SCOPED_CONNECTION, + GET_DISPLAY_VIEWPORT }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 377fe68c41..ad8a8b09d0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -79,6 +79,9 @@ public: static status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info); + // Get the display viewport for the given display + static status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport); + // Get the index of the current active configuration (relative to the list // returned by getDisplayInfo) static int getActiveConfig(const sp<IBinder>& display); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 2c02ba657d..6e196bfac8 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -581,6 +581,9 @@ public: Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; } status_t getDisplayStats(const sp<IBinder>& /*display*/, DisplayStatInfo* /*stats*/) override { return NO_ERROR; } + status_t getDisplayViewport(const sp<IBinder>& /*display*/, Rect* /*outViewport*/) override { + return NO_ERROR; + } int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; } status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/) override { diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 03824795ed..c50d1d038e 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -376,6 +376,10 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& status_t GraphicBuffer::unflatten( void const*& buffer, size_t& size, int const*& fds, size_t& count) { + if (size < 12 * sizeof(int)) { + android_errorWriteLog(0x534e4554, "114223584"); + return NO_MEMORY; + } int const* buf = static_cast<int const*>(buffer); diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index b37b7fd392..efa6f88a87 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -3089,6 +3089,7 @@ TouchInputMapper::TouchInputMapper(InputDevice* device) : InputMapper(device), mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), + mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0), mSurfaceOrientation(DISPLAY_ORIENTATION_0) { } @@ -3596,6 +3597,11 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { break; } + mPhysicalWidth = naturalPhysicalWidth; + mPhysicalHeight = naturalPhysicalHeight; + mPhysicalLeft = naturalPhysicalLeft; + mPhysicalTop = naturalPhysicalTop; + mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; @@ -3604,6 +3610,11 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mSurfaceOrientation = mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0; } else { + mPhysicalWidth = rawWidth; + mPhysicalHeight = rawHeight; + mPhysicalLeft = 0; + mPhysicalTop = 0; + mSurfaceWidth = rawWidth; mSurfaceHeight = rawHeight; mSurfaceLeft = 0; @@ -3914,6 +3925,10 @@ void TouchInputMapper::dumpSurface(std::string& dump) { dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); + dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth); + dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight); + dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft); + dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop); dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); } @@ -5118,10 +5133,10 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate; + x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale; y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate; - left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate; - right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; + left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale; + right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale; bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; orientation -= M_PI; @@ -5130,10 +5145,10 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_270: - x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate; + x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale; y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; - right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; + left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale; + right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale; bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; orientation += M_PI_2; @@ -6531,8 +6546,12 @@ void TouchInputMapper::cancelTouch(nsecs_t when) { } bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { + const float scaledX = x * mXScale; + const float scaledY = y * mYScale; return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue - && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue; + && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth + && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue + && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight; } const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit( diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index cef3212684..2f98e69800 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -1517,13 +1517,21 @@ private: // in the natural orientation. // The surface origin specifies how the surface coordinates should be translated // to align with the logical display coordinate space. - // The orientation may be different from the viewport orientation as it specifies - // the rotation of the surface coordinates required to produce the viewport's - // requested orientation, so it will depend on whether the device is orientation aware. int32_t mSurfaceWidth; int32_t mSurfaceHeight; int32_t mSurfaceLeft; int32_t mSurfaceTop; + + // Similar to the surface coordinates, but in the raw display coordinate space rather than in + // the logical coordinate space. + int32_t mPhysicalWidth; + int32_t mPhysicalHeight; + int32_t mPhysicalLeft; + int32_t mPhysicalTop; + + // The orientation may be different from the viewport orientation as it specifies + // the rotation of the surface coordinates required to produce the viewport's + // requested orientation, so it will depend on whether the device is orientation aware. int32_t mSurfaceOrientation; // Translation and scaling factors, orientation-independent. diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 3db633b7d1..f5b5eda9ec 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -704,6 +704,8 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { } void BufferLayer::onFirstRef() { + Layer::onFirstRef(); + // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cf53930fa1..11e7ff0f68 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -981,6 +981,21 @@ status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */, return NO_ERROR; } +status_t SurfaceFlinger::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) { + if (outViewport == nullptr || display.get() == nullptr) { + return BAD_VALUE; + } + + sp<const DisplayDevice> device(getDisplayDevice(display)); + if (device == nullptr) { + return BAD_VALUE; + } + + *outViewport = device->getViewport(); + + return NO_ERROR; +} + int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) { if (display == nullptr) { ALOGE("%s : display is nullptr", __func__); @@ -2180,11 +2195,15 @@ void SurfaceFlinger::postFramebuffer() displayDevice->onSwapBuffersCompleted(); displayDevice->makeCurrent(); for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + sp<Fence> releaseFence = Fence::NO_FENCE; + // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. auto hwcLayer = layer->getHwcLayer(hwcId); - sp<Fence> releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer); + if (hwcId >= 0) { + releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer); + } // If the layer was client composited in the previous frame, we // need to merge with the previous client target acquire fence. @@ -2331,8 +2350,10 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { bool hasWideColorGamut = false; std::unordered_map<ColorMode, std::vector<RenderIntent>> hwcColorModes; + HdrCapabilities hdrCapabilities; + int32_t supportedPerFrameMetadata = 0; - if (hasWideColorDisplay) { + if (hasWideColorDisplay && hwcId >= 0) { std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId); for (ColorMode colorMode : modes) { switch (colorMode) { @@ -2351,8 +2372,10 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( } } - HdrCapabilities hdrCapabilities; - getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities); + if (hwcId >= 0) { + getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities); + supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(hwcId); + } auto nativeWindowSurface = mCreateNativeWindowSurface(producer); auto nativeWindow = nativeWindowSurface->getNativeWindow(); @@ -2386,8 +2409,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, dispSurface, std::move(renderSurface), displayWidth, displayHeight, hasWideColorGamut, hdrCapabilities, - getHwComposer().getSupportedPerFrameMetadata(hwcId), - hwcColorModes, initialPowerMode); + supportedPerFrameMetadata, hwcColorModes, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); @@ -3038,22 +3060,17 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev } } - if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) { - // just to be on the safe side, we don't set the - // scissor on the main display. It should never be needed - // anyways (though in theory it could since the API allows it). - const Rect& bounds(displayDevice->getBounds()); - const Rect& scissor(displayDevice->getScissor()); - if (scissor != bounds) { - // scissor doesn't match the screen's dimensions, so we - // need to clear everything outside of it and enable - // the GL scissor so we don't draw anything where we shouldn't - - // enable scissor for this frame - const uint32_t height = displayDevice->getHeight(); - getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom, - scissor.getWidth(), scissor.getHeight()); - } + const Rect& bounds(displayDevice->getBounds()); + const Rect& scissor(displayDevice->getScissor()); + if (scissor != bounds) { + // scissor doesn't match the screen's dimensions, so we + // need to clear everything outside of it and enable + // the GL scissor so we don't draw anything where we shouldn't + + // enable scissor for this frame + const uint32_t height = displayDevice->getHeight(); + getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom, + scissor.getWidth(), scissor.getHeight()); } } @@ -4401,6 +4418,12 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.append("\n"); /* + * Tracing state + */ + mTracing.dump(result); + result.append("\n"); + + /* * HWC layer minidump */ for (size_t d = 0; d < mDisplays.size(); d++) { @@ -4747,12 +4770,12 @@ status_t SurfaceFlinger::onTransact( case 1025: { // Set layer tracing n = data.readInt32(); if (n) { - ALOGV("LayerTracing enabled"); + ALOGD("LayerTracing enabled"); mTracing.enable(); doTracing("tracing.enable"); reply->writeInt32(NO_ERROR); } else { - ALOGV("LayerTracing disabled"); + ALOGD("LayerTracing disabled"); status_t err = mTracing.disable(); reply->writeInt32(err); } @@ -4821,6 +4844,16 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuf const sp<const DisplayDevice> device(getDisplayDeviceLocked(display)); if (CC_UNLIKELY(device == 0)) return BAD_VALUE; + const Rect& dispScissor = device->getScissor(); + if (!dispScissor.isEmpty()) { + sourceCrop.set(dispScissor); + // adb shell screencap will default reqWidth and reqHeight to zeros. + if (reqWidth == 0 || reqHeight == 0) { + reqWidth = uint32_t(device->getViewport().width()); + reqHeight = uint32_t(device->getViewport().height()); + } + } + DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8f724e98d1..0148ab6754 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -429,6 +429,7 @@ private: const Rect& sourceCrop, float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats); + virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport); virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs); virtual int getActiveConfig(const sp<IBinder>& display); diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index f8c466ea19..67dcd06187 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -27,52 +27,67 @@ namespace android { void SurfaceTracing::enable() { + ATRACE_CALL(); + std::lock_guard<std::mutex> protoGuard(mTraceMutex); + if (mEnabled) { return; } - ATRACE_CALL(); mEnabled = true; - std::lock_guard<std::mutex> protoGuard(mTraceMutex); - mTrace.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | - LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); + mTrace = std::make_unique<LayersTraceFileProto>(); + mTrace->set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | + LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); } status_t SurfaceTracing::disable() { + ATRACE_CALL(); + std::lock_guard<std::mutex> protoGuard(mTraceMutex); + if (!mEnabled) { return NO_ERROR; } - ATRACE_CALL(); - std::lock_guard<std::mutex> protoGuard(mTraceMutex); mEnabled = false; status_t err(writeProtoFileLocked()); ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied"); ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields"); - mTrace.Clear(); + mTrace.reset(); return err; } -bool SurfaceTracing::isEnabled() { +bool SurfaceTracing::isEnabled() const { + std::lock_guard<std::mutex> protoGuard(mTraceMutex); return mEnabled; } void SurfaceTracing::traceLayers(const char* where, LayersProto layers) { std::lock_guard<std::mutex> protoGuard(mTraceMutex); - - LayersTraceProto* entry = mTrace.add_entry(); + if (!mEnabled) { + return; + } + LayersTraceProto* entry = mTrace->add_entry(); entry->set_elapsed_realtime_nanos(elapsedRealtimeNano()); entry->set_where(where); entry->mutable_layers()->Swap(&layers); + + constexpr int maxBufferedEntryCount = 3600; + if (mTrace->entry_size() >= maxBufferedEntryCount) { + // TODO: flush buffered entries without disabling tracing + ALOGE("too many buffered frames; force disable tracing"); + mEnabled = false; + writeProtoFileLocked(); + mTrace.reset(); + } } status_t SurfaceTracing::writeProtoFileLocked() { ATRACE_CALL(); - if (!mTrace.IsInitialized()) { + if (!mTrace->IsInitialized()) { return NOT_ENOUGH_DATA; } std::string output; - if (!mTrace.SerializeToString(&output)) { + if (!mTrace->SerializeToString(&output)) { return PERMISSION_DENIED; } if (!android::base::WriteStringToFile(output, mOutputFileName, true)) { @@ -82,4 +97,11 @@ status_t SurfaceTracing::writeProtoFileLocked() { return NO_ERROR; } +void SurfaceTracing::dump(String8& result) const { + std::lock_guard<std::mutex> protoGuard(mTraceMutex); + + result.appendFormat("Tracing state: %s\n", mEnabled ? "enabled" : "disabled"); + result.appendFormat(" number of entries: %d\n", mTrace ? mTrace->entry_size() : 0); +} + } // namespace android diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h index 590ab9680f..fd8cb82a9b 100644 --- a/services/surfaceflinger/SurfaceTracing.h +++ b/services/surfaceflinger/SurfaceTracing.h @@ -18,7 +18,9 @@ #include <layerproto/LayerProtoHeader.h> #include <utils/Errors.h> +#include <utils/String8.h> +#include <memory> #include <mutex> using namespace android::surfaceflinger; @@ -32,9 +34,10 @@ class SurfaceTracing { public: void enable(); status_t disable(); - bool isEnabled(); + bool isEnabled() const; void traceLayers(const char* where, LayersProto); + void dump(String8& result) const; private: static constexpr auto DEFAULT_FILENAME = "/data/misc/wmtrace/layers_trace.pb"; @@ -43,8 +46,8 @@ private: bool mEnabled = false; std::string mOutputFileName = DEFAULT_FILENAME; - std::mutex mTraceMutex; - LayersTraceFileProto mTrace; + mutable std::mutex mTraceMutex; + std::unique_ptr<LayersTraceFileProto> mTrace; }; } // namespace android diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 9b308bfcc8..9ac5f3b73e 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -658,8 +658,7 @@ using NonHwcVirtualDisplayCase = using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>; using HwcVirtualDisplayCase = Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant, - HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>, - NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>; + NonHwcDisplayHdrSupportVariant, NonHwcPerFrameMetadataSupportVariant>; using WideColorP3ColorimetricDisplayCase = Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>, HdrNotSupportedVariant<PrimaryDisplayVariant>, |