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
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b273712..9407c92 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2432,27 +2432,7 @@
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 @@
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 @@
// 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