[sf]   Avoid  rounded corners without EGL_EXT_protected_content with new frontend

Override the rounded corner state in the layer snapshots if the device
doesn't support EGL_EXT_protected_content. This is passed in via a new
arg to LayerSnapshotBuilder.

Test: libsurfaceflinger_unittest
Fixes: 196271643
Change-Id: I8cbe6ea2818305c93494177df239381b0d02b464
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 23cfe928..f7b685d 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -854,8 +854,9 @@
     }
 
     if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
-        snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
-        updateRoundedCorner(snapshot, requested, parentSnapshot);
+        snapshot.changes.any(RequestedLayerState::Changes::Geometry |
+                             RequestedLayerState::Changes::BufferUsageFlags)) {
+        updateRoundedCorner(snapshot, requested, parentSnapshot, args);
     }
 
     if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
@@ -886,7 +887,12 @@
 
 void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
                                                const RequestedLayerState& requested,
-                                               const LayerSnapshot& parentSnapshot) {
+                                               const LayerSnapshot& parentSnapshot,
+                                               const Args& args) {
+    if (args.skipRoundCornersWhenProtected && requested.isProtected()) {
+        snapshot.roundedCorner = RoundedCornerState();
+        return;
+    }
     snapshot.roundedCorner = RoundedCornerState();
     RoundedCornerState parentRoundedCorner;
     if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index d361605..3d64b36 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -54,6 +54,7 @@
         std::unordered_set<uint32_t> excludeLayerIds;
         const std::unordered_map<std::string, bool>& supportedLayerGenericMetadata;
         const std::unordered_map<std::string, uint32_t>& genericLayerMetadataKeyMap;
+        bool skipRoundCornersWhenProtected = false;
     };
     LayerSnapshotBuilder();
 
@@ -103,7 +104,7 @@
                                     bool parentIsRelative, const Args& args);
     static void resetRelativeState(LayerSnapshot& snapshot);
     static void updateRoundedCorner(LayerSnapshot& snapshot, const RequestedLayerState& layerState,
-                                    const LayerSnapshot& parentSnapshot);
+                                    const LayerSnapshot& parentSnapshot, const Args& args);
     void updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& layerState,
                            const LayerSnapshot& parentSnapshot, uint32_t displayRotationFlags);
     static void updateShadows(LayerSnapshot& snapshot, const RequestedLayerState& requested,
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index a4777d1..d979c46 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -147,6 +147,8 @@
     const ui::Size oldBufferSize = hadBuffer
             ? ui::Size(externalTexture->getWidth(), externalTexture->getHeight())
             : ui::Size();
+    const uint64_t oldUsageFlags = hadBuffer ? externalTexture->getUsage() : 0;
+
     const bool hadSideStream = sidebandStream != nullptr;
     const layer_state_t& clientState = resolvedComposerState.state;
     const bool hadBlur = hasBlur();
@@ -177,6 +179,10 @@
                 changes |= RequestedLayerState::Changes::BufferSize;
                 changes |= RequestedLayerState::Changes::Geometry;
             }
+            const uint64_t usageFlags = hasBuffer ? externalTexture->getUsage() : 0;
+            if (oldUsageFlags != usageFlags) {
+                changes |= RequestedLayerState::Changes::BufferUsageFlags;
+            }
         }
 
         if (hasBuffer != hadBuffer) {
@@ -570,6 +576,10 @@
     return true;
 }
 
+bool RequestedLayerState::isProtected() const {
+    return externalTexture && externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
+}
+
 void RequestedLayerState::clearChanges() {
     what = 0;
     changes.clear();
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 1c19d6d..0309302 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -56,6 +56,7 @@
         Animation = 1u << 17,
         BufferSize = 1u << 18,
         GameMode = 1u << 19,
+        BufferUsageFlags = 1u << 20,
     };
     static Rect reduce(const Rect& win, const Region& exclude);
     RequestedLayerState(const LayerCreationArgs&);
@@ -85,6 +86,7 @@
     bool willReleaseBufferOnLatch() const;
     bool backpressureEnabled() const;
     bool isSimpleBufferUpdate(const layer_state_t&) const;
+    bool isProtected() const;
 
     // Layer serial number.  This gives layers an explicit ordering, so we
     // have a stable sort order when their layer stack and Z-order are
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9de623f..bcce2a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2315,7 +2315,9 @@
                      .forceFullDamage = mForceFullDamage,
                      .supportedLayerGenericMetadata =
                              getHwComposer().getSupportedLayerGenericMetadata(),
-                     .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
+                     .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap(),
+                     .skipRoundCornersWhenProtected =
+                             !getRenderEngine().supportsProtectedContent()};
         mLayerSnapshotBuilder.update(args);
     }
 
@@ -8547,7 +8549,9 @@
                      .excludeLayerIds = std::move(excludeLayerIds),
                      .supportedLayerGenericMetadata =
                              getHwComposer().getSupportedLayerGenericMetadata(),
-                     .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
+                     .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap(),
+                     .skipRoundCornersWhenProtected =
+                             !getRenderEngine().supportsProtectedContent()};
         mLayerSnapshotBuilder.update(args);
 
         auto getLayerSnapshotsFn =
@@ -8582,7 +8586,9 @@
                      .excludeLayerIds = std::move(excludeLayerIds),
                      .supportedLayerGenericMetadata =
                              getHwComposer().getSupportedLayerGenericMetadata(),
