diff options
author | 2023-11-28 21:16:03 +0000 | |
---|---|---|
committer | 2023-12-05 16:51:45 +0000 | |
commit | 18fa7c60ccd9697973308fce60482e67dee58d98 (patch) | |
tree | 41e7a6b09741f6d8fd8e9bb0ed1d3e3aff2e9c93 | |
parent | a4326c9f9c4fbdde71cb1e265dbc0450b9aa5faa (diff) |
Add isProtected flag to Output
Allow outputs to decide if they want to render protected content, not
just if they support it. The current code checks if the Output is secure
when deciding whether to render protected content. By adding a new flag,
it will allow displays to decide if they want to render secure,
protected, or both.
This code doesn't have a way to create displays with only protected and
will still rely on the isSecure flag to ensure backwards compatibility.
Test: presubmit
Fixes: 285553970
Fixes: 300492271
Change-Id: If5e65388825d37f4ddaea5190259a136cfa89264
18 files changed, 86 insertions, 30 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h index 98c4af487e..6e60839dd9 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h @@ -42,6 +42,10 @@ struct DisplayCreationArgs { // True if this display should be considered secure bool isSecure = false; + // True if this display should be considered protected, as in this display should render DRM + // content. + bool isProtected = false; + // Optional pointer to the power advisor interface, if one is needed for // this display. Hwc2::PowerAdvisor* powerAdvisor = nullptr; @@ -73,6 +77,11 @@ public: return *this; } + DisplayCreationArgsBuilder& setIsProtected(bool isProtected) { + mArgs.isProtected = isProtected; + return *this; + } + DisplayCreationArgsBuilder& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) { mArgs.powerAdvisor = powerAdvisor; return *this; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index ccff1eccb6..a1d61323a8 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -97,7 +97,7 @@ public: const bool isSecure; // If set to true, the target buffer has protected content support. - const bool supportsProtectedContent; + const bool isProtected; // Viewport of the target being rendered to. This is used to determine // the shadow light position. @@ -167,8 +167,7 @@ using LayerFESet = std::unordered_set<sp<LayerFE>, LayerFESpHash>; static inline bool operator==(const LayerFE::ClientCompositionTargetSettings& lhs, const LayerFE::ClientCompositionTargetSettings& rhs) { return lhs.clip.hasSameRects(rhs.clip) && lhs.needsFiltering == rhs.needsFiltering && - lhs.isSecure == rhs.isSecure && - lhs.supportsProtectedContent == rhs.supportsProtectedContent && + lhs.isSecure == rhs.isSecure && lhs.isProtected == rhs.isProtected && lhs.viewport == rhs.viewport && lhs.dataspace == rhs.dataspace && lhs.realContentIsVisible == rhs.realContentIsVisible && lhs.clearContent == rhs.clearContent; @@ -189,7 +188,7 @@ static inline void PrintTo(const LayerFE::ClientCompositionTargetSettings& setti PrintTo(settings.clip, os); *os << "\n .needsFiltering = " << settings.needsFiltering; *os << "\n .isSecure = " << settings.isSecure; - *os << "\n .supportsProtectedContent = " << settings.supportsProtectedContent; + *os << "\n .isProtected = " << settings.isProtected; *os << "\n .viewport = "; PrintTo(settings.viewport, os); *os << "\n .dataspace = "; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index 692ed24899..6b1c318d1c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -53,6 +53,9 @@ struct OutputCompositionState { // If false, this output is not considered secure bool isSecure{false}; + // If false, this output is not considered protected + bool isProtected{false}; + // If true, the current frame on this output uses client composition bool usesClientComposition{false}; diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 0475881bae..690d35f068 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -57,6 +57,7 @@ void Display::setConfiguration(const compositionengine::DisplayCreationArgs& arg mId = args.id; mPowerAdvisor = args.powerAdvisor; editState().isSecure = args.isSecure; + editState().isProtected = args.isProtected; editState().displaySpace.setBounds(args.pixels); setName(args.name); } diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index e4d757810a..c399224491 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1232,10 +1232,18 @@ void Output::updateProtectedContentState() { auto& renderEngine = getCompositionEngine().getRenderEngine(); const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); - // If we the display is secure, protected content support is enabled, and at - // least one layer has protected content, we need to use a secure back - // buffer. - if (outputState.isSecure && supportsProtectedContent) { + bool isProtected; + if (FlagManager::getInstance().display_protected()) { + isProtected = outputState.isProtected; + } else { + isProtected = outputState.isSecure; + } + + // We need to set the render surface as protected (DRM) if all the following conditions are met: + // 1. The display is protected (in legacy, check if the display is secure) + // 2. Protected content is supported + // 3. At least one layer has protected content. + if (isProtected && supportsProtectedContent) { auto layers = getOutputLayersOrderedByZ(); bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) { return layer->getLayerFE().getCompositionState()->hasProtectedContent; @@ -1475,12 +1483,16 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( BlurRegionsOnly : LayerFE::ClientCompositionTargetSettings::BlurSetting:: Enabled); + bool isProtected = supportsProtectedContent; + if (FlagManager::getInstance().display_protected()) { + isProtected = outputState.isProtected && supportsProtectedContent; + } compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{.clip = clip, .needsFiltering = layer->needsFiltering() || outputState.needsFiltering, .isSecure = outputState.isSecure, - .supportsProtectedContent = supportsProtectedContent, + .isProtected = isProtected, .viewport = outputState.layerStackSpace.getContent(), .dataspace = outputDataspace, .realContentIsVisible = realContentIsVisible, diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index 579c6ba772..869dda61bb 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -184,7 +184,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te targetSettings{.clip = Region(viewport), .needsFiltering = false, .isSecure = outputState.isSecure, - .supportsProtectedContent = false, + .isProtected = false, .viewport = viewport, .dataspace = outputDataspace, .realContentIsVisible = true, diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 249c40b473..950b05e1da 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -72,6 +72,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) mRefreshRateSelector(std::move(args.refreshRateSelector)), mHasDesiredModeTrace(concatId("HasDesiredMode"), false) { mCompositionDisplay->editState().isSecure = args.isSecure; + mCompositionDisplay->editState().isProtected = args.isProtected; mCompositionDisplay->createRenderSurface( compositionengine::RenderSurfaceCreationArgsBuilder() .setDisplayWidth(ANativeWindow_getWidth(args.nativeWindow.get())) diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 51c7be0490..ac390cb8ff 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -332,6 +332,7 @@ struct DisplayDeviceState { uint32_t height = 0; std::string displayName; bool isSecure = false; + bool isProtected = false; // Refer to DisplayDevice::mRequestedRefreshRate, for virtual display only Fps requestedRefreshRate; @@ -353,6 +354,7 @@ struct DisplayDeviceCreationArgs { int32_t sequenceId{0}; bool isSecure{false}; + bool isProtected{false}; sp<ANativeWindow> nativeWindow; sp<compositionengine::DisplaySurface> displaySurface; ui::Rotation physicalOrientation{ui::ROTATION_0}; diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index f25619a6c0..2dbcb841ac 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -208,9 +208,15 @@ void LayerFE::prepareBufferStateClientComposition( // activeBuffer, then we need to return LayerSettings. return; } - const bool blackOutLayer = - (mSnapshot->hasProtectedContent && !targetSettings.supportsProtectedContent) || - ((mSnapshot->isSecure || mSnapshot->hasProtectedContent) && !targetSettings.isSecure); + bool blackOutLayer; + if (FlagManager::getInstance().display_protected()) { + blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) || + (mSnapshot->isSecure && !targetSettings.isSecure); + } else { + blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) || + ((mSnapshot->isSecure || mSnapshot->hasProtectedContent) && + !targetSettings.isSecure); + } const bool bufferCanBeUsedAsHwTexture = mSnapshot->externalTexture->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; if (blackOutLayer || !bufferCanBeUsedAsHwTexture) { diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 6db39f143f..c888ccc8ae 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -374,10 +374,11 @@ void RegionSamplingThread::captureSample() { constexpr bool kRegionSampling = true; constexpr bool kGrayscale = false; + constexpr bool kIsProtected = false; if (const auto fenceResult = mFlinger.captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, buffer, - kRegionSampling, kGrayscale, nullptr) + kRegionSampling, kGrayscale, kIsProtected, nullptr) .get(); fenceResult.ok()) { fenceResult.value()->waitForever(LOG_TAG); diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp index 57b0d5e0ea..a4a5ce2b46 100644 --- a/services/surfaceflinger/ScreenCaptureOutput.cpp +++ b/services/surfaceflinger/ScreenCaptureOutput.cpp @@ -32,6 +32,7 @@ std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutp bool>(args.compositionEngine, args.renderArea, args.colorProfile, args.regionSampling, args.dimInGammaSpaceForEnhancedScreenshots); output->editState().isSecure = args.renderArea.isSecure(); + output->editState().isProtected = args.isProtected; output->setCompositionEnabled(true); output->setLayerFilter({args.layerStack}); output->setRenderSurface(std::make_unique<ScreenCaptureRenderSurface>(std::move(args.buffer))); diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h index fc095def99..1c16308e15 100644 --- a/services/surfaceflinger/ScreenCaptureOutput.h +++ b/services/surfaceflinger/ScreenCaptureOutput.h @@ -38,6 +38,7 @@ struct ScreenCaptureOutputArgs { bool regionSampling; bool treat170mAsSrgb; bool dimInGammaSpaceForEnhancedScreenshots; + bool isProtected = false; }; // ScreenCaptureOutput is used to compose a set of layers into a preallocated buffer. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1dcc19e40d..c4de02fce9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -565,6 +565,9 @@ sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secur // Display ID is assigned when virtual display is allocated by HWC. DisplayDeviceState state; state.isSecure = secure; + // Set display as protected when marked as secure to ensure no behavior change + // TODO (b/314820005): separate as a different arg when creating the display. + state.isProtected = secure; state.displayName = displayName; state.requestedRefreshRate = Fps::fromValue(requestedRefreshRate); mCurrentState.displays.add(token, state); @@ -3381,6 +3384,7 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, .hwcDisplayId = hwcDisplayId, .activeMode = std::move(activeMode)}; state.isSecure = true; // All physical displays are currently considered secure. + state.isProtected = true; state.displayName = std::move(info.name); mCurrentState.displays.add(token, state); @@ -3412,6 +3416,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( displayToken, compositionDisplay); creationArgs.sequenceId = state.sequenceId; creationArgs.isSecure = state.isSecure; + creationArgs.isProtected = state.isProtected; creationArgs.displaySurface = displaySurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; @@ -3543,6 +3548,7 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, builder.setPixels(resolution); builder.setIsSecure(state.isSecure); + builder.setIsProtected(state.isProtected); builder.setPowerAdvisor(mPowerAdvisor.get()); builder.setName(state.displayName); auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); @@ -7856,12 +7862,11 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, }) .get(); } - + const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected; const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE | - (hasProtectedLayer && allowProtected && supportsProtected - ? GRALLOC_USAGE_PROTECTED - : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + (isProtected ? 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), @@ -7881,14 +7886,15 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, renderengine::impl::ExternalTexture::Usage:: WRITEABLE); auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture, - false /* regionSampling */, grayscale, captureListener); + false /* regionSampling */, grayscale, isProtected, + captureListener); fence.get(); } ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, - bool grayscale, const sp<IScreenCaptureListener>& captureListener) { + bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); auto future = mScheduler->schedule( @@ -7907,8 +7913,9 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> renderFuture; renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { - renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, - regionSampling, grayscale, captureResults); + renderFuture = + renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling, + grayscale, isProtected, captureResults); }); if (captureListener) { @@ -7936,7 +7943,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, - bool grayscale, ScreenCaptureResults& captureResults) { + bool grayscale, bool isProtected, ScreenCaptureResults& captureResults) { ATRACE_CALL(); auto layers = getLayerSnapshots(); @@ -8031,9 +8038,9 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( }; auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace, - sdrWhitePointNits, displayBrightnessNits, grayscale, layerFEs = copyLayerFEs(), - layerStack, regionSampling, renderArea = std::move(renderArea), - renderIntent]() -> FenceResult { + sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected, + layerFEs = copyLayerFEs(), layerStack, regionSampling, + renderArea = std::move(renderArea), renderIntent]() -> FenceResult { std::unique_ptr<compositionengine::CompositionEngine> compositionEngine = mFactory.createCompositionEngine(); compositionEngine->setRenderEngine(mRenderEngine.get()); @@ -8067,7 +8074,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( .regionSampling = regionSampling, .treat170mAsSrgb = mTreat170mAsSrgb, .dimInGammaSpaceForEnhancedScreenshots = - dimInGammaSpaceForEnhancedScreenshots}); + dimInGammaSpaceForEnhancedScreenshots, + .isProtected = isProtected}); const float colorSaturation = grayscale ? 0 : 1; compositionengine::CompositionRefreshArgs refreshArgs{ diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c4af271742..6909055801 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -855,11 +855,11 @@ private: ftl::SharedFuture<FenceResult> captureScreenCommon( RenderAreaFuture, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, - bool grayscale, const sp<IScreenCaptureListener>&); + bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&); ftl::SharedFuture<FenceResult> renderScreenImpl( std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, - bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock) + bool grayscale, bool isProtected, ScreenCaptureResults&) EXCLUDES(mStateLock) REQUIRES(kMainThreadContext); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp index 07a606c9ed..2d7482862a 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -124,6 +124,7 @@ void FlagManager::dump(std::string& result) const { DUMP_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency); DUMP_READ_ONLY_FLAG(cache_if_source_crop_layer_only_moved); DUMP_READ_ONLY_FLAG(enable_fro_dependent_features); + DUMP_READ_ONLY_FLAG(display_protected); #undef DUMP_READ_ONLY_FLAG #undef DUMP_SERVER_FLAG @@ -197,6 +198,7 @@ FLAG_MANAGER_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency, "") FLAG_MANAGER_READ_ONLY_FLAG(cache_if_source_crop_layer_only_moved, "debug.sf.cache_source_crop_only_moved") FLAG_MANAGER_READ_ONLY_FLAG(enable_fro_dependent_features, "") +FLAG_MANAGER_READ_ONLY_FLAG(display_protected, "") /// Trunk stable server flags /// FLAG_MANAGER_SERVER_FLAG(late_boot_misc2, "") diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h index 38cb43a269..e0f620465c 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -63,6 +63,7 @@ public: bool use_known_refresh_rate_for_fps_consistency() const; bool cache_if_source_crop_layer_only_moved() const; bool enable_fro_dependent_features() const; + bool display_protected() const; protected: // overridden for unit tests diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig index fcb52c72f4..620ac26cfd 100644 --- a/services/surfaceflinger/surfaceflinger_flags.aconfig +++ b/services/surfaceflinger/surfaceflinger_flags.aconfig @@ -107,3 +107,11 @@ flag { bug: "314217419" is_fixed_read_only: true } + +flag { + name: "display_protected" + namespace: "core_graphics" + description: "Introduce protected displays to specify whether they should render protected content" + bug: "301647974" + is_fixed_read_only: true +} diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index ebb05d4da7..8ba6bf87e2 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -498,7 +498,8 @@ public: return FTL_FAKE_GUARD(kMainThreadContext, mFlinger->renderScreenImpl(std::move(renderArea), traverseLayers, buffer, regionSampling, - false /* grayscale */, captureResults)); + false /* grayscale */, + false /* isProtected */, captureResults)); } auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid, |