Forward input windows from SurfaceFlinger to InputDispatcher.
We re-use values from visible region computation to fill in
the frames, ensuring input always reflects the most recent
state of the scene.
Test: Extensive manual testing. Existing tests pass.
Bug: 80101428
Bug: 113136004
Bug: 111440400
Change-Id: I9908a1bd6cba6abf16f2f6a43b6fe63f07a124a6
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 088c256..1007b3d 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -54,6 +54,7 @@
"libsync",
"libtimestats_proto",
"libui",
+ "libinput",
"libutils",
],
static_libs: [
@@ -183,6 +184,7 @@
"libdisplayservicehidl",
"libhidlbase",
"libhidltransport",
+ "libinput",
"liblayers_proto",
"liblog",
"libsync",
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f3182be..d9ec44a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1057,6 +1057,11 @@
clearSyncPoints();
}
+ if (mCurrentState.inputInfoChanged) {
+ flags |= eInputInfoChanged;
+ mCurrentState.inputInfoChanged = false;
+ }
+
// Commit the transaction
commitTransaction(c);
mCurrentState.callbackHandles = {};
@@ -1928,6 +1933,13 @@
mDrawingParent = mCurrentParent;
}
+void Layer::setInputInfo(const InputWindowInfo& info) {
+ mCurrentState.inputInfo = info;
+ mCurrentState.modified = true;
+ mCurrentState.inputInfoChanged = true;
+ setTransactionFlags(eTransactionNeeded);
+}
+
void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
@@ -2055,6 +2067,24 @@
return mRemovedFromCurrentState;
}
+InputWindowInfo Layer::fillInputInfo(const Rect& screenBounds) {
+ InputWindowInfo info = mDrawingState.inputInfo;
+ info.frameLeft = screenBounds.left;
+ info.inputInfo.frameTop = screenBounds.top;
+ info.inputInfo.frameRight = screenBounds.right;
+ info.inputInfo.frameBottom = screenBounds.bottom;
+
+ info.touchableRegion = mDrawingState.inputInfo.touchableRegion.translate(
+ screenBounds.left,
+ screenBounds.top);
+ info.visible = isVisible();
+ return info;
+}
+
+bool Layer::hasInput() const {
+ return mDrawingState.inputInfo.inputChannel != nullptr;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index ed51c61..fe8d5a9 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -22,6 +22,7 @@
#include <gui/BufferQueue.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
+#include <input/InputWindow.h>
#include <layerproto/LayerProtoHeader.h>
#include <math/vec4.h>
#include <renderengine/Mesh.h>
@@ -109,6 +110,7 @@
enum { // flags for doTransaction()
eDontUpdateGeometryState = 0x00000001,
eVisibleRegion = 0x00000002,
+ eInputInfoChanged = 0x00000004
};
struct Geometry {
@@ -166,6 +168,9 @@
half4 color;
+ bool inputInfoChanged;
+ InputWindowInfo inputInfo;
+
// The fields below this point are only used by BufferStateLayer
Geometry active;
@@ -708,6 +713,10 @@
bool getPremultipledAlpha() const;
bool mPendingHWCDestroy{false};
+ void setInputInfo(const InputWindowInfo& info);
+
+ InputWindowInfo fillInputInfo(const Rect& screenBounds);
+ bool hasInput() const;
protected:
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index af73346..e9dd6bc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,6 +37,8 @@
#include <dvr/vr_flinger.h>
+#include <input/IInputFlinger.h>
+
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
@@ -554,6 +556,13 @@
if (window != 0) {
window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
+ sp<IBinder> input(defaultServiceManager()->getService(
+ String16("inputflinger")));
+ if (input == nullptr) {
+ ALOGE("Failed to link to input service");
+ } else {
+ mInputFlinger = interface_cast<IInputFlinger>(input);
+ }
if (mVrFlinger) {
mVrFlinger->OnBootFinished();
@@ -2569,6 +2578,7 @@
* (perform the transaction for each of them if needed)
*/
+ bool inputChanged = false;
if (transactionFlags & eTraversalNeeded) {
mCurrentState.traverseInZOrder([&](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
@@ -2577,6 +2587,10 @@
const uint32_t flags = layer->doTransaction(0);
if (flags & Layer::eVisibleRegion)
mVisibleRegionsDirty = true;
+
+ if (flags & Layer::eInputInfoChanged) {
+ inputChanged = true;
+ }
});
}
@@ -2686,9 +2700,26 @@
commitTransaction();
+ if ((inputChanged || mVisibleRegionsDirty) && mInputFlinger) {
+ updateInputWindows();
+ }
+
updateCursorAsync();
}
+void SurfaceFlinger::updateInputWindows() {
+ ATRACE_CALL();
+
+ Vector<InputWindowInfo> inputHandles;
+
+ mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
+ if (layer->hasInput()) {
+ inputHandles.add(layer->fillInputInfo(layer->computeScreenBounds()));
+ }
+ });
+ mInputFlinger->setInputWindows(inputHandles);
+}
+
void SurfaceFlinger::updateCursorAsync()
{
for (const auto& [token, display] : mDisplays) {
@@ -2796,6 +2827,7 @@
if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque(s);
Rect bounds(layer->computeScreenBounds());
+
visibleRegion.set(bounds);
ui::Transform tr = layer->getTransform();
if (!visibleRegion.isEmpty()) {
@@ -3611,7 +3643,10 @@
if (what & layer_state_t::eSidebandStreamChanged) {
if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
}
-
+ if (what & layer_state_t::eInputInfoChanged) {
+ layer->setInputInfo(s.inputInfo);
+ flags |= eTraversalNeeded;
+ }
std::vector<sp<CallbackHandle>> callbackHandles;
if ((what & layer_state_t::eListenerCallbacksChanged) && (!s.listenerCallbacks.empty())) {
mTransactionCompletedThread.run();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f98dddf..4a14de7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -98,6 +98,7 @@
class EventThread;
class IGraphicBufferConsumer;
class IGraphicBufferProducer;
+class IInputFlinger;
class InjectVSyncSource;
class Layer;
class Surface;
@@ -531,6 +532,7 @@
void handleTransaction(uint32_t transactionFlags);
void handleTransactionLocked(uint32_t transactionFlags);
+ void updateInputWindows();
void updateCursorAsync();
/* handlePageFlip - latch a new buffer if available and compute the dirty
@@ -986,6 +988,8 @@
std::unique_ptr<Scheduler> mScheduler;
sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
+
+ sp<IInputFlinger> mInputFlinger;
};
}; // namespace android