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
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 98c4af4..6e60839 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -42,6 +42,10 @@
// 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 @@
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 ccff1ec..a1d6132 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -97,7 +97,7 @@
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 @@
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 @@
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 692ed24..6b1c318 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -53,6 +53,9 @@
// 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 0475881..690d35f 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -57,6 +57,7 @@
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 e4d7578..c399224 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1232,10 +1232,18 @@
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 @@
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 579c6ba..869dda6 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -184,7 +184,7 @@
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 249c40b..950b05e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -72,6 +72,7 @@
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 51c7be0..ac390cb 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -332,6 +332,7 @@
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 @@
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 f25619a..2dbcb84 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -208,9 +208,15 @@
// 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 6db39f1..c888ccc 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -374,10 +374,11 @@
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 57b0d5e..a4a5ce2 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.cpp
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -32,6 +32,7 @@
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 fc095de..1c16308 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.h
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -38,6 +38,7 @@
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 1dcc19e..c4de02f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -565,6 +565,9 @@
// 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 @@
.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 @@
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 @@
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 @@
})
.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 @@
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> 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::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 @@
};
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 @@
.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 c4af271..6909055 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -855,11 +855,11 @@
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 07a606c..2d74828 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -124,6 +124,7 @@
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(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 38cb43a..e0f6204 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -63,6 +63,7 @@
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 fcb52c7..620ac26 100644
--- a/services/surfaceflinger/surfaceflinger_flags.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags.aconfig
@@ -107,3 +107,11 @@
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 ebb05d4..8ba6bf8 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -498,7 +498,8 @@
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,