Improve blur caching heuristic

This allows for caching the following scenario where notification shade
applies a background blur radius: If the layers behind the notification
shade are not changing, the notification shade's blur radius not
changing, but the notification shade's buffer does change, then we want
to cache the contribution of the blur radius onto the resulting
CachedSet.

Bug: 187705068
Test: Enable blur and swipe notification shade very slowly

Change-Id: I7019be4b8438b79ebb29b2a05e8860916198f18f
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 6677f40..52e0428 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3784,6 +3784,46 @@
     EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp);
 }
 
+MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") {
+    *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n";
+    *result_listener << "expected " << expectedBlurSetting << "\n";
+    *result_listener << "actual " << arg.blurSetting << "\n";
+
+    return expectedBlurSetting == arg.blurSetting;
+}
+
+TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, overridesBlur) {
+    LayerFE::LayerSettings mShadowSettings;
+    mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
+
+    mLayers[2].mOutputLayerState.overrideInfo.disableBackgroundBlur = true;
+
+    EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(_))
+            .WillOnce(Return(std::vector<LayerFE::LayerSettings>()));
+    EXPECT_CALL(*mLayers[1].mLayerFE, prepareClientCompositionList(_))
+            .WillOnce(Return(std::vector<LayerFE::LayerSettings>({mLayers[1].mLayerSettings})));
+    EXPECT_CALL(*mLayers[2].mLayerFE,
+                prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+                        LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly)))
+            .WillOnce(Return(std::vector<LayerFE::LayerSettings>(
+                    {mShadowSettings, mLayers[2].mLayerSettings})));
+
+    Region accumClearRegion(Rect(10, 11, 12, 13));
+    auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
+                                                              accumClearRegion, kDisplayDataspace);
+    ASSERT_EQ(3u, requests.size());
+    EXPECT_EQ(mLayers[1].mLayerSettings, requests[0]);
+    EXPECT_EQ(mShadowSettings, requests[1]);
+    EXPECT_EQ(mLayers[2].mLayerSettings, requests[2]);
+
+    EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
+
+    // Check that a timestamp was set for the layers that generated requests
+    EXPECT_TRUE(0 == mLayers[0].mOutputLayerState.clientCompositionTimestamp);
+    EXPECT_TRUE(0 != mLayers[1].mOutputLayerState.clientCompositionTimestamp);
+    EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp);
+}
+
 TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
        onlyClientComposesClientComposedLayersIfNoClearingNeeded) {
     EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
@@ -3867,7 +3907,7 @@
             kDisplayDataspace,
             false /* realContentIsVisible */,
             true /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -3879,7 +3919,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     LayerFE::LayerSettings mBlackoutSettings = mLayers[1].mLayerSettings;
@@ -3923,7 +3963,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(Rect(0, 0, 30, 30)),
@@ -3935,7 +3975,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(Rect(0, 0, 40, 201)),
@@ -3947,7 +3987,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -3979,7 +4019,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
@@ -3991,7 +4031,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4003,7 +4043,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4035,7 +4075,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
 
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
@@ -4048,7 +4088,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4060,7 +4100,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4091,7 +4131,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
@@ -4103,7 +4143,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4115,7 +4155,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4144,7 +4184,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
             Region(kDisplayFrame),
@@ -4156,7 +4196,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
     compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
             Region(kDisplayFrame),
@@ -4168,7 +4208,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4306,7 +4346,7 @@
             kOutputDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(leftLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
@@ -4324,7 +4364,7 @@
             kOutputDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(rightLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
@@ -4358,7 +4398,7 @@
             kDisplayDataspace,
             false /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     LayerFE::LayerSettings mShadowSettings;
@@ -4404,7 +4444,7 @@
             kDisplayDataspace,
             true /* realContentIsVisible */,
             false /* clearContent */,
-            false /* disabledBlurs */,
+            compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
     };
 
     EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index 8f44677..591f981 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -24,6 +24,7 @@
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <ui/GraphicTypes.h>
+#include <utils/Errors.h>
 #include <memory>
 
 namespace android::compositionengine {
@@ -42,6 +43,14 @@
 
 namespace {
 
+MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") {
+    *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n";
+    *result_listener << "expected " << expectedBlurSetting << "\n";
+    *result_listener << "actual " << arg.blurSetting << "\n";
+
+    return expectedBlurSetting == arg.blurSetting;
+}
+
 class CachedSetTest : public testing::Test {
 public:
     CachedSetTest() = default;
@@ -593,5 +602,78 @@
     EXPECT_TRUE(cachedSet4.hasBlurBehind());
 }
 
+TEST_F(CachedSetTest, addBackgroundBlurLayer) {
+    CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
+    CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
+    CachedSet cachedSet(layer1);
+
+    EXPECT_EQ(nullptr, cachedSet.getBlurLayer());
+
+    cachedSet.addBackgroundBlurLayer(layer2);
+    EXPECT_EQ(layer2.getState()->getOutputLayer(), cachedSet.getBlurLayer());
+}
+
+TEST_F(CachedSetTest, addBlur) {
+    mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
+    CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
+    sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
+
+    CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
+    sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
+
+    CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
+    sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
+
+    CachedSet cachedSet(layer1);
+    cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
+
+    cachedSet.addBackgroundBlurLayer(layer3);
+
+    std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
+    clientCompList1.push_back({});
+    std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
+    clientCompList2.push_back({});
+    std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
+    clientCompList3.push_back({});
+
+    clientCompList3[0].source.buffer.buffer = std::make_shared<
+            renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
+                                           renderengine::ExternalTexture::READABLE);
+
+    EXPECT_CALL(*layerFE1,
+                prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+                        compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
+                                Enabled)))
+            .WillOnce(Return(clientCompList1));
+    EXPECT_CALL(*layerFE2,
+                prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+                        compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
+                                Enabled)))
+            .WillOnce(Return(clientCompList2));
+    EXPECT_CALL(*layerFE3,
+                prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+                        compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
+                                BackgroundBlurOnly)))
+            .WillOnce(Return(clientCompList3));
+
+    const auto drawLayers = [&](const renderengine::DisplaySettings&,
+                                const std::vector<const renderengine::LayerSettings*>& layers,
+                                const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
+                                base::unique_fd&&, base::unique_fd*) -> int32_t {
+        // If the highlight layer is enabled, it will increase the size by 1.
+        // We're interested in the third layer either way.
+        EXPECT_GE(layers.size(), 3u);
+        const auto* blurSettings = layers[2];
+        EXPECT_TRUE(blurSettings->skipContentDraw);
+        EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings->source.solidColor);
+        EXPECT_EQ(0.0f, blurSettings->alpha);
+
+        return NO_ERROR;
+    };
+
+    EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
+    cachedSet.render(mRenderEngine, mOutputState);
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 7ec2c98..8b03964 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -27,6 +27,7 @@
 
 namespace android::compositionengine {
 using namespace std::chrono_literals;
+using impl::planner::CachedSet;
 using impl::planner::Flattener;
 using impl::planner::LayerState;
 using impl::planner::NonBufferHash;
@@ -43,9 +44,15 @@
 
 namespace {
 
+class TestableFlattener : public Flattener {
+public:
+    TestableFlattener(bool enableHolePunch) : Flattener(enableHolePunch) {}
+    const std::optional<CachedSet>& getNewCachedSetForTesting() const { return mNewCachedSet; }
+};
+
 class FlattenerTest : public testing::Test {
 public:
-    FlattenerTest() : mFlattener(std::make_unique<Flattener>(true)) {}
+    FlattenerTest() : mFlattener(std::make_unique<TestableFlattener>(true)) {}
     void SetUp() override;
 
 protected:
@@ -55,7 +62,7 @@
 
     // mRenderEngine may be held as a pointer to mFlattener, so mFlattener must be destroyed first.
     renderengine::mock::RenderEngine mRenderEngine;
-    std::unique_ptr<Flattener> mFlattener;
+    std::unique_ptr<TestableFlattener> mFlattener;
 
     const std::chrono::steady_clock::time_point kStartTime = std::chrono::steady_clock::now();
     std::chrono::steady_clock::time_point mTime = kStartTime;
@@ -786,6 +793,56 @@
     EXPECT_EQ(overrideBuffer3, overrideBuffer4);
 }
 
+TEST_F(FlattenerTest, flattenLayers_whenBlurLayerIsChanging_appliesBlurToInactiveBehindLayers) {
+    auto& layerState1 = mTestLayers[0]->layerState;
+    auto& layerState2 = mTestLayers[1]->layerState;
+
+    auto& layerStateWithBlurBehind = mTestLayers[2]->layerState;
+    mTestLayers[2]->layerFECompositionState.backgroundBlurRadius = 1;
+    layerStateWithBlurBehind->update(&mTestLayers[2]->outputLayer);
+    const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+    const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
+    const auto& blurOverrideBuffer =
+            layerStateWithBlurBehind->getOutputLayer()->getState().overrideInfo.buffer;
+
+    const std::vector<const LayerState*> layers = {
+            layerState1.get(),
+            layerState2.get(),
+            layerStateWithBlurBehind.get(),
+    };
+
+    initializeFlattener(layers);
+
+    // Mark the first two layers inactive, but update the blur layer
+    mTime += 200ms;
+    layerStateWithBlurBehind->resetFramesSinceBufferUpdate();
+
+    // layers would be flattened but the buffer would not be overridden
+    EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
+
+    initializeOverrideBuffer(layers);
+    EXPECT_EQ(getNonBufferHash(layers),
+              mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+
+    const auto& cachedSet = mFlattener->getNewCachedSetForTesting();
+    ASSERT_NE(std::nullopt, cachedSet);
+    EXPECT_EQ(&mTestLayers[2]->outputLayer, cachedSet->getBlurLayer());
+
+    for (const auto layer : layers) {
+        EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
+    }
+
+    // the new flattened layer is replaced
+    initializeOverrideBuffer(layers);
+    EXPECT_NE(getNonBufferHash(layers),
+              mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    EXPECT_NE(nullptr, overrideBuffer1);
+    EXPECT_EQ(overrideBuffer2, overrideBuffer1);
+    EXPECT_EQ(nullptr, blurOverrideBuffer);
+}
+
 TEST_F(FlattenerTest, flattenLayers_renderCachedSets_doesNotRenderTwice) {
     auto& layerState1 = mTestLayers[0]->layerState;
     auto& layerState2 = mTestLayers[1]->layerState;