Inform SurfaceFlinger about displays which receive input

Right now, multiple display devices can share a layerstack.
This means that when constructing InputWindowInfo, its
impossible to know which display transform matches the
display viewport that inputflinger dispatches against. To
remedy this, have displaymanager inform surfaceflinger
which displays "receiveInput" using the same logic that
controls which display viewport it sends to inputflinger.

Bug: 179274888
Test: atest SetDisplayStateLockedTest
Change-Id: If0ffb1b5405f7e7dcdf8ea2f12c109d661a540fe
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index 3798ba7..29d4409 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -100,6 +100,10 @@
     required uint32 layer_stack = 1;
 }
 
+message DisplayFlagsChange {
+    required uint32 flags = 1;
+}
+
 message HiddenFlagChange {
     required bool hidden_flag = 1;
 }
@@ -120,6 +124,7 @@
         LayerStackChange  layer_stack = 3;
         SizeChange        size        = 4;
         ProjectionChange  projection  = 5;
+        DisplayFlagsChange flags      = 6;
     }
 }
 
@@ -212,4 +217,4 @@
 message Origin {
     required int32 pid = 1;
     required int32 uid = 2;
-}
\ No newline at end of file
+}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e65c721..d102e07 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -315,6 +315,7 @@
 DisplayState::DisplayState()
       : what(0),
         layerStack(0),
+        flags(0),
         layerStackSpaceRect(Rect::EMPTY_RECT),
         orientedDisplaySpaceRect(Rect::EMPTY_RECT),
         width(0),
@@ -325,6 +326,7 @@
     SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(surface));
     SAFE_PARCEL(output.writeUint32, what);
     SAFE_PARCEL(output.writeUint32, layerStack);
+    SAFE_PARCEL(output.writeUint32, flags);
     SAFE_PARCEL(output.writeUint32, toRotationInt(orientation));
     SAFE_PARCEL(output.write, layerStackSpaceRect);
     SAFE_PARCEL(output.write, orientedDisplaySpaceRect);
@@ -341,6 +343,7 @@
 
     SAFE_PARCEL(input.readUint32, &what);
     SAFE_PARCEL(input.readUint32, &layerStack);
+    SAFE_PARCEL(input.readUint32, &flags);
     uint32_t tmpUint = 0;
     SAFE_PARCEL(input.readUint32, &tmpUint);
     orientation = ui::toRotation(tmpUint);
@@ -361,6 +364,10 @@
         what |= eLayerStackChanged;
         layerStack = other.layerStack;
     }
+    if (other.what & eFlagsChanged) {
+        what |= eFlagsChanged;
+        flags = other.flags;
+    }
     if (other.what & eDisplayProjectionChanged) {
         what |= eDisplayProjectionChanged;
         orientation = other.orientation;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index aa93808..25d9b2b 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1730,6 +1730,12 @@
     s.what |= DisplayState::eLayerStackChanged;
 }
 
+void SurfaceComposerClient::Transaction::setDisplayFlags(const sp<IBinder>& token, uint32_t flags) {
+    DisplayState& s(getDisplayState(token));
+    s.flags = flags;
+    s.what |= DisplayState::eFlagsChanged;
+}
+
 void SurfaceComposerClient::Transaction::setDisplayProjection(const sp<IBinder>& token,
                                                               ui::Rotation orientation,
                                                               const Rect& layerStackRect,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 16430b3..869c082 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -247,7 +247,8 @@
         eSurfaceChanged = 0x01,
         eLayerStackChanged = 0x02,
         eDisplayProjectionChanged = 0x04,
-        eDisplaySizeChanged = 0x08
+        eDisplaySizeChanged = 0x08,
+        eFlagsChanged = 0x10
     };
 
     DisplayState();
@@ -257,6 +258,7 @@
     sp<IBinder> token;
     sp<IGraphicBufferProducer> surface;
     uint32_t layerStack;
+    uint32_t flags;
 
     // These states define how layers are projected onto the physical display.
     //
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0940e9d..ccd59a4 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -562,6 +562,8 @@
 
         void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
 
