Report gui::DisplayInfo to clients with window info changes
InputFlinger needs to know specifications about displays such as
orientation and projection from SurfaceFlinger to support the
MotionEvent#getRaw API, which returns coordinates in logical display
space at the moment.
Since dispatcher gets window information from SF, we need to send the
display information that affects input dispatching at the same time as
updating window information to ensure those two pieces of information
remain in sync.
Instead of sending display information along with each window, we
attempt to reduce the amount of information sent through binder by
sending DisplayInfo separately to WindowInfos. The newly added
DisplayInfo struct should only be used by InputFlinger to support raw
coordinates for now, with the goal of removing it altogether in the
future.
Bug: 179274888
Test: atest libgui_test inputflinger_tests
Test: manual, ensure input works
Change-Id: I87429ca4ced5f105f49a117c676cba29f8a5c4da
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 802a17d..fd93b2d 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -139,6 +139,34 @@
return mCompositionDisplay->getRenderSurface()->getPageFlipCount();
}
+std::pair<gui::DisplayInfo, ui::Transform> DisplayDevice::getInputInfo() const {
+ gui::DisplayInfo info;
+ info.displayId = getLayerStack().id;
+
+ // The physical orientation is set when the orientation of the display panel is
+ // different than the default orientation of the device. Other services like
+ // InputFlinger do not know about this, so we do not need to expose the physical
+ // orientation of the panel outside of SurfaceFlinger.
+ const ui::Rotation inversePhysicalOrientation = ui::ROTATION_0 - mPhysicalOrientation;
+ auto width = getWidth();
+ auto height = getHeight();
+ if (inversePhysicalOrientation == ui::ROTATION_90 ||
+ inversePhysicalOrientation == ui::ROTATION_270) {
+ std::swap(width, height);
+ }
+ const ui::Transform undoPhysicalOrientation(ui::Transform::toRotationFlags(
+ inversePhysicalOrientation),
+ width, height);
+ const auto& displayTransform = undoPhysicalOrientation * getTransform();
+ // Send the inverse display transform to input so it can convert display coordinates to
+ // logical display.
+ info.transform = displayTransform.inverse();
+
+ info.logicalWidth = getLayerStackSpaceRect().width();
+ info.logicalHeight = getLayerStackSpaceRect().height();
+ return {info, displayTransform};
+}
+
// ----------------------------------------------------------------------------
void DisplayDevice::setPowerMode(hal::PowerMode mode) {
mPowerMode = mode;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 43a6bd5..7762054 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -167,6 +167,10 @@
return mDeviceProductInfo;
}
+ // Get the DisplayInfo that will be sent to InputFlinger, and the display transform that should
+ // be applied to all the input windows on the display.
+ std::pair<gui::DisplayInfo, ui::Transform> getInputInfo() const;
+
/* ------------------------------------------------------------------------
* Display power mode management.
*/
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 804cf9a..2376b83 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2131,7 +2131,7 @@
if (traceFlags & SurfaceTracing::TRACE_INPUT) {
WindowInfo info;
if (useDrawing) {
- info = fillInputInfo(nullptr);
+ info = fillInputInfo(ui::Transform());
} else {
info = state.inputInfo;
}
@@ -2265,7 +2265,7 @@
}
}
-WindowInfo Layer::fillInputInfo(const DisplayDevice* display) {
+WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform) {
if (!hasInputInfo()) {
mDrawingState.inputInfo.name = getName();
mDrawingState.inputInfo.ownerUid = mOwnerUid;
@@ -2279,35 +2279,6 @@
info.id = sequence;
info.displayId = getLayerStack().id;
- // Transform that maps from LayerStack space to display space, e.g. rotated to non-rotated.
- // Used when InputFlinger operates in display space.
- ui::Transform displayTransform;
- if (display) {
- // The physical orientation is set when the orientation of the display panel is different
- // than the default orientation of the device. Other services like InputFlinger do not know
- // about this, so we do not need to expose the physical orientation of the panel outside of
- // SurfaceFlinger.
- const ui::Rotation inversePhysicalOrientation =
- ui::ROTATION_0 - display->getPhysicalOrientation();
- auto width = display->getWidth();
- auto height = display->getHeight();
- if (inversePhysicalOrientation == ui::ROTATION_90 ||
- inversePhysicalOrientation == ui::ROTATION_270) {
- std::swap(width, height);
- }
- const ui::Transform undoPhysicalOrientation(ui::Transform::toRotationFlags(
- inversePhysicalOrientation),
- width, height);
- displayTransform = undoPhysicalOrientation * display->getTransform();
-
- // Send the inverse of the display orientation so that input can transform points back to
- // the rotated display space.
- const ui::Rotation inverseOrientation = ui::ROTATION_0 - display->getOrientation();
- info.displayOrientation = ui::Transform::toRotationFlags(inverseOrientation);
-
- info.displayWidth = width;
- info.displayHeight = height;
- }
fillInputFrameInfo(info, displayTransform);
// For compatibility reasons we let layers which can receive input
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 4200be4..3c3c7d0 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -851,7 +851,7 @@
bool getPremultipledAlpha() const;
void setInputInfo(const gui::WindowInfo& info);
- gui::WindowInfo fillInputInfo(const DisplayDevice*);
+ gui::WindowInfo fillInputInfo(const ui::Transform& displayTransform);
/**
* Returns whether this layer has an explicitly set input-info.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 21b889e..12389d1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -169,6 +169,7 @@
using android::hardware::power::Boost;
using base::StringAppendF;
+using gui::DisplayInfo;
using gui::IWindowInfosListener;
using gui::WindowInfo;
using ui::ColorMode;
@@ -3053,6 +3054,16 @@
void SurfaceFlinger::notifyWindowInfos() {
std::vector<WindowInfo> windowInfos;
+ std::vector<DisplayInfo> displayInfos;
+ std::unordered_map<const DisplayDevice*, const ui::Transform> displayTransforms;
+
+ if (enablePerWindowInputRotation()) {
+ for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
+ const auto& [info, transform] = display->getInputInfo();
+ displayInfos.emplace_back(info);
+ displayTransforms.emplace(display.get(), transform);
+ }
+ }
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (!layer->needsInputInfo()) return;
@@ -3064,9 +3075,11 @@
// When calculating the screen bounds we ignore the transparent region since it may
// result in an unwanted offset.
- windowInfos.push_back(layer->fillInputInfo(display));
+ const auto it = displayTransforms.find(display);
+ windowInfos.push_back(
+ layer->fillInputInfo(it != displayTransforms.end() ? it->second : ui::Transform()));
});
- mWindowInfosListenerInvoker->windowInfosChanged(windowInfos,
+ mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
mInputWindowCommands.syncInputWindows);
}
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
index dc2aa58..b93d127 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
@@ -21,6 +21,7 @@
namespace android {
+using gui::DisplayInfo;
using gui::IWindowInfosListener;
using gui::WindowInfo;
@@ -67,6 +68,7 @@
}
void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos,
+ const std::vector<DisplayInfo>& displayInfos,
bool shouldSync) {
std::unordered_set<sp<IWindowInfosListener>, ISurfaceComposer::SpHash<IWindowInfosListener>>
windowInfosListeners;
@@ -81,7 +83,7 @@
mCallbacksPending = windowInfosListeners.size();
for (const auto& listener : windowInfosListeners) {
- listener->onWindowInfosChanged(windowInfos,
+ listener->onWindowInfosChanged(windowInfos, displayInfos,
shouldSync ? mWindowInfosReportedListener : nullptr);
}
}
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h
index 5e5796f..ecd797a 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.h
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.h
@@ -33,7 +33,8 @@
void addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
- void windowInfosChanged(const std::vector<gui::WindowInfo>& windowInfos, bool shouldSync);
+ void windowInfosChanged(const std::vector<gui::WindowInfo>&,
+ const std::vector<gui::DisplayInfo>&, bool shouldSync);
protected:
void binderDied(const wp<IBinder>& who) override;
diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
index de116f2..0069111 100644
--- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp
+++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
@@ -22,6 +22,7 @@
namespace android {
using Transaction = SurfaceComposerClient::Transaction;
+using gui::DisplayInfo;
using gui::WindowInfo;
class WindowInfosListenerTest : public ::testing::Test {
@@ -40,7 +41,8 @@
struct SyncWindowInfosListener : public gui::WindowInfosListener {
public:
- void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos) override {
+ void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos,
+ const std::vector<DisplayInfo>&) override {
windowInfosPromise.set_value(windowInfos);
}