Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83aca388 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Reland: Send WindowInfo even if the window isn't associated with a DisplayDevice

Previously reverted for b/240320932. Fixed broken test.

The previous behavior was the following: If a window was in a layerStack
for which there were no DisplayDevices that mapped to it, there was no
WindowInfo sent for it.

When a display is turned OFF, it is mapped to an invalid layer stack.
So when the primary display is turned OFF, there is no WindowInfo sent
for any windows on layerStack 0 as there are no DisplayDevices that now
map to it. In this model, no window can receive input when the display
is OFF.

In this CL, we change the behavior so that WindowInfos are sent even if
there are no DisplayDevices that map to its layerStack -- except that
in this case, we do not let the window receive touches, as we do not
have a valid transform associated with it.

Bug: 239788987
Test: See bug for repro steps
Test: Observe logs at runtime
Test: atest libgui_tests
Change-Id: Ib7e343685a0e3a87769883bdd5e24ac0e6d5e83f
(cherry picked from commit da0f62ce)
parent 901a5975
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -1184,18 +1184,23 @@ public:
    std::vector<sp<IGraphicBufferProducer>> mProducers;
};

TEST_F(MultiDisplayTests, drop_input_if_layer_on_invalid_display) {
TEST_F(MultiDisplayTests, drop_touch_if_layer_on_invalid_display) {
    ui::LayerStack layerStack = ui::LayerStack::fromValue(42);
    // Do not create a display associated with the LayerStack.
    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
    surface->doTransaction([&](auto &t, auto &sc) { t.setLayerStack(sc, layerStack); });
    surface->showAt(100, 100);

    // Touches should be dropped if the layer is on an invalid display.
    injectTapOnDisplay(101, 101, layerStack.id);
    EXPECT_EQ(surface->consumeEvent(100), nullptr);

    // However, we still let the window be focused and receive keys.
    surface->requestFocus(layerStack.id);
    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
    surface->assertFocusChange(true);

    EXPECT_EQ(surface->consumeEvent(100), nullptr);
    injectKeyOnDisplay(AKEYCODE_V, layerStack.id);
    surface->expectKey(AKEYCODE_V);
}

TEST_F(MultiDisplayTests, virtual_display_receives_input) {
+14 −3
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@
namespace android {
namespace {
constexpr int kDumpTableRowLength = 159;
const ui::Transform kIdentityTransform;
} // namespace

using namespace ftl::flag_operators;
@@ -2162,7 +2163,8 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
    if ((traceFlags & LayerTracing::TRACE_INPUT) && needsInputInfo()) {
        WindowInfo info;
        if (useDrawing) {
            info = fillInputInfo(ui::Transform(), /* displayIsSecure */ true);
            info = fillInputInfo(
                    InputDisplayArgs{.transform = &kIdentityTransform, .isSecure = true});
        } else {
            info = state.inputInfo;
        }
@@ -2369,7 +2371,7 @@ void Layer::handleDropInputMode(gui::WindowInfo& info) const {
    }
}

WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure) {
WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) {
    if (!hasInputInfo()) {
        mDrawingState.inputInfo.name = getName();
        mDrawingState.inputInfo.ownerUid = mOwnerUid;
@@ -2378,12 +2380,21 @@ WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool disp
        mDrawingState.inputInfo.displayId = getLayerStack().id;
    }

    const ui::Transform& displayTransform =
            displayArgs.transform != nullptr ? *displayArgs.transform : kIdentityTransform;

    WindowInfo info = mDrawingState.inputInfo;
    info.id = sequence;
    info.displayId = getLayerStack().id;

    fillInputFrameInfo(info, displayTransform);

    if (displayArgs.transform == nullptr) {
        // Do not let the window receive touches if it is not associated with a valid display
        // transform. We still allow the window to receive keys and prevent ANRs.
        info.inputConfig |= WindowInfo::InputConfig::NOT_TOUCHABLE;
    }

    // For compatibility reasons we let layers which can receive input
    // receive input before they have actually submitted a buffer. Because
    // of this we use canReceiveInput instead of isVisible to check the
@@ -2401,7 +2412,7 @@ WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool disp

    // If the window will be blacked out on a display because the display does not have the secure
    // flag and the layer has the secure flag set, then drop input.
    if (!displayIsSecure && isSecure()) {
    if (!displayArgs.isSecure && isSecure()) {
        info.inputConfig |= WindowInfo::InputConfig::DROP_INPUT;
    }

+5 −1
Original line number Diff line number Diff line
@@ -844,7 +844,11 @@ public:
    bool getPremultipledAlpha() const;
    void setInputInfo(const gui::WindowInfo& info);

    gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform, bool displayIsSecure);
    struct InputDisplayArgs {
        const ui::Transform* transform = nullptr;
        bool isSecure = false;
    };
    gui::WindowInfo fillInputInfo(const InputDisplayArgs& displayArgs);

    /**
     * Returns whether this layer has an explicitly set input-info.
+5 −5
Original line number Diff line number Diff line
@@ -3329,11 +3329,11 @@ void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
        if (!layer->needsInputInfo()) return;

        // Do not create WindowInfos for windows on displays that cannot receive input.
        if (const auto opt = displayInputInfos.get(layer->getLayerStack())) {
            const auto& info = opt->get();
            outWindowInfos.push_back(layer->fillInputInfo(info.transform, info.isSecure));
        }
        const auto opt = displayInputInfos.get(layer->getLayerStack(),
                                               [](const auto& info) -> Layer::InputDisplayArgs {
                                                   return {&info.transform, info.isSecure};
                                               });
        outWindowInfos.push_back(layer->fillInputInfo(opt.value_or(Layer::InputDisplayArgs{})));
    });

    sNumWindowInfos = outWindowInfos.size();