+        void setDisplayFlags(const sp<IBinder>& token, uint32_t flags);
+
         /* setDisplayProjection() defines the projection of layer stacks
          * to a given display.
          *
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 0f18235..d1e2ca0 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -219,6 +219,10 @@
     mCompositionDisplay->setLayerStackFilter(stack, isPrimary());
 }
 
+void DisplayDevice::setFlags(uint32_t flags) {
+    mFlags = flags;
+}
+
 void DisplayDevice::setDisplaySize(int width, int height) {
     LOG_FATAL_IF(!isVirtual(), "Changing the display size is supported only for virtual displays.");
     mCompositionDisplay->setDisplaySize(ui::Size(width, height));
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bf249cd..3c39a92 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -64,6 +64,7 @@
 public:
     constexpr static float sDefaultMinLumiance = 0.0;
     constexpr static float sDefaultMaxLumiance = 500.0;
+    enum { eReceivesInput = 0x01 };
 
     explicit DisplayDevice(DisplayDeviceCreationArgs& args);
 
@@ -90,6 +91,7 @@
     void setLayerStack(ui::LayerStack);
     void setDisplaySize(int width, int height);
     void setProjection(ui::Rotation orientation, Rect viewport, Rect frame);
+    void setFlags(uint32_t flags);
 
     ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; }
     ui::Rotation getOrientation() const { return mOrientation; }
@@ -102,6 +104,7 @@
     const Rect& getOrientedDisplaySpaceRect() const;
     bool needsFiltering() const;
     ui::LayerStack getLayerStack() const;
+    bool receivesInput() const { return mFlags & eReceivesInput; }
 
     // Returns the physical ID of this display. This function asserts the ID is physical and it
     // shouldn't be called for other display types, e.g. virtual.
@@ -221,6 +224,8 @@
     // TODO(b/74619554): Remove special cases for primary display.
     const bool mIsPrimary;
 
+    uint32_t mFlags = 0;
+
     std::optional<DeviceProductInfo> mDeviceProductInfo;
 
     std::vector<ui::Hdr> mOverrideHdrTypes;
@@ -246,6 +251,7 @@
     std::optional<Physical> physical;
     sp<IGraphicBufferProducer> surface;
     ui::LayerStack layerStack = ui::NO_LAYER_STACK;
+    uint32_t flags = 0;
     Rect layerStackSpaceRect;
     Rect orientedDisplaySpaceRect;
     ui::Rotation orientation = ui::ROTATION_0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a5b7107..dae799a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2758,6 +2758,9 @@
         if (currentState.layerStack != drawingState.layerStack) {
             display->setLayerStack(currentState.layerStack);
         }
+        if (currentState.flags != drawingState.flags) {
+            display->setFlags(currentState.flags);
+        }
         if ((currentState.orientation != drawingState.orientation) ||
             (currentState.layerStackSpaceRect != drawingState.layerStackSpaceRect) ||
             (currentState.orientedDisplaySpaceRect != drawingState.orientedDisplaySpaceRect)) {
@@ -2974,18 +2977,9 @@
 
     mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
         if (!layer->needsInputInfo()) return;
-        sp<DisplayDevice> display;
-        if (enablePerWindowInputRotation()) {
-            for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
-                const auto& displayDevice = pair.second;
-                if (!displayDevice->getCompositionDisplay()
-                             ->belongsInOutput(layer->getLayerStack(),
-                                               layer->getPrimaryDisplayOnly())) {
-                    continue;
-                }
-                display = displayDevice;
-            }
-        }
+        sp<DisplayDevice> display = enablePerWindowInputRotation()
+                ? ON_MAIN_THREAD(getDisplayWithInputByLayer(layer))
+                : nullptr;
         // When calculating the screen bounds we ignore the transparent region since it may
         // result in an unwanted offset.
         inputInfos.push_back(layer->fillInputInfo(display));
@@ -3723,6 +3717,12 @@
             flags |= eDisplayTransactionNeeded;
         }
     }
+    if (what & DisplayState::eFlagsChanged) {
+        if (state.flags != s.flags) {
+            state.flags = s.flags;
+            flags |= eDisplayTransactionNeeded;
+        }
+    }
     if (what & DisplayState::eDisplayProjectionChanged) {
         if (state.orientation != s.orientation) {
             state.orientation = s.orientation;
@@ -4382,6 +4382,26 @@
     static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); }));
 }
 
+sp<DisplayDevice> SurfaceFlinger::getDisplayWithInputByLayer(Layer* layer) const {
+    sp<DisplayDevice> display;
+    for (const auto& pair : mDisplays) {
+        const auto& displayDevice = pair.second;
+        if (!displayDevice->receivesInput() ||
+            !displayDevice->getCompositionDisplay()
+                     ->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
+            continue;
+        }
+        // Don't return immediately so that we can log duplicates.
+        if (display) {
+            ALOGE("Multiple display devices claim to accept input for the same layerstack: %d",
+                  layer->getLayerStack());
+            continue;
+        }
+        display = displayDevice;
+    }
+    return display;
+}
+
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {
     if (display->isVirtual()) {
         ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index cb8d312..e8f26b5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -967,6 +967,8 @@
     // region of all screens presenting this layer stack.
     void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
 
+    sp<DisplayDevice> getDisplayWithInputByLayer(Layer* layer) const REQUIRES(mStateLock);
+
     /*
      * H/W composer
      */
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index c5f1598..843c966 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -160,6 +160,7 @@
 
     addDisplaySurfaceLocked(transaction, display.sequenceId, display.surface);
     addDisplayLayerStackLocked(transaction, display.sequenceId, display.layerStack);