-                     .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
+                     .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap(),
+                     .skipRoundCornersWhenProtected =
+                             !getRenderEngine().supportsProtectedContent()};
         mLayerSnapshotBuilder.update(args);
 
         auto getLayerSnapshotsFn =
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index e475b84..1380555 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -17,6 +17,8 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include <gui/fake/BufferData.h>
+
 #include "Client.h" // temporarily needed for LayerCreationArgs
 #include "FrontEnd/LayerCreationArgs.h"
 #include "FrontEnd/LayerHierarchy.h"
@@ -333,6 +335,32 @@
         mLifecycleManager.applyTransactions(transactions);
     }
 
+    void setRoundedCorners(uint32_t id, float radius) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        transactions.back().states.front().state.what = layer_state_t::eCornerRadiusChanged;
+        transactions.back().states.front().layerId = id;
+        transactions.back().states.front().state.cornerRadius = radius;
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    void setBuffer(uint32_t id, std::shared_ptr<renderengine::ExternalTexture> texture) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        transactions.back().states.front().state.what = layer_state_t::eBufferChanged;
+        transactions.back().states.front().layerId = id;
+        transactions.back().states.front().externalTexture = texture;
+        transactions.back().states.front().state.bufferData =
+                std::make_shared<fake::BufferData>(texture->getId(), texture->getWidth(),
+                                                   texture->getHeight(), texture->getPixelFormat(),
+                                                   texture->getUsage());
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
     LayerLifecycleManager mLifecycleManager;
 };
 
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index a581d5b..65bac00 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -17,6 +17,8 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include <renderengine/mock/FakeExternalTexture.h>
+
 #include "FrontEnd/LayerHierarchy.h"
 #include "FrontEnd/LayerLifecycleManager.h"
 #include "FrontEnd/LayerSnapshotBuilder.h"
@@ -68,12 +70,17 @@
         setColor(id);
     }
 
-    void updateAndVerify(LayerSnapshotBuilder& actualBuilder, bool hasDisplayChanges,
-                         const std::vector<uint32_t> expectedVisibleLayerIdsInZOrder) {
+    void update(LayerSnapshotBuilder& actualBuilder, LayerSnapshotBuilder::Args& args) {
         if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) {
             mHierarchyBuilder.update(mLifecycleManager.getLayers(),
                                      mLifecycleManager.getDestroyedLayers());
         }
+        args.root = mHierarchyBuilder.getHierarchy();
+        actualBuilder.update(args);
+    }
+
+    void updateAndVerify(LayerSnapshotBuilder& actualBuilder, bool hasDisplayChanges,
+                         const std::vector<uint32_t> expectedVisibleLayerIdsInZOrder) {
         LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
                                         .layerLifecycleManager = mLifecycleManager,
                                         .includeMetadata = false,
@@ -83,7 +90,7 @@
                                         .supportsBlur = true,
                                         .supportedLayerGenericMetadata = {},
                                         .genericLayerMetadataKeyMap = {}};
-        actualBuilder.update(args);
+        update(actualBuilder, args);
 
         // rebuild layer snapshots from scratch and verify that it matches the updated state.
         LayerSnapshotBuilder expectedBuilder(args);
@@ -596,4 +603,50 @@
               scheduler::LayerInfo::FrameRateCompatibility::Default);
 }
 
+TEST_F(LayerSnapshotTest, skipRoundCornersWhenProtected) {
+    setRoundedCorners(1, 42.f);
+    setRoundedCorners(2, 42.f);
+    setCrop(1, Rect{1000, 1000});
+    setCrop(2, Rect{1000, 1000});
+
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasRoundedCorners());
+    EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, 42.f);
+    EXPECT_TRUE(getSnapshot({.id = 2})->roundedCorner.hasRoundedCorners());
+
+    // add a buffer with the protected bit, check rounded corners are not set when
+    // skipRoundCornersWhenProtected == true
+    setBuffer(1,
+              std::make_shared<
+                      renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                               1ULL /* bufferId */,
+                                                               HAL_PIXEL_FORMAT_RGBA_8888,
+                                                               GRALLOC_USAGE_PROTECTED /*usage*/));
+
+    LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+                                    .layerLifecycleManager = mLifecycleManager,
+                                    .includeMetadata = false,
+                                    .displays = mFrontEndDisplayInfos,
+                                    .displayChanges = false,
+                                    .globalShadowSettings = globalShadowSettings,
+                                    .supportsBlur = true,
+                                    .supportedLayerGenericMetadata = {},
+                                    .genericLayerMetadataKeyMap = {},
+                                    .skipRoundCornersWhenProtected = true};
+    update(mSnapshotBuilder, args);
+    EXPECT_FALSE(getSnapshot({.id = 1})->roundedCorner.hasRoundedCorners());
+    // layer 2 doesn't have a buffer and should be unaffected
+    EXPECT_TRUE(getSnapshot({.id = 2})->roundedCorner.hasRoundedCorners());
+
+    // remove protected bit, check rounded corners are set
+    setBuffer(1,
+              std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                                        2ULL /* bufferId */,
+                                                                        HAL_PIXEL_FORMAT_RGBA_8888,
+                                                                        0 /*usage*/));
+    update(mSnapshotBuilder, args);
+    EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasRoundedCorners());
+    EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, 42.f);
+}
+
 } // namespace android::surfaceflinger::frontend