Loading libs/gui/LayerState.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,7 @@ status_t CaptureArgs::write(Parcel& output) const { SAFE_PARCEL(output.writeBool, captureSecureLayers); SAFE_PARCEL(output.writeInt32, uid); SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(dataspace)); SAFE_PARCEL(output.writeBool, allowProtected); return NO_ERROR; } Loading @@ -599,6 +600,7 @@ status_t CaptureArgs::read(const Parcel& input) { SAFE_PARCEL(input.readInt32, &uid); SAFE_PARCEL(input.readInt32, &value); dataspace = static_cast<ui::Dataspace>(value); SAFE_PARCEL(input.readBool, &allowProtected); return NO_ERROR; } Loading libs/gui/include/gui/LayerState.h +9 −1 Original line number Diff line number Diff line Loading @@ -318,6 +318,14 @@ struct CaptureArgs { // NOTE: In normal cases, we want the screen to be captured in display's colorspace. ui::Dataspace dataspace = ui::Dataspace::UNKNOWN; // The receiver of the capture can handle protected buffer. A protected buffer has // GRALLOC_USAGE_PROTECTED usage bit and must not be accessed unprotected behaviour. // Any read/write access from unprotected context will result in undefined behaviour. // Protected contents are typically DRM contents. This has no direct implication to the // secure property of the surface, which is specified by the application explicitly to avoid // the contents being accessed/captured by screenshot or unsecure display. bool allowProtected = false; virtual status_t write(Parcel& output) const; virtual status_t read(const Parcel& input); }; Loading Loading @@ -345,7 +353,7 @@ struct ScreenCaptureResults { sp<GraphicBuffer> buffer; bool capturedSecureLayers{false}; ui::Dataspace capturedDataspace{ui::Dataspace::V0_SRGB}; status_t result = NO_ERROR; status_t result = OK; status_t write(Parcel& output) const; status_t read(const Parcel& input); Loading services/surfaceflinger/Layer.h +3 −2 Original line number Diff line number Diff line Loading @@ -465,7 +465,7 @@ public: virtual bool canReceiveInput() const; /* * isProtected - true if the layer may contain protected content in the * isProtected - true if the layer may contain protected contents in the * GRALLOC_USAGE_PROTECTED sense. */ virtual bool isProtected() const { return false; } Loading Loading @@ -677,7 +677,8 @@ public: /* * isSecure - true if this surface is secure, that is if it prevents * screenshots or VNC servers. * screenshots or VNC servers. A surface can be set to be secure by the * application, being secure doesn't mean the surface has DRM contents. */ bool isSecure() const; Loading services/surfaceflinger/SurfaceFlinger.cpp +67 −49 Original line number Diff line number Diff line Loading @@ -5381,6 +5381,45 @@ static status_t validateScreenshotPermissions(const CaptureArgs& captureArgs) { return PERMISSION_DENIED; } status_t SurfaceFlinger::setSchedFifo(bool enabled) { static constexpr int kFifoPriority = 2; static constexpr int kOtherPriority = 0; struct sched_param param = {0}; int sched_policy; if (enabled) { sched_policy = SCHED_FIFO; param.sched_priority = kFifoPriority; } else { sched_policy = SCHED_OTHER; param.sched_priority = kOtherPriority; } if (sched_setscheduler(0, sched_policy, ¶m) != 0) { return -errno; } return NO_ERROR; } sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { if (const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(PhysicalDisplayId{displayOrLayerStack})) { return getDisplayDeviceLocked(displayToken); } // Couldn't find display by displayId. Try to get display by layerStack since virtual displays // may not have a displayId. return getDisplayByLayerStack(displayOrLayerStack); } sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { for (const auto& [token, display] : mDisplays) { if (display->getLayerStack() == layerStack) { return display; } } return nullptr; } status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading Loading @@ -5429,46 +5468,7 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, args.pixelFormat, captureListener); } status_t SurfaceFlinger::setSchedFifo(bool enabled) { static constexpr int kFifoPriority = 2; static constexpr int kOtherPriority = 0; struct sched_param param = {0}; int sched_policy; if (enabled) { sched_policy = SCHED_FIFO; param.sched_priority = kFifoPriority; } else { sched_policy = SCHED_OTHER; param.sched_priority = kOtherPriority; } if (sched_setscheduler(0, sched_policy, ¶m) != 0) { return -errno; } return NO_ERROR; } sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { if (const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(PhysicalDisplayId{displayOrLayerStack})) { return getDisplayDeviceLocked(displayToken); } // Couldn't find display by displayId. Try to get display by layerStack since virtual displays // may not have a displayId. return getDisplayByLayerStack(displayOrLayerStack); } sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { for (const auto& [token, display] : mDisplays) { if (display->getLayerStack() == layerStack) { return display; } } return nullptr; args.pixelFormat, args.allowProtected, captureListener); } status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack, Loading Loading @@ -5503,7 +5503,8 @@ status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack, }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, ui::PixelFormat::RGBA_8888, captureListener); ui::PixelFormat::RGBA_8888, false /* allowProtected */, captureListener); } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, Loading Loading @@ -5624,18 +5625,32 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, args.pixelFormat, captureListener); args.pixelFormat, args.allowProtected, captureListener); } status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, const bool allowProtected, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); // 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; // Loop over all visible layers to see whether there's any protected layer. A protected layer is // typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer. // A protected layer has no implication on whether it's secure, which is explicitly set by // application to avoid being screenshot or drawn via unsecure display. const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; if (allowProtected && supportsProtected) { traverseLayers([&](Layer* layer) { hasProtectedLayer = hasProtectedLayer || (layer->isVisible() && layer->isProtected()); }); } const uint32_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE | (hasProtectedLayer && allowProtected && supportsProtected ? GRALLOC_USAGE_PROTECTED : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); sp<GraphicBuffer> buffer = getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), static_cast<android_pixel_format>(reqPixelFormat), Loading @@ -5646,7 +5661,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, sp<GraphicBuffer>& buffer, bool regionSampling, sp<GraphicBuffer>& buffer, const bool regionSampling, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading Loading @@ -5704,6 +5719,8 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED; // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place // the impetus on WindowManager to not persist them. Loading Loading @@ -5748,14 +5765,13 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, std::vector<Layer*> renderedLayers; Region clearRegion = Region::INVALID_REGION; traverseLayers([&](Layer* layer) { const bool supportProtectedContent = false; Region clip(renderArea.getBounds()); compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ clip, layer->needsFilteringForScreenshots(display.get(), transform) || renderArea.needsFiltering(), renderArea.isSecure(), supportProtectedContent, useProtected, clearRegion, layerStackSpaceRect, clientCompositionDisplay.outputDataspace, Loading Loading @@ -5793,7 +5809,7 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, // there is no need for synchronization with the GPU. base::unique_fd bufferFence; base::unique_fd drawFence; getRenderEngine().useProtectedContext(false); getRenderEngine().useProtectedContext(useProtected); getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence); Loading @@ -5805,6 +5821,8 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, layer->onLayerDisplayed(releaseFence); } } // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); return NO_ERROR; } Loading services/surfaceflinger/SurfaceFlinger.h +5 −4 Original line number Diff line number Diff line Loading @@ -797,13 +797,14 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, const sp<GraphicBuffer>&, bool forSystem, int* outSyncFd, bool regionSampling, ScreenCaptureResults&); status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, const sp<IScreenCaptureListener>&); ui::PixelFormat, const bool allowProtected, const sp<IScreenCaptureListener>&); status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp<GraphicBuffer>&, bool regionSampling, const sp<IScreenCaptureListener>&); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, const sp<GraphicBuffer>&, bool forSystem, int* outSyncFd, bool regionSampling, ScreenCaptureResults&); sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock); sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock); Loading Loading
libs/gui/LayerState.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -586,6 +586,7 @@ status_t CaptureArgs::write(Parcel& output) const { SAFE_PARCEL(output.writeBool, captureSecureLayers); SAFE_PARCEL(output.writeInt32, uid); SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(dataspace)); SAFE_PARCEL(output.writeBool, allowProtected); return NO_ERROR; } Loading @@ -599,6 +600,7 @@ status_t CaptureArgs::read(const Parcel& input) { SAFE_PARCEL(input.readInt32, &uid); SAFE_PARCEL(input.readInt32, &value); dataspace = static_cast<ui::Dataspace>(value); SAFE_PARCEL(input.readBool, &allowProtected); return NO_ERROR; } Loading
libs/gui/include/gui/LayerState.h +9 −1 Original line number Diff line number Diff line Loading @@ -318,6 +318,14 @@ struct CaptureArgs { // NOTE: In normal cases, we want the screen to be captured in display's colorspace. ui::Dataspace dataspace = ui::Dataspace::UNKNOWN; // The receiver of the capture can handle protected buffer. A protected buffer has // GRALLOC_USAGE_PROTECTED usage bit and must not be accessed unprotected behaviour. // Any read/write access from unprotected context will result in undefined behaviour. // Protected contents are typically DRM contents. This has no direct implication to the // secure property of the surface, which is specified by the application explicitly to avoid // the contents being accessed/captured by screenshot or unsecure display. bool allowProtected = false; virtual status_t write(Parcel& output) const; virtual status_t read(const Parcel& input); }; Loading Loading @@ -345,7 +353,7 @@ struct ScreenCaptureResults { sp<GraphicBuffer> buffer; bool capturedSecureLayers{false}; ui::Dataspace capturedDataspace{ui::Dataspace::V0_SRGB}; status_t result = NO_ERROR; status_t result = OK; status_t write(Parcel& output) const; status_t read(const Parcel& input); Loading
services/surfaceflinger/Layer.h +3 −2 Original line number Diff line number Diff line Loading @@ -465,7 +465,7 @@ public: virtual bool canReceiveInput() const; /* * isProtected - true if the layer may contain protected content in the * isProtected - true if the layer may contain protected contents in the * GRALLOC_USAGE_PROTECTED sense. */ virtual bool isProtected() const { return false; } Loading Loading @@ -677,7 +677,8 @@ public: /* * isSecure - true if this surface is secure, that is if it prevents * screenshots or VNC servers. * screenshots or VNC servers. A surface can be set to be secure by the * application, being secure doesn't mean the surface has DRM contents. */ bool isSecure() const; Loading
services/surfaceflinger/SurfaceFlinger.cpp +67 −49 Original line number Diff line number Diff line Loading @@ -5381,6 +5381,45 @@ static status_t validateScreenshotPermissions(const CaptureArgs& captureArgs) { return PERMISSION_DENIED; } status_t SurfaceFlinger::setSchedFifo(bool enabled) { static constexpr int kFifoPriority = 2; static constexpr int kOtherPriority = 0; struct sched_param param = {0}; int sched_policy; if (enabled) { sched_policy = SCHED_FIFO; param.sched_priority = kFifoPriority; } else { sched_policy = SCHED_OTHER; param.sched_priority = kOtherPriority; } if (sched_setscheduler(0, sched_policy, ¶m) != 0) { return -errno; } return NO_ERROR; } sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { if (const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(PhysicalDisplayId{displayOrLayerStack})) { return getDisplayDeviceLocked(displayToken); } // Couldn't find display by displayId. Try to get display by layerStack since virtual displays // may not have a displayId. return getDisplayByLayerStack(displayOrLayerStack); } sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { for (const auto& [token, display] : mDisplays) { if (display->getLayerStack() == layerStack) { return display; } } return nullptr; } status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading Loading @@ -5429,46 +5468,7 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, args.pixelFormat, captureListener); } status_t SurfaceFlinger::setSchedFifo(bool enabled) { static constexpr int kFifoPriority = 2; static constexpr int kOtherPriority = 0; struct sched_param param = {0}; int sched_policy; if (enabled) { sched_policy = SCHED_FIFO; param.sched_priority = kFifoPriority; } else { sched_policy = SCHED_OTHER; param.sched_priority = kOtherPriority; } if (sched_setscheduler(0, sched_policy, ¶m) != 0) { return -errno; } return NO_ERROR; } sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { if (const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(PhysicalDisplayId{displayOrLayerStack})) { return getDisplayDeviceLocked(displayToken); } // Couldn't find display by displayId. Try to get display by layerStack since virtual displays // may not have a displayId. return getDisplayByLayerStack(displayOrLayerStack); } sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) { for (const auto& [token, display] : mDisplays) { if (display->getLayerStack() == layerStack) { return display; } } return nullptr; args.pixelFormat, args.allowProtected, captureListener); } status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack, Loading Loading @@ -5503,7 +5503,8 @@ status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack, }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, ui::PixelFormat::RGBA_8888, captureListener); ui::PixelFormat::RGBA_8888, false /* allowProtected */, captureListener); } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, Loading Loading @@ -5624,18 +5625,32 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, }; return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, args.pixelFormat, captureListener); args.pixelFormat, args.allowProtected, captureListener); } status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, const bool allowProtected, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); // 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; // Loop over all visible layers to see whether there's any protected layer. A protected layer is // typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer. // A protected layer has no implication on whether it's secure, which is explicitly set by // application to avoid being screenshot or drawn via unsecure display. const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; if (allowProtected && supportsProtected) { traverseLayers([&](Layer* layer) { hasProtectedLayer = hasProtectedLayer || (layer->isVisible() && layer->isProtected()); }); } const uint32_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE | (hasProtectedLayer && allowProtected && supportsProtected ? GRALLOC_USAGE_PROTECTED : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); sp<GraphicBuffer> buffer = getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), static_cast<android_pixel_format>(reqPixelFormat), Loading @@ -5646,7 +5661,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, sp<GraphicBuffer>& buffer, bool regionSampling, sp<GraphicBuffer>& buffer, const bool regionSampling, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading Loading @@ -5704,6 +5719,8 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED; // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place // the impetus on WindowManager to not persist them. Loading Loading @@ -5748,14 +5765,13 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, std::vector<Layer*> renderedLayers; Region clearRegion = Region::INVALID_REGION; traverseLayers([&](Layer* layer) { const bool supportProtectedContent = false; Region clip(renderArea.getBounds()); compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ clip, layer->needsFilteringForScreenshots(display.get(), transform) || renderArea.needsFiltering(), renderArea.isSecure(), supportProtectedContent, useProtected, clearRegion, layerStackSpaceRect, clientCompositionDisplay.outputDataspace, Loading Loading @@ -5793,7 +5809,7 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, // there is no need for synchronization with the GPU. base::unique_fd bufferFence; base::unique_fd drawFence; getRenderEngine().useProtectedContext(false); getRenderEngine().useProtectedContext(useProtected); getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence); Loading @@ -5805,6 +5821,8 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, layer->onLayerDisplayed(releaseFence); } } // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); return NO_ERROR; } Loading
services/surfaceflinger/SurfaceFlinger.h +5 −4 Original line number Diff line number Diff line Loading @@ -797,13 +797,14 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, const sp<GraphicBuffer>&, bool forSystem, int* outSyncFd, bool regionSampling, ScreenCaptureResults&); status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, const sp<IScreenCaptureListener>&); ui::PixelFormat, const bool allowProtected, const sp<IScreenCaptureListener>&); status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp<GraphicBuffer>&, bool regionSampling, const sp<IScreenCaptureListener>&); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, const sp<GraphicBuffer>&, bool forSystem, int* outSyncFd, bool regionSampling, ScreenCaptureResults&); sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock); sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock); Loading