+    addDisplayFlagsLocked(transaction, display.sequenceId, display.flags);
     addDisplaySizeLocked(transaction, display.sequenceId, display.width, display.height);
     addDisplayProjectionLocked(transaction, display.sequenceId, toRotationInt(display.orientation),
                                display.layerStackSpaceRect, display.orientedDisplaySpaceRect);
@@ -474,6 +475,9 @@
     if (state.what & DisplayState::eLayerStackChanged) {
         addDisplayLayerStackLocked(transaction, sequenceId, state.layerStack);
     }
+    if (state.what & DisplayState::eFlagsChanged) {
+        addDisplayFlagsLocked(transaction, sequenceId, state.flags);
+    }
     if (state.what & DisplayState::eDisplaySizeChanged) {
         addDisplaySizeLocked(transaction, sequenceId, state.width, state.height);
     }
@@ -565,6 +569,13 @@
     layerStackChange->set_layer_stack(layerStack);
 }
 
+void SurfaceInterceptor::addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId,
+                                               uint32_t flags) {
+    DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId));
+    DisplayFlagsChange* flagsChange(dispChange->mutable_flags());
+    flagsChange->set_flags(flags);
+}
+
 void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId,
         uint32_t w, uint32_t h)
 {
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 30aca83..e498e7d 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -184,6 +184,7 @@
             const sp<const IGraphicBufferProducer>& surface);
     void addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId,
             uint32_t layerStack);
+    void addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId, uint32_t flags);
     void addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId, uint32_t w,
             uint32_t h);
     void addDisplayProjectionLocked(Transaction* transaction, int32_t sequenceId,
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
index be01984..fc40818 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
@@ -224,6 +224,74 @@
     EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
 }
 
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfFlagsNotChanged) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display has flags set
+    display.mutableCurrentDisplayState().flags = 1u;
+
+    // The incoming request sets a different layer stack
+    DisplayState state;
+    state.what = DisplayState::eFlagsChanged;
+    state.token = display.token();
+    state.flags = 1u;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags are empty
+    EXPECT_EQ(0u, flags);
+
+    // The desired display state has been set to the new value.
+    EXPECT_EQ(1u, display.getCurrentDisplayState().flags);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfFlagsChanged) {
+    using Case = SimplePrimaryDisplayCase;
+
+    // --------------------------------------------------------------------
+    // Preconditions
+
+    // A display is set up
+    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+    display.inject();
+
+    // The display has a layer stack set
+    display.mutableCurrentDisplayState().flags = 0u;
+
+    // The incoming request sets a different layer stack
+    DisplayState state;
+    state.what = DisplayState::eFlagsChanged;
+    state.token = display.token();
+    state.flags = 1u;
+
+    // --------------------------------------------------------------------
+    // Invocation
+
+    uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+    // --------------------------------------------------------------------
+    // Postconditions
+
+    // The returned flags indicate a transaction is needed
+    EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+    // The desired display state has been set to the new value.
+    EXPECT_EQ(1u, display.getCurrentDisplayState().flags);
+}
+
 TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) {
     using Case = SimplePrimaryDisplayCase;
     constexpr ui::Rotation initialOrientation = ui::ROTATION_180;