surfaceflinger: signalRefresh after boot animation starts

Assume BootStage::BOOTLOADER initially.  Switch to
BootStage::BOOTANIMATION on first buffer latch and switch to
BootStage::FINISHED after bootFinished is called.

Do not invoke signalRefresh when in BootStage::BOOTLOADER.  We do
not want to replace bootloader splash by a blank screen.  This saves
HWC from workarounds that may or may not work reliably.

Bug: 79434305
Bug: 110772452
Test: reboot and observe
Change-Id: I9e892e629303177431acd2cfe23f0f984ca6866e
Merged-In: I9e892e629303177431acd2cfe23f0f984ca6866e
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cd51dd1..6859466 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -223,6 +223,7 @@
         mVisibleRegionsDirty(false),
         mGeometryInvalid(false),
         mAnimCompositionPending(false),
+        mBootStage(BootStage::BOOTLOADER),
         mDebugRegion(0),
         mDebugDDMS(0),
         mDebugDisableHWC(0),
@@ -231,7 +232,6 @@
         mLastSwapBufferTime(0),
         mDebugInTransaction(0),
         mLastTransactionTime(0),
-        mBootFinished(false),
         mForceFullDamage(false),
         mPrimaryDispSync("PrimaryDispSync"),
         mPrimaryHWVsyncEnabled(false),
@@ -498,6 +498,7 @@
 
     sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
         readPersistentProperties();
+        mBootStage = BootStage::FINISHED;
     });
     postMessageAsync(readProperties);
 }
@@ -1527,7 +1528,7 @@
             bool refreshNeeded = handleMessageTransaction();
             refreshNeeded |= handleMessageInvalidate();
             refreshNeeded |= mRepaintEverything;
-            if (refreshNeeded) {
+            if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
                 // Signal a refresh if a transaction modified the window state,
                 // a new buffer was latched, or if HWC has requested a full
                 // repaint
@@ -2886,6 +2887,12 @@
         signalLayerUpdate();
     }
 
+    // enter boot animation on first buffer latch
+    if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) {
+        ALOGI("Enter boot animation");
+        mBootStage = BootStage::BOOTANIMATION;
+    }
+
     // Only continue with the refresh if there is actually new work to do
     return !mLayersWithQueuedFrames.empty() && newDataLatched;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8da97b1..87bc9cc 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -808,6 +808,13 @@
     sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
     bool mHadClientComposition = false;
 
+    enum class BootStage {
+        BOOTLOADER,
+        BOOTANIMATION,
+        FINISHED,
+    };
+    BootStage mBootStage;
+
     struct HotplugEvent {
         hwc2_display_t display;
         HWC2::Connection connection = HWC2::Connection::Invalid;
@@ -828,7 +835,6 @@
     nsecs_t mLastSwapBufferTime;
     volatile nsecs_t mDebugInTransaction;
     nsecs_t mLastTransactionTime;
-    bool mBootFinished;
     bool mForceFullDamage;
     bool mPropagateBackpressure = true;
     std::unique_ptr<SurfaceInterceptor> mInterceptor =