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

Commit 7e72caf3 authored by chaviw's avatar chaviw
Browse files

Use empty frame for input when layer bounds is invalid

Fixed a few issues:
1. Return INVALID_RECT for size if there's no buffer for BLAST. This was
already done in BufferQueueLayer. This ensures we don't assume the layer
has a valid size when there's no buffer

2. Don't transform invalid layer bounds in fillInputInfo since it could
result in sending a valid frame when the layer actually has no bounds.
Instead just set input frame to empty, reset the transform, and return
early.

Test: Window with no width or height doesn't get untrusted touch
Test: InputSurfacesTest
Fixes: 173297887
Change-Id: I191d411b0f83ce57b6fdc20a1def8070110d418b
parent 16abdd2a
Loading
Loading
Loading
Loading
+41 −2
Original line number Diff line number Diff line
@@ -95,6 +95,15 @@ public:
        return std::make_unique<InputSurface>(surfaceControl, width, height);
    }

    static std::unique_ptr<InputSurface> makeBlastInputSurface(const sp<SurfaceComposerClient> &scc,
                                                               int width, int height) {
        sp<SurfaceControl> surfaceControl =
                scc->createSurface(String8("Test Buffer Surface"), width, height,
                                   PIXEL_FORMAT_RGBA_8888,
                                   ISurfaceComposerClient::eFXSurfaceBufferState);
        return std::make_unique<InputSurface>(surfaceControl, width, height);
    }

    static std::unique_ptr<InputSurface> makeContainerInputSurface(
            const sp<SurfaceComposerClient> &scc, int width, int height) {
        sp<SurfaceControl> surfaceControl =
@@ -180,13 +189,13 @@ public:
        t.apply(true);
    }

    void showAt(int x, int y) {
    void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) {
        SurfaceComposerClient::Transaction t;
        t.show(mSurfaceControl);
        t.setInputWindowInfo(mSurfaceControl, mInputInfo);
        t.setLayer(mSurfaceControl, LAYER_BASE);
        t.setPosition(mSurfaceControl, x, y);
        t.setCrop_legacy(mSurfaceControl, Rect(0, 0, 100, 100));
        t.setCrop_legacy(mSurfaceControl, crop);
        t.setAlpha(mSurfaceControl, 1);
        t.apply(true);
    }
@@ -684,4 +693,34 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) {
    surface->expectTap(1, 10);
}

TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_bql) {
    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);

    std::unique_ptr<InputSurface> bufferSurface =
            InputSurface::makeBufferInputSurface(mComposerClient, 0, 0);
    bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
    bufferSurface->mInputInfo.ownerUid = 22222;

    surface->showAt(10, 10);
    bufferSurface->showAt(50, 50, Rect::EMPTY_RECT);

    injectTap(11, 11);
    surface->expectTap(1, 1);
}

TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) {
    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);

    std::unique_ptr<InputSurface> bufferSurface =
            InputSurface::makeBlastInputSurface(mComposerClient, 0, 0);
    bufferSurface->mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCHABLE;
    bufferSurface->mInputInfo.ownerUid = 22222;

    surface->showAt(10, 10);
    bufferSurface->showAt(50, 50, Rect::EMPTY_RECT);

    injectTap(11, 11);
    surface->expectTap(1, 1);
}

} // namespace android::test
+4 −0
Original line number Diff line number Diff line
@@ -479,6 +479,10 @@ Rect BufferStateLayer::getBufferSize(const State& s) const {
        return Rect(getActiveWidth(s), getActiveHeight(s));
    }

    if (mBufferInfo.mBuffer == nullptr) {
        return Rect::INVALID_RECT;
    }

    // if the display frame is not defined, use the parent bounds as the buffer size.
    const auto& p = mDrawingParent.promote();
    if (p != nullptr) {
+36 −21
Original line number Diff line number Diff line
@@ -2432,27 +2432,7 @@ bool Layer::isRemovedFromCurrentState() const {
    return mRemovedFromCurrentState;
}

InputWindowInfo Layer::fillInputInfo() {
    if (!hasInputInfo()) {
        mDrawingState.inputInfo.name = getName();
        mDrawingState.inputInfo.ownerUid = mOwnerUid;
        mDrawingState.inputInfo.ownerPid = mOwnerPid;
        mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL;
        mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
        mDrawingState.inputInfo.displayId = getLayerStack();
    }

    InputWindowInfo info = mDrawingState.inputInfo;
    info.id = sequence;

    if (info.displayId == ADISPLAY_ID_NONE) {
        info.displayId = getLayerStack();
    }

    ui::Transform t = getTransform();
    int32_t xSurfaceInset = info.surfaceInset;
    int32_t ySurfaceInset = info.surfaceInset;

void Layer::fillInputFrameInfo(InputWindowInfo& info) {
    // Transform layer size to screen space and inset it by surface insets.
    // If this is a portal window, set the touchableRegion to the layerBounds.
    Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
@@ -2462,6 +2442,20 @@ InputWindowInfo Layer::fillInputInfo() {
        layerBounds = getCroppedBufferSize(getDrawingState());
    }

    if (!layerBounds.isValid()) {
        // If the layer bounds is empty, set the frame to empty and clear the transform
        info.frameLeft = 0;
        info.frameTop = 0;
        info.frameRight = 0;
        info.frameBottom = 0;
        info.transform.reset();
        return;
    }

    ui::Transform t = getTransform();
    int32_t xSurfaceInset = info.surfaceInset;
    int32_t ySurfaceInset = info.surfaceInset;

    const float xScale = t.getScaleX();
    const float yScale = t.getScaleY();
    if (xScale != 1.0f || yScale != 1.0f) {
@@ -2528,6 +2522,27 @@ InputWindowInfo Layer::fillInputInfo() {
    // Position the touchable region relative to frame screen location and restrict it to frame
    // bounds.
    info.touchableRegion = inputTransform.transform(info.touchableRegion);
}

InputWindowInfo Layer::fillInputInfo() {
    if (!hasInputInfo()) {
        mDrawingState.inputInfo.name = getName();
        mDrawingState.inputInfo.ownerUid = mOwnerUid;
        mDrawingState.inputInfo.ownerPid = mOwnerPid;
        mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL;
        mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
        mDrawingState.inputInfo.displayId = getLayerStack();
    }

    InputWindowInfo info = mDrawingState.inputInfo;
    info.id = sequence;

    if (info.displayId == ADISPLAY_ID_NONE) {
        info.displayId = getLayerStack();
    }

    fillInputFrameInfo(info);

    // 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
+3 −0
Original line number Diff line number Diff line
@@ -1114,6 +1114,9 @@ private:
    // null.
    sp<Layer> getRootLayer();

    // Fills in the frame and transform info for the InputWindowInfo
    void fillInputFrameInfo(InputWindowInfo& info);

    // Cached properties computed from drawing state
    // Effective transform taking into account parent transforms and any parent scaling, which is
    // a transform from the current layer coordinate space to display(screen) coordinate space.