Loading services/surfaceflinger/DisplayDevice.h +23 −16 Original line number Diff line number Diff line Loading @@ -59,12 +59,14 @@ class Display; class DisplaySurface; } // namespace compositionengine class DisplayDevice : public LightRefBase<DisplayDevice> { class DisplayDevice : public RefBase { public: constexpr static float sDefaultMinLumiance = 0.0; constexpr static float sDefaultMaxLumiance = 500.0; explicit DisplayDevice(DisplayDeviceCreationArgs& args); // Must be destroyed on the main thread because it may call into HWComposer. virtual ~DisplayDevice(); std::shared_ptr<compositionengine::Display> getCompositionDisplay() const { Loading Loading @@ -246,21 +248,18 @@ struct DisplayDeviceCreationArgs { class DisplayRenderArea : public RenderArea { public: DisplayRenderArea(const sp<const DisplayDevice>& display, RotationFlags rotation = ui::Transform::ROT_0) : DisplayRenderArea(display, display->getBounds(), static_cast<uint32_t>(display->getWidth()), static_cast<uint32_t>(display->getHeight()), display->getCompositionDataSpace(), rotation) {} DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers = true) : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(), applyDeviceOrientation(rotation, display)), mDisplay(std::move(display)), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} static std::unique_ptr<RenderArea> create(wp<const DisplayDevice> displayWeak, const Rect& sourceCrop, ui::Size reqSize, ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers = true) { if (auto display = displayWeak.promote()) { // Using new to access a private constructor. return std::unique_ptr<DisplayRenderArea>( new DisplayRenderArea(std::move(display), sourceCrop, reqSize, reqDataSpace, rotation, allowSecureLayers)); } return nullptr; } const ui::Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { return mDisplay->getBounds(); } Loading Loading @@ -307,6 +306,14 @@ public: } private: DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop, ui::Size reqSize, ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers) : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(), applyDeviceOrientation(rotation, display)), mDisplay(std::move(display)), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} static RotationFlags applyDeviceOrientation(RotationFlags orientationFlag, const sp<const DisplayDevice>& device) { uint32_t inverseRotate90 = 0; Loading services/surfaceflinger/DisplayHardware/HWComposer.h +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ struct KnownHWCGenericLayerMetadata { const uint32_t id; }; // See the comment for SurfaceFlinger::getHwComposer for the thread safety rules for accessing // this class. class HWComposer { public: struct DeviceRequestedChanges { Loading services/surfaceflinger/RegionSamplingThread.cpp +35 −19 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include "DisplayDevice.h" #include "Layer.h" #include "Promise.h" #include "Scheduler/DispSync.h" #include "SurfaceFlinger.h" Loading Loading @@ -336,8 +337,20 @@ void RegionSamplingThread::captureSample() { return; } const auto device = mFlinger.getDefaultDisplayDevice(); const auto orientation = ui::Transform::toRotationFlags(device->getOrientation()); wp<const DisplayDevice> displayWeak; ui::LayerStack layerStack; ui::Transform::RotationFlags orientation; ui::Size displaySize; { // TODO(b/159112860): Don't keep sp<DisplayDevice> outside of SF main thread const sp<const DisplayDevice> display = mFlinger.getDefaultDisplayDevice(); displayWeak = display; layerStack = display->getLayerStack(); orientation = ui::Transform::toRotationFlags(display->getOrientation()); displaySize = display->getSize(); } std::vector<RegionSamplingThread::Descriptor> descriptors; Region sampleRegion; Loading @@ -346,20 +359,18 @@ void RegionSamplingThread::captureSample() { descriptors.emplace_back(descriptor); } const Rect sampledArea = sampleRegion.bounds(); auto dx = 0; auto dy = 0; switch (orientation) { case ui::Transform::ROT_90: dx = device->getWidth(); dx = displaySize.getWidth(); break; case ui::Transform::ROT_180: dx = device->getWidth(); dy = device->getHeight(); dx = displaySize.getWidth(); dy = displaySize.getHeight(); break; case ui::Transform::ROT_270: dy = device->getHeight(); dy = displaySize.getHeight(); break; default: break; Loading @@ -368,8 +379,13 @@ void RegionSamplingThread::captureSample() { ui::Transform t(orientation); auto screencapRegion = t.transform(sampleRegion); screencapRegion = screencapRegion.translate(dx, dy); DisplayRenderArea renderArea(device, screencapRegion.bounds(), sampledArea.getWidth(), sampledArea.getHeight(), ui::Dataspace::V0_SRGB, orientation); const Rect sampledBounds = sampleRegion.bounds(); SurfaceFlinger::RenderAreaFuture renderAreaFuture = promise::defer([=] { return DisplayRenderArea::create(displayWeak, sampledBounds, sampledBounds.getSize(), ui::Dataspace::V0_SRGB, orientation); }); std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners; Loading @@ -393,9 +409,9 @@ void RegionSamplingThread::captureSample() { constexpr bool roundOutwards = true; Rect transformed = transform.transform(bounds, roundOutwards); // If this layer doesn't intersect with the larger sampledArea, skip capturing it // If this layer doesn't intersect with the larger sampledBounds, skip capturing it Rect ignore; if (!transformed.intersect(sampledArea, &ignore)) return; if (!transformed.intersect(sampledBounds, &ignore)) return; // If the layer doesn't intersect a sampling area, skip capturing it bool intersectsAnyArea = false; Loading @@ -411,22 +427,22 @@ void RegionSamplingThread::captureSample() { bounds.top, bounds.right, bounds.bottom); visitor(layer); }; mFlinger.traverseLayersInDisplay(device, filterVisitor); mFlinger.traverseLayersInLayerStack(layerStack, filterVisitor); }; sp<GraphicBuffer> buffer = nullptr; if (mCachedBuffer && mCachedBuffer->getWidth() == sampledArea.getWidth() && mCachedBuffer->getHeight() == sampledArea.getHeight()) { if (mCachedBuffer && mCachedBuffer->getWidth() == sampledBounds.getWidth() && mCachedBuffer->getHeight() == sampledBounds.getHeight()) { buffer = mCachedBuffer; } else { const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER; buffer = new GraphicBuffer(sampledArea.getWidth(), sampledArea.getHeight(), buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); } bool ignored; mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false /* identityTransform */, true /* regionSampling */, ignored); mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, false /* identityTransform */, true /* regionSampling */, ignored); std::vector<Descriptor> activeDescriptors; for (const auto& descriptor : descriptors) { Loading @@ -437,7 +453,7 @@ void RegionSamplingThread::captureSample() { ALOGV("Sampling %zu descriptors", activeDescriptors.size()); std::vector<float> lumas = sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors, orientation); sampleBuffer(buffer, sampledBounds.leftTop(), activeDescriptors, orientation); if (lumas.size() != activeDescriptors.size()) { ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(), activeDescriptors.size()); Loading services/surfaceflinger/RenderArea.h +6 −9 Original line number Diff line number Diff line Loading @@ -23,11 +23,9 @@ public: static float getCaptureFillValue(CaptureFill captureFill); RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill, ui::Dataspace reqDataSpace, const Rect& displayViewport, RotationFlags rotation = ui::Transform::ROT_0) : mReqWidth(reqWidth), mReqHeight(reqHeight), RenderArea(ui::Size reqSize, CaptureFill captureFill, ui::Dataspace reqDataSpace, const Rect& displayViewport, RotationFlags rotation = ui::Transform::ROT_0) : mReqSize(reqSize), mReqDataSpace(reqDataSpace), mCaptureFill(captureFill), mRotationFlags(rotation), Loading Loading @@ -70,8 +68,8 @@ public: RotationFlags getRotationFlags() const { return mRotationFlags; } // Returns the size of the physical render area. int getReqWidth() const { return static_cast<int>(mReqWidth); } int getReqHeight() const { return static_cast<int>(mReqHeight); } int getReqWidth() const { return mReqSize.width; } int getReqHeight() const { return mReqSize.height; } // Returns the composition data space of the render area. ui::Dataspace getReqDataSpace() const { return mReqDataSpace; } Loading @@ -86,8 +84,7 @@ public: const Rect& getDisplayViewport() const { return mDisplayViewport; } private: const uint32_t mReqWidth; const uint32_t mReqHeight; const ui::Size mReqSize; const ui::Dataspace mReqDataSpace; const CaptureFill mCaptureFill; const RotationFlags mRotationFlags; Loading services/surfaceflinger/SurfaceFlinger.cpp +76 −58 Original line number Diff line number Diff line Loading @@ -5415,27 +5415,33 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken, renderAreaRotation = ui::Transform::ROT_0; } sp<DisplayDevice> display; wp<DisplayDevice> displayWeak; ui::LayerStack layerStack; ui::Size reqSize(reqWidth, reqHeight); { Mutex::Autolock lock(mStateLock); display = getDisplayDeviceLocked(displayToken); sp<DisplayDevice> display = getDisplayDeviceLocked(displayToken); if (!display) return NAME_NOT_FOUND; displayWeak = display; layerStack = display->getLayerStack(); // set the requested width/height to the logical display viewport size // by default if (reqWidth == 0 || reqHeight == 0) { reqWidth = uint32_t(display->getViewport().width()); reqHeight = uint32_t(display->getViewport().height()); reqSize = display->getViewport().getSize(); } } DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace, RenderAreaFuture renderAreaFuture = promise::defer([=] { return DisplayRenderArea::create(displayWeak, sourceCrop, reqSize, reqDataspace, renderAreaRotation, captureSecureLayers); auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display, std::placeholders::_1); return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, useIdentityTransform, outCapturedSecureLayers); }); auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, visitor); }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, outBuffer, reqPixelFormat, useIdentityTransform, outCapturedSecureLayers); } static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) { Loading Loading @@ -5491,19 +5497,20 @@ sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* outDataspace, sp<GraphicBuffer>* outBuffer) { sp<DisplayDevice> display; uint32_t width; uint32_t height; ui::LayerStack layerStack; wp<DisplayDevice> displayWeak; ui::Size size; ui::Transform::RotationFlags captureOrientation; { Mutex::Autolock lock(mStateLock); display = getDisplayByIdOrLayerStack(displayOrLayerStack); sp<DisplayDevice> display = getDisplayByIdOrLayerStack(displayOrLayerStack); if (!display) { return NAME_NOT_FOUND; } layerStack = display->getLayerStack(); displayWeak = display; width = uint32_t(display->getViewport().width()); height = uint32_t(display->getViewport().height()); size = display->getViewport().getSize(); const auto orientation = display->getOrientation(); captureOrientation = ui::Transform::toRotationFlags(orientation); Loading @@ -5529,14 +5536,19 @@ status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode); } DisplayRenderArea renderArea(display, Rect(), width, height, *outDataspace, captureOrientation, false /* captureSecureLayers */); RenderAreaFuture renderAreaFuture = promise::defer([=] { return DisplayRenderArea::create(displayWeak, Rect(), size, *outDataspace, captureOrientation, false /* captureSecureLayers */); }); auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, visitor); }; auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display, std::placeholders::_1); bool ignored = false; return captureScreenCommon(renderArea, traverseLayers, outBuffer, ui::PixelFormat::RGBA_8888, false /* useIdentityTransform */, return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, outBuffer, ui::PixelFormat::RGBA_8888, false /* useIdentityTransform */, ignored /* outCapturedSecureLayers */); } Loading @@ -5550,9 +5562,9 @@ status_t SurfaceFlinger::captureLayers( class LayerRenderArea : public RenderArea { public: LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop, int32_t reqWidth, int32_t reqHeight, Dataspace reqDataSpace, bool childrenOnly, const Rect& displayViewport) : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR, reqDataSpace, displayViewport), ui::Size reqSize, Dataspace reqDataSpace, bool childrenOnly, const Rect& displayViewport) : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, displayViewport), mLayer(layer), mCrop(crop), mNeedsFiltering(false), Loading Loading @@ -5627,8 +5639,7 @@ status_t SurfaceFlinger::captureLayers( const bool mChildrenOnly; }; int reqWidth = 0; int reqHeight = 0; ui::Size reqSize; sp<Layer> parent; Rect crop(sourceCrop); std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers; Loading Loading @@ -5665,8 +5676,7 @@ status_t SurfaceFlinger::captureLayers( // crop was not specified, or an invalid frame scale was provided. return BAD_VALUE; } reqWidth = crop.width() * frameScale; reqHeight = crop.height() * frameScale; reqSize = ui::Size(crop.width() * frameScale, crop.height() * frameScale); for (const auto& handle : excludeHandles) { sp<Layer> excludeLayer = fromHandleLocked(handle).promote(); Loading @@ -5687,15 +5697,18 @@ status_t SurfaceFlinger::captureLayers( } // mStateLock // really small crop or frameScale if (reqWidth <= 0) { reqWidth = 1; if (reqSize.width <= 0) { reqSize.width = 1; } if (reqHeight <= 0) { reqHeight = 1; if (reqSize.height <= 0) { reqSize.height = 1; } LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly, displayViewport); RenderAreaFuture renderAreaFuture = promise::defer([=]() -> std::unique_ptr<RenderArea> { return std::make_unique<LayerRenderArea>(this, parent, crop, reqSize, reqDataspace, childrenOnly, displayViewport); }); auto traverseLayers = [parent, childrenOnly, &excludeLayers](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { Loading @@ -5718,14 +5731,14 @@ status_t SurfaceFlinger::captureLayers( }; bool outCapturedSecureLayers = false; return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, false, outCapturedSecureLayers); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, outBuffer, reqPixelFormat, false, outCapturedSecureLayers); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, sp<GraphicBuffer>* outBuffer, const ui::PixelFormat reqPixelFormat, ui::Size bufferSize, sp<GraphicBuffer>* outBuffer, ui::PixelFormat reqPixelFormat, bool useIdentityTransform, bool& outCapturedSecureLayers) { ATRACE_CALL(); Loading @@ -5733,16 +5746,16 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, // TODO(b/116112787) Make buffer usage a parameter. const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; *outBuffer = getFactory().createGraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), static_cast<android_pixel_format>(reqPixelFormat), 1, usage, "screenshot"); *outBuffer = getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), static_cast<android_pixel_format>(reqPixelFormat), 1, usage, "screenshot"); return captureScreenCommon(renderArea, traverseLayers, *outBuffer, useIdentityTransform, false /* regionSampling */, outCapturedSecureLayers); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, *outBuffer, useIdentityTransform, false /* regionSampling */, outCapturedSecureLayers); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const sp<GraphicBuffer>& buffer, bool useIdentityTransform, bool regionSampling, Loading @@ -5755,23 +5768,28 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, do { std::tie(result, syncFd) = schedule([&] { schedule([&]() -> std::pair<status_t, int> { if (mRefreshPending) { ATRACE_NAME("Skipping screenshot for now"); return std::make_pair(EAGAIN, -1); ALOGW("Skipping screenshot for now"); return {EAGAIN, -1}; } std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get(); if (!renderArea) { ALOGW("Skipping screen capture because of invalid render area."); return {NO_MEMORY, -1}; } status_t result = NO_ERROR; int fd = -1; Mutex::Autolock lock(mStateLock); renderArea.render([&] { result = captureScreenImplLocked(renderArea, traverseLayers, buffer.get(), renderArea->render([&] { result = captureScreenImplLocked(*renderArea, traverseLayers, buffer.get(), useIdentityTransform, forSystem, &fd, regionSampling, outCapturedSecureLayers); }); return std::make_pair(result, fd); return {result, fd}; }).get(); } while (result == EAGAIN); Loading Loading @@ -5930,17 +5948,17 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& display, void SurfaceFlinger::traverseLayersInLayerStack(ui::LayerStack layerStack, const LayerVector::Visitor& visitor) { // We loop through the first level of layers without traversing, // as we need to determine which layers belong to the requested display. for (const auto& layer : mDrawingState.layersSortedByZ) { if (!layer->belongsToDisplay(display->getLayerStack(), false)) { if (!layer->belongsToDisplay(layerStack, false)) { continue; } // relative layers are traversed in Layer::traverseInZOrder layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->belongsToDisplay(display->getLayerStack(), false)) { if (!layer->belongsToDisplay(layerStack, false)) { return; } if (!layer->isVisible()) { Loading Loading
services/surfaceflinger/DisplayDevice.h +23 −16 Original line number Diff line number Diff line Loading @@ -59,12 +59,14 @@ class Display; class DisplaySurface; } // namespace compositionengine class DisplayDevice : public LightRefBase<DisplayDevice> { class DisplayDevice : public RefBase { public: constexpr static float sDefaultMinLumiance = 0.0; constexpr static float sDefaultMaxLumiance = 500.0; explicit DisplayDevice(DisplayDeviceCreationArgs& args); // Must be destroyed on the main thread because it may call into HWComposer. virtual ~DisplayDevice(); std::shared_ptr<compositionengine::Display> getCompositionDisplay() const { Loading Loading @@ -246,21 +248,18 @@ struct DisplayDeviceCreationArgs { class DisplayRenderArea : public RenderArea { public: DisplayRenderArea(const sp<const DisplayDevice>& display, RotationFlags rotation = ui::Transform::ROT_0) : DisplayRenderArea(display, display->getBounds(), static_cast<uint32_t>(display->getWidth()), static_cast<uint32_t>(display->getHeight()), display->getCompositionDataSpace(), rotation) {} DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers = true) : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(), applyDeviceOrientation(rotation, display)), mDisplay(std::move(display)), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} static std::unique_ptr<RenderArea> create(wp<const DisplayDevice> displayWeak, const Rect& sourceCrop, ui::Size reqSize, ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers = true) { if (auto display = displayWeak.promote()) { // Using new to access a private constructor. return std::unique_ptr<DisplayRenderArea>( new DisplayRenderArea(std::move(display), sourceCrop, reqSize, reqDataSpace, rotation, allowSecureLayers)); } return nullptr; } const ui::Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { return mDisplay->getBounds(); } Loading Loading @@ -307,6 +306,14 @@ public: } private: DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop, ui::Size reqSize, ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers) : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(), applyDeviceOrientation(rotation, display)), mDisplay(std::move(display)), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} static RotationFlags applyDeviceOrientation(RotationFlags orientationFlag, const sp<const DisplayDevice>& device) { uint32_t inverseRotate90 = 0; Loading
services/surfaceflinger/DisplayHardware/HWComposer.h +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ struct KnownHWCGenericLayerMetadata { const uint32_t id; }; // See the comment for SurfaceFlinger::getHwComposer for the thread safety rules for accessing // this class. class HWComposer { public: struct DeviceRequestedChanges { Loading
services/surfaceflinger/RegionSamplingThread.cpp +35 −19 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include "DisplayDevice.h" #include "Layer.h" #include "Promise.h" #include "Scheduler/DispSync.h" #include "SurfaceFlinger.h" Loading Loading @@ -336,8 +337,20 @@ void RegionSamplingThread::captureSample() { return; } const auto device = mFlinger.getDefaultDisplayDevice(); const auto orientation = ui::Transform::toRotationFlags(device->getOrientation()); wp<const DisplayDevice> displayWeak; ui::LayerStack layerStack; ui::Transform::RotationFlags orientation; ui::Size displaySize; { // TODO(b/159112860): Don't keep sp<DisplayDevice> outside of SF main thread const sp<const DisplayDevice> display = mFlinger.getDefaultDisplayDevice(); displayWeak = display; layerStack = display->getLayerStack(); orientation = ui::Transform::toRotationFlags(display->getOrientation()); displaySize = display->getSize(); } std::vector<RegionSamplingThread::Descriptor> descriptors; Region sampleRegion; Loading @@ -346,20 +359,18 @@ void RegionSamplingThread::captureSample() { descriptors.emplace_back(descriptor); } const Rect sampledArea = sampleRegion.bounds(); auto dx = 0; auto dy = 0; switch (orientation) { case ui::Transform::ROT_90: dx = device->getWidth(); dx = displaySize.getWidth(); break; case ui::Transform::ROT_180: dx = device->getWidth(); dy = device->getHeight(); dx = displaySize.getWidth(); dy = displaySize.getHeight(); break; case ui::Transform::ROT_270: dy = device->getHeight(); dy = displaySize.getHeight(); break; default: break; Loading @@ -368,8 +379,13 @@ void RegionSamplingThread::captureSample() { ui::Transform t(orientation); auto screencapRegion = t.transform(sampleRegion); screencapRegion = screencapRegion.translate(dx, dy); DisplayRenderArea renderArea(device, screencapRegion.bounds(), sampledArea.getWidth(), sampledArea.getHeight(), ui::Dataspace::V0_SRGB, orientation); const Rect sampledBounds = sampleRegion.bounds(); SurfaceFlinger::RenderAreaFuture renderAreaFuture = promise::defer([=] { return DisplayRenderArea::create(displayWeak, sampledBounds, sampledBounds.getSize(), ui::Dataspace::V0_SRGB, orientation); }); std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners; Loading @@ -393,9 +409,9 @@ void RegionSamplingThread::captureSample() { constexpr bool roundOutwards = true; Rect transformed = transform.transform(bounds, roundOutwards); // If this layer doesn't intersect with the larger sampledArea, skip capturing it // If this layer doesn't intersect with the larger sampledBounds, skip capturing it Rect ignore; if (!transformed.intersect(sampledArea, &ignore)) return; if (!transformed.intersect(sampledBounds, &ignore)) return; // If the layer doesn't intersect a sampling area, skip capturing it bool intersectsAnyArea = false; Loading @@ -411,22 +427,22 @@ void RegionSamplingThread::captureSample() { bounds.top, bounds.right, bounds.bottom); visitor(layer); }; mFlinger.traverseLayersInDisplay(device, filterVisitor); mFlinger.traverseLayersInLayerStack(layerStack, filterVisitor); }; sp<GraphicBuffer> buffer = nullptr; if (mCachedBuffer && mCachedBuffer->getWidth() == sampledArea.getWidth() && mCachedBuffer->getHeight() == sampledArea.getHeight()) { if (mCachedBuffer && mCachedBuffer->getWidth() == sampledBounds.getWidth() && mCachedBuffer->getHeight() == sampledBounds.getHeight()) { buffer = mCachedBuffer; } else { const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER; buffer = new GraphicBuffer(sampledArea.getWidth(), sampledArea.getHeight(), buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); } bool ignored; mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false /* identityTransform */, true /* regionSampling */, ignored); mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, false /* identityTransform */, true /* regionSampling */, ignored); std::vector<Descriptor> activeDescriptors; for (const auto& descriptor : descriptors) { Loading @@ -437,7 +453,7 @@ void RegionSamplingThread::captureSample() { ALOGV("Sampling %zu descriptors", activeDescriptors.size()); std::vector<float> lumas = sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors, orientation); sampleBuffer(buffer, sampledBounds.leftTop(), activeDescriptors, orientation); if (lumas.size() != activeDescriptors.size()) { ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(), activeDescriptors.size()); Loading
services/surfaceflinger/RenderArea.h +6 −9 Original line number Diff line number Diff line Loading @@ -23,11 +23,9 @@ public: static float getCaptureFillValue(CaptureFill captureFill); RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill, ui::Dataspace reqDataSpace, const Rect& displayViewport, RotationFlags rotation = ui::Transform::ROT_0) : mReqWidth(reqWidth), mReqHeight(reqHeight), RenderArea(ui::Size reqSize, CaptureFill captureFill, ui::Dataspace reqDataSpace, const Rect& displayViewport, RotationFlags rotation = ui::Transform::ROT_0) : mReqSize(reqSize), mReqDataSpace(reqDataSpace), mCaptureFill(captureFill), mRotationFlags(rotation), Loading Loading @@ -70,8 +68,8 @@ public: RotationFlags getRotationFlags() const { return mRotationFlags; } // Returns the size of the physical render area. int getReqWidth() const { return static_cast<int>(mReqWidth); } int getReqHeight() const { return static_cast<int>(mReqHeight); } int getReqWidth() const { return mReqSize.width; } int getReqHeight() const { return mReqSize.height; } // Returns the composition data space of the render area. ui::Dataspace getReqDataSpace() const { return mReqDataSpace; } Loading @@ -86,8 +84,7 @@ public: const Rect& getDisplayViewport() const { return mDisplayViewport; } private: const uint32_t mReqWidth; const uint32_t mReqHeight; const ui::Size mReqSize; const ui::Dataspace mReqDataSpace; const CaptureFill mCaptureFill; const RotationFlags mRotationFlags; Loading
services/surfaceflinger/SurfaceFlinger.cpp +76 −58 Original line number Diff line number Diff line Loading @@ -5415,27 +5415,33 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken, renderAreaRotation = ui::Transform::ROT_0; } sp<DisplayDevice> display; wp<DisplayDevice> displayWeak; ui::LayerStack layerStack; ui::Size reqSize(reqWidth, reqHeight); { Mutex::Autolock lock(mStateLock); display = getDisplayDeviceLocked(displayToken); sp<DisplayDevice> display = getDisplayDeviceLocked(displayToken); if (!display) return NAME_NOT_FOUND; displayWeak = display; layerStack = display->getLayerStack(); // set the requested width/height to the logical display viewport size // by default if (reqWidth == 0 || reqHeight == 0) { reqWidth = uint32_t(display->getViewport().width()); reqHeight = uint32_t(display->getViewport().height()); reqSize = display->getViewport().getSize(); } } DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace, RenderAreaFuture renderAreaFuture = promise::defer([=] { return DisplayRenderArea::create(displayWeak, sourceCrop, reqSize, reqDataspace, renderAreaRotation, captureSecureLayers); auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display, std::placeholders::_1); return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, useIdentityTransform, outCapturedSecureLayers); }); auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, visitor); }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, outBuffer, reqPixelFormat, useIdentityTransform, outCapturedSecureLayers); } static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) { Loading Loading @@ -5491,19 +5497,20 @@ sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* outDataspace, sp<GraphicBuffer>* outBuffer) { sp<DisplayDevice> display; uint32_t width; uint32_t height; ui::LayerStack layerStack; wp<DisplayDevice> displayWeak; ui::Size size; ui::Transform::RotationFlags captureOrientation; { Mutex::Autolock lock(mStateLock); display = getDisplayByIdOrLayerStack(displayOrLayerStack); sp<DisplayDevice> display = getDisplayByIdOrLayerStack(displayOrLayerStack); if (!display) { return NAME_NOT_FOUND; } layerStack = display->getLayerStack(); displayWeak = display; width = uint32_t(display->getViewport().width()); height = uint32_t(display->getViewport().height()); size = display->getViewport().getSize(); const auto orientation = display->getOrientation(); captureOrientation = ui::Transform::toRotationFlags(orientation); Loading @@ -5529,14 +5536,19 @@ status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode); } DisplayRenderArea renderArea(display, Rect(), width, height, *outDataspace, captureOrientation, false /* captureSecureLayers */); RenderAreaFuture renderAreaFuture = promise::defer([=] { return DisplayRenderArea::create(displayWeak, Rect(), size, *outDataspace, captureOrientation, false /* captureSecureLayers */); }); auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, visitor); }; auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display, std::placeholders::_1); bool ignored = false; return captureScreenCommon(renderArea, traverseLayers, outBuffer, ui::PixelFormat::RGBA_8888, false /* useIdentityTransform */, return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, outBuffer, ui::PixelFormat::RGBA_8888, false /* useIdentityTransform */, ignored /* outCapturedSecureLayers */); } Loading @@ -5550,9 +5562,9 @@ status_t SurfaceFlinger::captureLayers( class LayerRenderArea : public RenderArea { public: LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop, int32_t reqWidth, int32_t reqHeight, Dataspace reqDataSpace, bool childrenOnly, const Rect& displayViewport) : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR, reqDataSpace, displayViewport), ui::Size reqSize, Dataspace reqDataSpace, bool childrenOnly, const Rect& displayViewport) : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, displayViewport), mLayer(layer), mCrop(crop), mNeedsFiltering(false), Loading Loading @@ -5627,8 +5639,7 @@ status_t SurfaceFlinger::captureLayers( const bool mChildrenOnly; }; int reqWidth = 0; int reqHeight = 0; ui::Size reqSize; sp<Layer> parent; Rect crop(sourceCrop); std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers; Loading Loading @@ -5665,8 +5676,7 @@ status_t SurfaceFlinger::captureLayers( // crop was not specified, or an invalid frame scale was provided. return BAD_VALUE; } reqWidth = crop.width() * frameScale; reqHeight = crop.height() * frameScale; reqSize = ui::Size(crop.width() * frameScale, crop.height() * frameScale); for (const auto& handle : excludeHandles) { sp<Layer> excludeLayer = fromHandleLocked(handle).promote(); Loading @@ -5687,15 +5697,18 @@ status_t SurfaceFlinger::captureLayers( } // mStateLock // really small crop or frameScale if (reqWidth <= 0) { reqWidth = 1; if (reqSize.width <= 0) { reqSize.width = 1; } if (reqHeight <= 0) { reqHeight = 1; if (reqSize.height <= 0) { reqSize.height = 1; } LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly, displayViewport); RenderAreaFuture renderAreaFuture = promise::defer([=]() -> std::unique_ptr<RenderArea> { return std::make_unique<LayerRenderArea>(this, parent, crop, reqSize, reqDataspace, childrenOnly, displayViewport); }); auto traverseLayers = [parent, childrenOnly, &excludeLayers](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { Loading @@ -5718,14 +5731,14 @@ status_t SurfaceFlinger::captureLayers( }; bool outCapturedSecureLayers = false; return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat, false, outCapturedSecureLayers); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, outBuffer, reqPixelFormat, false, outCapturedSecureLayers); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, sp<GraphicBuffer>* outBuffer, const ui::PixelFormat reqPixelFormat, ui::Size bufferSize, sp<GraphicBuffer>* outBuffer, ui::PixelFormat reqPixelFormat, bool useIdentityTransform, bool& outCapturedSecureLayers) { ATRACE_CALL(); Loading @@ -5733,16 +5746,16 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, // TODO(b/116112787) Make buffer usage a parameter. const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; *outBuffer = getFactory().createGraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), static_cast<android_pixel_format>(reqPixelFormat), 1, usage, "screenshot"); *outBuffer = getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), static_cast<android_pixel_format>(reqPixelFormat), 1, usage, "screenshot"); return captureScreenCommon(renderArea, traverseLayers, *outBuffer, useIdentityTransform, false /* regionSampling */, outCapturedSecureLayers); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, *outBuffer, useIdentityTransform, false /* regionSampling */, outCapturedSecureLayers); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const sp<GraphicBuffer>& buffer, bool useIdentityTransform, bool regionSampling, Loading @@ -5755,23 +5768,28 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, do { std::tie(result, syncFd) = schedule([&] { schedule([&]() -> std::pair<status_t, int> { if (mRefreshPending) { ATRACE_NAME("Skipping screenshot for now"); return std::make_pair(EAGAIN, -1); ALOGW("Skipping screenshot for now"); return {EAGAIN, -1}; } std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get(); if (!renderArea) { ALOGW("Skipping screen capture because of invalid render area."); return {NO_MEMORY, -1}; } status_t result = NO_ERROR; int fd = -1; Mutex::Autolock lock(mStateLock); renderArea.render([&] { result = captureScreenImplLocked(renderArea, traverseLayers, buffer.get(), renderArea->render([&] { result = captureScreenImplLocked(*renderArea, traverseLayers, buffer.get(), useIdentityTransform, forSystem, &fd, regionSampling, outCapturedSecureLayers); }); return std::make_pair(result, fd); return {result, fd}; }).get(); } while (result == EAGAIN); Loading Loading @@ -5930,17 +5948,17 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& display, void SurfaceFlinger::traverseLayersInLayerStack(ui::LayerStack layerStack, const LayerVector::Visitor& visitor) { // We loop through the first level of layers without traversing, // as we need to determine which layers belong to the requested display. for (const auto& layer : mDrawingState.layersSortedByZ) { if (!layer->belongsToDisplay(display->getLayerStack(), false)) { if (!layer->belongsToDisplay(layerStack, false)) { continue; } // relative layers are traversed in Layer::traverseInZOrder layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->belongsToDisplay(display->getLayerStack(), false)) { if (!layer->belongsToDisplay(layerStack, false)) { return; } if (!layer->isVisible()) { Loading