Add support for background blurs

Bug: 141640413
Fixes: 146384234
Test: adb shell setprop debug.sf.disableBlurs 1
Test: adb shell setprop debug.sf.gaussianBlur 0
Test: adb shell setprop ro.surface_flinger.supports_background_blur 1
Test: ./SurfaceFlinger_test --gtest_filter=Layer*Tests/Layer*Test.SetBackgroundBlur*
Test: ./librenderengine_test --gtest_filter=*BlurBackground*"
Test: atest SurfaceFlinger_test:SurfaceInterceptorTest#InterceptBackgroundBlurRadiusUpdateWorks
Change-Id: I5194c910fe7062f33e70943867012539e6c6626a
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index a64fdbf..3dbd25e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -63,6 +63,9 @@
     // The alpha value for this layer
     float alpha{1.f};
 
+    // Background blur in pixels
+    int backgroundBlurRadius{0};
+
     // The transform from layer local coordinates to composition coordinates
     ui::Transform geomLayerTransform;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 159e928..3a9776d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -116,6 +116,7 @@
 
 private:
     void dirtyEntireOutput();
+    compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const;
     ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const;
     compositionengine::Output::ColorProfile pickColorProfile(
             const compositionengine::CompositionRefreshArgs&) const;
@@ -126,6 +127,7 @@
     std::unique_ptr<compositionengine::RenderSurface> mRenderSurface;
 
     ReleasedLayers mReleasedLayers;
+    OutputLayer* mLayerRequestingBackgroundBlur = nullptr;
 };
 
 // This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
index 085e838..8065e65 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
@@ -61,6 +61,7 @@
     out.append("\n      ");
     dumpVal(out, "blend", toString(blendMode), blendMode);
     dumpVal(out, "alpha", alpha);
+    dumpVal(out, "backgroundBlurRadius", backgroundBlurRadius);
 
     out.append("\n      ");
     dumpVal(out, "type", type);
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 01413b9..650b5c1 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -578,15 +578,33 @@
         return;
     }
 
+    mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition();
+    bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr;
+
     for (auto* layer : getOutputLayersOrderedByZ()) {
         layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,
-                                      refreshArgs.devOptForceClientComposition);
+                                      refreshArgs.devOptForceClientComposition ||
+                                              forceClientComposition);
+
+        if (mLayerRequestingBackgroundBlur == layer) {
+            forceClientComposition = false;
+        }
 
         // Send the updated state to the HWC, if appropriate.
         layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame);
     }
 }
 
+compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const {
+    compositionengine::OutputLayer* layerRequestingBgComposition = nullptr;
+    for (auto* layer : getOutputLayersOrderedByZ()) {
+        if (layer->getLayer().getFEState().backgroundBlurRadius > 0) {
+            layerRequestingBgComposition = layer;
+        }
+    }
+    return layerRequestingBgComposition;
+}
+
 void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
     setColorProfile(pickColorProfile(refreshArgs));
 }
@@ -854,11 +872,12 @@
     }
 
     // We boost GPU frequency here because there will be color spaces conversion
-    // and it's expensive. We boost the GPU frequency so that GPU composition can
-    // finish in time. We must reset GPU frequency afterwards, because high frequency
-    // consumes extra battery.
+    // or complex GPU shaders and it's expensive. We boost the GPU frequency so that
+    // GPU composition can finish in time. We must reset GPU frequency afterwards,
+    // because high frequency consumes extra battery.
     const bool expensiveRenderingExpected =
-            clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
+            clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3 ||
+            mLayerRequestingBackgroundBlur != nullptr;
     if (expensiveRenderingExpected) {
         setExpensiveRenderingExpected(true);
     }
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 24311c7..6761b86 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -138,6 +138,10 @@
         EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
         EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
         EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
+
+        EXPECT_CALL(mLayer1, getFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
+        EXPECT_CALL(mLayer2, getFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
+        EXPECT_CALL(mLayer3, getFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
     }
 
     void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
@@ -3637,6 +3641,29 @@
                                                                 kDisplayDataspace));
 }
 
+TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) {
+    // Layer requesting blur, or below, should request client composition.
+    EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
+    EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
+    EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
+    EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
+    EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
+    EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
+
+    mLayer2FEState.backgroundBlurRadius = 10;
+
+    injectLayer(std::move(mOutputLayer1));
+    injectLayer(std::move(mOutputLayer2));
+    injectLayer(std::move(mOutputLayer3));
+
+    mOutput->editState().isEnabled = true;
+
+    CompositionRefreshArgs args;
+    args.updatingGeometryThisFrame = false;
+    args.devOptForceClientComposition = false;
+    mOutput->updateAndWriteCompositionState(args);
+}
+
 TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) {
     // In split-screen landscape mode, the screen is rotated 90 degrees, with
     // one layer on the left covering the left side of the output, and one layer