Introduce WindowInfo::InputConfig flag to control input behavior
Instead of re-using layoutParams flags and layoutParam types and having
redundant information in WindowInfo, we add a new InputConfig flag that
the native input pipeline will use for all input window configurations.
This also reduces WindowInfo's size by converting booleans into flags.
Bug: 216806304
Test: atest libgui_test
Test: atest inputflinger_tests
Change-Id: If0354cc2cfc84986f7f0d48cd9348be1ff82293d
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index a866786..2c25e7e 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -18,7 +18,6 @@
#define LOG_TAG "WindowInfo"
#define LOG_NDEBUG 0
-#include <android-base/stringprintf.h>
#include <binder/Parcel.h>
#include <gui/WindowInfo.h>
@@ -27,6 +26,14 @@
namespace android::gui {
// --- WindowInfo ---
+void WindowInfo::setInputConfig(Flags<InputConfig> config, bool value) {
+ if (value) {
+ inputConfig |= config;
+ return;
+ }
+ inputConfig &= ~config;
+}
+
void WindowInfo::addTouchableRegion(const Rect& region) {
touchableRegion.orSelf(region);
}
@@ -40,7 +47,7 @@
}
bool WindowInfo::supportsSplitTouch() const {
- return flags.test(Flag::SPLIT_TOUCH);
+ return inputConfig.test(InputConfig::SPLIT_TOUCH);
}
bool WindowInfo::isSpy() const {
@@ -58,20 +65,19 @@
}
bool WindowInfo::operator==(const WindowInfo& info) const {
- return info.token == token && info.id == id && info.name == name && info.flags == flags &&
- info.type == type && info.dispatchingTimeout == dispatchingTimeout &&
- info.frameLeft == frameLeft && info.frameTop == frameTop &&
- info.frameRight == frameRight && info.frameBottom == frameBottom &&
- info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor &&
- info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) &&
- info.visible == visible && info.trustedOverlay == trustedOverlay &&
- info.focusable == focusable && info.touchOcclusionMode == touchOcclusionMode &&
- info.hasWallpaper == hasWallpaper && info.paused == paused &&
- info.ownerPid == ownerPid && info.ownerUid == ownerUid &&
- info.packageName == packageName && info.inputFeatures == inputFeatures &&
+ return info.token == token && info.id == id && info.name == name &&
+ info.dispatchingTimeout == dispatchingTimeout && info.frameLeft == frameLeft &&
+ info.frameTop == frameTop && info.frameRight == frameRight &&
+ info.frameBottom == frameBottom && info.surfaceInset == surfaceInset &&
+ info.globalScaleFactor == globalScaleFactor && info.transform == transform &&
+ info.touchableRegion.hasSameRects(touchableRegion) &&
+ info.touchOcclusionMode == touchOcclusionMode && info.ownerPid == ownerPid &&
+ info.ownerUid == ownerUid && info.packageName == packageName &&
+ info.inputFeatures == inputFeatures && info.inputConfig == inputConfig &&
info.displayId == displayId &&
info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
- info.applicationInfo == applicationInfo;
+ info.applicationInfo == applicationInfo && info.layoutParamsType == layoutParamsType &&
+ info.layoutParamsFlags == layoutParamsFlags;
}
status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
@@ -85,13 +91,18 @@
}
parcel->writeInt32(1);
+ // Ensure that the size of the flags that we use is 32 bits for writing into the parcel.
+ static_assert(sizeof(inputFeatures) == 4u);
+ static_assert(sizeof(inputConfig) == 4u);
+
// clang-format off
status_t status = parcel->writeStrongBinder(token) ?:
parcel->writeInt64(dispatchingTimeout.count()) ?:
parcel->writeInt32(id) ?:
parcel->writeUtf8AsUtf16(name) ?:
- parcel->writeInt32(flags.get()) ?:
- parcel->writeInt32(static_cast<std::underlying_type_t<WindowInfo::Type>>(type)) ?:
+ parcel->writeInt32(layoutParamsFlags.get()) ?:
+ parcel->writeInt32(
+ static_cast<std::underlying_type_t<WindowInfo::Type>>(layoutParamsType)) ?:
parcel->writeInt32(frameLeft) ?:
parcel->writeInt32(frameTop) ?:
parcel->writeInt32(frameRight) ?:
@@ -105,16 +116,12 @@
parcel->writeFloat(transform.dtdy()) ?:
parcel->writeFloat(transform.dsdy()) ?:
parcel->writeFloat(transform.ty()) ?:
- parcel->writeBool(visible) ?:
- parcel->writeBool(focusable) ?:
- parcel->writeBool(hasWallpaper) ?:
- parcel->writeBool(paused) ?:
- parcel->writeBool(trustedOverlay) ?:
parcel->writeInt32(static_cast<int32_t>(touchOcclusionMode)) ?:
parcel->writeInt32(ownerPid) ?:
parcel->writeInt32(ownerUid) ?:
parcel->writeUtf8AsUtf16(packageName) ?:
parcel->writeInt32(inputFeatures.get()) ?:
+ parcel->writeInt32(inputConfig.get()) ?:
parcel->writeInt32(displayId) ?:
applicationInfo.writeToParcel(parcel) ?:
parcel->write(touchableRegion) ?:
@@ -141,8 +148,8 @@
return status;
}
- flags = Flags<Flag>(parcel->readInt32());
- type = static_cast<Type>(parcel->readInt32());
+ layoutParamsFlags = Flags<Flag>(parcel->readInt32());
+ layoutParamsType = static_cast<Type>(parcel->readInt32());
float dsdx, dtdx, tx, dtdy, dsdy, ty;
int32_t touchOcclusionModeInt;
// clang-format off
@@ -159,11 +166,6 @@
parcel->readFloat(&dtdy) ?:
parcel->readFloat(&dsdy) ?:
parcel->readFloat(&ty) ?:
- parcel->readBool(&visible) ?:
- parcel->readBool(&focusable) ?:
- parcel->readBool(&hasWallpaper) ?:
- parcel->readBool(&paused) ?:
- parcel->readBool(&trustedOverlay) ?:
parcel->readInt32(&touchOcclusionModeInt) ?:
parcel->readInt32(&ownerPid) ?:
parcel->readInt32(&ownerUid) ?:
@@ -177,6 +179,7 @@
touchOcclusionMode = static_cast<TouchOcclusionMode>(touchOcclusionModeInt);
inputFeatures = Flags<Feature>(parcel->readInt32());
+ inputConfig = Flags<InputConfig>(parcel->readInt32());
// clang-format off
status = parcel->readInt32(&displayId) ?:
applicationInfo.readFromParcel(parcel) ?:
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index eb64ac9..1b3419a 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -151,6 +151,34 @@
// clang-format on
};
+ // Flags used to determine configuration of this input window.
+ // Input windows can be configured with two sets of flags: InputFeature (WindowInfo::Feature
+ // defined above), and InputConfig. When adding a new configuration for an input window:
+ // - If you are adding a new flag that's visible and accessible to apps, it should be added
+ // as an InputFeature.
+ // - If you are adding an internal behaviour that is used within the system or shell and is
+ // not exposed to apps, it should be added as an InputConfig.
+ enum class InputConfig : uint32_t {
+ // clang-format off
+ NONE = 0,
+ NOT_VISIBLE = 1 << 0,
+ NOT_FOCUSABLE = 1 << 1,
+ NOT_TOUCHABLE = 1 << 2,
+ NOT_TOUCH_MODAL = 1 << 3,
+ SPLIT_TOUCH = 1 << 4,
+ DUPLICATE_TOUCH_TO_WALLPAPER = 1 << 5,
+ IS_WALLPAPER = 1 << 6,
+ PAUSE_DISPATCHING = 1 << 7,
+ // This flag is set when the window is of a trusted type that is allowed to silently
+ // overlay other windows for the purpose of implementing the secure views feature.
+ // Trusted overlays, such as IME windows, can partly obscure other windows without causing
+ // motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
+ TRUSTED_OVERLAY = 1 << 8,
+ WATCH_OUTSIDE_TOUCH = 1 << 9,
+ SLIPPERY = 1 << 10,
+ // clang-format on
+ };
+
/* These values are filled in by the WM and passed through SurfaceFlinger
* unless specified otherwise.
*/
@@ -164,8 +192,6 @@
// This uniquely identifies the input window.
int32_t id = -1;
std::string name;
- Flags<Flag> flags;
- Type type = Type::UNKNOWN;
std::chrono::nanoseconds dispatchingTimeout = std::chrono::seconds(5);
/* These values are filled in by SurfaceFlinger. */
@@ -198,26 +224,24 @@
* to absolute coordinates by SurfaceFlinger once the frame is computed.
*/
Region touchableRegion;
- bool visible = false;
- bool focusable = false;
- bool hasWallpaper = false;
- bool paused = false;
- /* This flag is set when the window is of a trusted type that is allowed to silently
- * overlay other windows for the purpose of implementing the secure views feature.
- * Trusted overlays, such as IME windows, can partly obscure other windows without causing
- * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
- */
- bool trustedOverlay = false;
+
TouchOcclusionMode touchOcclusionMode = TouchOcclusionMode::BLOCK_UNTRUSTED;
int32_t ownerPid = -1;
int32_t ownerUid = -1;
std::string packageName;
Flags<Feature> inputFeatures;
+ Flags<InputConfig> inputConfig;
int32_t displayId = ADISPLAY_ID_NONE;
InputApplicationInfo applicationInfo;
bool replaceTouchableRegionWithCrop = false;
wp<IBinder> touchableRegionCropHandle;
+ // The window's layout params flags and type set by WM.
+ Type layoutParamsType = Type::UNKNOWN;
+ Flags<Flag> layoutParamsFlags;
+
+ void setInputConfig(Flags<InputConfig> config, bool value);
+
void addTouchableRegion(const Rect& region);
bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 06a0aca..1151aa3 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -266,13 +266,10 @@
void populateInputInfo(int width, int height) {
mInputInfo.token = mClientChannel->getConnectionToken();
mInputInfo.name = "Test info";
- mInputInfo.flags = WindowInfo::Flag::NOT_TOUCH_MODAL;
- mInputInfo.type = WindowInfo::Type::BASE_APPLICATION;
mInputInfo.dispatchingTimeout = 5s;
mInputInfo.globalScaleFactor = 1.0;
- mInputInfo.focusable = true;
- mInputInfo.hasWallpaper = false;
- mInputInfo.paused = false;
+ mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCH_MODAL, true);
+ mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, false);
mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));
@@ -750,7 +747,7 @@
// Add non touchable window to fully cover touchable window. Window behind gets touch, but
// with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED
std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
- nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
+ nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
nonTouchableSurface->mInputInfo.ownerUid = 22222;
// Overriding occlusion mode otherwise the touch would be discarded at InputDispatcher by
// the default obscured/untrusted touch filter introduced in S.
@@ -770,8 +767,8 @@
// AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED
std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
- nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
- parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
+ nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
+ parentSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
nonTouchableSurface->mInputInfo.ownerUid = 22222;
parentSurface->mInputInfo.ownerUid = 22222;
nonTouchableSurface->showAt(0, 0);
@@ -794,8 +791,8 @@
// the touchable window. Window behind gets touch with no obscured flags.
std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
- nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
- parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
+ nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
+ parentSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
nonTouchableSurface->mInputInfo.ownerUid = 22222;
parentSurface->mInputInfo.ownerUid = 22222;
nonTouchableSurface->showAt(0, 0);
@@ -815,7 +812,7 @@
std::unique_ptr<InputSurface> bufferSurface =
InputSurface::makeBufferInputSurface(mComposerClient, 0, 0);
- bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
+ bufferSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
bufferSurface->mInputInfo.ownerUid = 22222;
surface->showAt(10, 10);
@@ -830,7 +827,7 @@
std::unique_ptr<BlastInputSurface> bufferSurface =
BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0);
- bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
+ bufferSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
bufferSurface->mInputInfo.ownerUid = 22222;
surface->showAt(10, 10);
@@ -883,7 +880,7 @@
[&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
surface->showAt(100, 100);
std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100);
- obscuringSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
+ obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
obscuringSurface->mInputInfo.ownerUid = 22222;
obscuringSurface->showAt(100, 100);
injectTap(101, 101);
@@ -902,7 +899,7 @@
[&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
surface->showAt(100, 100);
std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100);
- obscuringSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE;
+ obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
obscuringSurface->mInputInfo.ownerUid = 22222;
obscuringSurface->showAt(190, 190);
diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index ff3ba2a..ff9bae2 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -49,8 +49,8 @@
i.windowToken = new BBinder();
i.id = 1;
i.name = "Foobar";
- i.flags = WindowInfo::Flag::SLIPPERY;
- i.type = WindowInfo::Type::INPUT_METHOD;
+ i.layoutParamsFlags = WindowInfo::Flag::SLIPPERY;
+ i.layoutParamsType = WindowInfo::Type::INPUT_METHOD;
i.dispatchingTimeout = 12s;
i.frameLeft = 93;
i.frameTop = 34;
@@ -60,15 +60,12 @@
i.globalScaleFactor = 0.3;
i.alpha = 0.7;
i.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1});
- i.visible = false;
- i.focusable = false;
- i.hasWallpaper = false;
- i.paused = false;
i.touchOcclusionMode = TouchOcclusionMode::ALLOW;
i.ownerPid = 19;
i.ownerUid = 24;
i.packageName = "com.example.package";
i.inputFeatures = WindowInfo::Feature::DISABLE_USER_ACTIVITY;
+ i.inputConfig = WindowInfo::InputConfig::NOT_FOCUSABLE;
i.displayId = 34;
i.replaceTouchableRegionWithCrop = true;
i.touchableRegionCropHandle = touchableRegionCropHandle;
@@ -85,8 +82,8 @@
ASSERT_EQ(i.windowToken, i2.windowToken);
ASSERT_EQ(i.id, i2.id);
ASSERT_EQ(i.name, i2.name);
- ASSERT_EQ(i.flags, i2.flags);
- ASSERT_EQ(i.type, i2.type);
+ ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
+ ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout);
ASSERT_EQ(i.frameLeft, i2.frameLeft);
ASSERT_EQ(i.frameTop, i2.frameTop);
@@ -96,15 +93,12 @@
ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor);
ASSERT_EQ(i.alpha, i2.alpha);
ASSERT_EQ(i.transform, i2.transform);
- ASSERT_EQ(i.visible, i2.visible);
- ASSERT_EQ(i.focusable, i2.focusable);
- ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper);
- ASSERT_EQ(i.paused, i2.paused);
ASSERT_EQ(i.touchOcclusionMode, i2.touchOcclusionMode);
ASSERT_EQ(i.ownerPid, i2.ownerPid);
ASSERT_EQ(i.ownerUid, i2.ownerUid);
ASSERT_EQ(i.packageName, i2.packageName);
ASSERT_EQ(i.inputFeatures, i2.inputFeatures);
+ ASSERT_EQ(i.inputConfig, i2.inputConfig);
ASSERT_EQ(i.displayId, i2.displayId);
ASSERT_EQ(i.replaceTouchableRegionWithCrop, i2.replaceTouchableRegionWithCrop);
ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle);