From 9be5b33a32563da95c598fec8d55f2b4ff60f054 Mon Sep 17 00:00:00 2001 From: mincheli Date: Tue, 3 Mar 2020 14:45:05 +0800 Subject: Makes TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY as trusted overlay A MotionEvent dispatched within the area of trusted overlay would not referred as an obscured event even a trusted overlay overlaps other windows. If a MotionEvent is referred as obscured when clicking accessibility settings dialog, it would stop users from switching on an accessibility settings and show a warning toast. This change could make magnification window as trusted overlay that users able to switch on an accessibility setting by touching inside the area of the magnification window. Bug: 144075853 Test: Verified an a11y settings is abled to be switched on when the MotionEevent is dispatched within the magnification overlay. Change-Id: I83a6ce1f6e66c55c45746e5a16d0d988d1c1ae0b --- libs/input/InputWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 03ca459fb9..28da8b4f3b 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -43,7 +43,8 @@ bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { } bool InputWindowInfo::isTrustedOverlay() const { - return layoutParamsType == TYPE_INPUT_METHOD + return layoutParamsType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY + || layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY || layoutParamsType == TYPE_STATUS_BAR -- cgit v1.2.3-59-g8ed1b From 67d445093b678d58ee3c9d42577d3bfd6b6bc372 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 9 Apr 2020 11:09:29 -0700 Subject: Print window flags in dumpsys input Previously, the flag in dumpsys input would show up like this: flags=0x21800128 which made it difficult to figure out which flags are actually set on the window. Instead, propose to stringify the flags: flags: NOT_FOCUSABLE | LAYOUT_IN_SCREEN | LAYOUT_NO_LIMITS | LAYOUT_INSET_DECOR | which would make the window portion of dumpsys input to look like: Windows: 0: name='Window{565cbb2 u0 ScreenDecorOverlayBottom}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x21800128, type=0x000007e8, frame=[0,2883][1440,3040], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=, inputFeatures=0x00000000, ownerPid=4114, ownerUid=10201, dispatchingTimeout=5000.000ms flags: NOT_FOCUSABLE | NOT_TOUCH_MODAL | LAYOUT_IN_SCREEN | SPLIT_TOUCH | HARDWARE_ACCELERATED | SLIPPERY | 1: name='Window{427d84e u0 ScreenDecorOverlay}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x21800128, type=0x000007e8, frame=[0,0][1440,157], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=, inputFeatures=0x00000000, ownerPid=4114, ownerUid=10201, dispatchingTimeout=5000.000ms flags: NOT_FOCUSABLE | NOT_TOUCH_MODAL | LAYOUT_IN_SCREEN | SPLIT_TOUCH | HARDWARE_ACCELERATED | SLIPPERY | 2: name='Window{66c2ce u0 NavigationBar0}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x21840068, type=0x000007e3, frame=[0,2872][1440,3040], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=, inputFeatures=0x00000000, ownerPid=4114, ownerUid=10201, dispatchingTimeout=5000.000ms flags: NOT_FOCUSABLE | NOT_TOUCH_MODAL | TOUCHABLE_WHEN_WAKING | WATCH_OUTSIDE_TOUCH | SPLIT_TOUCH | HARDWARE_ACCELERATED | SLIPPERY | 3: name='Window{9de0939 u0 NotificationShade}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=true, hasWallpaper=false, visible=true, canReceiveKeys=true, flags=0x81860060, type=0x000007f8, frame=[0,0][1440,3040], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[-1440,-3040][2880,6080], inputFeatures=0x00000004, ownerPid=4114, ownerUid=10201, dispatchingTimeout=5000.000ms flags: NOT_TOUCH_MODAL | TOUCHABLE_WHEN_WAKING | ALT_FOCUSABLE_IM | WATCH_OUTSIDE_TOUCH | SPLIT_TOUCH | HARDWARE_ACCELERATED | DRAWS_SYSTEM_BAR_BACKGROUNDS | Bug: none Test: dumpsys input Change-Id: I7065fda194adb0bf63126c6b3647f3af0f5ca1ba --- include/input/InputWindow.h | 40 ++++--- libs/input/InputWindow.cpp | 115 ++++++++++++++++++++- .../inputflinger/dispatcher/InputDispatcher.cpp | 3 + 3 files changed, 141 insertions(+), 17 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index aa85e6d717..717b7a6d56 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -37,23 +37,23 @@ struct InputWindowInfo { InputWindowInfo(const Parcel& from); // Window flags from WindowManager.LayoutParams - enum { - FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, - FLAG_DIM_BEHIND = 0x00000002, - FLAG_BLUR_BEHIND = 0x00000004, - FLAG_NOT_FOCUSABLE = 0x00000008, - FLAG_NOT_TOUCHABLE = 0x00000010, - FLAG_NOT_TOUCH_MODAL = 0x00000020, + enum : uint32_t { + FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, + FLAG_DIM_BEHIND = 0x00000002, + FLAG_BLUR_BEHIND = 0x00000004, + FLAG_NOT_FOCUSABLE = 0x00000008, + FLAG_NOT_TOUCHABLE = 0x00000010, + FLAG_NOT_TOUCH_MODAL = 0x00000020, FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040, - FLAG_KEEP_SCREEN_ON = 0x00000080, - FLAG_LAYOUT_IN_SCREEN = 0x00000100, - FLAG_LAYOUT_NO_LIMITS = 0x00000200, - FLAG_FULLSCREEN = 0x00000400, - FLAG_FORCE_NOT_FULLSCREEN = 0x00000800, - FLAG_DITHER = 0x00001000, - FLAG_SECURE = 0x00002000, - FLAG_SCALED = 0x00004000, - FLAG_IGNORE_CHEEK_PRESSES = 0x00008000, + FLAG_KEEP_SCREEN_ON = 0x00000080, + FLAG_LAYOUT_IN_SCREEN = 0x00000100, + FLAG_LAYOUT_NO_LIMITS = 0x00000200, + FLAG_FULLSCREEN = 0x00000400, + FLAG_FORCE_NOT_FULLSCREEN = 0x00000800, + FLAG_DITHER = 0x00001000, + FLAG_SECURE = 0x00002000, + FLAG_SCALED = 0x00004000, + FLAG_IGNORE_CHEEK_PRESSES = 0x00008000, FLAG_LAYOUT_INSET_DECOR = 0x00010000, FLAG_ALT_FOCUSABLE_IM = 0x00020000, FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000, @@ -62,7 +62,14 @@ struct InputWindowInfo { FLAG_TURN_SCREEN_ON = 0x00200000, FLAG_DISMISS_KEYGUARD = 0x00400000, FLAG_SPLIT_TOUCH = 0x00800000, + FLAG_HARDWARE_ACCELERATED = 0x01000000, + FLAG_LAYOUT_IN_OVERSCAN = 0x02000000, + FLAG_TRANSLUCENT_STATUS = 0x04000000, + FLAG_TRANSLUCENT_NAVIGATION = 0x08000000, + FLAG_LOCAL_FOCUS_MODE = 0x10000000, FLAG_SLIPPERY = 0x20000000, + FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000, + FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000, }; // Window types from WindowManager.LayoutParams @@ -191,6 +198,7 @@ struct InputWindowInfo { static InputWindowInfo read(const Parcel& from); }; +std::string inputWindowFlagsToString(uint32_t flags); /* * Handle for a window that can receive input. diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 28da8b4f3b..99b718bae3 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -17,9 +17,10 @@ #define LOG_TAG "InputWindow" #define LOG_NDEBUG 0 +#include #include -#include #include +#include #include @@ -28,6 +29,118 @@ namespace android { +const char* inputWindowFlagToString(uint32_t flag) { + switch (flag) { + case InputWindowInfo::FLAG_ALLOW_LOCK_WHILE_SCREEN_ON: { + return "ALLOW_LOCK_WHILE_SCREEN_ON"; + } + case InputWindowInfo::FLAG_DIM_BEHIND: { + return "DIM_BEHIND"; + } + case InputWindowInfo::FLAG_BLUR_BEHIND: { + return "BLUR_BEHIND"; + } + case InputWindowInfo::FLAG_NOT_FOCUSABLE: { + return "NOT_FOCUSABLE"; + } + case InputWindowInfo::FLAG_NOT_TOUCHABLE: { + return "NOT_TOUCHABLE"; + } + case InputWindowInfo::FLAG_NOT_TOUCH_MODAL: { + return "NOT_TOUCH_MODAL"; + } + case InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING: { + return "TOUCHABLE_WHEN_WAKING"; + } + case InputWindowInfo::FLAG_KEEP_SCREEN_ON: { + return "KEEP_SCREEN_ON"; + } + case InputWindowInfo::FLAG_LAYOUT_IN_SCREEN: { + return "LAYOUT_IN_SCREEN"; + } + case InputWindowInfo::FLAG_LAYOUT_NO_LIMITS: { + return "LAYOUT_NO_LIMITS"; + } + case InputWindowInfo::FLAG_FULLSCREEN: { + return "FULLSCREEN"; + } + case InputWindowInfo::FLAG_FORCE_NOT_FULLSCREEN: { + return "FORCE_NOT_FULLSCREEN"; + } + case InputWindowInfo::FLAG_DITHER: { + return "DITHER"; + } + case InputWindowInfo::FLAG_SECURE: { + return "SECURE"; + } + case InputWindowInfo::FLAG_SCALED: { + return "SCALED"; + } + case InputWindowInfo::FLAG_IGNORE_CHEEK_PRESSES: { + return "IGNORE_CHEEK_PRESSES"; + } + case InputWindowInfo::FLAG_LAYOUT_INSET_DECOR: { + return "LAYOUT_INSET_DECOR"; + } + case InputWindowInfo::FLAG_ALT_FOCUSABLE_IM: { + return "ALT_FOCUSABLE_IM"; + } + case InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH: { + return "WATCH_OUTSIDE_TOUCH"; + } + case InputWindowInfo::FLAG_SHOW_WHEN_LOCKED: { + return "SHOW_WHEN_LOCKED"; + } + case InputWindowInfo::FLAG_SHOW_WALLPAPER: { + return "SHOW_WALLPAPER"; + } + case InputWindowInfo::FLAG_TURN_SCREEN_ON: { + return "TURN_SCREEN_ON"; + } + case InputWindowInfo::FLAG_DISMISS_KEYGUARD: { + return "DISMISS_KEYGUARD"; + } + case InputWindowInfo::FLAG_SPLIT_TOUCH: { + return "SPLIT_TOUCH"; + } + case InputWindowInfo::FLAG_HARDWARE_ACCELERATED: { + return "HARDWARE_ACCELERATED"; + } + case InputWindowInfo::FLAG_LAYOUT_IN_OVERSCAN: { + return "LAYOUT_IN_OVERSCAN"; + } + case InputWindowInfo::FLAG_TRANSLUCENT_STATUS: { + return "TRANSLUCENT_STATUS"; + } + case InputWindowInfo::FLAG_TRANSLUCENT_NAVIGATION: { + return "TRANSLUCENT_NAVIGATION"; + } + case InputWindowInfo::FLAG_LOCAL_FOCUS_MODE: { + return "LOCAL_FOCUS_MODE"; + } + case InputWindowInfo::FLAG_SLIPPERY: { + return "SLIPPERY"; + } + case InputWindowInfo::FLAG_LAYOUT_ATTACHED_IN_DECOR: { + return "LAYOUT_ATTACHED_IN_DECOR"; + } + case InputWindowInfo::FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS: { + return "DRAWS_SYSTEM_BAR_BACKGROUNDS"; + } + } + return "UNKNOWN"; +} + +std::string inputWindowFlagsToString(uint32_t flags) { + std::string result; + for (BitSet32 bits(flags); !bits.isEmpty();) { + uint32_t bit = bits.clearLastMarkedBit(); // counts from left + const uint32_t flag = 1 << (32 - bit - 1); + result += android::base::StringPrintf("%s | ", inputWindowFlagToString(flag)); + } + return result; +} + // --- InputWindowInfo --- void InputWindowInfo::addTouchableRegion(const Rect& region) { touchableRegion.orSelf(region); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8942433c00..a3ec3b0e9e 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -4101,6 +4101,9 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", windowInfo->ownerPid, windowInfo->ownerUid, windowInfo->dispatchingTimeout / 1000000.0); + dump += StringPrintf(INDENT4 " flags: %s\n", + inputWindowFlagsToString(windowInfo->layoutParamsFlags) + .c_str()); } } else { dump += INDENT2 "Windows: \n"; -- cgit v1.2.3-59-g8ed1b From 599042ff56b9f13bb842ff687875652a2cd98603 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Mon, 4 May 2020 16:24:58 +0800 Subject: Makes TYPE_NOTIFICATION_SHADE as trusted overlay Fix the side effect after we split notification_shade window from status bar. Bug: 155373298 Test: follow the steps from b/149320322 Change-Id: I3362186b22505d21ec6e0ad779d4a26304ed782c --- include/input/InputWindow.h | 79 +++++++++++++++++++++++---------------------- libs/input/InputWindow.cpp | 21 ++++++------ 2 files changed, 50 insertions(+), 50 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index a258a6771f..98518e0fe8 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -75,47 +75,48 @@ struct InputWindowInfo { // Window types from WindowManager.LayoutParams enum { FIRST_APPLICATION_WINDOW = 1, - TYPE_BASE_APPLICATION = 1, - TYPE_APPLICATION = 2, + TYPE_BASE_APPLICATION = 1, + TYPE_APPLICATION = 2, TYPE_APPLICATION_STARTING = 3, LAST_APPLICATION_WINDOW = 99, - FIRST_SUB_WINDOW = 1000, - TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, - TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1, - TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2, - TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3, - TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4, - LAST_SUB_WINDOW = 1999, - FIRST_SYSTEM_WINDOW = 2000, - TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, - TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1, - TYPE_PHONE = FIRST_SYSTEM_WINDOW+2, - TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3, - TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4, - TYPE_TOAST = FIRST_SYSTEM_WINDOW+5, - TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6, - TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7, - TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8, - TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9, - TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10, - TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11, - TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12, - TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13, - TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14, - TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15, - TYPE_DRAG = FIRST_SYSTEM_WINDOW+16, - TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17, - TYPE_POINTER = FIRST_SYSTEM_WINDOW+18, - TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19, - TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20, - TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21, - TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22, - TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24, - TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27, - TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32, - TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34, - TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+39, - LAST_SYSTEM_WINDOW = 2999, + FIRST_SUB_WINDOW = 1000, + TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, + TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1, + TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2, + TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3, + TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4, + LAST_SUB_WINDOW = 1999, + FIRST_SYSTEM_WINDOW = 2000, + TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, + TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1, + TYPE_PHONE = FIRST_SYSTEM_WINDOW + 2, + TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3, + TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW + 4, + TYPE_TOAST = FIRST_SYSTEM_WINDOW + 5, + TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6, + TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7, + TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8, + TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9, + TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10, + TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11, + TYPE_INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12, + TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW + 13, + TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14, + TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15, + TYPE_DRAG = FIRST_SYSTEM_WINDOW + 16, + TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17, + TYPE_POINTER = FIRST_SYSTEM_WINDOW + 18, + TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19, + TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20, + TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21, + TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22, + TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24, + TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27, + TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, + TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, + TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39, + TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, + LAST_SYSTEM_WINDOW = 2999, }; enum { diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 998cef6268..d7f8ae5d12 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -156,17 +156,16 @@ bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { } bool InputWindowInfo::isTrustedOverlay() const { - return layoutParamsType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY - || layoutParamsType == TYPE_INPUT_METHOD - || layoutParamsType == TYPE_INPUT_METHOD_DIALOG - || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY - || layoutParamsType == TYPE_STATUS_BAR - || layoutParamsType == TYPE_NAVIGATION_BAR - || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL - || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY - || layoutParamsType == TYPE_DOCK_DIVIDER - || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY - || layoutParamsType == TYPE_INPUT_CONSUMER; + return layoutParamsType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY || + layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG || + layoutParamsType == TYPE_MAGNIFICATION_OVERLAY || layoutParamsType == TYPE_STATUS_BAR || + layoutParamsType == TYPE_NOTIFICATION_SHADE || + layoutParamsType == TYPE_NAVIGATION_BAR || + layoutParamsType == TYPE_NAVIGATION_BAR_PANEL || + layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY || + layoutParamsType == TYPE_DOCK_DIVIDER || + layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY || + layoutParamsType == TYPE_INPUT_CONSUMER; } bool InputWindowInfo::supportsSplitTouch() const { -- cgit v1.2.3-59-g8ed1b From fcdff3e735ced7d15d4cf19681c5c3b8613c299f Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Sun, 10 May 2020 15:16:04 -0700 Subject: Change InputWindowInfo::isTrustedOverlay() to be permission and flag based. Add private flag to WindowManager.LayoutParams. If the flag is set, check if caller has INTERNAL_SYSTEM_WINDOW permission. Bug: 155781676 Test: atest WindowManagerServiceTests Change-Id: I58cf9f38c496e0ae8b2193dca45c0805e831bc9e --- include/input/InputWindow.h | 16 ++++++++-------- libs/input/InputWindow.cpp | 17 ++--------------- services/inputflinger/dispatcher/InputDispatcher.cpp | 2 +- 3 files changed, 11 insertions(+), 24 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index f2841ea4e6..231c9fbd83 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -116,7 +116,6 @@ struct InputWindowInfo { TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39, TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, - TYPE_TRUSTED_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 42, LAST_SYSTEM_WINDOW = 2999, }; @@ -171,6 +170,12 @@ struct InputWindowInfo { bool hasFocus = 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; int32_t ownerPid = -1; int32_t ownerUid = -1; int32_t inputFeatures = 0; @@ -183,20 +188,15 @@ struct InputWindowInfo { void addTouchableRegion(const Rect& region); bool touchableRegionContainsPoint(int32_t x, int32_t y) const; - bool frameContainsPoint(int32_t x, int32_t y) const; - /* Returns true if 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 isTrustedOverlay() const; + bool frameContainsPoint(int32_t x, int32_t y) const; bool supportsSplitTouch() const; bool overlaps(const InputWindowInfo* other) const; status_t write(Parcel& output) const; + static InputWindowInfo read(const Parcel& from); }; diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 3d3bec8ba4..04550227e3 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -155,21 +155,6 @@ bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { && y >= frameTop && y < frameBottom; } -// TODO(b/155781676): Remove and replace call points with trustedOverlay when that is ready. -bool InputWindowInfo::isTrustedOverlay() const { - return layoutParamsType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY || - layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG || - layoutParamsType == TYPE_MAGNIFICATION_OVERLAY || layoutParamsType == TYPE_STATUS_BAR || - layoutParamsType == TYPE_NOTIFICATION_SHADE || - layoutParamsType == TYPE_NAVIGATION_BAR || - layoutParamsType == TYPE_NAVIGATION_BAR_PANEL || - layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY || - layoutParamsType == TYPE_DOCK_DIVIDER || - layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY || - layoutParamsType == TYPE_INPUT_CONSUMER || - layoutParamsType == TYPE_TRUSTED_APPLICATION_OVERLAY; -} - bool InputWindowInfo::supportsSplitTouch() const { return layoutParamsFlags & FLAG_SPLIT_TOUCH; } @@ -206,6 +191,7 @@ status_t InputWindowInfo::write(Parcel& output) const { output.writeBool(hasFocus); output.writeBool(hasWallpaper); output.writeBool(paused); + output.writeBool(trustedOverlay); output.writeInt32(ownerPid); output.writeInt32(ownerUid); output.writeInt32(inputFeatures); @@ -244,6 +230,7 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) { ret.hasFocus = from.readBool(); ret.hasWallpaper = from.readBool(); ret.paused = from.readBool(); + ret.trustedOverlay = from.readBool(); ret.ownerPid = from.readInt32(); ret.ownerUid = from.readInt32(); ret.inputFeatures = from.readInt32(); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 1d5870a6ca..6d8f0367c9 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1969,7 +1969,7 @@ static bool canBeObscuredBy(const sp& windowHandle, // windows with an input channel from the same PID as occluding, and so we // preserve this behavior with the getToken() == null check. return false; - } else if (otherInfo->isTrustedOverlay()) { + } else if (otherInfo->trustedOverlay) { return false; } else if (otherInfo->displayId != info->displayId) { return false; -- cgit v1.2.3-59-g8ed1b From c1ae5568e5d6b39499f0c46e7f5ae2a8759d2ecd Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Tue, 30 Jun 2020 14:22:57 -0500 Subject: Use chrono for dispatching timeout To prevent confusion about the units of dispatchingTimeout, convert to chrono. Bug: 155931890 Test: atest inputflinger_tests Change-Id: Icfcb3bad7188052a6b047b3cbe836be8d928fad2 --- include/input/InputApplication.h | 6 +--- include/input/InputWindow.h | 6 +--- libs/gui/tests/EndToEndNativeInputTest.cpp | 4 +-- libs/input/InputApplication.cpp | 6 ++-- libs/input/InputWindow.cpp | 4 +-- libs/input/tests/InputWindow_test.cpp | 4 ++- .../benchmarks/InputDispatcher_benchmarks.cpp | 40 ++++++++++------------ .../inputflinger/dispatcher/InputDispatcher.cpp | 34 +++++++++--------- services/inputflinger/dispatcher/InputDispatcher.h | 4 +-- .../include/InputDispatcherPolicyInterface.h | 5 +-- .../inputflinger/tests/InputDispatcher_test.cpp | 15 ++++---- 11 files changed, 61 insertions(+), 67 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h index 86de394a31..ccffeb1327 100644 --- a/include/input/InputApplication.h +++ b/include/input/InputApplication.h @@ -34,7 +34,7 @@ namespace android { struct InputApplicationInfo { sp token; std::string name; - nsecs_t dispatchingTimeout; + std::chrono::nanoseconds dispatchingTimeout; status_t write(Parcel& output) const; static InputApplicationInfo read(const Parcel& from); @@ -57,10 +57,6 @@ public: return !mInfo.name.empty() ? mInfo.name : ""; } - inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const { - return mInfo.token ? mInfo.dispatchingTimeout : defaultValue; - } - inline std::chrono::nanoseconds getDispatchingTimeout( std::chrono::nanoseconds defaultValue) const { return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue; diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 6740855791..f8c759c85d 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -136,7 +136,7 @@ struct InputWindowInfo { std::string name; int32_t layoutParamsFlags = 0; int32_t layoutParamsType = 0; - nsecs_t dispatchingTimeout = -1; + std::chrono::nanoseconds dispatchingTimeout = std::chrono::seconds(5); /* These values are filled in by SurfaceFlinger. */ int32_t frameLeft = -1; @@ -227,10 +227,6 @@ public: return !mInfo.name.empty() ? mInfo.name : ""; } - inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const { - return mInfo.token ? mInfo.dispatchingTimeout : defaultValue; - } - inline std::chrono::nanoseconds getDispatchingTimeout( std::chrono::nanoseconds defaultValue) const { return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index b1d3ecbf36..32c7fc2588 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -189,7 +189,7 @@ private: mInputInfo.name = "Test info"; mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION; - mInputInfo.dispatchingTimeout = seconds_to_nanoseconds(5); + mInputInfo.dispatchingTimeout = 5s; mInputInfo.globalScaleFactor = 1.0; mInputInfo.canReceiveKeys = true; mInputInfo.hasFocus = true; @@ -207,7 +207,7 @@ private: InputApplicationInfo aInfo; aInfo.token = new BBinder(); aInfo.name = "Test app info"; - aInfo.dispatchingTimeout = seconds_to_nanoseconds(5); + aInfo.dispatchingTimeout = 5s; mInputInfo.applicationInfo = aInfo; } diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp index 1d9f8a7091..c745c24c66 100644 --- a/libs/input/InputApplication.cpp +++ b/libs/input/InputApplication.cpp @@ -34,7 +34,7 @@ InputApplicationInfo InputApplicationInfo::read(const Parcel& from) { InputApplicationInfo ret; ret.token = from.readStrongBinder(); ret.name = from.readString8().c_str(); - ret.dispatchingTimeout = from.readInt64(); + ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); return ret; } @@ -42,8 +42,8 @@ InputApplicationInfo InputApplicationInfo::read(const Parcel& from) { status_t InputApplicationInfo::write(Parcel& output) const { output.writeStrongBinder(token); output.writeString8(String8(name.c_str())); - output.writeInt64(dispatchingTimeout); - + output.writeInt64(dispatchingTimeout.count()); + return OK; } diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 04550227e3..3700e8f0f8 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -177,7 +177,7 @@ status_t InputWindowInfo::write(Parcel& output) const { output.writeString8(String8(name.c_str())); output.writeInt32(layoutParamsFlags); output.writeInt32(layoutParamsType); - output.writeInt64(dispatchingTimeout); + output.writeInt64(dispatchingTimeout.count()); output.writeInt32(frameLeft); output.writeInt32(frameTop); output.writeInt32(frameRight); @@ -216,7 +216,7 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) { ret.name = from.readString8().c_str(); ret.layoutParamsFlags = from.readInt32(); ret.layoutParamsType = from.readInt32(); - ret.dispatchingTimeout = from.readInt64(); + ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); ret.frameLeft = from.readInt32(); ret.frameTop = from.readInt32(); ret.frameRight = from.readInt32(); diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index d1cb527a57..87505323c3 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -22,6 +22,8 @@ #include #include +using std::chrono_literals::operator""s; + namespace android { namespace test { @@ -44,7 +46,7 @@ TEST(InputWindowInfo, Parcelling) { i.name = "Foobar"; i.layoutParamsFlags = 7; i.layoutParamsType = 39; - i.dispatchingTimeout = 12; + i.dispatchingTimeout = 12s; i.frameLeft = 93; i.frameTop = 34; i.frameRight = 16; diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 5a14133eb2..7d8ab753f3 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -45,49 +45,45 @@ protected: virtual ~FakeInputDispatcherPolicy() {} private: - virtual void notifyConfigurationChanged(nsecs_t) override {} + void notifyConfigurationChanged(nsecs_t) override {} - virtual nsecs_t notifyAnr(const sp&, const sp&, - const std::string& name) override { + std::chrono::nanoseconds notifyAnr(const sp&, const sp&, + const std::string& name) override { ALOGE("The window is not responding : %s", name.c_str()); - return 0; + return 0s; } - virtual void notifyInputChannelBroken(const sp&) override {} + void notifyInputChannelBroken(const sp&) override {} - virtual void notifyFocusChanged(const sp&, const sp&) override {} + void notifyFocusChanged(const sp&, const sp&) override {} - virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override { + void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override { *outConfig = mConfig; } - virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override { + bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override { return true; } - virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {} + void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {} - virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {} + void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {} - virtual nsecs_t interceptKeyBeforeDispatching(const sp&, const KeyEvent*, - uint32_t) override { + nsecs_t interceptKeyBeforeDispatching(const sp&, const KeyEvent*, uint32_t) override { return 0; } - virtual bool dispatchUnhandledKey(const sp&, const KeyEvent*, uint32_t, - KeyEvent*) override { + bool dispatchUnhandledKey(const sp&, const KeyEvent*, uint32_t, KeyEvent*) override { return false; } - virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) override {} + void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) override {} - virtual void pokeUserActivity(nsecs_t, int32_t) override {} + void pokeUserActivity(nsecs_t, int32_t) override {} - virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { - return false; - } + bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; } - virtual void onPointerDownOutsideFocus(const sp& newToken) override {} + void onPointerDownOutsideFocus(const sp& newToken) override {} InputDispatcherConfiguration mConfig; }; @@ -98,7 +94,7 @@ public: virtual ~FakeApplicationHandle() {} virtual bool updateInfo() { - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; return true; } }; @@ -163,7 +159,7 @@ public: mInfo.name = "FakeWindowHandle"; mInfo.layoutParamsFlags = 0; mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; mInfo.frameLeft = mFrame.left; mInfo.frameTop = mFrame.top; mInfo.frameRight = mFrame.right; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 14f7caf671..0fa2332e40 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -159,6 +159,10 @@ static bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t po } } +static int64_t millis(std::chrono::nanoseconds t) { + return std::chrono::duration_cast(t).count(); +} + static bool validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCount, const PointerProperties* pointerProperties) { if (!isValidMotionAction(action, actionButton, pointerCount)) { @@ -1473,13 +1477,13 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) { if (!mNoFocusedWindowTimeoutTime.has_value()) { // We just discovered that there's no focused window. Start the ANR timer - const nsecs_t timeout = focusedApplicationHandle->getDispatchingTimeout( - DEFAULT_INPUT_DISPATCHING_TIMEOUT.count()); - mNoFocusedWindowTimeoutTime = currentTime + timeout; + std::chrono::nanoseconds timeout = focusedApplicationHandle->getDispatchingTimeout( + DEFAULT_INPUT_DISPATCHING_TIMEOUT); + mNoFocusedWindowTimeoutTime = currentTime + timeout.count(); mAwaitedFocusedApplication = focusedApplicationHandle; ALOGW("Waiting because no window has focus but %s may eventually add a " "window when it finishes starting up. Will wait for %" PRId64 "ms", - mAwaitedFocusedApplication->getName().c_str(), ns2ms(timeout)); + mAwaitedFocusedApplication->getName().c_str(), millis(timeout)); *nextWakeupTime = *mNoFocusedWindowTimeoutTime; return INPUT_EVENT_INJECTION_PENDING; } else if (currentTime > *mNoFocusedWindowTimeoutTime) { @@ -4063,13 +4067,11 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { for (auto& it : mFocusedApplicationHandlesByDisplay) { const int32_t displayId = it.first; const sp& applicationHandle = it.second; + const int64_t timeoutMillis = millis( + applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT)); dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s', dispatchingTimeout=%" PRId64 "ms\n", - displayId, applicationHandle->getName().c_str(), - ns2ms(applicationHandle - ->getDispatchingTimeout( - DEFAULT_INPUT_DISPATCHING_TIMEOUT) - .count())); + displayId, applicationHandle->getName().c_str(), timeoutMillis); } } else { dump += StringPrintf(INDENT "FocusedApplications: \n"); @@ -4152,7 +4154,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%" PRId64 "ms\n", windowInfo->ownerPid, windowInfo->ownerUid, - ns2ms(windowInfo->dispatchingTimeout)); + millis(windowInfo->dispatchingTimeout)); dump += StringPrintf(INDENT4 " flags: %s\n", inputWindowFlagsToString(windowInfo->layoutParamsFlags) .c_str()); @@ -4653,12 +4655,12 @@ void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) commandEntry->inputChannel ? commandEntry->inputChannel->getConnectionToken() : nullptr; mLock.unlock(); - const nsecs_t timeoutExtension = + const std::chrono::nanoseconds timeoutExtension = mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason); mLock.lock(); - if (timeoutExtension > 0) { + if (timeoutExtension > 0s) { extendAnrTimeoutsLocked(commandEntry->inputApplicationHandle, token, timeoutExtension); } else { // stop waking up for events in this connection, it is already not responding @@ -4672,12 +4674,12 @@ void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) void InputDispatcher::extendAnrTimeoutsLocked(const sp& application, const sp& connectionToken, - nsecs_t timeoutExtension) { + std::chrono::nanoseconds timeoutExtension) { sp connection = getConnectionLocked(connectionToken); if (connection == nullptr) { if (mNoFocusedWindowTimeoutTime.has_value() && application != nullptr) { // Maybe ANR happened because there's no focused window? - mNoFocusedWindowTimeoutTime = now() + timeoutExtension; + mNoFocusedWindowTimeoutTime = now() + timeoutExtension.count(); mAwaitedFocusedApplication = application; } else { // It's also possible that the connection already disappeared. No action necessary. @@ -4686,10 +4688,10 @@ void InputDispatcher::extendAnrTimeoutsLocked(const sp& } ALOGI("Raised ANR, but the policy wants to keep waiting on %s for %" PRId64 "ms longer", - connection->inputChannel->getName().c_str(), ns2ms(timeoutExtension)); + connection->inputChannel->getName().c_str(), millis(timeoutExtension)); connection->responsive = true; - const nsecs_t newTimeout = now() + timeoutExtension; + const nsecs_t newTimeout = now() + timeoutExtension.count(); for (DispatchEntry* entry : connection->waitQueue) { if (newTimeout >= entry->timeoutTime) { // Already removed old entries when connection was marked unresponsive diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index e679c6b06f..42583bcabe 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -374,8 +374,8 @@ private: // prevent unneeded wakeups. AnrTracker mAnrTracker GUARDED_BY(mLock); void extendAnrTimeoutsLocked(const sp& application, - const sp& connectionToken, nsecs_t timeoutExtension) - REQUIRES(mLock); + const sp& connectionToken, + std::chrono::nanoseconds timeoutExtension) REQUIRES(mLock); // Contains the last window which received a hover event. sp mLastHoverWindowHandle GUARDED_BY(mLock); diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 667af9bbd8..21255dd0d6 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -47,8 +47,9 @@ public: /* Notifies the system that an application is not responding. * Returns a new timeout to continue waiting, or 0 to abort dispatch. */ - virtual nsecs_t notifyAnr(const sp& inputApplicationHandle, - const sp& token, const std::string& reason) = 0; + virtual std::chrono::nanoseconds notifyAnr( + const sp& inputApplicationHandle, const sp& token, + const std::string& reason) = 0; /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp& token) = 0; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index ea4d885ed5..cf5a3ab32c 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -198,13 +198,14 @@ private: mConfigurationChangedTime = when; } - virtual nsecs_t notifyAnr(const sp& application, - const sp& windowToken, const std::string&) override { + std::chrono::nanoseconds notifyAnr(const sp& application, + const sp& windowToken, + const std::string&) override { std::scoped_lock lock(mLock); mAnrApplications.push(application); mAnrWindowTokens.push(windowToken); mNotifyAnr.notify_all(); - return mAnrTimeout.count(); + return mAnrTimeout; } virtual void notifyInputChannelBroken(const sp&) override {} @@ -585,7 +586,7 @@ public: FakeApplicationHandle() { mInfo.name = "Fake Application"; mInfo.token = new BBinder(); - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; } virtual ~FakeApplicationHandle() {} @@ -594,7 +595,7 @@ public: } void setDispatchingTimeout(std::chrono::nanoseconds timeout) { - mInfo.dispatchingTimeout = timeout.count(); + mInfo.dispatchingTimeout = timeout; } }; @@ -767,7 +768,7 @@ public: mInfo.name = name; mInfo.layoutParamsFlags = 0; mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count(); + mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; mInfo.frameLeft = 0; mInfo.frameTop = 0; mInfo.frameRight = WIDTH; @@ -791,7 +792,7 @@ public: void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; } void setDispatchingTimeout(std::chrono::nanoseconds timeout) { - mInfo.dispatchingTimeout = timeout.count(); + mInfo.dispatchingTimeout = timeout; } void setPaused(bool paused) { mInfo.paused = paused; } -- cgit v1.2.3-59-g8ed1b From 0783e99d457c9d9a3ede400bdb355ba35e828de6 Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Tue, 2 Jun 2020 21:34:49 -0700 Subject: AIDL-ize InputManager IInputFlinger interface. Use AIDL interface to define the IInputFlinger interface and replace the manual interface. Bug:155425003 Test: atest libgui_test, atest libinput_test. Change-Id: Ibad036b8ceb3a3f5c6d58f8de4ea8c79379d29b5 --- include/input/IInputFlinger.h | 62 ---- include/input/ISetInputWindowsListener.h | 40 -- include/input/InputApplication.h | 12 +- include/input/InputTransport.h | 49 ++- include/input/InputWindow.h | 35 +- libs/gui/LayerState.cpp | 6 +- libs/gui/SurfaceComposerClient.cpp | 2 +- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/tests/EndToEndNativeInputTest.cpp | 13 +- libs/input/Android.bp | 9 +- libs/input/IInputFlinger.cpp | 101 ----- libs/input/ISetInputWindowsListener.cpp | 53 --- libs/input/InputApplication.cpp | 41 ++- libs/input/InputTransport.cpp | 67 ++-- libs/input/InputWindow.cpp | 185 ++++++---- libs/input/android/InputChannelInfo.aidl | 20 + libs/input/android/InputWindowInfo.aidl | 20 + libs/input/android/os/IInputFlinger.aidl | 30 ++ .../input/android/os/ISetInputWindowsListener.aidl | 23 ++ libs/input/tests/InputChannel_test.cpp | 32 ++ libs/input/tests/InputWindow_test.cpp | 12 +- services/inputflinger/InputManager.cpp | 29 +- services/inputflinger/InputManager.h | 23 +- .../dispatcher/include/InputDispatcherInterface.h | 9 +- .../include/InputDispatcherPolicyInterface.h | 2 +- services/inputflinger/host/Android.bp | 3 +- services/inputflinger/host/InputFlinger.h | 20 +- services/inputflinger/tests/Android.bp | 7 + .../inputflinger/tests/IInputFlingerQuery.aidl | 27 ++ .../tests/InputFlingerService_test.cpp | 408 +++++++++++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 40 +- services/surfaceflinger/SurfaceFlinger.h | 22 +- 32 files changed, 915 insertions(+), 489 deletions(-) delete mode 100644 include/input/IInputFlinger.h delete mode 100644 include/input/ISetInputWindowsListener.h delete mode 100644 libs/input/IInputFlinger.cpp delete mode 100644 libs/input/ISetInputWindowsListener.cpp create mode 100644 libs/input/android/InputChannelInfo.aidl create mode 100644 libs/input/android/InputWindowInfo.aidl create mode 100644 libs/input/android/os/IInputFlinger.aidl create mode 100644 libs/input/android/os/ISetInputWindowsListener.aidl create mode 100644 services/inputflinger/tests/IInputFlingerQuery.aidl create mode 100644 services/inputflinger/tests/InputFlingerService_test.cpp (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h deleted file mode 100644 index d23e3b7767..0000000000 --- a/include/input/IInputFlinger.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _LIBINPUT_IINPUT_FLINGER_H -#define _LIBINPUT_IINPUT_FLINGER_H - -#include -#include - -#include - -#include -#include - -namespace android { - -/* - * This class defines the Binder IPC interface for accessing various - * InputFlinger features. - */ -class IInputFlinger : public IInterface { -public: - DECLARE_META_INTERFACE(InputFlinger) - - virtual void setInputWindows(const std::vector& inputHandles, - const sp& setInputWindowsListener) = 0; - virtual void registerInputChannel(const sp& channel) = 0; - virtual void unregisterInputChannel(const sp& channel) = 0; -}; - - -/** - * Binder implementation. - */ -class BnInputFlinger : public BnInterface { -public: - enum { - SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, - REGISTER_INPUT_CHANNEL_TRANSACTION, - UNREGISTER_INPUT_CHANNEL_TRANSACTION - }; - - virtual status_t onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags = 0); -}; - -} // namespace android - -#endif // _LIBINPUT_IINPUT_FLINGER_H diff --git a/include/input/ISetInputWindowsListener.h b/include/input/ISetInputWindowsListener.h deleted file mode 100644 index 15d31b25c1..0000000000 --- a/include/input/ISetInputWindowsListener.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -namespace android { - -class ISetInputWindowsListener : public IInterface { -public: - DECLARE_META_INTERFACE(SetInputWindowsListener) - virtual void onSetInputWindowsFinished() = 0; -}; - -class BnSetInputWindowsListener: public BnInterface { -public: - enum SetInputWindowsTag : uint32_t { - ON_SET_INPUT_WINDOWS_FINISHED - }; - - virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags = 0) override; -}; - -}; // namespace android diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h index ccffeb1327..b6b935329b 100644 --- a/include/input/InputApplication.h +++ b/include/input/InputApplication.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -31,15 +32,17 @@ namespace android { /* * Describes the properties of an application that can receive input. */ -struct InputApplicationInfo { +struct InputApplicationInfo : public Parcelable { sp token; std::string name; std::chrono::nanoseconds dispatchingTimeout; - status_t write(Parcel& output) const; - static InputApplicationInfo read(const Parcel& from); -}; + InputApplicationInfo() = default; + + status_t readFromParcel(const android::Parcel* parcel) override; + status_t writeToParcel(android::Parcel* parcel) const override; +}; /* * Handle for an application that can receive input. @@ -76,6 +79,7 @@ public: * Returns true on success, or false if the handle is no longer valid. */ virtual bool updateInfo() = 0; + protected: InputApplicationHandle(); virtual ~InputApplicationHandle(); diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 7ca9031f77..0219cf7c2a 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -34,7 +34,9 @@ #include #include +#include #include +#include #include #include #include @@ -174,6 +176,18 @@ struct InputMessage { void getSanitizedCopy(InputMessage* msg) const; }; +struct InputChannelInfo : public Parcelable { + std::string mName; + android::base::unique_fd mFd; + sp mToken; + + InputChannelInfo() = default; + InputChannelInfo(const std::string& name, android::base::unique_fd fd, sp token) + : mName(name), mFd(std::move(fd)), mToken(token){}; + status_t readFromParcel(const android::Parcel* parcel) override; + status_t writeToParcel(android::Parcel* parcel) const override; +}; + /* * An input channel consists of a local unix domain socket used to send and receive * input messages across processes. Each channel has a descriptive name for debugging purposes. @@ -183,10 +197,10 @@ struct InputMessage { * The input channel is closed when all references to it are released. */ class InputChannel : public RefBase { -protected: +public: + InputChannel(); virtual ~InputChannel(); -public: static sp create(const std::string& name, android::base::unique_fd fd, sp token); @@ -200,8 +214,10 @@ public: static status_t openInputChannelPair(const std::string& name, sp& outServerChannel, sp& outClientChannel); - inline std::string getName() const { return mName; } - inline int getFd() const { return mFd.get(); } + inline std::string getName() const { return mInfo.mName; } + inline int getFd() const { return mInfo.mFd.get(); } + inline sp getToken() const { return mInfo.mToken; } + inline InputChannelInfo& getInfo() { return mInfo; } /* Send a message to the other endpoint. * @@ -231,8 +247,9 @@ public: /* Return a new object that has a duplicate of this channel's fd. */ sp dup() const; - status_t write(Parcel& out) const; - static sp read(const Parcel& from); + status_t readFromParcel(const android::Parcel* parcel); + + status_t writeToParcel(android::Parcel* parcel) const; /** * The connection token is used to identify the input connection, i.e. @@ -248,12 +265,23 @@ public: */ sp getConnectionToken() const; + bool operator==(const InputChannel& inputChannel) const { + struct stat lhsInfo, rhsInfo; + if (fstat(mInfo.mFd.get(), &lhsInfo) != 0) { + return false; + } + if (fstat(inputChannel.getFd(), &rhsInfo) != 0) { + return false; + } + // If file descriptors are pointing to same inode they are duplicated fds. + return inputChannel.getName() == getName() && + inputChannel.getConnectionToken() == mInfo.mToken && + lhsInfo.st_ino == rhsInfo.st_ino; + } + private: InputChannel(const std::string& name, android::base::unique_fd fd, sp token); - std::string mName; - android::base::unique_fd mFd; - - sp mToken; + InputChannelInfo mInfo; }; /* @@ -325,7 +353,6 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: - sp mChannel; }; diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index f8c759c85d..582e73d858 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -17,6 +17,8 @@ #ifndef _UI_INPUT_WINDOW_H #define _UI_INPUT_WINDOW_H +#include +#include #include #include #include @@ -27,14 +29,12 @@ #include "InputApplication.h" namespace android { -class Parcel; /* * Describes the properties of a window that can receive input. */ -struct InputWindowInfo { +struct InputWindowInfo : public Parcelable { InputWindowInfo() = default; - InputWindowInfo(const Parcel& from); // Window flags from WindowManager.LayoutParams enum : uint32_t { @@ -195,9 +195,11 @@ struct InputWindowInfo { bool overlaps(const InputWindowInfo* other) const; - status_t write(Parcel& output) const; + bool operator==(const InputWindowInfo& inputChannel) const; - static InputWindowInfo read(const Parcel& from); + status_t writeToParcel(android::Parcel* parcel) const override; + + status_t readFromParcel(const android::Parcel* parcel) override; }; std::string inputWindowFlagsToString(uint32_t flags); @@ -210,22 +212,19 @@ std::string inputWindowFlagsToString(uint32_t flags); */ class InputWindowHandle : public RefBase { public: + explicit InputWindowHandle(); + InputWindowHandle(const InputWindowHandle& other); + InputWindowHandle(const InputWindowInfo& other); - inline const InputWindowInfo* getInfo() const { - return &mInfo; - } + inline const InputWindowInfo* getInfo() const { return &mInfo; } sp getToken() const; int32_t getId() const { return mInfo.id; } - sp getApplicationToken() { - return mInfo.applicationInfo.token; - } + sp getApplicationToken() { return mInfo.applicationInfo.token; } - inline std::string getName() const { - return !mInfo.name.empty() ? mInfo.name : ""; - } + inline std::string getName() const { return !mInfo.name.empty() ? mInfo.name : ""; } inline std::chrono::nanoseconds getDispatchingTimeout( std::chrono::nanoseconds defaultValue) const { @@ -235,13 +234,14 @@ public: /** * Requests that the state of this object be updated to reflect * the most current available information about the application. + * As this class is created as RefBase object, no pure virtual function is allowed. * * This method should only be called from within the input dispatcher's * critical section. * * Returns true on success, or false if the handle is no longer valid. */ - virtual bool updateInfo() = 0; + virtual bool updateInfo() { return false; } /** * Updates from another input window handle. @@ -254,8 +254,11 @@ public: */ void releaseChannel(); + // Not override since this class is not derrived from Parcelable. + status_t readFromParcel(const android::Parcel* parcel); + status_t writeToParcel(android::Parcel* parcel) const; + protected: - explicit InputWindowHandle(); virtual ~InputWindowHandle(); InputWindowInfo mInfo; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e43446ac8c..1030b82f14 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -55,7 +55,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.g); output.writeFloat(color.b); #ifndef NO_INPUT - inputInfo.write(output); + inputHandle->writeToParcel(&output); #endif output.write(transparentRegion); output.writeUint32(transform); @@ -152,7 +152,7 @@ status_t layer_state_t::read(const Parcel& input) color.b = input.readFloat(); #ifndef NO_INPUT - inputInfo = InputWindowInfo::read(input); + inputHandle->readFromParcel(&input); #endif input.read(transparentRegion); @@ -404,7 +404,7 @@ void layer_state_t::merge(const layer_state_t& other) { #ifndef NO_INPUT if (other.what & eInputInfoChanged) { what |= eInputInfoChanged; - inputInfo = other.inputInfo; + inputHandle = new InputWindowHandle(*other.inputHandle); } #endif diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 16b46df4f6..d797a3547a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1359,7 +1359,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput mStatus = BAD_INDEX; return *this; } - s->inputInfo = info; + s->inputHandle = new InputWindowHandle(info); s->what |= layer_state_t::eInputInfoChanged; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e60f6777ae..00ae220906 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -201,7 +201,7 @@ struct layer_state_t { mat4 colorTransform; #ifndef NO_INPUT - InputWindowInfo inputInfo; + sp inputHandle = new InputWindowHandle(); #endif client_cache_t cachedBuffer; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 32c7fc2588..152f7ad56c 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -36,15 +36,16 @@ #include #include -#include -#include -#include +#include #include +#include +#include #include #include #include +using android::os::IInputFlinger; namespace android { namespace test { @@ -71,7 +72,7 @@ public: InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); mInputFlinger = getInputFlinger(); - mInputFlinger->registerInputChannel(mServerChannel); + mInputFlinger->registerInputChannel(mServerChannel->getInfo()); populateInputInfo(width, height); @@ -153,9 +154,7 @@ public: EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } - ~InputSurface() { - mInputFlinger->unregisterInputChannel(mServerChannel); - } + ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getInfo()); } void doTransaction(std::function&)> transactionBody) { diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 7037680935..ade9c25c53 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -46,14 +46,14 @@ cc_library { target: { android: { srcs: [ - "IInputFlinger.cpp", "InputApplication.cpp", "InputTransport.cpp", "InputWindow.cpp", - "ISetInputWindowsListener.cpp", "LatencyStatistics.cpp", "VelocityControl.cpp", "VelocityTracker.cpp", + "android/os/IInputFlinger.aidl", + "android/os/ISetInputWindowsListener.aidl", ], shared_libs: [ @@ -72,6 +72,11 @@ cc_library { }, }, }, + + aidl: { + local_include_dirs: ["."], + export_aidl_headers: true + }, } subdirs = ["tests"] diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp deleted file mode 100644 index 8ec51653a8..0000000000 --- a/libs/input/IInputFlinger.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include -#include - -#include - -namespace android { - -class BpInputFlinger : public BpInterface { -public: - explicit BpInputFlinger(const sp& impl) : - BpInterface(impl) { } - - virtual void setInputWindows(const std::vector& inputInfo, - const sp& setInputWindowsListener) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - - data.writeUint32(static_cast(inputInfo.size())); - for (const auto& info : inputInfo) { - info.write(data); - } - data.writeStrongBinder(IInterface::asBinder(setInputWindowsListener)); - - remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply, - IBinder::FLAG_ONEWAY); - } - - virtual void registerInputChannel(const sp& channel) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - channel->write(data); - remote()->transact(BnInputFlinger::REGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply); - } - - virtual void unregisterInputChannel(const sp& channel) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - channel->write(data); - remote()->transact(BnInputFlinger::UNREGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply); - } -}; - -IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger"); - -status_t BnInputFlinger::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { - switch(code) { - case SET_INPUT_WINDOWS_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - size_t count = data.readUint32(); - if (count > data.dataSize()) { - return BAD_VALUE; - } - std::vector handles; - for (size_t i = 0; i < count; i++) { - handles.push_back(InputWindowInfo::read(data)); - } - const sp setInputWindowsListener = - ISetInputWindowsListener::asInterface(data.readStrongBinder()); - setInputWindows(handles, setInputWindowsListener); - break; - } - case REGISTER_INPUT_CHANNEL_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = InputChannel::read(data); - registerInputChannel(channel); - break; - } - case UNREGISTER_INPUT_CHANNEL_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = InputChannel::read(data); - unregisterInputChannel(channel); - break; - } - default: - return BBinder::onTransact(code, data, reply, flags); - } - return NO_ERROR; -} - -}; diff --git a/libs/input/ISetInputWindowsListener.cpp b/libs/input/ISetInputWindowsListener.cpp deleted file mode 100644 index a0330da89e..0000000000 --- a/libs/input/ISetInputWindowsListener.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -namespace android { - -class BpSetInputWindowsListener : public BpInterface { -public: - explicit BpSetInputWindowsListener(const sp& impl) - : BpInterface(impl) { - } - - virtual ~BpSetInputWindowsListener() = default; - - virtual void onSetInputWindowsFinished() { - Parcel data, reply; - data.writeInterfaceToken(ISetInputWindowsListener::getInterfaceDescriptor()); - remote()->transact(BnSetInputWindowsListener::ON_SET_INPUT_WINDOWS_FINISHED, data, &reply, - IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(SetInputWindowsListener, "android.input.ISetInputWindowsListener"); - -status_t BnSetInputWindowsListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags) { - switch(code) { - case ON_SET_INPUT_WINDOWS_FINISHED: { - CHECK_INTERFACE(ISetInputWindowsListener, data, reply); - onSetInputWindowsFinished(); - return NO_ERROR; - } - default: { - return BBinder::onTransact(code, data, reply, flags); - } - } -} - -} // namespace android diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp index c745c24c66..41721a7344 100644 --- a/libs/input/InputApplication.cpp +++ b/libs/input/InputApplication.cpp @@ -22,29 +22,34 @@ namespace android { -// --- InputApplicationHandle --- - -InputApplicationHandle::InputApplicationHandle() { -} - -InputApplicationHandle::~InputApplicationHandle() { +status_t InputApplicationInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + token = parcel->readStrongBinder(); + dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); + status_t status = parcel->readUtf8FromUtf16(&name); + + return status; } -InputApplicationInfo InputApplicationInfo::read(const Parcel& from) { - InputApplicationInfo ret; - ret.token = from.readStrongBinder(); - ret.name = from.readString8().c_str(); - ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); +status_t InputApplicationInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + status_t status = parcel->writeStrongBinder(token) + ?: parcel->writeInt64(dispatchingTimeout.count()) + ?: parcel->writeUtf8AsUtf16(name) ; - return ret; + return status; } -status_t InputApplicationInfo::write(Parcel& output) const { - output.writeStrongBinder(token); - output.writeString8(String8(name.c_str())); - output.writeInt64(dispatchingTimeout.count()); +// --- InputApplicationHandle --- - return OK; -} +InputApplicationHandle::InputApplicationHandle() {} + +InputApplicationHandle::~InputApplicationHandle() {} } // namespace android diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 11af23e1a2..c6043ac203 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -246,6 +246,28 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { } } +// --- InputChannelInfo --- + +status_t InputChannelInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + status_t status = parcel->writeStrongBinder(mToken) + ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd); + return status; +} + +status_t InputChannelInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + mToken = parcel->readStrongBinder(); + status_t status = parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd); + return status; +} + // --- InputChannel --- sp InputChannel::create(const std::string& name, android::base::unique_fd fd, @@ -260,15 +282,17 @@ sp InputChannel::create(const std::string& name, android::base::un } InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp token) - : mName(name), mFd(std::move(fd)), mToken(token) { + : mInfo(name, std::move(fd), token) { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), mFd.get()); + ALOGD("Input channel constructed: name='%s', fd=%d", mInfo.mName.c_str(), mInfo.mFd.get()); } } +InputChannel::InputChannel() {} + InputChannel::~InputChannel() { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); + ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd()); } } @@ -308,7 +332,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { msg->getSanitizedCopy(&cleanMsg); ssize_t nWrite; do { - nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); + nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); } while (nWrite == -1 && errno == EINTR); if (nWrite < 0) { @@ -343,7 +367,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { status_t InputChannel::receiveMessage(InputMessage* msg) { ssize_t nRead; do { - nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT); + nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT); } while (nRead == -1 && errno == EINTR); if (nRead < 0) { @@ -383,7 +407,7 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { sp InputChannel::dup() const { android::base::unique_fd newFd(::dup(getFd())); if (!newFd.ok()) { - ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), mName.c_str(), + ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding @@ -394,38 +418,19 @@ sp InputChannel::dup() const { getName().c_str()); return nullptr; } - return InputChannel::create(mName, std::move(newFd), mToken); + return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); } -status_t InputChannel::write(Parcel& out) const { - status_t s = out.writeCString(getName().c_str()); - if (s != OK) { - return s; - } - - s = out.writeStrongBinder(mToken); - if (s != OK) { - return s; - } - - s = out.writeUniqueFileDescriptor(mFd); - return s; +status_t InputChannel::writeToParcel(android::Parcel* parcel) const { + return mInfo.writeToParcel(parcel); } -sp InputChannel::read(const Parcel& from) { - std::string name = from.readCString(); - sp token = from.readStrongBinder(); - android::base::unique_fd rawFd; - status_t fdResult = from.readUniqueFileDescriptor(&rawFd); - if (fdResult != OK) { - return nullptr; - } - - return InputChannel::create(name, std::move(rawFd), token); +status_t InputChannel::readFromParcel(const android::Parcel* parcel) { + return mInfo.readFromParcel(parcel); } sp InputChannel::getConnectionToken() const { - return mToken; + return mInfo.mToken; } // --- InputPublisher --- diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 3700e8f0f8..ae9b3f0994 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -24,9 +24,6 @@ #include -#include -#include - namespace android { const char* inputWindowFlagToString(uint32_t flag) { @@ -164,96 +161,130 @@ bool InputWindowInfo::overlaps(const InputWindowInfo* other) const { && frameTop < other->frameBottom && frameBottom > other->frameTop; } -status_t InputWindowInfo::write(Parcel& output) const { +bool InputWindowInfo::operator==(const InputWindowInfo& info) const { + return info.token == token && info.id == id && info.name == name && + info.layoutParamsFlags == layoutParamsFlags && + info.layoutParamsType == layoutParamsType && + info.dispatchingTimeout == dispatchingTimeout && info.frameLeft == frameLeft && + info.frameTop == frameTop && info.frameRight == frameRight && + info.frameBottom == frameBottom && info.surfaceInset == surfaceInset && + info.globalScaleFactor == globalScaleFactor && info.windowXScale == windowXScale && + info.windowYScale == windowYScale && + info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && + info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay && + info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper && + info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.inputFeatures == inputFeatures && info.displayId == displayId && + info.portalToDisplayId == portalToDisplayId && + info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && + info.applicationInfo.name == applicationInfo.name && + info.applicationInfo.token == applicationInfo.token && + info.applicationInfo.dispatchingTimeout == applicationInfo.dispatchingTimeout; +} + +status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } if (name.empty()) { - output.writeInt32(0); + parcel->writeInt32(0); return OK; } - output.writeInt32(1); - status_t s = output.writeStrongBinder(token); - if (s != OK) return s; + parcel->writeInt32(1); - output.writeInt32(id); - output.writeString8(String8(name.c_str())); - output.writeInt32(layoutParamsFlags); - output.writeInt32(layoutParamsType); - output.writeInt64(dispatchingTimeout.count()); - output.writeInt32(frameLeft); - output.writeInt32(frameTop); - output.writeInt32(frameRight); - output.writeInt32(frameBottom); - output.writeInt32(surfaceInset); - output.writeFloat(globalScaleFactor); - output.writeFloat(windowXScale); - output.writeFloat(windowYScale); - output.writeBool(visible); - output.writeBool(canReceiveKeys); - output.writeBool(hasFocus); - output.writeBool(hasWallpaper); - output.writeBool(paused); - output.writeBool(trustedOverlay); - output.writeInt32(ownerPid); - output.writeInt32(ownerUid); - output.writeInt32(inputFeatures); - output.writeInt32(displayId); - output.writeInt32(portalToDisplayId); - applicationInfo.write(output); - output.write(touchableRegion); - output.writeBool(replaceTouchableRegionWithCrop); - output.writeStrongBinder(touchableRegionCropHandle.promote()); - return OK; -} + status_t status = parcel->writeStrongBinder(token) ?: + parcel->writeInt64(dispatchingTimeout.count()) ?: + parcel->writeInt32(id) ?: + parcel->writeUtf8AsUtf16(name) ?: + parcel->writeInt32(layoutParamsFlags) ?: + parcel->writeInt32(layoutParamsType) ?: + parcel->writeInt32(frameLeft) ?: + parcel->writeInt32(frameTop) ?: + parcel->writeInt32(frameRight) ?: + parcel->writeInt32(frameBottom) ?: + parcel->writeInt32(surfaceInset) ?: + parcel->writeFloat(globalScaleFactor) ?: + parcel->writeFloat(windowXScale) ?: + parcel->writeFloat(windowYScale) ?: + parcel->writeBool(visible) ?: + parcel->writeBool(canReceiveKeys) ?: + parcel->writeBool(hasFocus) ?: + parcel->writeBool(hasWallpaper) ?: + parcel->writeBool(paused) ?: + parcel->writeBool(trustedOverlay) ?: + parcel->writeInt32(ownerPid) ?: + parcel->writeInt32(ownerUid) ?: + parcel->writeInt32(inputFeatures) ?: + parcel->writeInt32(displayId) ?: + parcel->writeInt32(portalToDisplayId) ?: + applicationInfo.writeToParcel(parcel) ?: + parcel->write(touchableRegion) ?: + parcel->writeBool(replaceTouchableRegionWithCrop) ?: + parcel->writeStrongBinder(touchableRegionCropHandle.promote()); -InputWindowInfo InputWindowInfo::read(const Parcel& from) { - InputWindowInfo ret; + return status; +} - if (from.readInt32() == 0) { - return ret; +status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + if (parcel->readInt32() == 0) { + return OK; } - ret.token = from.readStrongBinder(); - ret.id = from.readInt32(); - ret.name = from.readString8().c_str(); - ret.layoutParamsFlags = from.readInt32(); - ret.layoutParamsType = from.readInt32(); - ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); - ret.frameLeft = from.readInt32(); - ret.frameTop = from.readInt32(); - ret.frameRight = from.readInt32(); - ret.frameBottom = from.readInt32(); - ret.surfaceInset = from.readInt32(); - ret.globalScaleFactor = from.readFloat(); - ret.windowXScale = from.readFloat(); - ret.windowYScale = from.readFloat(); - ret.visible = from.readBool(); - ret.canReceiveKeys = from.readBool(); - ret.hasFocus = from.readBool(); - ret.hasWallpaper = from.readBool(); - ret.paused = from.readBool(); - ret.trustedOverlay = from.readBool(); - ret.ownerPid = from.readInt32(); - ret.ownerUid = from.readInt32(); - ret.inputFeatures = from.readInt32(); - ret.displayId = from.readInt32(); - ret.portalToDisplayId = from.readInt32(); - ret.applicationInfo = InputApplicationInfo::read(from); - from.read(ret.touchableRegion); - ret.replaceTouchableRegionWithCrop = from.readBool(); - ret.touchableRegionCropHandle = from.readStrongBinder(); + token = parcel->readStrongBinder(); + dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); + status_t status = parcel->readInt32(&id) ?: + parcel->readUtf8FromUtf16(&name) ?: + parcel->readInt32(&layoutParamsFlags) ?: + parcel->readInt32(&layoutParamsType) ?: + parcel->readInt32(&frameLeft) ?: + parcel->readInt32(&frameTop) ?: + parcel->readInt32(&frameRight) ?: + parcel->readInt32(&frameBottom) ?: + parcel->readInt32(&surfaceInset) ?: + parcel->readFloat(&globalScaleFactor) ?: + parcel->readFloat(&windowXScale) ?: + parcel->readFloat(&windowYScale) ?: + parcel->readBool(&visible) ?: + parcel->readBool(&canReceiveKeys) ?: + parcel->readBool(&hasFocus) ?: + parcel->readBool(&hasWallpaper) ?: + parcel->readBool(&paused) ?: + parcel->readBool(&trustedOverlay) ?: + parcel->readInt32(&ownerPid) ?: + parcel->readInt32(&ownerUid) ?: + parcel->readInt32(&inputFeatures) ?: + parcel->readInt32(&displayId) ?: + parcel->readInt32(&portalToDisplayId) ?: + applicationInfo.readFromParcel(parcel) ?: + parcel->read(touchableRegion) ?: + parcel->readBool(&replaceTouchableRegionWithCrop); - return ret; -} + touchableRegionCropHandle = parcel->readStrongBinder(); -InputWindowInfo::InputWindowInfo(const Parcel& from) { - *this = read(from); + return status; } // --- InputWindowHandle --- -InputWindowHandle::InputWindowHandle() { +InputWindowHandle::InputWindowHandle() {} + +InputWindowHandle::~InputWindowHandle() {} + +InputWindowHandle::InputWindowHandle(const InputWindowHandle& other) : mInfo(other.mInfo) {} + +InputWindowHandle::InputWindowHandle(const InputWindowInfo& other) : mInfo(other) {} + +status_t InputWindowHandle::writeToParcel(android::Parcel* parcel) const { + return mInfo.writeToParcel(parcel); } -InputWindowHandle::~InputWindowHandle() { +status_t InputWindowHandle::readFromParcel(const android::Parcel* parcel) { + return mInfo.readFromParcel(parcel); } void InputWindowHandle::releaseChannel() { diff --git a/libs/input/android/InputChannelInfo.aidl b/libs/input/android/InputChannelInfo.aidl new file mode 100644 index 0000000000..2e83b966f1 --- /dev/null +++ b/libs/input/android/InputChannelInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/InputChannel.aidl +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android; + +parcelable InputChannelInfo cpp_header "input/InputTransport.h"; diff --git a/libs/input/android/InputWindowInfo.aidl b/libs/input/android/InputWindowInfo.aidl new file mode 100644 index 0000000000..eeaf400227 --- /dev/null +++ b/libs/input/android/InputWindowInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/InputChannel.aidl +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android; + +parcelable InputWindowInfo cpp_header "input/InputWindow.h"; diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl new file mode 100644 index 0000000000..8ff9dae47e --- /dev/null +++ b/libs/input/android/os/IInputFlinger.aidl @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.InputChannelInfo; +import android.InputWindowInfo; +import android.os.ISetInputWindowsListener; + +/** @hide */ +interface IInputFlinger +{ + void setInputWindows(in InputWindowInfo[] inputHandles, + in @nullable ISetInputWindowsListener setInputWindowsListener); + void registerInputChannel(in InputChannelInfo info); + void unregisterInputChannel(in InputChannelInfo info); +} diff --git a/libs/input/android/os/ISetInputWindowsListener.aidl b/libs/input/android/os/ISetInputWindowsListener.aidl new file mode 100644 index 0000000000..bb58fb671b --- /dev/null +++ b/libs/input/android/os/ISetInputWindowsListener.aidl @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** @hide */ +oneway interface ISetInputWindowsListener +{ + void onSetInputWindowsFinished(); +} diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index ada275d014..7f4bd6eac2 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -197,5 +198,36 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { } } +TEST_F(InputChannelTest, InputChannelParcelAndUnparcel) { + sp serverChannel, clientChannel; + + status_t result = + InputChannel::openInputChannelPair("channel parceling", serverChannel, clientChannel); + + ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; + + InputChannel chan; + Parcel parcel; + ASSERT_EQ(OK, serverChannel->writeToParcel(&parcel)); + parcel.setDataPosition(0); + chan.readFromParcel(&parcel); + + EXPECT_EQ(chan == *serverChannel, true) + << "inputchannel should be equal after parceling and unparceling.\n" + << "name " << chan.getName() << " name " << serverChannel->getName(); +} + +TEST_F(InputChannelTest, DuplicateChannelAndAssertEqual) { + sp serverChannel, clientChannel; + + status_t result = + InputChannel::openInputChannelPair("channel dup", serverChannel, clientChannel); + + ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; + + sp dupChan = serverChannel->dup(); + + EXPECT_EQ(*serverChannel == *dupChan, true) << "inputchannel should be equal after duplication"; +} } // namespace android diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 87505323c3..cdea922bd2 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -28,13 +28,13 @@ namespace android { namespace test { TEST(InputWindowInfo, ParcellingWithoutToken) { - InputWindowInfo i; + InputWindowInfo i, i2; i.token = nullptr; Parcel p; - ASSERT_EQ(OK, i.write(p)); + ASSERT_EQ(OK, i.writeToParcel(&p)); p.setDataPosition(0); - InputWindowInfo i2 = InputWindowInfo::read(p); + i2.readFromParcel(&p); ASSERT_TRUE(i2.token == nullptr); } @@ -69,10 +69,10 @@ TEST(InputWindowInfo, Parcelling) { i.touchableRegionCropHandle = touchableRegionCropHandle; Parcel p; - i.write(p); - + i.writeToParcel(&p); p.setDataPosition(0); - InputWindowInfo i2 = InputWindowInfo::read(p); + InputWindowInfo i2; + i2.readFromParcel(&p); ASSERT_EQ(i.token, i2.token); ASSERT_EQ(i.id, i2.id); ASSERT_EQ(i.name, i2.name); diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index f2a0014da4..c5f60ade96 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -93,16 +93,15 @@ sp InputManager::getDispatcher() { class BinderWindowHandle : public InputWindowHandle { public: - BinderWindowHandle(const InputWindowInfo& info) { - mInfo = info; - } + BinderWindowHandle(const InputWindowInfo& info) { mInfo = info; } bool updateInfo() override { return true; } }; -void InputManager::setInputWindows(const std::vector& infos, +binder::Status InputManager::setInputWindows( + const std::vector& infos, const sp& setInputWindowsListener) { std::unordered_map>> handlesPerDisplay; @@ -116,22 +115,38 @@ void InputManager::setInputWindows(const std::vector& infos, if (setInputWindowsListener) { setInputWindowsListener->onSetInputWindowsFinished(); } + return binder::Status::ok(); } // Used by tests only. -void InputManager::registerInputChannel(const sp& channel) { +binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) { IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); if (uid != AID_SHELL && uid != AID_ROOT) { ALOGE("Invalid attempt to register input channel over IPC" "from non shell/root entity (PID: %d)", ipc->getCallingPid()); - return; + return binder::Status::ok(); } + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); mDispatcher->registerInputChannel(channel); + return binder::Status::ok(); } -void InputManager::unregisterInputChannel(const sp& channel) { +binder::Status InputManager::unregisterInputChannel(const InputChannelInfo& info) { + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); mDispatcher->unregisterInputChannel(channel); + return binder::Status::ok(); +} + +status_t InputManager::dump(int fd, const Vector& args) { + std::string dump; + + dump += " InputFlinger dump\n"; + + ::write(fd, dump.c_str(), dump.size()); + return NO_ERROR; } } // namespace android diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 41d9478147..4993b54b5c 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -26,18 +26,23 @@ #include #include -#include +#include #include #include -#include +#include +#include #include -#include -#include #include +#include +#include + +using android::os::BnInputFlinger; +using android::os::ISetInputWindowsListener; namespace android { class InputChannel; +class InputDispatcherThread; /* * The input manager is the core of the system event processing. @@ -98,11 +103,13 @@ public: sp getClassifier() override; sp getDispatcher() override; - void setInputWindows(const std::vector& handles, - const sp& setInputWindowsListener) override; + status_t dump(int fd, const Vector& args) override; + binder::Status setInputWindows( + const std::vector& handles, + const sp& setInputWindowsListener) override; - void registerInputChannel(const sp& channel) override; - void unregisterInputChannel(const sp& channel) override; + binder::Status registerInputChannel(const InputChannelInfo& info) override; + binder::Status unregisterInputChannel(const InputChannelInfo& info) override; private: sp mReader; diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 9b002f437c..f25131c7c7 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -18,15 +18,14 @@ #define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H #include -#include +#include +#include +#include +#include #include namespace android { -class InputApplicationHandle; -class InputChannel; -class InputWindowHandle; - /* * Constants used to report the outcome of input event injection. */ diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 21255dd0d6..c886bee263 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -21,11 +21,11 @@ #include #include +#include #include namespace android { -class InputApplicationHandle; /* * Input dispatcher policy interface. diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp index b56f356dfd..2643c228ff 100644 --- a/services/inputflinger/host/Android.bp +++ b/services/inputflinger/host/Android.bp @@ -59,7 +59,8 @@ cc_binary { shared_libs: [ "libbinder", "libinputflingerhost", - "libutils" + "libutils", + "libinput" ], static_libs: [ "libarect", diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index 973b4f92fa..9364a2a767 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -22,13 +22,17 @@ #include "InputHost.h" +#include +#include +#include #include -#include -#include -#include #include +#include #include +using android::os::BnInputFlinger; +using android::os::ISetInputWindowsListener; + namespace android { class InputFlinger : public BnInputFlinger { @@ -40,10 +44,12 @@ public: InputFlinger() ANDROID_API; virtual status_t dump(int fd, const Vector& args); - void setInputWindows(const std::vector&, - const sp&) {} - void registerInputChannel(const sp&) {} - void unregisterInputChannel(const sp&) {} + binder::Status setInputWindows(const std::vector&, + const sp&) { + return binder::Status::ok(); + } + binder::Status registerInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } + binder::Status unregisterInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } private: virtual ~InputFlinger(); diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index a0d2f4f172..eae09633af 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -35,7 +35,14 @@ cc_test { "InputClassifierConverter_test.cpp", "InputDispatcher_test.cpp", "InputReader_test.cpp", + "InputFlingerService_test.cpp", "UinputDevice.cpp", + "IInputFlingerQuery.aidl" ], + aidl: { + include_dirs: [ + "frameworks/native/libs/input", + ], + }, require_root: true, } diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl new file mode 100644 index 0000000000..1edc08965f --- /dev/null +++ b/services/inputflinger/tests/IInputFlingerQuery.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.InputChannelInfo; +import android.InputWindowInfo; +import android.os.ISetInputWindowsListener; + +/** @hide */ +interface IInputFlingerQuery +{ + /* Test interfaces */ + void getInputWindows(out InputWindowInfo[] inputHandles); + void getInputChannels(out InputChannelInfo[] infos); +} diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp new file mode 100644 index 0000000000..fd3f5627b7 --- /dev/null +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TAG "InputFlingerServiceTest" + +using android::os::BnInputFlinger; +using android::os::BnSetInputWindowsListener; +using android::os::IInputFlinger; +using android::os::ISetInputWindowsListener; + +using std::chrono_literals::operator""ms; +using std::chrono_literals::operator""s; + +namespace android { + +static const sp TestInfoToken = new BBinder(); +static constexpr int32_t TestInfoId = 1; +static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo"; +static constexpr int32_t TestInfoLayoutParamsFlags = 0xABCD; +static constexpr int32_t TestInfoLayoutParamsType = 39; +static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms; +static constexpr int32_t TestInfoFrameLeft = 93; +static constexpr int32_t TestInfoFrameTop = 34; +static constexpr int32_t TestInfoFrameRight = 16; +static constexpr int32_t TestInfoFrameBottom = 19; +static constexpr int32_t TestInfoSurfaceInset = 17; +static constexpr float TestInfoGlobalScaleFactor = 0.3; +static constexpr float TestInfoWindowXScale = 0.4; +static constexpr float TestInfoWindowYScale = 0.5; +static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 400 /* right */, + 450 /* bottom */}; +static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect); +static constexpr bool TestInfoVisible = false; +static constexpr bool TestInfoCanReceiveKeys = false; +static constexpr bool TestInfoTrustedOverlay = true; +static constexpr bool TestInfoHasFocus = false; +static constexpr bool TestInfoHasWallpaper = false; +static constexpr bool TestInfoPaused = false; +static constexpr int32_t TestInfoOwnerPid = 19; +static constexpr int32_t TestInfoOwnerUid = 24; +static constexpr int32_t TestInfoInputFeatures = 29; +static constexpr int32_t TestInfoDisplayId = 34; +static constexpr int32_t TestInfoPortalToDisplayId = 2; +static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true; +static const sp TestInfoTouchableRegionCropHandle = new BBinder(); + +static const std::string TestAppInfoName = "InputFlingerServiceTestInputApplicationInfo"; +static const sp TestAppInfoToken = new BBinder(); +static constexpr std::chrono::duration TestAppInfoDispatchingTimeout = 12345678ms; + +static const String16 kTestServiceName = String16("InputFlingerService"); +static const String16 kQueryServiceName = String16("InputFlingerQueryService"); + +struct SetInputWindowsListener; +// --- InputFlingerServiceTest --- +class InputFlingerServiceTest : public testing::Test { +public: + void SetUp() override; + void TearDown() override; + +protected: + void InitializeInputFlinger(); + void setInputWindowsByInfos(std::vector& infos); + + void setInputWindowsFinished(); + void verifyInputWindowInfo(const InputWindowInfo& info) const; + InputWindowInfo& getInfo() const { return const_cast(mInfo); } + + sp mService; + sp mQuery; + +private: + sp mSetInputWindowsListener; + sp mServerChannel, mClientChannel; + InputWindowInfo mInfo; + std::mutex mLock; + std::condition_variable mSetInputWindowsFinishedCondition; +}; + +struct SetInputWindowsListener : BnSetInputWindowsListener { + explicit SetInputWindowsListener(std::function cbFunc) : mCbFunc(cbFunc) {} + + binder::Status onSetInputWindowsFinished() override; + + std::function mCbFunc; +}; + +class TestInputManager : public BnInputFlinger { +protected: + virtual ~TestInputManager(){}; + +public: + TestInputManager(){}; + void checkFdFlags(const android::base::unique_fd& fd); + + binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles); + binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos); + + status_t dump(int fd, const Vector& args) override; + + binder::Status setInputWindows( + const std::vector& handles, + const sp& setInputWindowsListener) override; + + binder::Status registerInputChannel(const InputChannelInfo& channel) override; + binder::Status unregisterInputChannel(const InputChannelInfo& channel) override; + +private: + mutable Mutex mLock; + std::unordered_map>> mHandlesPerDisplay; + std::vector> mInputChannels; +}; + +class TestInputQuery : public BnInputFlingerQuery { +public: + TestInputQuery(sp manager) : mManager(manager){}; + binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override; + binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos) override; + +private: + sp mManager; +}; + +binder::Status TestInputQuery::getInputWindows( + std::vector<::android::InputWindowInfo>* inputHandles) { + return mManager->getInputWindows(inputHandles); +} + +binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { + return mManager->getInputChannels(infos); +} + +binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { + if (mCbFunc != nullptr) { + mCbFunc(); + } + return binder::Status::ok(); +} + +binder::Status TestInputManager::setInputWindows( + const std::vector& infos, + const sp& setInputWindowsListener) { + AutoMutex _l(mLock); + + for (const auto& info : infos) { + mHandlesPerDisplay.emplace(info.displayId, std::vector>()); + mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info)); + } + if (setInputWindowsListener) { + setInputWindowsListener->onSetInputWindowsFinished(); + } + return binder::Status::ok(); +} + +void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) { + const int result = fcntl(fd, F_GETFL); + EXPECT_NE(result, -1); + EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK); +} + +binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) { + AutoMutex _l(mLock); + // check Fd flags + checkFdFlags(info.mFd); + + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + mInputChannels.push_back(channel); + + return binder::Status::ok(); +} + +binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) { + AutoMutex _l(mLock); + // check Fd flags + checkFdFlags(info.mFd); + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + + auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(), + [&](sp& it) { return *it == *channel; }); + if (it != mInputChannels.end()) { + mInputChannels.erase(it); + } + + return binder::Status::ok(); +} + +status_t TestInputManager::dump(int fd, const Vector& args) { + std::string dump; + + dump += " InputFlinger dump\n"; + + ::write(fd, dump.c_str(), dump.size()); + return NO_ERROR; +} + +binder::Status TestInputManager::getInputWindows( + std::vector<::android::InputWindowInfo>* inputInfos) { + for (auto& [displayId, inputHandles] : mHandlesPerDisplay) { + for (auto& inputHandle : inputHandles) { + inputInfos->push_back(*inputHandle->getInfo()); + } + } + return binder::Status::ok(); +} + +binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { + infos->clear(); + for (auto& channel : mInputChannels) { + auto chanDup = channel->dup(); + infos->push_back(std::move(chanDup->getInfo())); + } + return binder::Status::ok(); +} + +void InputFlingerServiceTest::SetUp() { + mSetInputWindowsListener = new SetInputWindowsListener([&]() { + std::unique_lock lock(mLock); + mSetInputWindowsFinishedCondition.notify_all(); + }); + InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); + + mInfo.token = TestInfoToken; + mInfo.id = TestInfoId; + mInfo.name = TestInfoName; + mInfo.layoutParamsFlags = TestInfoLayoutParamsFlags; + mInfo.layoutParamsType = TestInfoLayoutParamsType; + mInfo.dispatchingTimeout = TestInfoDispatchingTimeout; + mInfo.frameLeft = TestInfoFrameLeft; + mInfo.frameTop = TestInfoFrameTop; + mInfo.frameRight = TestInfoFrameRight; + mInfo.frameBottom = TestInfoFrameBottom; + mInfo.surfaceInset = TestInfoSurfaceInset; + mInfo.globalScaleFactor = TestInfoGlobalScaleFactor; + mInfo.windowXScale = TestInfoWindowXScale; + mInfo.windowYScale = TestInfoWindowYScale; + mInfo.touchableRegion = TestInfoTouchableRegion; + mInfo.visible = TestInfoVisible; + mInfo.canReceiveKeys = TestInfoCanReceiveKeys; + mInfo.trustedOverlay = TestInfoTrustedOverlay; + mInfo.hasFocus = TestInfoHasFocus; + mInfo.hasWallpaper = TestInfoHasWallpaper; + mInfo.paused = TestInfoPaused; + mInfo.ownerPid = TestInfoOwnerPid; + mInfo.ownerUid = TestInfoOwnerUid; + mInfo.inputFeatures = TestInfoInputFeatures; + mInfo.displayId = TestInfoDisplayId; + mInfo.portalToDisplayId = TestInfoPortalToDisplayId; + mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop; + mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle; + + mInfo.applicationInfo.name = TestAppInfoName; + mInfo.applicationInfo.token = TestAppInfoToken; + mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout; + + InitializeInputFlinger(); +} + +void InputFlingerServiceTest::TearDown() {} + +void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const { + EXPECT_EQ(mInfo, info); +} + +void InputFlingerServiceTest::InitializeInputFlinger() { + sp input(defaultServiceManager()->waitForService(kTestServiceName)); + ASSERT_TRUE(input != nullptr); + mService = interface_cast(input); + + input = defaultServiceManager()->waitForService(kQueryServiceName); + ASSERT_TRUE(input != nullptr); + mQuery = interface_cast(input); +} + +void InputFlingerServiceTest::setInputWindowsByInfos(std::vector& infos) { + std::unique_lock lock(mLock); + mService->setInputWindows(infos, mSetInputWindowsListener); + // Verify listener call + EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout); + // Verify input windows from service + std::vector<::android::InputWindowInfo> inputHandles; + mQuery->getInputWindows(&inputHandles); + for (auto& inputInfo : inputHandles) { + verifyInputWindowInfo(inputInfo); + } +} + +/** + * Test InputFlinger service interface SetInputWindows + */ +TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) { + std::vector infos = {getInfo()}; + setInputWindowsByInfos(infos); +} + +/** + * Test InputFlinger service interface registerInputChannel + */ +TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) { + sp serverChannel, clientChannel; + + InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); + mService->registerInputChannel(serverChannel->getInfo()); + + std::vector<::android::InputChannelInfo> infos(2); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 1UL); + + auto& info = infos[0]; + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + EXPECT_EQ(*channel, *serverChannel); + + mService->unregisterInputChannel(serverChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); +} + +/** + * Test InputFlinger service interface registerInputChannel with invalid cases + */ +TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) { + sp serverChannel, clientChannel; + InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); + + std::vector<::android::InputChannelInfo> infos(2); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); + + mService->registerInputChannel(InputChannelInfo()); + mService->unregisterInputChannel(clientChannel->getInfo()); + + mService->registerInputChannel(serverChannel->getInfo()); + mService->registerInputChannel(clientChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 2UL); + + mService->unregisterInputChannel(clientChannel->getInfo()); + mService->unregisterInputChannel(serverChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); +} + +} // namespace android + +int main(int argc, char** argv) { + pid_t forkPid = fork(); + + if (forkPid == 0) { + // Server process + android::sp manager = new android::TestInputManager(); + android::sp query = new android::TestInputQuery(manager); + + android::defaultServiceManager()->addService(android::kTestServiceName, manager, + false /*allowIsolated*/); + android::defaultServiceManager()->addService(android::kQueryServiceName, query, + false /*allowIsolated*/); + android::ProcessState::self()->startThreadPool(); + android::IPCThreadState::self()->joinThreadPool(); + } else { + android::ProcessState::self()->startThreadPool(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); + } + return 0; +} diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e5e3f48732..aa7b90348a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -256,6 +257,21 @@ private: } // namespace anonymous +struct SetInputWindowsListener : os::BnSetInputWindowsListener { + explicit SetInputWindowsListener(std::function listenerCb) : mListenerCb(listenerCb) {} + + binder::Status onSetInputWindowsFinished() override; + + std::function mListenerCb; +}; + +binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { + if (mListenerCb != nullptr) { + mListenerCb(); + } + return binder::Status::ok(); +} + // --------------------------------------------------------------------------- const String16 sHardwareTest("android.permission.HARDWARE_TEST"); @@ -321,7 +337,9 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()), mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)), - mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {} + mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) { + mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); }); +} SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) { ALOGI("SurfaceFlinger is starting"); @@ -623,7 +641,7 @@ void SurfaceFlinger::bootFinished() if (input == nullptr) { ALOGE("Failed to link to input service"); } else { - mInputFlinger = interface_cast(input); + mInputFlinger = interface_cast(input); } readPersistentProperties(); @@ -2892,19 +2910,19 @@ void SurfaceFlinger::updateInputFlinger() { } void SurfaceFlinger::updateInputWindowInfo() { - std::vector inputHandles; + std::vector inputInfos; mDrawingState.traverseInReverseZOrder([&](Layer* layer) { if (layer->needsInputInfo()) { // When calculating the screen bounds we ignore the transparent region since it may // result in an unwanted offset. - inputHandles.push_back(layer->fillInputInfo()); + inputInfos.push_back(layer->fillInputInfo()); } }); - mInputFlinger->setInputWindows(inputHandles, - mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener - : nullptr); + mInputFlinger->setInputWindows(inputInfos, + mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener + : nullptr); } void SurfaceFlinger::commitInputWindowCommands() { @@ -3807,7 +3825,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eInputInfoChanged) { if (privileged) { - layer->setInputInfo(s.inputInfo); + layer->setInputInfo(*s.inputHandle->getInfo()); flags |= eTraversalNeeded; } else { ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER"); @@ -6059,10 +6077,6 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp& display } } -void SurfaceFlinger::SetInputWindowsListener::onSetInputWindowsFinished() { - mFlinger->setInputWindowsFinished(); -} - wp SurfaceFlinger::fromHandle(const sp& handle) { Mutex::Autolock _l(mStateLock); return fromHandleLocked(handle); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d8ea5016e8..7ab0729f35 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -89,8 +88,8 @@ namespace android { class Client; class EventThread; class HWComposer; +struct SetInputWindowsListener; class IGraphicBufferProducer; -class IInputFlinger; class Layer; class MessageBase; class RefreshRateOverlay; @@ -99,6 +98,10 @@ class RenderArea; class TimeStats; class FrameTracer; +namespace os { + class IInputFlinger; +} + namespace compositionengine { class DisplaySurface; class OutputLayer; @@ -336,6 +339,7 @@ public: // If set, disables reusing client composition buffers. This can be set by // debug.sf.disable_client_composition_cache bool mDisableClientCompositionCache = false; + void setInputWindowsFinished(); private: friend class BufferLayer; @@ -606,7 +610,6 @@ private: void updateInputFlinger(); void updateInputWindowInfo(); void commitInputWindowCommands() REQUIRES(mStateLock); - void setInputWindowsFinished(); void updateCursorAsync(); void initScheduler(DisplayId primaryDisplayId); @@ -1254,21 +1257,12 @@ private: const float mInternalDisplayDensity; const float mEmulatedDisplayDensity; - sp mInputFlinger; + sp mInputFlinger; InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock); // Should only be accessed by the main thread. InputWindowCommands mInputWindowCommands; - struct SetInputWindowsListener : BnSetInputWindowsListener { - explicit SetInputWindowsListener(sp flinger) - : mFlinger(std::move(flinger)) {} - - void onSetInputWindowsFinished() override; - - const sp mFlinger; - }; - - const sp mSetInputWindowsListener = new SetInputWindowsListener(this); + sp mSetInputWindowsListener; bool mPendingSyncInputWindows GUARDED_BY(mStateLock) = false; Hwc2::impl::PowerAdvisor mPowerAdvisor; -- cgit v1.2.3-59-g8ed1b From 44753b15e754a33be9203b1dddbbdcae78afd493 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 8 Jul 2020 13:48:11 +0100 Subject: Move things in InputWindowInfo to enum classes Also introduce a new Flag class to make it possible to deal with flags while treating the individual flags as part of an enum class in a type safe manner. Bug: 160010896 Test: atest inputflinger_tests, atest libinput_tests Change-Id: I915a1c1e3b31f1c0fd99b83ba5fad7e537cd6f84 --- include/input/Flags.h | 179 ++++++++++++++ include/input/InputWindow.h | 168 ++++++------- libs/gui/tests/EndToEndNativeInputTest.cpp | 5 +- libs/input/InputWindow.cpp | 268 +++++++++++---------- libs/input/tests/Android.bp | 1 + libs/input/tests/Flags_test.cpp | 200 +++++++++++++++ libs/input/tests/InputWindow_test.cpp | 10 +- .../benchmarks/InputDispatcher_benchmarks.cpp | 4 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 67 +++--- services/inputflinger/dispatcher/TouchState.cpp | 3 +- .../inputflinger/tests/InputDispatcher_test.cpp | 53 ++-- .../tests/InputFlingerService_test.cpp | 11 +- services/surfaceflinger/Layer.cpp | 12 +- services/surfaceflinger/Layer.h | 4 +- services/surfaceflinger/LayerProtoHelper.cpp | 8 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 8 +- 17 files changed, 698 insertions(+), 309 deletions(-) create mode 100644 include/input/Flags.h create mode 100644 libs/input/tests/Flags_test.cpp (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/Flags.h b/include/input/Flags.h new file mode 100644 index 0000000000..f3198c9e91 --- /dev/null +++ b/include/input/Flags.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include "utils/BitSet.h" + +#ifndef __UI_INPUT_FLAGS_H +#define __UI_INPUT_FLAGS_H + +namespace android { + +// A trait for determining whether a type is specifically an enum class or not. +template > +struct is_enum_class : std::false_type {}; + +// By definition, an enum class is an enum that is not implicitly convertible to its underlying +// type. +template +struct is_enum_class + : std::bool_constant>> {}; + +template +inline constexpr bool is_enum_class_v = is_enum_class::value; + +/* A class for handling flags defined by an enum or enum class in a type-safe way. */ +template >> +class Flags { + // F must be an enum or its underlying type is undefined. Theoretically we could specialize this + // further to avoid this restriction but in general we want to encourage the use of enums + // anyways. + using U = typename std::underlying_type_t; + +public: + constexpr Flags(F f) : flags(static_cast(f)) {} + constexpr Flags() : flags(0) {} + constexpr Flags(const Flags& f) : flags(f.flags) {} + + // Provide a non-explicit construct for non-enum classes since they easily convert to their + // underlying types (e.g. when used with bitwise operators). For enum classes, however, we + // should force them to be explicitly constructed from their underlying types to make full use + // of the type checker. + template + constexpr Flags(T t, typename std::enable_if_t, T>* = nullptr) : flags(t) {} + template + explicit constexpr Flags(T t, typename std::enable_if_t, T>* = nullptr) + : flags(t) {} + /* + * Tests whether the given flag is set. + */ + bool test(F flag) const { + U f = static_cast(flag); + return (f & flags) == f; + } + + /* Tests whether any of the given flags are set */ + bool any(Flags f) { return (flags & f.flags) != 0; } + + /* Tests whether all of the given flags are set */ + bool all(Flags f) { return (flags & f.flags) == f.flags; } + + Flags operator|(Flags rhs) const { return static_cast(flags | rhs.flags); } + Flags& operator|=(Flags rhs) { + flags = flags | rhs.flags; + return *this; + } + + Flags operator&(Flags rhs) const { return static_cast(flags & rhs.flags); } + Flags& operator&=(Flags rhs) { + flags = flags & rhs.flags; + return *this; + } + + Flags operator^(Flags rhs) const { return static_cast(flags ^ rhs.flags); } + Flags& operator^=(Flags rhs) { + flags = flags ^ rhs.flags; + return *this; + } + + Flags operator~() { return static_cast(~flags); } + + bool operator==(Flags rhs) const { return flags == rhs.flags; } + bool operator!=(Flags rhs) const { return !operator==(rhs); } + + Flags& operator=(const Flags& rhs) { + flags = rhs.flags; + return *this; + } + + /* + * Returns the stored set of flags. + * + * Note that this returns the underlying type rather than the base enum class. This is because + * the value is no longer necessarily a strict member of the enum since the returned value could + * be multiple enum variants OR'd together. + */ + U get() const { return flags; } + + std::string string() const { return string(defaultStringify); } + + std::string string(std::function(F)> stringify) const { + // The type can't be larger than 64-bits otherwise it won't fit in BitSet64. + static_assert(sizeof(U) <= sizeof(uint64_t)); + std::string result; + bool first = true; + U unstringified = 0; + for (BitSet64 bits(flags); !bits.isEmpty();) { + uint64_t bit = bits.clearLastMarkedBit(); // counts from left + const U flag = 1 << (64 - bit - 1); + std::optional flagString = stringify(static_cast(flag)); + if (flagString) { + appendFlag(result, flagString.value(), first); + } else { + unstringified |= flag; + } + } + + if (unstringified != 0) { + appendFlag(result, base::StringPrintf("0x%08x", unstringified), first); + } + + if (first) { + result += "0x0"; + } + + return result; + } + +private: + U flags; + + static std::optional defaultStringify(F) { return std::nullopt; } + static void appendFlag(std::string& str, const std::string& flag, bool& first) { + if (first) { + first = false; + } else { + str += " | "; + } + str += flag; + } +}; + +// This namespace provides operator overloads for enum classes to make it easier to work with them +// as flags. In order to use these, add them via a `using namespace` declaration. +namespace flag_operators { + +template >> +inline Flags operator~(F f) { + using U = typename std::underlying_type_t; + return static_cast(~static_cast(f)); +} +template >> +Flags operator|(F lhs, F rhs) { + using U = typename std::underlying_type_t; + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +} // namespace flag_operators +} // namespace android + +#endif // __UI_INPUT_FLAGS_H \ No newline at end of file diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 18cca2c26c..233c7aea4f 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -38,92 +39,92 @@ struct InputWindowInfo : public Parcelable { InputWindowInfo() = default; // Window flags from WindowManager.LayoutParams - enum : uint32_t { - FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, - FLAG_DIM_BEHIND = 0x00000002, - FLAG_BLUR_BEHIND = 0x00000004, - FLAG_NOT_FOCUSABLE = 0x00000008, - FLAG_NOT_TOUCHABLE = 0x00000010, - FLAG_NOT_TOUCH_MODAL = 0x00000020, - FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040, - FLAG_KEEP_SCREEN_ON = 0x00000080, - FLAG_LAYOUT_IN_SCREEN = 0x00000100, - FLAG_LAYOUT_NO_LIMITS = 0x00000200, - FLAG_FULLSCREEN = 0x00000400, - FLAG_FORCE_NOT_FULLSCREEN = 0x00000800, - FLAG_DITHER = 0x00001000, - FLAG_SECURE = 0x00002000, - FLAG_SCALED = 0x00004000, - FLAG_IGNORE_CHEEK_PRESSES = 0x00008000, - FLAG_LAYOUT_INSET_DECOR = 0x00010000, - FLAG_ALT_FOCUSABLE_IM = 0x00020000, - FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000, - FLAG_SHOW_WHEN_LOCKED = 0x00080000, - FLAG_SHOW_WALLPAPER = 0x00100000, - FLAG_TURN_SCREEN_ON = 0x00200000, - FLAG_DISMISS_KEYGUARD = 0x00400000, - FLAG_SPLIT_TOUCH = 0x00800000, - FLAG_HARDWARE_ACCELERATED = 0x01000000, - FLAG_LAYOUT_IN_OVERSCAN = 0x02000000, - FLAG_TRANSLUCENT_STATUS = 0x04000000, - FLAG_TRANSLUCENT_NAVIGATION = 0x08000000, - FLAG_LOCAL_FOCUS_MODE = 0x10000000, - FLAG_SLIPPERY = 0x20000000, - FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000, - FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000, - }; - - // Window types from WindowManager.LayoutParams - enum { + enum class Flag : uint32_t { + ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, + DIM_BEHIND = 0x00000002, + BLUR_BEHIND = 0x00000004, + NOT_FOCUSABLE = 0x00000008, + NOT_TOUCHABLE = 0x00000010, + NOT_TOUCH_MODAL = 0x00000020, + TOUCHABLE_WHEN_WAKING = 0x00000040, + KEEP_SCREEN_ON = 0x00000080, + LAYOUT_IN_SCREEN = 0x00000100, + LAYOUT_NO_LIMITS = 0x00000200, + FULLSCREEN = 0x00000400, + FORCE_NOT_FULLSCREEN = 0x00000800, + DITHER = 0x00001000, + SECURE = 0x00002000, + SCALED = 0x00004000, + IGNORE_CHEEK_PRESSES = 0x00008000, + LAYOUT_INSET_DECOR = 0x00010000, + ALT_FOCUSABLE_IM = 0x00020000, + WATCH_OUTSIDE_TOUCH = 0x00040000, + SHOW_WHEN_LOCKED = 0x00080000, + SHOW_WALLPAPER = 0x00100000, + TURN_SCREEN_ON = 0x00200000, + DISMISS_KEYGUARD = 0x00400000, + SPLIT_TOUCH = 0x00800000, + HARDWARE_ACCELERATED = 0x01000000, + LAYOUT_IN_OVERSCAN = 0x02000000, + TRANSLUCENT_STATUS = 0x04000000, + TRANSLUCENT_NAVIGATION = 0x08000000, + LOCAL_FOCUS_MODE = 0x10000000, + SLIPPERY = 0x20000000, + LAYOUT_ATTACHED_IN_DECOR = 0x40000000, + DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000, + }; // Window types from WindowManager.LayoutParams + + enum class Type : int32_t { + UNKNOWN = 0, FIRST_APPLICATION_WINDOW = 1, - TYPE_BASE_APPLICATION = 1, - TYPE_APPLICATION = 2, - TYPE_APPLICATION_STARTING = 3, + BASE_APPLICATION = 1, + APPLICATION = 2, + APPLICATION_STARTING = 3, LAST_APPLICATION_WINDOW = 99, FIRST_SUB_WINDOW = 1000, - TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, - TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1, - TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2, - TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3, - TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4, + APPLICATION_PANEL = FIRST_SUB_WINDOW, + APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1, + APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2, + APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3, + APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4, LAST_SUB_WINDOW = 1999, FIRST_SYSTEM_WINDOW = 2000, - TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, - TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1, - TYPE_PHONE = FIRST_SYSTEM_WINDOW + 2, - TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3, - TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW + 4, - TYPE_TOAST = FIRST_SYSTEM_WINDOW + 5, - TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6, - TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7, - TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8, - TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9, - TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10, - TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11, - TYPE_INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12, - TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW + 13, - TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14, - TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15, - TYPE_DRAG = FIRST_SYSTEM_WINDOW + 16, - TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17, - TYPE_POINTER = FIRST_SYSTEM_WINDOW + 18, - TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19, - TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20, - TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21, - TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22, - TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24, - TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27, - TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, - TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, - TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39, - TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, + STATUS_BAR = FIRST_SYSTEM_WINDOW, + SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1, + PHONE = FIRST_SYSTEM_WINDOW + 2, + SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3, + KEYGUARD = FIRST_SYSTEM_WINDOW + 4, + TOAST = FIRST_SYSTEM_WINDOW + 5, + SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6, + PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7, + SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8, + KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9, + SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10, + INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11, + INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12, + WALLPAPER = FIRST_SYSTEM_WINDOW + 13, + STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14, + SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15, + DRAG = FIRST_SYSTEM_WINDOW + 16, + STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17, + POINTER = FIRST_SYSTEM_WINDOW + 18, + NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19, + VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20, + BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21, + INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22, + NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24, + MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27, + ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, + DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, + ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39, + NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, LAST_SYSTEM_WINDOW = 2999, }; - enum { - INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001, - INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002, - INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004, + enum class Feature { + DISABLE_TOUCH_PAD_GESTURES = 0x00000001, + NO_INPUT_CHANNEL = 0x00000002, + DISABLE_USER_ACTIVITY = 0x00000004, }; /* These values are filled in by the WM and passed through SurfaceFlinger @@ -135,8 +136,8 @@ struct InputWindowInfo : public Parcelable { // This uniquely identifies the input window. int32_t id = -1; std::string name; - int32_t layoutParamsFlags = 0; - int32_t layoutParamsType = 0; + Flags flags; + Type type = Type::UNKNOWN; std::chrono::nanoseconds dispatchingTimeout = std::chrono::seconds(5); /* These values are filled in by SurfaceFlinger. */ @@ -182,7 +183,7 @@ struct InputWindowInfo : public Parcelable { bool trustedOverlay = false; int32_t ownerPid = -1; int32_t ownerUid = -1; - int32_t inputFeatures = 0; + Flags inputFeatures; int32_t displayId = ADISPLAY_ID_NONE; int32_t portalToDisplayId = ADISPLAY_ID_NONE; InputApplicationInfo applicationInfo; @@ -204,9 +205,9 @@ struct InputWindowInfo : public Parcelable { status_t writeToParcel(android::Parcel* parcel) const override; status_t readFromParcel(const android::Parcel* parcel) override; -}; -std::string inputWindowFlagsToString(uint32_t flags); + static std::optional flagToString(Flag f); +}; /* * Handle for a window that can receive input. @@ -267,7 +268,6 @@ protected: InputWindowInfo mInfo; }; - } // namespace android #endif // _UI_INPUT_WINDOW_H diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 152f7ad56c..383d5916a4 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -186,8 +186,8 @@ private: void populateInputInfo(int width, int height) { mInputInfo.token = mServerChannel->getConnectionToken(); mInputInfo.name = "Test info"; - mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; - mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION; + mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; + mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; mInputInfo.dispatchingTimeout = 5s; mInputInfo.globalScaleFactor = 1.0; mInputInfo.canReceiveKeys = true; @@ -200,7 +200,6 @@ private: // TODO: Fill in from SF? mInputInfo.ownerPid = 11111; mInputInfo.ownerUid = 11111; - mInputInfo.inputFeatures = 0; mInputInfo.displayId = 0; InputApplicationInfo aInfo; diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index ae9b3f0994..36c1f8068d 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #define LOG_TAG "InputWindow" #define LOG_NDEBUG 0 @@ -26,117 +27,6 @@ namespace android { -const char* inputWindowFlagToString(uint32_t flag) { - switch (flag) { - case InputWindowInfo::FLAG_ALLOW_LOCK_WHILE_SCREEN_ON: { - return "ALLOW_LOCK_WHILE_SCREEN_ON"; - } - case InputWindowInfo::FLAG_DIM_BEHIND: { - return "DIM_BEHIND"; - } - case InputWindowInfo::FLAG_BLUR_BEHIND: { - return "BLUR_BEHIND"; - } - case InputWindowInfo::FLAG_NOT_FOCUSABLE: { - return "NOT_FOCUSABLE"; - } - case InputWindowInfo::FLAG_NOT_TOUCHABLE: { - return "NOT_TOUCHABLE"; - } - case InputWindowInfo::FLAG_NOT_TOUCH_MODAL: { - return "NOT_TOUCH_MODAL"; - } - case InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING: { - return "TOUCHABLE_WHEN_WAKING"; - } - case InputWindowInfo::FLAG_KEEP_SCREEN_ON: { - return "KEEP_SCREEN_ON"; - } - case InputWindowInfo::FLAG_LAYOUT_IN_SCREEN: { - return "LAYOUT_IN_SCREEN"; - } - case InputWindowInfo::FLAG_LAYOUT_NO_LIMITS: { - return "LAYOUT_NO_LIMITS"; - } - case InputWindowInfo::FLAG_FULLSCREEN: { - return "FULLSCREEN"; - } - case InputWindowInfo::FLAG_FORCE_NOT_FULLSCREEN: { - return "FORCE_NOT_FULLSCREEN"; - } - case InputWindowInfo::FLAG_DITHER: { - return "DITHER"; - } - case InputWindowInfo::FLAG_SECURE: { - return "SECURE"; - } - case InputWindowInfo::FLAG_SCALED: { - return "SCALED"; - } - case InputWindowInfo::FLAG_IGNORE_CHEEK_PRESSES: { - return "IGNORE_CHEEK_PRESSES"; - } - case InputWindowInfo::FLAG_LAYOUT_INSET_DECOR: { - return "LAYOUT_INSET_DECOR"; - } - case InputWindowInfo::FLAG_ALT_FOCUSABLE_IM: { - return "ALT_FOCUSABLE_IM"; - } - case InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH: { - return "WATCH_OUTSIDE_TOUCH"; - } - case InputWindowInfo::FLAG_SHOW_WHEN_LOCKED: { - return "SHOW_WHEN_LOCKED"; - } - case InputWindowInfo::FLAG_SHOW_WALLPAPER: { - return "SHOW_WALLPAPER"; - } - case InputWindowInfo::FLAG_TURN_SCREEN_ON: { - return "TURN_SCREEN_ON"; - } - case InputWindowInfo::FLAG_DISMISS_KEYGUARD: { - return "DISMISS_KEYGUARD"; - } - case InputWindowInfo::FLAG_SPLIT_TOUCH: { - return "SPLIT_TOUCH"; - } - case InputWindowInfo::FLAG_HARDWARE_ACCELERATED: { - return "HARDWARE_ACCELERATED"; - } - case InputWindowInfo::FLAG_LAYOUT_IN_OVERSCAN: { - return "LAYOUT_IN_OVERSCAN"; - } - case InputWindowInfo::FLAG_TRANSLUCENT_STATUS: { - return "TRANSLUCENT_STATUS"; - } - case InputWindowInfo::FLAG_TRANSLUCENT_NAVIGATION: { - return "TRANSLUCENT_NAVIGATION"; - } - case InputWindowInfo::FLAG_LOCAL_FOCUS_MODE: { - return "LOCAL_FOCUS_MODE"; - } - case InputWindowInfo::FLAG_SLIPPERY: { - return "SLIPPERY"; - } - case InputWindowInfo::FLAG_LAYOUT_ATTACHED_IN_DECOR: { - return "LAYOUT_ATTACHED_IN_DECOR"; - } - case InputWindowInfo::FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS: { - return "DRAWS_SYSTEM_BAR_BACKGROUNDS"; - } - } - return "UNKNOWN"; -} - -std::string inputWindowFlagsToString(uint32_t flags) { - std::string result; - for (BitSet32 bits(flags); !bits.isEmpty();) { - uint32_t bit = bits.clearLastMarkedBit(); // counts from left - const uint32_t flag = 1 << (32 - bit - 1); - result += android::base::StringPrintf("%s | ", inputWindowFlagToString(flag)); - } - return result; -} // --- InputWindowInfo --- void InputWindowInfo::addTouchableRegion(const Rect& region) { @@ -153,7 +43,7 @@ bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { } bool InputWindowInfo::supportsSplitTouch() const { - return layoutParamsFlags & FLAG_SPLIT_TOUCH; + return flags.test(Flag::SPLIT_TOUCH); } bool InputWindowInfo::overlaps(const InputWindowInfo* other) const { @@ -162,14 +52,12 @@ bool InputWindowInfo::overlaps(const InputWindowInfo* other) const { } bool InputWindowInfo::operator==(const InputWindowInfo& info) const { - return info.token == token && info.id == id && info.name == name && - info.layoutParamsFlags == layoutParamsFlags && - info.layoutParamsType == layoutParamsType && - info.dispatchingTimeout == dispatchingTimeout && info.frameLeft == frameLeft && - info.frameTop == frameTop && info.frameRight == frameRight && - info.frameBottom == frameBottom && info.surfaceInset == surfaceInset && - info.globalScaleFactor == globalScaleFactor && info.windowXScale == windowXScale && - info.windowYScale == windowYScale && + 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.windowXScale == windowXScale && info.windowYScale == windowYScale && info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay && info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper && @@ -197,8 +85,8 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeInt64(dispatchingTimeout.count()) ?: parcel->writeInt32(id) ?: parcel->writeUtf8AsUtf16(name) ?: - parcel->writeInt32(layoutParamsFlags) ?: - parcel->writeInt32(layoutParamsType) ?: + parcel->writeInt32(flags.get()) ?: + parcel->writeInt32(static_cast>(type)) ?: parcel->writeInt32(frameLeft) ?: parcel->writeInt32(frameTop) ?: parcel->writeInt32(frameRight) ?: @@ -215,7 +103,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeBool(trustedOverlay) ?: parcel->writeInt32(ownerPid) ?: parcel->writeInt32(ownerUid) ?: - parcel->writeInt32(inputFeatures) ?: + parcel->writeInt32(inputFeatures.get()) ?: parcel->writeInt32(displayId) ?: parcel->writeInt32(portalToDisplayId) ?: applicationInfo.writeToParcel(parcel) ?: @@ -236,12 +124,15 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { } token = parcel->readStrongBinder(); - dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); - status_t status = parcel->readInt32(&id) ?: - parcel->readUtf8FromUtf16(&name) ?: - parcel->readInt32(&layoutParamsFlags) ?: - parcel->readInt32(&layoutParamsType) ?: - parcel->readInt32(&frameLeft) ?: + dispatchingTimeout = static_cast(parcel->readInt64()); + status_t status = parcel->readInt32(&id) ?: parcel->readUtf8FromUtf16(&name); + if (status != OK) { + return status; + } + + flags = Flags(parcel->readInt32()); + type = static_cast(parcel->readInt32()); + status = parcel->readInt32(&frameLeft) ?: parcel->readInt32(&frameTop) ?: parcel->readInt32(&frameRight) ?: parcel->readInt32(&frameBottom) ?: @@ -256,17 +147,26 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readBool(&paused) ?: parcel->readBool(&trustedOverlay) ?: parcel->readInt32(&ownerPid) ?: - parcel->readInt32(&ownerUid) ?: - parcel->readInt32(&inputFeatures) ?: - parcel->readInt32(&displayId) ?: + parcel->readInt32(&ownerUid); + + if (status != OK) { + return status; + } + + inputFeatures = Flags(parcel->readInt32()); + status = parcel->readInt32(&displayId) ?: parcel->readInt32(&portalToDisplayId) ?: applicationInfo.readFromParcel(parcel) ?: parcel->read(touchableRegion) ?: parcel->readBool(&replaceTouchableRegionWithCrop); + if (status != OK) { + return status; + } + touchableRegionCropHandle = parcel->readStrongBinder(); - return status; + return OK; } // --- InputWindowHandle --- @@ -299,4 +199,106 @@ void InputWindowHandle::updateFrom(sp handle) { mInfo = handle->mInfo; } +std::optional InputWindowInfo::flagToString(Flag flag) { + switch (flag) { + case InputWindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON: { + return "ALLOW_LOCK_WHILE_SCREEN_ON"; + } + case InputWindowInfo::Flag::DIM_BEHIND: { + return "DIM_BEHIND"; + } + case InputWindowInfo::Flag::BLUR_BEHIND: { + return "BLUR_BEHIND"; + } + case InputWindowInfo::Flag::NOT_FOCUSABLE: { + return "NOT_FOCUSABLE"; + } + case InputWindowInfo::Flag::NOT_TOUCHABLE: { + return "NOT_TOUCHABLE"; + } + case InputWindowInfo::Flag::NOT_TOUCH_MODAL: { + return "NOT_TOUCH_MODAL"; + } + case InputWindowInfo::Flag::TOUCHABLE_WHEN_WAKING: { + return "TOUCHABLE_WHEN_WAKING"; + } + case InputWindowInfo::Flag::KEEP_SCREEN_ON: { + return "KEEP_SCREEN_ON"; + } + case InputWindowInfo::Flag::LAYOUT_IN_SCREEN: { + return "LAYOUT_IN_SCREEN"; + } + case InputWindowInfo::Flag::LAYOUT_NO_LIMITS: { + return "LAYOUT_NO_LIMITS"; + } + case InputWindowInfo::Flag::FULLSCREEN: { + return "FULLSCREEN"; + } + case InputWindowInfo::Flag::FORCE_NOT_FULLSCREEN: { + return "FORCE_NOT_FULLSCREEN"; + } + case InputWindowInfo::Flag::DITHER: { + return "DITHER"; + } + case InputWindowInfo::Flag::SECURE: { + return "SECURE"; + } + case InputWindowInfo::Flag::SCALED: { + return "SCALED"; + } + case InputWindowInfo::Flag::IGNORE_CHEEK_PRESSES: { + return "IGNORE_CHEEK_PRESSES"; + } + case InputWindowInfo::Flag::LAYOUT_INSET_DECOR: { + return "LAYOUT_INSET_DECOR"; + } + case InputWindowInfo::Flag::ALT_FOCUSABLE_IM: { + return "ALT_FOCUSABLE_IM"; + } + case InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH: { + return "WATCH_OUTSIDE_TOUCH"; + } + case InputWindowInfo::Flag::SHOW_WHEN_LOCKED: { + return "SHOW_WHEN_LOCKED"; + } + case InputWindowInfo::Flag::SHOW_WALLPAPER: { + return "SHOW_WALLPAPER"; + } + case InputWindowInfo::Flag::TURN_SCREEN_ON: { + return "TURN_SCREEN_ON"; + } + case InputWindowInfo::Flag::DISMISS_KEYGUARD: { + return "DISMISS_KEYGUARD"; + } + case InputWindowInfo::Flag::SPLIT_TOUCH: { + return "SPLIT_TOUCH"; + } + case InputWindowInfo::Flag::HARDWARE_ACCELERATED: { + return "HARDWARE_ACCELERATED"; + } + case InputWindowInfo::Flag::LAYOUT_IN_OVERSCAN: { + return "LAYOUT_IN_OVERSCAN"; + } + case InputWindowInfo::Flag::TRANSLUCENT_STATUS: { + return "TRANSLUCENT_STATUS"; + } + case InputWindowInfo::Flag::TRANSLUCENT_NAVIGATION: { + return "TRANSLUCENT_NAVIGATION"; + } + case InputWindowInfo::Flag::LOCAL_FOCUS_MODE: { + return "LOCAL_FOCUS_MODE"; + } + case InputWindowInfo::Flag::SLIPPERY: { + return "SLIPPERY"; + } + case InputWindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR: { + return "LAYOUT_ATTACHED_IN_DECOR"; + } + case InputWindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS: { + return "DRAWS_SYSTEM_BAR_BACKGROUNDS"; + } + } + return std::nullopt; +} + } // namespace android diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index 3b57146461..9782c1a05a 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -2,6 +2,7 @@ cc_test { name: "libinput_tests", srcs: [ + "Flags_test.cpp", "IdGenerator_test.cpp", "InputChannel_test.cpp", "InputDevice_test.cpp", diff --git a/libs/input/tests/Flags_test.cpp b/libs/input/tests/Flags_test.cpp new file mode 100644 index 0000000000..800404df59 --- /dev/null +++ b/libs/input/tests/Flags_test.cpp @@ -0,0 +1,200 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +namespace android::test { + +using namespace android::flag_operators; + +enum class TestFlags { ONE = 0x1, TWO = 0x2, THREE = 0x4 }; + +static std::optional toStringComplete(TestFlags f) { + switch (f) { + case TestFlags::ONE: + return "ONE"; + case TestFlags::TWO: + return "TWO"; + case TestFlags::THREE: + return "THREE"; + } + return std::nullopt; +} + +static std::optional toStringIncomplete(TestFlags f) { + switch (f) { + case TestFlags::ONE: + return "ONE"; + case TestFlags::TWO: + return "TWO"; + case TestFlags::THREE: + default: + return std::nullopt; + } +} + +TEST(Flags, Test) { + Flags flags = TestFlags::ONE; + ASSERT_TRUE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); + ASSERT_FALSE(flags.test(TestFlags::THREE)); +} + +TEST(Flags, Any) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_TRUE(flags.any(TestFlags::ONE)); + ASSERT_TRUE(flags.any(TestFlags::TWO)); + ASSERT_FALSE(flags.any(TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO)); + ASSERT_TRUE(flags.any(TestFlags::TWO | TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::THREE)); + ASSERT_TRUE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, All) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_TRUE(flags.all(TestFlags::ONE)); + ASSERT_TRUE(flags.all(TestFlags::TWO)); + ASSERT_FALSE(flags.all(TestFlags::THREE)); + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO)); + ASSERT_FALSE(flags.all(TestFlags::TWO | TestFlags::THREE)); + ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, DefaultConstructor_hasNoFlagsSet) { + Flags flags; + ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, NotOperator_onEmptyFlagsSetsAllFlags) { + Flags flags; + flags = ~flags; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, NotOperator_onNonEmptyFlagsInvertsFlags) { + Flags flags = TestFlags::TWO; + flags = ~flags; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); +} + +TEST(Flags, OrOperator_withNewFlag) { + Flags flags = TestFlags::ONE; + Flags flags2 = flags | TestFlags::TWO; + ASSERT_FALSE(flags2.test(TestFlags::THREE)); + ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, OrOperator_withExistingFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags flags2 = flags | TestFlags::THREE; + ASSERT_FALSE(flags2.test(TestFlags::TWO)); + ASSERT_TRUE(flags2.all(TestFlags::ONE | TestFlags::THREE)); +} + +TEST(Flags, OrEqualsOperator_withNewFlag) { + Flags flags; + flags |= TestFlags::THREE; + ASSERT_TRUE(flags.test(TestFlags::THREE)); + ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, OrEqualsOperator_withExistingFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + flags |= TestFlags::THREE; + ASSERT_TRUE(flags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(flags.test(TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withOneSetFlag) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & TestFlags::THREE; + ASSERT_TRUE(andFlags.test(TestFlags::THREE)); + ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withMultipleSetFlags) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & (TestFlags::ONE | TestFlags::THREE); + ASSERT_TRUE(andFlags.all(TestFlags::ONE | TestFlags::THREE)); + ASSERT_FALSE(andFlags.test(TestFlags::TWO)); +} + +TEST(Flags, AndOperator_withNoSetFlags) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + Flags andFlags = flags & TestFlags::TWO; + ASSERT_FALSE(andFlags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, Equality) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags1, flags2); +} + +TEST(Flags, Inequality) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = TestFlags::ONE | TestFlags::THREE; + ASSERT_NE(flags1, flags2); +} + +TEST(Flags, EqualsOperator) { + Flags flags; + flags = TestFlags::ONE; + ASSERT_TRUE(flags.test(TestFlags::ONE)); + ASSERT_FALSE(flags.any(TestFlags::TWO | TestFlags::THREE)); +} + +TEST(Flags, EqualsOperator_DontShareState) { + Flags flags1 = TestFlags::ONE | TestFlags::TWO; + Flags flags2 = flags1; + ASSERT_EQ(flags1, flags2); + + flags1 &= TestFlags::TWO; + ASSERT_NE(flags1, flags2); +} + +TEST(Flags, String_NoFlagsWithDefaultStringify) { + Flags flags; + ASSERT_EQ(flags.string(), "0x0"); +} + +TEST(Flags, String_NoFlagsWithNonDefaultStringify) { + Flags flags; + ASSERT_EQ(flags.string(toStringComplete), "0x0"); +} + +TEST(Flags, String_WithDefaultStringify) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags.string(), "0x00000003"); +} + +TEST(Flags, String_WithCompleteStringify) { + Flags flags = TestFlags::ONE | TestFlags::TWO; + ASSERT_EQ(flags.string(toStringComplete), "ONE | TWO"); +} + +TEST(Flags, String_WithIncompleteStringify) { + Flags flags = TestFlags::ONE | TestFlags::THREE; + ASSERT_EQ(flags.string(toStringIncomplete), "ONE | 0x00000004"); +} + +} // namespace android::test \ No newline at end of file diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index cdea922bd2..e7a4587bfc 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -44,8 +44,8 @@ TEST(InputWindowInfo, Parcelling) { i.token = new BBinder(); i.id = 1; i.name = "Foobar"; - i.layoutParamsFlags = 7; - i.layoutParamsType = 39; + i.flags = InputWindowInfo::Flag::SLIPPERY; + i.type = InputWindowInfo::Type::INPUT_METHOD; i.dispatchingTimeout = 12s; i.frameLeft = 93; i.frameTop = 34; @@ -62,7 +62,7 @@ TEST(InputWindowInfo, Parcelling) { i.paused = false; i.ownerPid = 19; i.ownerUid = 24; - i.inputFeatures = 29; + i.inputFeatures = InputWindowInfo::Feature::DISABLE_USER_ACTIVITY; i.displayId = 34; i.portalToDisplayId = 2; i.replaceTouchableRegionWithCrop = true; @@ -76,8 +76,8 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.token, i2.token); ASSERT_EQ(i.id, i2.id); ASSERT_EQ(i.name, i2.name); - ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags); - ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType); + ASSERT_EQ(i.flags, i2.flags); + ASSERT_EQ(i.type, i2.type); ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout); ASSERT_EQ(i.frameLeft, i2.frameLeft); ASSERT_EQ(i.frameTop, i2.frameTop); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 7d8ab753f3..a15b7b25ef 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -157,8 +157,7 @@ public: virtual bool updateInfo() override { mInfo.token = mServerChannel->getConnectionToken(); mInfo.name = "FakeWindowHandle"; - mInfo.layoutParamsFlags = 0; - mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; + mInfo.type = InputWindowInfo::Type::APPLICATION; mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; mInfo.frameLeft = mFrame.left; mInfo.frameTop = mFrame.top; @@ -174,7 +173,6 @@ public: mInfo.paused = false; mInfo.ownerPid = INJECTOR_PID; mInfo.ownerUid = INJECTOR_UID; - mInfo.inputFeatures = 0; mInfo.displayId = ADISPLAY_ID_DEFAULT; return true; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 5df4aec7d5..36bbc6dd17 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -45,28 +45,29 @@ static constexpr bool DEBUG_FOCUS = false; #include "InputDispatcher.h" -#include "Connection.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include #include #include #include +#include #include #include #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include + +#include "Connection.h" + #define INDENT " " #define INDENT2 " " #define INDENT3 " " @@ -816,13 +817,12 @@ sp InputDispatcher::findTouchedWindowAtLocked(int32_t display for (const sp& windowHandle : windowHandles) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (windowInfo->displayId == displayId) { - int32_t flags = windowInfo->layoutParamsFlags; + auto flags = windowInfo->flags; if (windowInfo->visible) { - if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { - bool isTouchModal = (flags & - (InputWindowInfo::FLAG_NOT_FOCUSABLE | - InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; + if (!flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE)) { + bool isTouchModal = !flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE) && + !flags.test(InputWindowInfo::Flag::NOT_TOUCH_MODAL); if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { int32_t portalToDisplayId = windowInfo->portalToDisplayId; if (portalToDisplayId != ADISPLAY_ID_NONE && @@ -839,7 +839,7 @@ sp InputDispatcher::findTouchedWindowAtLocked(int32_t display } } - if (addOutsideTargets && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) { + if (addOutsideTargets && flags.test(InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH)) { touchState->addOrUpdateWindow(windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE, BitSet32(0)); @@ -1888,7 +1888,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, for (const sp& windowHandle : windowHandles) { const InputWindowInfo* info = windowHandle->getInfo(); if (info->displayId == displayId && - windowHandle->getInfo()->layoutParamsType == InputWindowInfo::TYPE_WALLPAPER) { + windowHandle->getInfo()->type == InputWindowInfo::Type::WALLPAPER) { tempTouchState .addOrUpdateWindow(windowHandle, InputTarget::FLAG_WINDOW_IS_OBSCURED | @@ -2170,7 +2170,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { getValueByKey(mFocusedWindowHandlesByDisplay, displayId); if (focusedWindowHandle != nullptr) { const InputWindowInfo* info = focusedWindowHandle->getInfo(); - if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) { + if (info->inputFeatures.test(InputWindowInfo::Feature::DISABLE_USER_ACTIVITY)) { #if DEBUG_DISPATCH_CYCLE ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str()); #endif @@ -3647,10 +3647,9 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked( if ((getInputChannelLocked(handle->getToken()) == nullptr && info->portalToDisplayId == ADISPLAY_ID_NONE)) { const bool noInputChannel = - info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL; - const bool canReceiveInput = - !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) || - !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE); + info->inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL); + const bool canReceiveInput = !info->flags.test(InputWindowInfo::Flag::NOT_TOUCHABLE) || + !info->flags.test(InputWindowInfo::Flag::NOT_FOCUSABLE); if (canReceiveInput && !noInputChannel) { ALOGV("Window handle %s has no registered input channel", handle->getName().c_str()); @@ -4140,7 +4139,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, " "portalToDisplayId=%d, paused=%s, hasFocus=%s, " "hasWallpaper=%s, visible=%s, canReceiveKeys=%s, " - "flags=0x%08x, type=0x%08x, " + "flags=%s, type=0x%08x, " "frame=[%d,%d][%d,%d], globalScale=%f, " "windowScale=(%f,%f), touchableRegion=", i, windowInfo->name.c_str(), windowInfo->displayId, @@ -4150,20 +4149,20 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { toString(windowInfo->hasWallpaper), toString(windowInfo->visible), toString(windowInfo->canReceiveKeys), - windowInfo->layoutParamsFlags, - windowInfo->layoutParamsType, windowInfo->frameLeft, - windowInfo->frameTop, windowInfo->frameRight, - windowInfo->frameBottom, windowInfo->globalScaleFactor, - windowInfo->windowXScale, windowInfo->windowYScale); + windowInfo->flags.string(InputWindowInfo::flagToString) + .c_str(), + static_cast(windowInfo->type), + windowInfo->frameLeft, windowInfo->frameTop, + windowInfo->frameRight, windowInfo->frameBottom, + windowInfo->globalScaleFactor, windowInfo->windowXScale, + windowInfo->windowYScale); dumpRegion(dump, windowInfo->touchableRegion); - dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures); + dump += StringPrintf(", inputFeatures=%s", + windowInfo->inputFeatures.string().c_str()); dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%" PRId64 "ms\n", windowInfo->ownerPid, windowInfo->ownerUid, millis(windowInfo->dispatchingTimeout)); - dump += StringPrintf(INDENT4 " flags: %s\n", - inputWindowFlagsToString(windowInfo->layoutParamsFlags) - .c_str()); } } else { dump += INDENT2 "Windows: \n"; diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp index 2baceba582..81b3cf025b 100644 --- a/services/inputflinger/dispatcher/TouchState.cpp +++ b/services/inputflinger/dispatcher/TouchState.cpp @@ -137,8 +137,7 @@ bool TouchState::isSlippery() const { for (const TouchedWindow& window : windows) { if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { if (haveSlipperyForegroundWindow || - !(window.windowHandle->getInfo()->layoutParamsFlags & - InputWindowInfo::FLAG_SLIPPERY)) { + !window.windowHandle->getInfo()->flags.test(InputWindowInfo::Flag::SLIPPERY)) { return false; } haveSlipperyForegroundWindow = true; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 86b486818f..c749806190 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -29,6 +29,7 @@ #include using android::base::StringPrintf; +using namespace android::flag_operators; namespace android::inputdispatcher { @@ -766,8 +767,7 @@ public: mInfo.token = token; mInfo.id = sId++; mInfo.name = name; - mInfo.layoutParamsFlags = 0; - mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; + mInfo.type = InputWindowInfo::Type::APPLICATION; mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; mInfo.frameLeft = 0; mInfo.frameTop = 0; @@ -783,7 +783,6 @@ public: mInfo.paused = false; mInfo.ownerPid = INJECTOR_PID; mInfo.ownerUid = INJECTOR_UID; - mInfo.inputFeatures = 0; mInfo.displayId = displayId; } @@ -806,7 +805,7 @@ public: mInfo.addTouchableRegion(frame); } - void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; } + void setFlags(Flags flags) { mInfo.flags = flags; } void setWindowScale(float xScale, float yScale) { mInfo.windowXScale = xScale; @@ -1165,7 +1164,7 @@ TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) { sp window = new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); window->setFrame(Rect(0, 0, 100, 100)); - window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, @@ -1188,7 +1187,7 @@ TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) { sp window = new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); window->setFrame(Rect(0, 0, 100, 100)); - window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); @@ -1298,11 +1297,11 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) { sp windowLeft = new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT); windowLeft->setFrame(Rect(0, 0, 600, 800)); - windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); sp windowRight = new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT); windowRight->setFrame(Rect(600, 0, 1200, 800)); - windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -1409,7 +1408,7 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) { sp window = new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); window->setFrame(Rect(0, 0, 1200, 800)); - window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -1491,11 +1490,11 @@ TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) { sp windowLeft = new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT); windowLeft->setFrame(Rect(0, 0, 600, 800)); - windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); sp windowRight = new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT); windowRight->setFrame(Rect(600, 0, 1200, 800)); - windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -1654,15 +1653,15 @@ TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) { sp firstWindow = new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT); firstWindow->setFrame(Rect(0, 0, 600, 400)); - firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL - | InputWindowInfo::FLAG_SPLIT_TOUCH); + firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | + InputWindowInfo::Flag::SPLIT_TOUCH); // Create a non touch modal window that supports split touch sp secondWindow = new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT); secondWindow->setFrame(Rect(0, 400, 600, 800)); - secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL - | InputWindowInfo::FLAG_SPLIT_TOUCH); + secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | + InputWindowInfo::Flag::SPLIT_TOUCH); // Add the windows to the dispatcher mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}}); @@ -2347,12 +2346,12 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30)); // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this // window. - mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); mFocusedWindow = new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT); mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); - mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); @@ -2440,14 +2439,14 @@ class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest { ADISPLAY_ID_DEFAULT); // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window. // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows. - mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | - InputWindowInfo::FLAG_SPLIT_TOUCH); + mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | + InputWindowInfo::Flag::SPLIT_TOUCH); mWindow1->setFrame(Rect(0, 0, 100, 100)); mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2", ADISPLAY_ID_DEFAULT, mWindow1->getToken()); - mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | - InputWindowInfo::FLAG_SPLIT_TOUCH); + mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | + InputWindowInfo::Flag::SPLIT_TOUCH); mWindow2->setFrame(Rect(100, 100, 200, 200)); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}}); @@ -2671,7 +2670,7 @@ class InputDispatcherSingleWindowAnr : public InputDispatcherTest { mWindow->setFocus(true); // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this // window. - mWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); + mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication); @@ -3053,16 +3052,16 @@ class InputDispatcherMultiWindowAnr : public InputDispatcherTest { // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this // window. // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped - mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | - InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH | - InputWindowInfo::FLAG_SPLIT_TOUCH); + mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | + InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH | + InputWindowInfo::Flag::SPLIT_TOUCH); mFocusedWindow = new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT); mFocusedWindow->setDispatchingTimeout(30ms); mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); - mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | - InputWindowInfo::FLAG_SPLIT_TOUCH); + mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL | + InputWindowInfo::Flag::SPLIT_TOUCH); // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication); diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index 6d50519768..193fe77878 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -57,8 +57,8 @@ namespace android { static const sp TestInfoToken = new BBinder(); static constexpr int32_t TestInfoId = 1; static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo"; -static constexpr int32_t TestInfoLayoutParamsFlags = 0xABCD; -static constexpr int32_t TestInfoLayoutParamsType = 39; +static constexpr Flags TestInfoFlags = InputWindowInfo::Flag::NOT_FOCUSABLE; +static constexpr InputWindowInfo::Type TestInfoType = InputWindowInfo::Type::INPUT_METHOD; static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms; static constexpr int32_t TestInfoFrameLeft = 93; static constexpr int32_t TestInfoFrameTop = 34; @@ -79,7 +79,8 @@ static constexpr bool TestInfoHasWallpaper = false; static constexpr bool TestInfoPaused = false; static constexpr int32_t TestInfoOwnerPid = 19; static constexpr int32_t TestInfoOwnerUid = 24; -static constexpr int32_t TestInfoInputFeatures = 29; +static constexpr InputWindowInfo::Feature TestInfoInputFeatures = + InputWindowInfo::Feature::NO_INPUT_CHANNEL; static constexpr int32_t TestInfoDisplayId = 34; static constexpr int32_t TestInfoPortalToDisplayId = 2; static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true; @@ -265,8 +266,8 @@ void InputFlingerServiceTest::SetUp() { mInfo.token = TestInfoToken; mInfo.id = TestInfoId; mInfo.name = TestInfoName; - mInfo.layoutParamsFlags = TestInfoLayoutParamsFlags; - mInfo.layoutParamsType = TestInfoLayoutParamsType; + mInfo.flags = TestInfoFlags; + mInfo.type = TestInfoType; mInfo.dispatchingTimeout = TestInfoDispatchingTimeout; mInfo.frameLeft = TestInfoFrameLeft; mInfo.frameTop = TestInfoFrameTop; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 67becab0d5..70822bd02b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -67,12 +67,14 @@ #include "MonitoredProducer.h" #include "SurfaceFlinger.h" #include "TimeStats/TimeStats.h" +#include "input/InputWindow.h" #define DEBUG_RESIZE 0 namespace android { using base::StringAppendF; +using namespace android::flag_operators; std::atomic Layer::sSequence{1}; @@ -80,7 +82,8 @@ Layer::Layer(const LayerCreationArgs& args) : mFlinger(args.flinger), mName(args.name), mClientRef(args.client), - mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) { + mWindowType(static_cast( + args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) { uint32_t layerFlags = 0; if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; @@ -2371,9 +2374,8 @@ InputWindowInfo Layer::fillInputInfo() { mDrawingState.inputInfo.name = getName(); mDrawingState.inputInfo.ownerUid = mCallingUid; mDrawingState.inputInfo.ownerPid = mCallingPid; - mDrawingState.inputInfo.inputFeatures = - InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL; - mDrawingState.inputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; + mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL; + mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; mDrawingState.inputInfo.displayId = getLayerStack(); } @@ -2575,7 +2577,7 @@ void Layer::updateClonedInputInfo(const std::map, sp>& clonedLa } // Cloned layers shouldn't handle watch outside since their z order is not determined by // WM or the client. - mDrawingState.inputInfo.layoutParamsFlags &= ~InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH; + mDrawingState.inputInfo.flags &= ~InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH; } void Layer::updateClonedRelatives(const std::map, sp>& clonedLayersMap) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6bcbfca5e3..99b1bb199a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -286,7 +286,7 @@ public: void onFirstRef() override; - int getWindowType() const { return mWindowType; } + InputWindowInfo::Type getWindowType() const { return mWindowType; } void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } bool getPrimaryDisplayOnly() const { return mPrimaryDisplayOnly; } @@ -1038,7 +1038,7 @@ protected: bool mChildrenChanged{false}; // Window types from WindowManager.LayoutParams - const int mWindowType; + const InputWindowInfo::Type mWindowType; private: virtual void setTransformHint(ui::Transform::RotationFlags) {} diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 0fe1421926..dd65cf4271 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -131,8 +131,12 @@ void LayerProtoHelper::writeToProto( } InputWindowInfoProto* proto = getInputWindowInfoProto(); - proto->set_layout_params_flags(inputInfo.layoutParamsFlags); - proto->set_layout_params_type(inputInfo.layoutParamsType); + proto->set_layout_params_flags(inputInfo.flags.get()); + using U = std::underlying_type_t; + // TODO(b/129481165): This static assert can be safely removed once conversion warnings + // are re-enabled. + static_assert(std::is_same_v); + proto->set_layout_params_type(static_cast(inputInfo.type)); LayerProtoHelper::writeToProto({inputInfo.frameLeft, inputInfo.frameTop, inputInfo.frameRight, inputInfo.frameBottom}, diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index ab63d64895..8dd4b0a26a 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -432,7 +432,7 @@ void Scheduler::registerLayer(Layer* layer) { const auto minFps = mRefreshRateConfigs.getMinRefreshRate().getFps(); const auto maxFps = mRefreshRateConfigs.getMaxRefreshRate().getFps(); - if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) { + if (layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) { mLayerHistory->registerLayer(layer, minFps, maxFps, scheduler::LayerHistory::LayerVoteType::NoVote); } else if (!mUseContentDetection) { @@ -445,12 +445,12 @@ void Scheduler::registerLayer(Layer* layer) { // In V1 of content detection, all layers are registered as Heuristic (unless it's // wallpaper). const auto highFps = - layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER ? minFps : maxFps; + layer->getWindowType() == InputWindowInfo::Type::WALLPAPER ? minFps : maxFps; mLayerHistory->registerLayer(layer, minFps, highFps, scheduler::LayerHistory::LayerVoteType::Heuristic); } else { - if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) { + if (layer->getWindowType() == InputWindowInfo::Type::WALLPAPER) { // Running Wallpaper at Min is considered as part of content detection. mLayerHistory->registerLayer(layer, minFps, maxFps, scheduler::LayerHistory::LayerVoteType::Min); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index aa7b90348a..93bc11a168 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -90,6 +90,7 @@ #include #include #include +#include #include #include "BufferLayer.h" @@ -3981,7 +3982,12 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie if (metadata.has(METADATA_WINDOW_TYPE)) { int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0); if (windowType == 441731) { - metadata.setInt32(METADATA_WINDOW_TYPE, InputWindowInfo::TYPE_NAVIGATION_BAR_PANEL); + using U = std::underlying_type_t; + // TODO(b/129481165): This static assert can be safely removed once conversion warnings + // are re-enabled. + static_assert(std::is_same_v); + metadata.setInt32(METADATA_WINDOW_TYPE, + static_cast(InputWindowInfo::Type::NAVIGATION_BAR_PANEL)); primaryDisplayOnly = true; } } -- cgit v1.2.3-59-g8ed1b From 1ff3d1e3cd851aff1e20fcb8958bbf3784d8f922 Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 1 Jul 2020 15:53:47 -0700 Subject: Use Transform in InputDispatcher Modified InputDispatcher to use the Transform object instead of offset and scale values. Bug: 158476194 Test: /data/nativetest64/inputflinger_tests/inputflinger_tests Test: /data/nativetest64/libinput_tests/libinput_tests Change-Id: I31242fa6af92b02158ccb0d292c208a4a21c9e43 --- include/input/InputWindow.h | 4 -- libs/input/InputWindow.cpp | 20 ++++-- libs/input/tests/InputWindow_test.cpp | 6 +- libs/ui/Transform.cpp | 8 +++ libs/ui/include/ui/Transform.h | 3 + services/inputflinger/dispatcher/Entry.cpp | 10 +-- services/inputflinger/dispatcher/Entry.h | 9 +-- .../inputflinger/dispatcher/InputDispatcher.cpp | 74 ++++++++++------------ services/inputflinger/dispatcher/InputTarget.cpp | 43 +++++-------- services/inputflinger/dispatcher/InputTarget.h | 33 +++------- .../inputflinger/tests/InputDispatcher_test.cpp | 12 ++-- .../tests/InputFlingerService_test.cpp | 4 +- services/surfaceflinger/Layer.cpp | 22 ++++--- services/surfaceflinger/LayerProtoHelper.cpp | 3 +- services/surfaceflinger/layerproto/layers.proto | 5 +- 15 files changed, 115 insertions(+), 141 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 233c7aea4f..d82f6fe59e 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -158,10 +158,6 @@ struct InputWindowInfo : public Parcelable { // in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis. float globalScaleFactor = 1.0f; - // Scaling factors applied to individual windows. - float windowXScale = 1.0f; - float windowYScale = 1.0f; - // Transform applied to individual windows. ui::Transform transform; diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 36c1f8068d..d5d35e6a96 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -57,7 +57,7 @@ bool InputWindowInfo::operator==(const InputWindowInfo& info) const { info.frameLeft == frameLeft && info.frameTop == frameTop && info.frameRight == frameRight && info.frameBottom == frameBottom && info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor && - info.windowXScale == windowXScale && info.windowYScale == windowYScale && + info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay && info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper && @@ -93,8 +93,12 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeInt32(frameBottom) ?: parcel->writeInt32(surfaceInset) ?: parcel->writeFloat(globalScaleFactor) ?: - parcel->writeFloat(windowXScale) ?: - parcel->writeFloat(windowYScale) ?: + parcel->writeFloat(transform.dsdx()) ?: + parcel->writeFloat(transform.dtdx()) ?: + parcel->writeFloat(transform.tx()) ?: + parcel->writeFloat(transform.dtdy()) ?: + parcel->writeFloat(transform.dsdy()) ?: + parcel->writeFloat(transform.ty()) ?: parcel->writeBool(visible) ?: parcel->writeBool(canReceiveKeys) ?: parcel->writeBool(hasFocus) ?: @@ -132,14 +136,19 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { flags = Flags(parcel->readInt32()); type = static_cast(parcel->readInt32()); + float dsdx, dtdx, tx, dtdy, dsdy, ty; status = parcel->readInt32(&frameLeft) ?: parcel->readInt32(&frameTop) ?: parcel->readInt32(&frameRight) ?: parcel->readInt32(&frameBottom) ?: parcel->readInt32(&surfaceInset) ?: parcel->readFloat(&globalScaleFactor) ?: - parcel->readFloat(&windowXScale) ?: - parcel->readFloat(&windowYScale) ?: + parcel->readFloat(&dsdx) ?: + parcel->readFloat(&dtdx) ?: + parcel->readFloat(&tx) ?: + parcel->readFloat(&dtdy) ?: + parcel->readFloat(&dsdy) ?: + parcel->readFloat(&ty) ?: parcel->readBool(&visible) ?: parcel->readBool(&canReceiveKeys) ?: parcel->readBool(&hasFocus) ?: @@ -165,6 +174,7 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { } touchableRegionCropHandle = parcel->readStrongBinder(); + transform.set(std::array{dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1}); return OK; } diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index e7a4587bfc..3da869b739 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -53,8 +53,7 @@ TEST(InputWindowInfo, Parcelling) { i.frameBottom = 19; i.surfaceInset = 17; i.globalScaleFactor = 0.3; - i.windowXScale = 0.4; - i.windowYScale = 0.5; + i.transform.set(std::array{0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); i.visible = false; i.canReceiveKeys = false; i.hasFocus = false; @@ -85,8 +84,7 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.frameBottom, i2.frameBottom); ASSERT_EQ(i.surfaceInset, i2.surfaceInset); ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor); - ASSERT_EQ(i.windowXScale, i2.windowXScale); - ASSERT_EQ(i.windowYScale, i2.windowYScale); + ASSERT_EQ(i.transform, i2.transform); ASSERT_EQ(i.visible, i2.visible); ASSERT_EQ(i.canReceiveKeys, i2.canReceiveKeys); ASSERT_EQ(i.hasFocus, i2.hasFocus); diff --git a/libs/ui/Transform.cpp b/libs/ui/Transform.cpp index 3bf3903929..5424a3ca9e 100644 --- a/libs/ui/Transform.cpp +++ b/libs/ui/Transform.cpp @@ -133,6 +133,14 @@ float Transform::dsdy() const { return mMatrix[1][1]; } +float Transform::getScaleX() const { + return sqrt(dsdx() * dsdx()) + (dtdx() * dtdx()); +} + +float Transform::getScaleY() const { + return sqrt((dtdy() * dtdy()) + (dsdy() * dsdy())); +} + void Transform::reset() { mType = IDENTITY; for(size_t i = 0; i < 3; i++) { diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h index cf59467367..2612e821d0 100644 --- a/libs/ui/include/ui/Transform.h +++ b/libs/ui/include/ui/Transform.h @@ -74,6 +74,9 @@ public: float dtdy() const; float dsdy() const; + float getScaleX() const; + float getScaleY() const; + // modify the transform void reset(); void set(float tx, float ty); diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index fdbb1d1b55..26a16448f7 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -240,17 +240,13 @@ void MotionEntry::appendDescription(std::string& msg) const { volatile int32_t DispatchEntry::sNextSeqAtomic; -DispatchEntry::DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, - float yOffset, float globalScaleFactor, float windowXScale, - float windowYScale) +DispatchEntry::DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, ui::Transform transform, + float globalScaleFactor) : seq(nextSeq()), eventEntry(eventEntry), targetFlags(targetFlags), - xOffset(xOffset), - yOffset(yOffset), + transform(transform), globalScaleFactor(globalScaleFactor), - windowXScale(windowXScale), - windowYScale(windowYScale), deliveryTime(0), resolvedAction(0), resolvedFlags(0) { diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 6b7697dde6..5dfcdd1965 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -193,11 +193,8 @@ struct DispatchEntry { EventEntry* eventEntry; // the event to dispatch int32_t targetFlags; - float xOffset; - float yOffset; + ui::Transform transform; float globalScaleFactor; - float windowXScale = 1.0f; - float windowYScale = 1.0f; // Both deliveryTime and timeoutTime are only populated when the entry is sent to the app, // and will be undefined before that. nsecs_t deliveryTime; // time when the event was actually delivered @@ -209,8 +206,8 @@ struct DispatchEntry { int32_t resolvedAction; int32_t resolvedFlags; - DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset, - float globalScaleFactor, float windowXScale, float windowYScale); + DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, ui::Transform transform, + float globalScaleFactor); ~DispatchEntry(); inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; } diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 3bdbcce79b..a4538bbbf9 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -271,12 +271,11 @@ static bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { static std::unique_ptr createDispatchEntry(const InputTarget& inputTarget, EventEntry* eventEntry, int32_t inputTargetFlags) { - if (inputTarget.useDefaultPointerInfo()) { - const PointerInfo& pointerInfo = inputTarget.getDefaultPointerInfo(); + if (inputTarget.useDefaultPointerTransform()) { + const ui::Transform& transform = inputTarget.getDefaultPointerTransform(); return std::make_unique(eventEntry, // increments ref - inputTargetFlags, pointerInfo.xOffset, - pointerInfo.yOffset, inputTarget.globalScaleFactor, - pointerInfo.windowXScale, pointerInfo.windowYScale); + inputTargetFlags, transform, + inputTarget.globalScaleFactor); } ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION); @@ -286,28 +285,24 @@ static std::unique_ptr createDispatchEntry(const InputTarget& inp // Use the first pointer information to normalize all other pointers. This could be any pointer // as long as all other pointers are normalized to the same value and the final DispatchEntry - // uses the offset and scale for the normalized pointer. - const PointerInfo& firstPointerInfo = - inputTarget.pointerInfos[inputTarget.pointerIds.firstMarkedBit()]; + // uses the transform for the normalized pointer. + const ui::Transform& firstPointerTransform = + inputTarget.pointerTransforms[inputTarget.pointerIds.firstMarkedBit()]; + ui::Transform inverseFirstTransform = firstPointerTransform.inverse(); // Iterate through all pointers in the event to normalize against the first. for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.pointerCount; pointerIndex++) { const PointerProperties& pointerProperties = motionEntry.pointerProperties[pointerIndex]; uint32_t pointerId = uint32_t(pointerProperties.id); - const PointerInfo& currPointerInfo = inputTarget.pointerInfos[pointerId]; - - // The scale factor is the ratio of the current pointers scale to the normalized scale. - float scaleXDiff = currPointerInfo.windowXScale / firstPointerInfo.windowXScale; - float scaleYDiff = currPointerInfo.windowYScale / firstPointerInfo.windowYScale; + const ui::Transform& currTransform = inputTarget.pointerTransforms[pointerId]; pointerCoords[pointerIndex].copyFrom(motionEntry.pointerCoords[pointerIndex]); - // First apply the current pointers offset to set the window at 0,0 - pointerCoords[pointerIndex].applyOffset(currPointerInfo.xOffset, currPointerInfo.yOffset); - // Next scale the coordinates. - pointerCoords[pointerIndex].scale(1, scaleXDiff, scaleYDiff); - // Lastly, offset the coordinates so they're in the normalized pointer's frame. - pointerCoords[pointerIndex].applyOffset(-firstPointerInfo.xOffset, - -firstPointerInfo.yOffset); + // First, apply the current pointer's transform to update the coordinates into + // window space. + pointerCoords[pointerIndex].transform(currTransform); + // Next, apply the inverse transform of the normalized coordinates so the + // current coordinates are transformed into the normalized coordinate space. + pointerCoords[pointerIndex].transform(inverseFirstTransform); } MotionEntry* combinedMotionEntry = @@ -329,10 +324,8 @@ static std::unique_ptr createDispatchEntry(const InputTarget& inp std::unique_ptr dispatchEntry = std::make_unique(combinedMotionEntry, // increments ref - inputTargetFlags, firstPointerInfo.xOffset, - firstPointerInfo.yOffset, inputTarget.globalScaleFactor, - firstPointerInfo.windowXScale, - firstPointerInfo.windowYScale); + inputTargetFlags, firstPointerTransform, + inputTarget.globalScaleFactor); combinedMotionEntry->release(); return dispatchEntry; } @@ -2044,8 +2037,7 @@ void InputDispatcher::addWindowTargetLocked(const sp& windowH ALOG_ASSERT(it->flags == targetFlags); ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor); - it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop, - windowInfo->windowXScale, windowInfo->windowYScale); + it->addPointers(pointerIds, windowInfo->transform); } void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector& inputTargets, @@ -2068,7 +2060,9 @@ void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xO InputTarget target; target.inputChannel = monitor.inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; - target.setDefaultPointerInfo(xOffset, yOffset, 1 /* windowXScale */, 1 /* windowYScale */); + ui::Transform t; + t.set(xOffset, yOffset); + target.setDefaultPointerTransform(t); inputTargets.push_back(target); } @@ -2587,15 +2581,9 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, const PointerCoords* usingCoords = motionEntry->pointerCoords; // Set the X and Y offset and X and Y scale depending on the input source. - float xOffset = 0.0f, yOffset = 0.0f; - float xScale = 1.0f, yScale = 1.0f; if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) { float globalScaleFactor = dispatchEntry->globalScaleFactor; - xScale = dispatchEntry->windowXScale; - yScale = dispatchEntry->windowYScale; - xOffset = dispatchEntry->xOffset * xScale; - yOffset = dispatchEntry->yOffset * yScale; if (globalScaleFactor != 1.0f) { for (uint32_t i = 0; i < motionEntry->pointerCount; i++) { scaledCoords[i] = motionEntry->pointerCoords[i]; @@ -2630,8 +2618,12 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, dispatchEntry->resolvedFlags, motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState, - motionEntry->classification, xScale, yScale, - xOffset, yOffset, motionEntry->xPrecision, + motionEntry->classification, + dispatchEntry->transform.dsdx(), + dispatchEntry->transform.dsdy(), + dispatchEntry->transform.tx(), + dispatchEntry->transform.ty(), + motionEntry->xPrecision, motionEntry->yPrecision, motionEntry->xCursorPosition, motionEntry->yCursorPosition, @@ -2909,8 +2901,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( getWindowHandleLocked(connection->inputChannel->getConnectionToken()); if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); - target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop, - windowInfo->windowXScale, windowInfo->windowYScale); + target.setDefaultPointerTransform(windowInfo->transform); target.globalScaleFactor = windowInfo->globalScaleFactor; } target.inputChannel = connection->inputChannel; @@ -2975,8 +2966,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( getWindowHandleLocked(connection->inputChannel->getConnectionToken()); if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); - target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop, - windowInfo->windowXScale, windowInfo->windowYScale); + target.setDefaultPointerTransform(windowInfo->transform); target.globalScaleFactor = windowInfo->globalScaleFactor; } target.inputChannel = connection->inputChannel; @@ -4219,7 +4209,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { "hasWallpaper=%s, visible=%s, canReceiveKeys=%s, " "flags=%s, type=0x%08x, " "frame=[%d,%d][%d,%d], globalScale=%f, " - "windowScale=(%f,%f), touchableRegion=", + "touchableRegion=", i, windowInfo->name.c_str(), windowInfo->displayId, windowInfo->portalToDisplayId, toString(windowInfo->paused), @@ -4232,8 +4222,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { static_cast(windowInfo->type), windowInfo->frameLeft, windowInfo->frameTop, windowInfo->frameRight, windowInfo->frameBottom, - windowInfo->globalScaleFactor, windowInfo->windowXScale, - windowInfo->windowYScale); + windowInfo->globalScaleFactor); dumpRegion(dump, windowInfo->touchableRegion); dump += StringPrintf(", inputFeatures=%s", windowInfo->inputFeatures.string().c_str()); @@ -4241,6 +4230,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { "ms\n", windowInfo->ownerPid, windowInfo->ownerUid, millis(windowInfo->dispatchingTimeout)); + windowInfo->transform.dump(dump, INDENT4 "transform="); } } else { dump += INDENT2 "Windows: \n"; diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp index 0588374292..f6958d4666 100644 --- a/services/inputflinger/dispatcher/InputTarget.cpp +++ b/services/inputflinger/dispatcher/InputTarget.cpp @@ -42,12 +42,11 @@ std::string dispatchModeToString(int32_t dispatchMode) { return StringPrintf("%" PRId32, dispatchMode); } -void InputTarget::addPointers(BitSet32 newPointerIds, float xOffset, float yOffset, - float windowXScale, float windowYScale) { +void InputTarget::addPointers(BitSet32 newPointerIds, const ui::Transform& transform) { // The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors // and non splittable windows since we will just use all the pointers from the input event. if (newPointerIds.isEmpty()) { - setDefaultPointerInfo(xOffset, yOffset, windowXScale, windowYScale); + setDefaultPointerTransform(transform); return; } @@ -57,47 +56,39 @@ void InputTarget::addPointers(BitSet32 newPointerIds, float xOffset, float yOffs pointerIds |= newPointerIds; while (!newPointerIds.isEmpty()) { int32_t pointerId = newPointerIds.clearFirstMarkedBit(); - pointerInfos[pointerId].xOffset = xOffset; - pointerInfos[pointerId].yOffset = yOffset; - pointerInfos[pointerId].windowXScale = windowXScale; - pointerInfos[pointerId].windowYScale = windowYScale; + pointerTransforms[pointerId] = transform; } } -void InputTarget::setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, - float windowYScale) { +void InputTarget::setDefaultPointerTransform(const ui::Transform& transform) { pointerIds.clear(); - pointerInfos[0].xOffset = xOffset; - pointerInfos[0].yOffset = yOffset; - pointerInfos[0].windowXScale = windowXScale; - pointerInfos[0].windowYScale = windowYScale; + pointerTransforms[0] = transform; } -bool InputTarget::useDefaultPointerInfo() const { +bool InputTarget::useDefaultPointerTransform() const { return pointerIds.isEmpty(); } -const PointerInfo& InputTarget::getDefaultPointerInfo() const { - return pointerInfos[0]; +const ui::Transform& InputTarget::getDefaultPointerTransform() const { + return pointerTransforms[0]; } std::string InputTarget::getPointerInfoString() const { - if (useDefaultPointerInfo()) { - const PointerInfo& pointerInfo = getDefaultPointerInfo(); - return StringPrintf("xOffset=%.1f, yOffset=%.1f windowScaleFactor=(%.1f, %.1f)", - pointerInfo.xOffset, pointerInfo.yOffset, pointerInfo.windowXScale, - pointerInfo.windowYScale); + std::string out; + if (useDefaultPointerTransform()) { + const ui::Transform& transform = getDefaultPointerTransform(); + transform.dump(out, "default"); + return out; } - std::string out; for (uint32_t i = pointerIds.firstMarkedBit(); i <= pointerIds.lastMarkedBit(); i++) { if (!pointerIds.hasBit(i)) { continue; } - out += StringPrintf("\n pointerId %d: xOffset=%.1f, yOffset=%.1f " - "windowScaleFactor=(%.1f, %.1f)", - i, pointerInfos[i].xOffset, pointerInfos[i].yOffset, - pointerInfos[i].windowXScale, pointerInfos[i].windowYScale); + + out += "\n"; + const std::string name = "pointerId " + std::to_string(i) + ":"; + pointerTransforms[i].dump(out, name.c_str()); } return out; } diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h index 499a75fdac..4287538935 100644 --- a/services/inputflinger/dispatcher/InputTarget.h +++ b/services/inputflinger/dispatcher/InputTarget.h @@ -18,27 +18,12 @@ #define _UI_INPUT_INPUTDISPATCHER_INPUTTARGET_H #include +#include #include #include namespace android::inputdispatcher { -/* - * Information about each pointer for an InputTarget. This includes offset and scale so - * all pointers can be normalized to a single offset and scale. - * - * These values are ignored for KeyEvents - */ -struct PointerInfo { - // The x and y offset to add to a MotionEvent as it is delivered. - float xOffset = 0.0f; - float yOffset = 0.0f; - - // Scaling factor to apply to MotionEvent as it is delivered. - float windowXScale = 1.0f; - float windowYScale = 1.0f; -}; - /* * An input target specifies how an input event is to be dispatched to a particular window * including the window's input channel, control flags, a timeout, and an X / Y offset to @@ -119,13 +104,11 @@ struct InputTarget { // if FLAG_SPLIT is set. BitSet32 pointerIds; // The data is stored by the pointerId. Use the bit position of pointerIds to look up - // PointerInfo per pointerId. - PointerInfo pointerInfos[MAX_POINTERS]; + // Transform per pointerId. + ui::Transform pointerTransforms[MAX_POINTERS]; - void addPointers(BitSet32 pointerIds, float xOffset, float yOffset, float windowXScale, - float windowYScale); - void setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, - float windowYScale); + void addPointers(BitSet32 pointerIds, const ui::Transform& transform); + void setDefaultPointerTransform(const ui::Transform& transform); /** * Returns whether the default pointer information should be used. This will be true when the @@ -133,13 +116,13 @@ struct InputTarget { * and non splittable windows since we want all pointers for the EventEntry to go to this * target. */ - bool useDefaultPointerInfo() const; + bool useDefaultPointerTransform() const; /** - * Returns the default PointerInfo object. This should be used when useDefaultPointerInfo is + * Returns the default Transform object. This should be used when useDefaultPointerTransform is * true. */ - const PointerInfo& getDefaultPointerInfo() const; + const ui::Transform& getDefaultPointerTransform() const; std::string getPointerInfoString() const; }; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index c749806190..cee66a7ded 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -773,6 +773,7 @@ public: mInfo.frameTop = 0; mInfo.frameRight = WIDTH; mInfo.frameBottom = HEIGHT; + mInfo.transform.set(0, 0); mInfo.globalScaleFactor = 1.0; mInfo.touchableRegion.clear(); mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT)); @@ -801,16 +802,14 @@ public: mInfo.frameTop = frame.top; mInfo.frameRight = frame.right; mInfo.frameBottom = frame.bottom; + mInfo.transform.set(frame.left, frame.top); mInfo.touchableRegion.clear(); mInfo.addTouchableRegion(frame); } void setFlags(Flags flags) { mInfo.flags = flags; } - void setWindowScale(float xScale, float yScale) { - mInfo.windowXScale = xScale; - mInfo.windowYScale = yScale; - } + void setWindowScale(float xScale, float yScale) { mInfo.transform.set(xScale, 0, 0, yScale); } void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) { consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, @@ -2458,9 +2457,8 @@ protected: // Helper function to convert the point from screen coordinates into the window's space static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) { - float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft); - float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop); - return {x, y}; + vec2 vals = windowInfo->transform.transform(point.x, point.y); + return {vals.x, vals.y}; } void consumeMotionEvent(const sp& window, int32_t expectedAction, diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index 193fe77878..f661bbaa43 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -275,8 +275,8 @@ void InputFlingerServiceTest::SetUp() { mInfo.frameBottom = TestInfoFrameBottom; mInfo.surfaceInset = TestInfoSurfaceInset; mInfo.globalScaleFactor = TestInfoGlobalScaleFactor; - mInfo.windowXScale = TestInfoWindowXScale; - mInfo.windowYScale = TestInfoWindowYScale; + mInfo.transform.set(std::array{TestInfoWindowXScale, 0, TestInfoFrameLeft, 0, + TestInfoWindowYScale, TestInfoFrameTop, 0, 0, 1}); mInfo.touchableRegion = TestInfoTouchableRegion; mInfo.visible = TestInfoVisible; mInfo.canReceiveKeys = TestInfoCanReceiveKeys; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 70822bd02b..89c95d2846 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2387,17 +2387,8 @@ InputWindowInfo Layer::fillInputInfo() { } ui::Transform t = getTransform(); - const float xScale = t.dsdx(); - const float yScale = t.dsdy(); int32_t xSurfaceInset = info.surfaceInset; int32_t ySurfaceInset = info.surfaceInset; - if (xScale != 1.0f || yScale != 1.0f) { - info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f; - info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f; - info.touchableRegion.scaleSelf(xScale, yScale); - xSurfaceInset = std::round(xSurfaceInset * xScale); - ySurfaceInset = std::round(ySurfaceInset * yScale); - } // Transform layer size to screen space and inset it by surface insets. // If this is a portal window, set the touchableRegion to the layerBounds. @@ -2407,6 +2398,15 @@ InputWindowInfo Layer::fillInputInfo() { if (!layerBounds.isValid()) { layerBounds = getCroppedBufferSize(getDrawingState()); } + + const float xScale = t.getScaleX(); + const float yScale = t.getScaleY(); + if (xScale != 1.0f || yScale != 1.0f) { + info.touchableRegion.scaleSelf(xScale, yScale); + xSurfaceInset = std::round(xSurfaceInset * xScale); + ySurfaceInset = std::round(ySurfaceInset * yScale); + } + layerBounds = t.transform(layerBounds); // clamp inset to layer bounds @@ -2421,6 +2421,10 @@ InputWindowInfo Layer::fillInputInfo() { info.frameRight = layerBounds.right; info.frameBottom = layerBounds.bottom; + ui::Transform inputTransform(t); + inputTransform.set(layerBounds.left, layerBounds.top); + info.transform = inputTransform.inverse(); + // Position the touchable region relative to frame screen location and restrict it to frame // bounds. info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop); diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index dd65cf4271..5d99908b77 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -151,8 +151,7 @@ void LayerProtoHelper::writeToProto( proto->set_has_wallpaper(inputInfo.hasWallpaper); proto->set_global_scale_factor(inputInfo.globalScaleFactor); - proto->set_window_x_scale(inputInfo.windowXScale); - proto->set_window_y_scale(inputInfo.windowYScale); + LayerProtoHelper::writeToProto(inputInfo.transform, proto->mutable_transform()); proto->set_replace_touchable_region_with_crop(inputInfo.replaceTouchableRegionWithCrop); auto cropLayer = touchableRegionBounds.promote(); if (cropLayer != nullptr) { diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 7f1f542e4b..8458d54356 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -196,12 +196,13 @@ message InputWindowInfoProto { bool has_wallpaper = 9; float global_scale_factor = 10; - float window_x_scale = 11; - float window_y_scale = 12; + float window_x_scale = 11 [deprecated=true]; + float window_y_scale = 12 [deprecated=true]; uint32 crop_layer_id = 13; bool replace_touchable_region_with_crop = 14; RectProto touchable_region_crop = 15; + TransformProto transform = 16; } message ColorTransformProto { -- cgit v1.2.3-59-g8ed1b From 8759d67465ed463db24e313597c16fe04a1ded55 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 21 Jul 2020 00:46:45 +0100 Subject: Automatically generate flag value strings for flag enums. Since there can generally only be a maximum of 64 flags for a given flage type, it isn't that expensive to generate the array of names at compile time by enumerating the possible flag values and then using a templated function's debug signature to extract the name. The debug signature should be relatively stable, and I've confirmed this works on both GCC as well as clang. If our parsing fails, however, we should just fallback to bare hex values again. Our tests should hopefully prevent this from happening for any extended period of time. Bug: 160010896 Test: atest libinput_tests Change-Id: I752100bbefb92e7a0ecf7a8473a47e37ff7b1662 --- include/input/Flags.h | 99 +++++++++++++++++--- include/input/InputWindow.h | 2 - libs/input/InputWindow.cpp | 103 --------------------- libs/input/tests/Flags_test.cpp | 60 ++++-------- .../inputflinger/dispatcher/InputDispatcher.cpp | 3 +- 5 files changed, 109 insertions(+), 158 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/Flags.h b/include/input/Flags.h index 0f52e18719..f43829f62c 100644 --- a/include/input/Flags.h +++ b/include/input/Flags.h @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -28,6 +29,69 @@ namespace android { +namespace details { +template +constexpr std::optional enum_value_name() { + // Should look something like (but all on one line): + // std::optional + // android::details::enum_value_name() + // [F = android::test::TestFlags, V = android::test::TestFlags::ONE] + std::string_view view = __PRETTY_FUNCTION__; + size_t templateStart = view.rfind("["); + size_t templateEnd = view.rfind("]"); + if (templateStart == std::string::npos || templateEnd == std::string::npos) { + return std::nullopt; + } + + // Extract the template parameters without the enclosing braces. + // Example (cont'd): F = android::test::TestFlags, V = android::test::TestFlags::ONE + view = view.substr(templateStart + 1, templateEnd - templateStart - 1); + size_t valStart = view.rfind("V = "); + if (valStart == std::string::npos) { + return std::nullopt; + } + + // Example (cont'd): V = android::test::TestFlags::ONE + view = view.substr(valStart); + size_t nameStart = view.rfind("::"); + if (nameStart == std::string::npos) { + return std::nullopt; + } + + // Chop off the initial "::" + nameStart += 2; + return view.substr(nameStart); +} + +template +inline constexpr auto flag_count = sizeof(F) * __CHAR_BIT__; + +template +constexpr auto generate_flag_values(std::integer_sequence seq) { + constexpr int count = seq.size(); + + std::array values{}; + for (int i = 0, v = 0; v < count; ++i) { + values[v++] = static_cast(T{1} << i); + } + + return values; +} + +template +inline constexpr auto flag_values = generate_flag_values( + std::make_integer_sequence, flag_count>{}); + +template +constexpr auto generate_flag_names(std::index_sequence) noexcept { + return std::array, sizeof...(I)>{ + {enum_value_name[I]>()...}}; +} + +template +inline constexpr auto flag_names = + generate_flag_names(std::make_index_sequence>{}); + // A trait for determining whether a type is specifically an enum class or not. template > struct is_enum_class : std::false_type {}; @@ -40,13 +104,28 @@ struct is_enum_class template inline constexpr bool is_enum_class_v = is_enum_class::value; +} // namespace details + +template +constexpr auto flag_name() { + using F = decltype(V); + return details::enum_value_name(); +} + +template +constexpr std::optional flag_name(F flag) { + using U = std::underlying_type_t; + auto idx = __builtin_ctzl(static_cast(flag)); + return details::flag_names[idx]; +} /* A class for handling flags defined by an enum or enum class in a type-safe way. */ -template >> +template class Flags { // F must be an enum or its underlying type is undefined. Theoretically we could specialize this // further to avoid this restriction but in general we want to encourage the use of enums // anyways. + static_assert(std::is_enum_v, "Flags type must be an enum"); using U = typename std::underlying_type_t; public: @@ -59,10 +138,11 @@ public: // should force them to be explicitly constructed from their underlying types to make full use // of the type checker. template - constexpr Flags(T t, typename std::enable_if_t, T>* = nullptr) + constexpr Flags(T t, typename std::enable_if_t, T>* = nullptr) : mFlags(t) {} template - explicit constexpr Flags(T t, typename std::enable_if_t, T>* = nullptr) + explicit constexpr Flags(T t, + typename std::enable_if_t, T>* = nullptr) : mFlags(t) {} class Iterator { @@ -176,14 +256,12 @@ public: */ U get() const { return mFlags; } - std::string string() const { return string(defaultStringify); } - - std::string string(std::function(F)> stringify) const { + std::string string() const { std::string result; bool first = true; U unstringified = 0; for (const F f : *this) { - std::optional flagString = stringify(f); + std::optional flagString = flag_name(f); if (flagString) { appendFlag(result, flagString.value(), first); } else { @@ -205,8 +283,7 @@ public: private: U mFlags; - static std::optional defaultStringify(F) { return std::nullopt; } - static void appendFlag(std::string& str, const std::string& flag, bool& first) { + static void appendFlag(std::string& str, const std::string_view& flag, bool& first) { if (first) { first = false; } else { @@ -220,12 +297,12 @@ private: // as flags. In order to use these, add them via a `using namespace` declaration. namespace flag_operators { -template >> +template >> inline Flags operator~(F f) { using U = typename std::underlying_type_t; return static_cast(~static_cast(f)); } -template >> +template >> Flags operator|(F lhs, F rhs) { using U = typename std::underlying_type_t; return static_cast(static_cast(lhs) | static_cast(rhs)); diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 233c7aea4f..268a3b8ccf 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -205,8 +205,6 @@ struct InputWindowInfo : public Parcelable { status_t writeToParcel(android::Parcel* parcel) const override; status_t readFromParcel(const android::Parcel* parcel) override; - - static std::optional flagToString(Flag f); }; /* diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 36c1f8068d..4a8e2722e8 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -198,107 +198,4 @@ sp InputWindowHandle::getToken() const { void InputWindowHandle::updateFrom(sp handle) { mInfo = handle->mInfo; } - -std::optional InputWindowInfo::flagToString(Flag flag) { - switch (flag) { - case InputWindowInfo::Flag::ALLOW_LOCK_WHILE_SCREEN_ON: { - return "ALLOW_LOCK_WHILE_SCREEN_ON"; - } - case InputWindowInfo::Flag::DIM_BEHIND: { - return "DIM_BEHIND"; - } - case InputWindowInfo::Flag::BLUR_BEHIND: { - return "BLUR_BEHIND"; - } - case InputWindowInfo::Flag::NOT_FOCUSABLE: { - return "NOT_FOCUSABLE"; - } - case InputWindowInfo::Flag::NOT_TOUCHABLE: { - return "NOT_TOUCHABLE"; - } - case InputWindowInfo::Flag::NOT_TOUCH_MODAL: { - return "NOT_TOUCH_MODAL"; - } - case InputWindowInfo::Flag::TOUCHABLE_WHEN_WAKING: { - return "TOUCHABLE_WHEN_WAKING"; - } - case InputWindowInfo::Flag::KEEP_SCREEN_ON: { - return "KEEP_SCREEN_ON"; - } - case InputWindowInfo::Flag::LAYOUT_IN_SCREEN: { - return "LAYOUT_IN_SCREEN"; - } - case InputWindowInfo::Flag::LAYOUT_NO_LIMITS: { - return "LAYOUT_NO_LIMITS"; - } - case InputWindowInfo::Flag::FULLSCREEN: { - return "FULLSCREEN"; - } - case InputWindowInfo::Flag::FORCE_NOT_FULLSCREEN: { - return "FORCE_NOT_FULLSCREEN"; - } - case InputWindowInfo::Flag::DITHER: { - return "DITHER"; - } - case InputWindowInfo::Flag::SECURE: { - return "SECURE"; - } - case InputWindowInfo::Flag::SCALED: { - return "SCALED"; - } - case InputWindowInfo::Flag::IGNORE_CHEEK_PRESSES: { - return "IGNORE_CHEEK_PRESSES"; - } - case InputWindowInfo::Flag::LAYOUT_INSET_DECOR: { - return "LAYOUT_INSET_DECOR"; - } - case InputWindowInfo::Flag::ALT_FOCUSABLE_IM: { - return "ALT_FOCUSABLE_IM"; - } - case InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH: { - return "WATCH_OUTSIDE_TOUCH"; - } - case InputWindowInfo::Flag::SHOW_WHEN_LOCKED: { - return "SHOW_WHEN_LOCKED"; - } - case InputWindowInfo::Flag::SHOW_WALLPAPER: { - return "SHOW_WALLPAPER"; - } - case InputWindowInfo::Flag::TURN_SCREEN_ON: { - return "TURN_SCREEN_ON"; - } - case InputWindowInfo::Flag::DISMISS_KEYGUARD: { - return "DISMISS_KEYGUARD"; - } - case InputWindowInfo::Flag::SPLIT_TOUCH: { - return "SPLIT_TOUCH"; - } - case InputWindowInfo::Flag::HARDWARE_ACCELERATED: { - return "HARDWARE_ACCELERATED"; - } - case InputWindowInfo::Flag::LAYOUT_IN_OVERSCAN: { - return "LAYOUT_IN_OVERSCAN"; - } - case InputWindowInfo::Flag::TRANSLUCENT_STATUS: { - return "TRANSLUCENT_STATUS"; - } - case InputWindowInfo::Flag::TRANSLUCENT_NAVIGATION: { - return "TRANSLUCENT_NAVIGATION"; - } - case InputWindowInfo::Flag::LOCAL_FOCUS_MODE: { - return "LOCAL_FOCUS_MODE"; - } - case InputWindowInfo::Flag::SLIPPERY: { - return "SLIPPERY"; - } - case InputWindowInfo::Flag::LAYOUT_ATTACHED_IN_DECOR: { - return "LAYOUT_ATTACHED_IN_DECOR"; - } - case InputWindowInfo::Flag::DRAWS_SYSTEM_BAR_BACKGROUNDS: { - return "DRAWS_SYSTEM_BAR_BACKGROUNDS"; - } - } - return std::nullopt; -} - } // namespace android diff --git a/libs/input/tests/Flags_test.cpp b/libs/input/tests/Flags_test.cpp index b979f37b86..0dbb4cfe32 100644 --- a/libs/input/tests/Flags_test.cpp +++ b/libs/input/tests/Flags_test.cpp @@ -25,30 +25,6 @@ using namespace android::flag_operators; enum class TestFlags { ONE = 0x1, TWO = 0x2, THREE = 0x4 }; -static std::optional toStringComplete(TestFlags f) { - switch (f) { - case TestFlags::ONE: - return "ONE"; - case TestFlags::TWO: - return "TWO"; - case TestFlags::THREE: - return "THREE"; - } - return std::nullopt; -} - -static std::optional toStringIncomplete(TestFlags f) { - switch (f) { - case TestFlags::ONE: - return "ONE"; - case TestFlags::TWO: - return "TWO"; - case TestFlags::THREE: - default: - return std::nullopt; - } -} - TEST(Flags, Test) { Flags flags = TestFlags::ONE; ASSERT_TRUE(flags.test(TestFlags::ONE)); @@ -172,29 +148,19 @@ TEST(Flags, EqualsOperator_DontShareState) { ASSERT_NE(flags1, flags2); } -TEST(Flags, String_NoFlagsWithDefaultStringify) { +TEST(Flags, String_NoFlags) { Flags flags; ASSERT_EQ(flags.string(), "0x0"); } -TEST(Flags, String_NoFlagsWithNonDefaultStringify) { - Flags flags; - ASSERT_EQ(flags.string(toStringComplete), "0x0"); -} - -TEST(Flags, String_WithDefaultStringify) { +TEST(Flags, String_KnownValues) { Flags flags = TestFlags::ONE | TestFlags::TWO; - ASSERT_EQ(flags.string(), "0x00000003"); + ASSERT_EQ(flags.string(), "ONE | TWO"); } -TEST(Flags, String_WithCompleteStringify) { - Flags flags = TestFlags::ONE | TestFlags::TWO; - ASSERT_EQ(flags.string(toStringComplete), "ONE | TWO"); -} - -TEST(Flags, String_WithIncompleteStringify) { - Flags flags = TestFlags::ONE | TestFlags::THREE; - ASSERT_EQ(flags.string(toStringIncomplete), "ONE | 0x00000004"); +TEST(Flags, String_UnknownValues) { + auto flags = Flags(0b1011); + ASSERT_EQ(flags.string(), "ONE | TWO | 0x00000008"); } TEST(FlagsIterator, IteratesOverAllFlags) { @@ -239,4 +205,18 @@ TEST(FlagsIterator, PreFixIncrement) { ASSERT_EQ(++iter, flags.end()); } +TEST(FlagNames, RuntimeFlagName) { + TestFlags f = TestFlags::ONE; + ASSERT_EQ(flag_name(f), "ONE"); +} + +TEST(FlagNames, RuntimeUnknownFlagName) { + TestFlags f = static_cast(0x8); + ASSERT_EQ(flag_name(f), std::nullopt); +} + +TEST(FlagNames, CompileTimeFlagName) { + static_assert(flag_name() == "TWO"); +} + } // namespace android::test \ No newline at end of file diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index da098984b1..5cdbfa32f2 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -4229,8 +4229,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { toString(windowInfo->hasWallpaper), toString(windowInfo->visible), toString(windowInfo->canReceiveKeys), - windowInfo->flags.string(InputWindowInfo::flagToString) - .c_str(), + windowInfo->flags.string().c_str(), static_cast(windowInfo->type), windowInfo->frameLeft, windowInfo->frameTop, windowInfo->frameRight, windowInfo->frameBottom, -- cgit v1.2.3-59-g8ed1b From 9eaa22cf6e0cdb872be3bd4eb2bdb568880653f3 Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 1 Jul 2020 16:21:27 -0700 Subject: Updated MotionEvent to use Transform Updated MotionEvent to use Transform instead of offset and scale. This allowed a lot of simplification since it no longer needs to manually do the transformation calculation and instead can rely on functions provided by the Transform class. Test: Input works Test: inputflinger_tests Test: libinput_tests Bug: 158476194 Change-Id: Id40ae0184ca778507166e60d0d3eaf9564f3172b --- include/input/Input.h | 18 +- include/input/InputTransport.h | 20 +- libs/input/Input.cpp | 170 +++++++-------- libs/input/InputTransport.cpp | 59 +++--- libs/input/InputWindow.cpp | 2 +- libs/input/tests/InputEvent_test.cpp | 30 +-- .../input/tests/InputPublisherAndConsumer_test.cpp | 30 +-- libs/input/tests/InputWindow_test.cpp | 2 +- libs/input/tests/StructLayout_test.cpp | 22 +- libs/input/tests/VelocityTracker_test.cpp | 27 ++- libs/input/tests/VerifiedInputEvent_test.cpp | 9 +- .../benchmarks/InputDispatcher_benchmarks.cpp | 4 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 15 +- .../inputflinger/tests/InputDispatcher_test.cpp | 232 +++++++++------------ .../tests/InputFlingerService_test.cpp | 4 +- 15 files changed, 313 insertions(+), 331 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/Input.h b/include/input/Input.h index 9525bcbef4..d40ba439db 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -527,13 +527,11 @@ public: inline void setActionButton(int32_t button) { mActionButton = button; } - inline float getXScale() const { return mXScale; } + inline float getXOffset() const { return mTransform.tx(); } - inline float getYScale() const { return mYScale; } + inline float getYOffset() const { return mTransform.ty(); } - inline float getXOffset() const { return mXOffset; } - - inline float getYOffset() const { return mYOffset; } + inline ui::Transform getTransform() const { return mTransform; } inline float getXPrecision() const { return mXPrecision; } @@ -695,8 +693,8 @@ public: void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId, std::array hmac, int32_t action, int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState, - MotionClassification classification, float xScale, float yScale, float xOffset, - float yOffset, float xPrecision, float yPrecision, float rawXCursorPosition, + MotionClassification classification, const ui::Transform& transform, + float xPrecision, float yPrecision, float rawXCursorPosition, float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime, size_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); @@ -713,7 +711,7 @@ public: // Apply 3x3 perspective matrix transformation. // Matrix is in row-major form and compatible with SkMatrix. - void transform(const float matrix[9]); + void transform(const std::array& matrix); #ifdef __ANDROID__ status_t readFromParcel(Parcel* parcel); @@ -747,10 +745,6 @@ protected: int32_t mMetaState; int32_t mButtonState; MotionClassification mClassification; - float mXScale; - float mYScale; - float mXOffset; - float mYOffset; ui::Transform mTransform; float mXPrecision; float mYPrecision; diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 24f8e77446..8e009699a3 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -115,10 +116,12 @@ struct InputMessage { uint8_t empty2[3]; // 3 bytes to fill gap created by classification int32_t edgeFlags; nsecs_t downTime __attribute__((aligned(8))); - float xScale; - float yScale; - float xOffset; - float yOffset; + float dsdx; + float dtdx; + float dtdy; + float dsdy; + float tx; + float ty; float xPrecision; float yPrecision; float xCursorPosition; @@ -319,11 +322,10 @@ public: int32_t displayId, std::array hmac, int32_t action, int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState, - MotionClassification classification, float xScale, float yScale, - float xOffset, float yOffset, float xPrecision, float yPrecision, - float xCursorPosition, float yCursorPosition, nsecs_t downTime, - nsecs_t eventTime, uint32_t pointerCount, - const PointerProperties* pointerProperties, + MotionClassification classification, const ui::Transform& transform, + float xPrecision, float yPrecision, float xCursorPosition, + float yCursorPosition, nsecs_t downTime, nsecs_t eventTime, + uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); /* Publishes a focus event to the input channel. diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 2ac079ec52..fc73de3ca5 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -325,10 +325,10 @@ void PointerProperties::copyFrom(const PointerProperties& other) { void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId, std::array hmac, int32_t action, int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, - int32_t buttonState, MotionClassification classification, float xScale, - float yScale, float xOffset, float yOffset, float xPrecision, - float yPrecision, float rawXCursorPosition, float rawYCursorPosition, - nsecs_t downTime, nsecs_t eventTime, size_t pointerCount, + int32_t buttonState, MotionClassification classification, + const ui::Transform& transform, float xPrecision, float yPrecision, + float rawXCursorPosition, float rawYCursorPosition, nsecs_t downTime, + nsecs_t eventTime, size_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) { InputEvent::initialize(id, deviceId, source, displayId, hmac); @@ -339,10 +339,7 @@ void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int3 mMetaState = metaState; mButtonState = buttonState; mClassification = classification; - mXScale = xScale; - mYScale = yScale; - mXOffset = xOffset; - mYOffset = yOffset; + mTransform = transform; mXPrecision = xPrecision; mYPrecision = yPrecision; mRawXCursorPosition = rawXCursorPosition; @@ -365,10 +362,7 @@ void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { mMetaState = other->mMetaState; mButtonState = other->mButtonState; mClassification = other->mClassification; - mXScale = other->mXScale; - mYScale = other->mYScale; - mXOffset = other->mXOffset; - mYOffset = other->mYOffset; + mTransform = other->mTransform; mXPrecision = other->mXPrecision; mYPrecision = other->mYPrecision; mRawXCursorPosition = other->mRawXCursorPosition; @@ -398,18 +392,20 @@ void MotionEvent::addSample( } float MotionEvent::getXCursorPosition() const { - const float rawX = getRawXCursorPosition(); - return rawX * mXScale + mXOffset; + vec2 vals = mTransform.transform(getRawXCursorPosition(), getRawYCursorPosition()); + return vals.x; } float MotionEvent::getYCursorPosition() const { - const float rawY = getRawYCursorPosition(); - return rawY * mYScale + mYOffset; + vec2 vals = mTransform.transform(getRawXCursorPosition(), getRawYCursorPosition()); + return vals.y; } void MotionEvent::setCursorPosition(float x, float y) { - mRawXCursorPosition = (x - mXOffset) / mXScale; - mRawYCursorPosition = (y - mYOffset) / mYScale; + ui::Transform inverse = mTransform.inverse(); + vec2 vals = inverse.transform(x, y); + mRawXCursorPosition = vals.x; + mRawYCursorPosition = vals.y; } const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { @@ -421,14 +417,7 @@ float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { } float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { - float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis); - switch (axis) { - case AMOTION_EVENT_AXIS_X: - return value * mXScale + mXOffset; - case AMOTION_EVENT_AXIS_Y: - return value * mYScale + mYOffset; - } - return value; + return getHistoricalAxisValue(axis, pointerIndex, getHistorySize()); } const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( @@ -443,14 +432,23 @@ float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { - float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); + if (axis != AMOTION_EVENT_AXIS_X && axis != AMOTION_EVENT_AXIS_Y) { + return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); + } + + float rawX = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getX(); + float rawY = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getY(); + vec2 vals = mTransform.transform(rawX, rawY); + switch (axis) { case AMOTION_EVENT_AXIS_X: - return value * mXScale + mXOffset; + return vals.x; case AMOTION_EVENT_AXIS_Y: - return value * mYScale + mYOffset; + return vals.y; } - return value; + + // This should never happen + return 0; } ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { @@ -464,23 +462,24 @@ ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { } void MotionEvent::offsetLocation(float xOffset, float yOffset) { - mXOffset += xOffset; - mYOffset += yOffset; + float currXOffset = mTransform.tx(); + float currYOffset = mTransform.ty(); + mTransform.set(currXOffset + xOffset, currYOffset + yOffset); } void MotionEvent::scale(float globalScaleFactor) { - mXOffset *= globalScaleFactor; - mYOffset *= globalScaleFactor; + mTransform.set(mTransform.tx() * globalScaleFactor, mTransform.ty() * globalScaleFactor); mXPrecision *= globalScaleFactor; mYPrecision *= globalScaleFactor; size_t numSamples = mSamplePointerCoords.size(); for (size_t i = 0; i < numSamples; i++) { - mSamplePointerCoords.editItemAt(i).scale(globalScaleFactor); + mSamplePointerCoords.editItemAt(i).scale(globalScaleFactor, globalScaleFactor, + globalScaleFactor); } } -static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) { +static vec2 transformPoint(const std::array& matrix, float x, float y) { // Apply perspective transform like Skia. float newX = matrix[0] * x + matrix[1] * y + matrix[2]; float newY = matrix[3] * x + matrix[4] * y + matrix[5]; @@ -488,22 +487,25 @@ static void transformPoint(const float matrix[9], float x, float y, float *outX, if (newZ) { newZ = 1.0f / newZ; } - *outX = newX * newZ; - *outY = newY * newZ; + vec2 transformedPoint; + transformedPoint.x = newX * newZ; + transformedPoint.y = newY * newZ; + return transformedPoint; } -static float transformAngle(const float matrix[9], float angleRadians, - float originX, float originY) { +static float transformAngle(const std::array& matrix, float angleRadians, float originX, + float originY) { // Construct and transform a vector oriented at the specified clockwise angle from vertical. // Coordinate system: down is increasing Y, right is increasing X. float x = sinf(angleRadians); float y = -cosf(angleRadians); - transformPoint(matrix, x, y, &x, &y); - x -= originX; - y -= originY; + vec2 transformedPoint = transformPoint(matrix, x, y); + + transformedPoint.x -= originX; + transformedPoint.y -= originY; // Derive the transformed vector's clockwise angle from vertical. - float result = atan2f(x, -y); + float result = atan2f(transformedPoint.x, -transformedPoint.y); if (result < - M_PI_2) { result += M_PI; } else if (result > M_PI_2) { @@ -512,51 +514,51 @@ static float transformAngle(const float matrix[9], float angleRadians, return result; } -void MotionEvent::transform(const float matrix[9]) { - // The tricky part of this implementation is to preserve the value of - // rawX and rawY. So we apply the transformation to the first point - // then derive an appropriate new X/Y offset that will preserve rawX - // and rawY for that point. - float oldXOffset = mXOffset; - float oldYOffset = mYOffset; - float newX, newY; - float scaledRawX = getRawX(0) * mXScale; - float scaledRawY = getRawY(0) * mYScale; - transformPoint(matrix, scaledRawX + oldXOffset, scaledRawY + oldYOffset, &newX, &newY); - mXOffset = newX - scaledRawX; - mYOffset = newY - scaledRawY; +void MotionEvent::transform(const std::array& matrix) { + // We want to preserve the rawX and rawY so we just update the transform + // using the values of the transform passed in + ui::Transform newTransform; + newTransform.set(matrix); + mTransform = newTransform * mTransform; // Determine how the origin is transformed by the matrix so that we // can transform orientation vectors. - float originX, originY; - transformPoint(matrix, 0, 0, &originX, &originY); - - // Apply the transformation to cursor position. - if (isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition)) { - float x = mRawXCursorPosition * mXScale + oldXOffset; - float y = mRawYCursorPosition * mYScale + oldYOffset; - transformPoint(matrix, x, y, &x, &y); - mRawXCursorPosition = (x - mXOffset) / mXScale; - mRawYCursorPosition = (y - mYOffset) / mYScale; - } + vec2 origin = transformPoint(matrix, 0, 0); // Apply the transformation to all samples. size_t numSamples = mSamplePointerCoords.size(); for (size_t i = 0; i < numSamples; i++) { PointerCoords& c = mSamplePointerCoords.editItemAt(i); - float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) * mXScale + oldXOffset; - float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) * mYScale + oldYOffset; - transformPoint(matrix, x, y, &x, &y); - c.setAxisValue(AMOTION_EVENT_AXIS_X, (x - mXOffset) / mXScale); - c.setAxisValue(AMOTION_EVENT_AXIS_Y, (y - mYOffset) / mYScale); - float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, - transformAngle(matrix, orientation, originX, originY)); + transformAngle(matrix, orientation, origin.x, origin.y)); } } #ifdef __ANDROID__ +static status_t readFromParcel(ui::Transform& transform, const Parcel& parcel) { + float dsdx, dtdx, tx, dtdy, dsdy, ty; + status_t status = parcel.readFloat(&dsdx); + status |= parcel.readFloat(&dtdx); + status |= parcel.readFloat(&tx); + status |= parcel.readFloat(&dtdy); + status |= parcel.readFloat(&dsdy); + status |= parcel.readFloat(&ty); + + transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1}); + return status; +} + +static status_t writeToParcel(const ui::Transform& transform, Parcel& parcel) { + status_t status = parcel.writeFloat(transform.dsdx()); + status |= parcel.writeFloat(transform.dtdx()); + status |= parcel.writeFloat(transform.tx()); + status |= parcel.writeFloat(transform.dtdy()); + status |= parcel.writeFloat(transform.dsdy()); + status |= parcel.writeFloat(transform.ty()); + return status; +} + status_t MotionEvent::readFromParcel(Parcel* parcel) { size_t pointerCount = parcel->readInt32(); size_t sampleCount = parcel->readInt32(); @@ -582,10 +584,11 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) { mMetaState = parcel->readInt32(); mButtonState = parcel->readInt32(); mClassification = static_cast(parcel->readByte()); - mXScale = parcel->readFloat(); - mYScale = parcel->readFloat(); - mXOffset = parcel->readFloat(); - mYOffset = parcel->readFloat(); + + result = android::readFromParcel(mTransform, *parcel); + if (result != OK) { + return result; + } mXPrecision = parcel->readFloat(); mYPrecision = parcel->readFloat(); mRawXCursorPosition = parcel->readFloat(); @@ -640,10 +643,11 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { parcel->writeInt32(mMetaState); parcel->writeInt32(mButtonState); parcel->writeByte(static_cast(mClassification)); - parcel->writeFloat(mXScale); - parcel->writeFloat(mYScale); - parcel->writeFloat(mXOffset); - parcel->writeFloat(mYOffset); + + status_t result = android::writeToParcel(mTransform, *parcel); + if (result != OK) { + return result; + } parcel->writeFloat(mXPrecision); parcel->writeFloat(mYPrecision); parcel->writeFloat(mRawXCursorPosition); diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 8dcc415940..b088ee714a 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -195,14 +195,14 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { msg->body.motion.edgeFlags = body.motion.edgeFlags; // nsecs_t downTime msg->body.motion.downTime = body.motion.downTime; - // float xScale - msg->body.motion.xScale = body.motion.xScale; - // float yScale - msg->body.motion.yScale = body.motion.yScale; - // float xOffset - msg->body.motion.xOffset = body.motion.xOffset; - // float yOffset - msg->body.motion.yOffset = body.motion.yOffset; + + msg->body.motion.dsdx = body.motion.dsdx; + msg->body.motion.dtdx = body.motion.dtdx; + msg->body.motion.dtdy = body.motion.dtdy; + msg->body.motion.dsdy = body.motion.dsdy; + msg->body.motion.tx = body.motion.tx; + msg->body.motion.ty = body.motion.ty; + // float xPrecision msg->body.motion.xPrecision = body.motion.xPrecision; // float yPrecision @@ -469,10 +469,10 @@ status_t InputPublisher::publishMotionEvent( uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId, std::array hmac, int32_t action, int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState, - MotionClassification classification, float xScale, float yScale, float xOffset, - float yOffset, float xPrecision, float yPrecision, float xCursorPosition, - float yCursorPosition, nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) { + MotionClassification classification, const ui::Transform& transform, float xPrecision, + float yPrecision, float xCursorPosition, float yCursorPosition, nsecs_t downTime, + nsecs_t eventTime, uint32_t pointerCount, const PointerProperties* pointerProperties, + const PointerCoords* pointerCoords) { if (ATRACE_ENABLED()) { std::string message = StringPrintf( "publishMotionEvent(inputChannel=%s, action=%" PRId32 ")", @@ -480,17 +480,18 @@ status_t InputPublisher::publishMotionEvent( ATRACE_NAME(message.c_str()); } if (DEBUG_TRANSPORT_ACTIONS) { + std::string transformString; + transform.dump(transformString, ""); ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, " "displayId=%" PRId32 ", " "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, " - "metaState=0x%x, buttonState=0x%x, classification=%s, xScale=%.1f, yScale=%.1f, " - "xOffset=%.1f, yOffset=%.1f, " + "metaState=0x%x, buttonState=0x%x, classification=%s," "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", " - "pointerCount=%" PRIu32, + "pointerCount=%" PRIu32 " transform=%s", mChannel->getName().c_str(), seq, deviceId, source, displayId, action, actionButton, flags, edgeFlags, metaState, buttonState, - motionClassificationToString(classification), xScale, yScale, xOffset, yOffset, - xPrecision, yPrecision, downTime, eventTime, pointerCount); + motionClassificationToString(classification), xPrecision, yPrecision, downTime, + eventTime, pointerCount, transformString.c_str()); } if (!seq) { @@ -519,10 +520,12 @@ status_t InputPublisher::publishMotionEvent( msg.body.motion.metaState = metaState; msg.body.motion.buttonState = buttonState; msg.body.motion.classification = classification; - msg.body.motion.xScale = xScale; - msg.body.motion.yScale = yScale; - msg.body.motion.xOffset = xOffset; - msg.body.motion.yOffset = yOffset; + msg.body.motion.dsdx = transform.dsdx(); + msg.body.motion.dtdx = transform.dtdx(); + msg.body.motion.dtdy = transform.dtdy(); + msg.body.motion.dsdy = transform.dsdy(); + msg.body.motion.tx = transform.tx(); + msg.body.motion.ty = transform.ty(); msg.body.motion.xPrecision = xPrecision; msg.body.motion.yPrecision = yPrecision; msg.body.motion.xCursorPosition = xCursorPosition; @@ -1166,16 +1169,18 @@ void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords); } + ui::Transform transform; + transform.set({msg->body.motion.dsdx, msg->body.motion.dtdx, msg->body.motion.tx, + msg->body.motion.dtdy, msg->body.motion.dsdy, msg->body.motion.ty, 0, 0, 1}); event->initialize(msg->body.motion.eventId, msg->body.motion.deviceId, msg->body.motion.source, msg->body.motion.displayId, msg->body.motion.hmac, msg->body.motion.action, msg->body.motion.actionButton, msg->body.motion.flags, msg->body.motion.edgeFlags, msg->body.motion.metaState, - msg->body.motion.buttonState, msg->body.motion.classification, - msg->body.motion.xScale, msg->body.motion.yScale, msg->body.motion.xOffset, - msg->body.motion.yOffset, msg->body.motion.xPrecision, - msg->body.motion.yPrecision, msg->body.motion.xCursorPosition, - msg->body.motion.yCursorPosition, msg->body.motion.downTime, - msg->body.motion.eventTime, pointerCount, pointerProperties, pointerCoords); + msg->body.motion.buttonState, msg->body.motion.classification, transform, + msg->body.motion.xPrecision, msg->body.motion.yPrecision, + msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition, + msg->body.motion.downTime, msg->body.motion.eventTime, pointerCount, + pointerProperties, pointerCoords); } void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) { diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 116b963463..51190a0451 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -174,7 +174,7 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { } touchableRegionCropHandle = parcel->readStrongBinder(); - transform.set(std::array{dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1}); + transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1}); return OK; } diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index 553dc4c068..069bc0eb4e 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -225,6 +225,7 @@ protected: static constexpr float Y_OFFSET = 1.1; int32_t mId; + ui::Transform mTransform; void initializeEventWithHistory(MotionEvent* event); void assertEqualsEventWithHistory(const MotionEvent* event); @@ -233,6 +234,7 @@ protected: void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { mId = InputEvent::nextId(); + mTransform.set({X_SCALE, 0, X_OFFSET, 0, Y_SCALE, Y_OFFSET, 0, 0, 1}); PointerProperties pointerProperties[2]; pointerProperties[0].clear(); @@ -266,7 +268,7 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { event->initialize(mId, 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC, AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, - MotionClassification::NONE, X_SCALE, Y_SCALE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f, + MotionClassification::NONE, mTransform, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, pointerProperties, pointerCoords); @@ -326,8 +328,7 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { ASSERT_EQ(AMETA_ALT_ON, event->getMetaState()); ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState()); ASSERT_EQ(MotionClassification::NONE, event->getClassification()); - EXPECT_EQ(X_SCALE, event->getXScale()); - EXPECT_EQ(Y_SCALE, event->getYScale()); + EXPECT_EQ(mTransform, event->getTransform()); ASSERT_EQ(X_OFFSET, event->getXOffset()); ASSERT_EQ(Y_OFFSET, event->getYOffset()); ASSERT_EQ(2.0f, event->getXPrecision()); @@ -545,7 +546,7 @@ TEST_F(MotionEventTest, Parcel) { ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent)); } -static void setRotationMatrix(float matrix[9], float angle) { +static void setRotationMatrix(std::array& matrix, float angle) { float sin = sinf(angle); float cos = cosf(angle); matrix[0] = cos; @@ -584,13 +585,14 @@ TEST_F(MotionEventTest, Transform) { pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle); } MotionEvent event; + ui::Transform identityTransform; event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/, - MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0 /*xOffset*/, - 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/, - 3 + RADIUS /*xCursorPosition*/, 2 /*yCursorPosition*/, 0 /*downTime*/, - 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords); + MotionClassification::NONE, identityTransform, 0 /*xPrecision*/, + 0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/, 2 /*yCursorPosition*/, + 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, + pointerCoords); float originalRawX = 0 + 3; float originalRawY = -RADIUS + 2; @@ -606,7 +608,7 @@ TEST_F(MotionEventTest, Transform) { ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001); // Apply a rotation about the origin by ROTATION degrees clockwise. - float matrix[9]; + std::array matrix; setRotationMatrix(matrix, ROTATION * PI_180); event.transform(matrix); @@ -648,11 +650,12 @@ TEST_F(MotionEventTest, Initialize_SetsClassification) { pointerCoords[i].clear(); } + ui::Transform identityTransform; for (MotionClassification classification : classifications) { event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, - AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, classification, 1 /*xScale*/, - 1 /*yScale*/, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, classification, + identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(classification, event.getClassification()); @@ -670,10 +673,11 @@ TEST_F(MotionEventTest, Initialize_SetsCursorPosition) { pointerCoords[i].clear(); } + ui::Transform identityTransform; event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, - AMETA_NONE, 0, MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0, 0, 0, - 0, 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/, + AMETA_NONE, 0, MotionClassification::NONE, identityTransform, 0, 0, + 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords); event.offsetLocation(20, 60); ASSERT_EQ(280, event.getRawXCursorPosition()); diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index 5ddc85877c..e1f2562129 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -173,12 +173,13 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i); } + ui::Transform transform; + transform.set({xScale, 0, xOffset, 0, yScale, yOffset, 0, 0, 1}); status = mPublisher->publishMotionEvent(seq, eventId, deviceId, source, displayId, hmac, action, actionButton, flags, edgeFlags, metaState, buttonState, - classification, xScale, yScale, xOffset, yOffset, - xPrecision, yPrecision, xCursorPosition, - yCursorPosition, downTime, eventTime, pointerCount, - pointerProperties, pointerCoords); + classification, transform, xPrecision, yPrecision, + xCursorPosition, yCursorPosition, downTime, eventTime, + pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(OK, status) << "publisher publishMotionEvent should return OK"; @@ -206,8 +207,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { EXPECT_EQ(metaState, motionEvent->getMetaState()); EXPECT_EQ(buttonState, motionEvent->getButtonState()); EXPECT_EQ(classification, motionEvent->getClassification()); - EXPECT_EQ(xScale, motionEvent->getXScale()); - EXPECT_EQ(yScale, motionEvent->getYScale()); + EXPECT_EQ(transform, motionEvent->getTransform()); EXPECT_EQ(xOffset, motionEvent->getXOffset()); EXPECT_EQ(yOffset, motionEvent->getYOffset()); EXPECT_EQ(xPrecision, motionEvent->getXPrecision()); @@ -326,10 +326,10 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZer pointerCoords[i].clear(); } + ui::Transform identityTransform; status = mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0, - 0, 0, 0, MotionClassification::NONE, 1 /* xScale */, - 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, + 0, 0, 0, MotionClassification::NONE, identityTransform, + 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(BAD_VALUE, status) @@ -342,10 +342,10 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha PointerProperties pointerProperties[pointerCount]; PointerCoords pointerCoords[pointerCount]; + ui::Transform identityTransform; status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0, - 0, 0, 0, MotionClassification::NONE, 1 /* xScale */, - 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, + 0, 0, 0, MotionClassification::NONE, identityTransform, + 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(BAD_VALUE, status) @@ -363,10 +363,10 @@ TEST_F(InputPublisherAndConsumerTest, pointerCoords[i].clear(); } + ui::Transform identityTransform; status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0, - 0, 0, 0, MotionClassification::NONE, 1 /* xScale */, - 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, + 0, 0, 0, MotionClassification::NONE, identityTransform, + 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(BAD_VALUE, status) diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 3da869b739..1b5846023c 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -53,7 +53,7 @@ TEST(InputWindowInfo, Parcelling) { i.frameBottom = 19; i.surfaceInset = 17; i.globalScaleFactor = 0.3; - i.transform.set(std::array{0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); + i.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); i.visible = false; i.canReceiveKeys = false; i.hasFocus = false; diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index 50be9adcfa..3c5fb22588 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -62,16 +62,18 @@ void TestInputMessageAlignment() { CHECK_OFFSET(InputMessage::Body::Motion, classification, 80); CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 84); CHECK_OFFSET(InputMessage::Body::Motion, downTime, 88); - CHECK_OFFSET(InputMessage::Body::Motion, xScale, 96); - CHECK_OFFSET(InputMessage::Body::Motion, yScale, 100); - CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 104); - CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 108); - CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 112); - CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 116); - CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 120); - CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 124); - CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 128); - CHECK_OFFSET(InputMessage::Body::Motion, pointers, 136); + CHECK_OFFSET(InputMessage::Body::Motion, dsdx, 96); + CHECK_OFFSET(InputMessage::Body::Motion, dtdx, 100); + CHECK_OFFSET(InputMessage::Body::Motion, dtdy, 104); + CHECK_OFFSET(InputMessage::Body::Motion, dsdy, 108); + CHECK_OFFSET(InputMessage::Body::Motion, tx, 112); + CHECK_OFFSET(InputMessage::Body::Motion, ty, 116); + CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 120); + CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 124); + CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 128); + CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 132); + CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 136); + CHECK_OFFSET(InputMessage::Body::Motion, pointers, 144); CHECK_OFFSET(InputMessage::Body::Focus, eventId, 0); CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4); diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp index 249d9d4490..e7db4b06a4 100644 --- a/libs/input/tests/VelocityTracker_test.cpp +++ b/libs/input/tests/VelocityTracker_test.cpp @@ -176,12 +176,12 @@ static std::vector createMotionEventStream( EXPECT_EQ(pointerIndex, pointerCount); MotionEvent event; + ui::Transform identityTransform; event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC, action, 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/, - MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0 /*xOffset*/, - 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/, - AMOTION_EVENT_INVALID_CURSOR_POSITION, + MotionClassification::NONE, identityTransform, 0 /*xPrecision*/, + 0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, entry.eventTime.count(), pointerCount, properties, coords); @@ -239,10 +239,10 @@ TEST_F(VelocityTrackerTest, ThreePointsPositiveVelocityTest) { // It is difficult to determine the correct answer here, but at least the direction // of the reported velocity should be positive. std::vector motions = { - {0ms, {{ 273, NAN}}}, - {12585us, {{293, NAN}}}, - {14730us, {{293, NAN}}}, - {14730us, {{293, NAN}}}, // ACTION_UP + {0ms, {{273, 0}}}, + {12585us, {{293, 0}}}, + {14730us, {{293, 0}}}, + {14730us, {{293, 0}}}, // ACTION_UP }; computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 1600); @@ -251,10 +251,10 @@ TEST_F(VelocityTrackerTest, ThreePointsPositiveVelocityTest) { TEST_F(VelocityTrackerTest, ThreePointsZeroVelocityTest) { // Same coordinate is reported 3 times in a row std::vector motions = { - { 0ms, {{293, NAN}} }, - { 6132us, {{293, NAN}} }, - { 11283us, {{293, NAN}} }, - { 11283us, {{293, NAN}} }, // ACTION_UP + {0ms, {{293, 0}}}, + {6132us, {{293, 0}}}, + {11283us, {{293, 0}}}, + {11283us, {{293, 0}}}, // ACTION_UP }; computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 0); computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 0); @@ -263,10 +263,7 @@ TEST_F(VelocityTrackerTest, ThreePointsZeroVelocityTest) { TEST_F(VelocityTrackerTest, ThreePointsLinearVelocityTest) { // Fixed velocity at 5 points per 10 milliseconds std::vector motions = { - { 0ms, {{0, NAN}} }, - { 10ms, {{5, NAN}} }, - { 20ms, {{10, NAN}} }, - { 20ms, {{10, NAN}} }, // ACTION_UP + {0ms, {{0, 0}}}, {10ms, {{5, 0}}}, {20ms, {{10, 0}}}, {20ms, {{10, 0}}}, // ACTION_UP }; computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 500); computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 500); diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp index 4e8e840d1c..21cfe8c36e 100644 --- a/libs/input/tests/VerifiedInputEvent_test.cpp +++ b/libs/input/tests/VerifiedInputEvent_test.cpp @@ -39,13 +39,14 @@ static MotionEvent getMotionEventWithFlags(int32_t flags) { pointerCoords[i].clear(); } + ui::Transform transform; + transform.set({2, 0, 4, 0, 3, 5, 0, 0, 1}); event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, flags, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/, - MotionClassification::NONE, 2 /*xScale*/, 3 /*yScale*/, 4 /*xOffset*/, - 5 /*yOffset*/, 0.1 /*xPrecision*/, 0.2 /*yPrecision*/, 280 /*xCursorPosition*/, - 540 /*yCursorPosition*/, 100 /*downTime*/, 200 /*eventTime*/, pointerCount, - pointerProperties, pointerCoords); + MotionClassification::NONE, transform, 0.1 /*xPrecision*/, 0.2 /*yPrecision*/, + 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 100 /*downTime*/, + 200 /*eventTime*/, pointerCount, pointerProperties, pointerCoords); return event; } diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 1914a38e09..4e4af7e1e7 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -199,13 +199,13 @@ static MotionEvent generateMotionEvent() { const nsecs_t currentTime = now(); + ui::Transform identityTransform; MotionEvent event; event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, /* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE, - 1 /* xScale */, 1 /* yScale */, - /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0, + identityTransform, /* xPrecision */ 0, /* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties, pointerCoords); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 82e0a4e15d..5a4143ab9a 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2620,10 +2620,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState, motionEntry->classification, - dispatchEntry->transform.dsdx(), - dispatchEntry->transform.dsdy(), - dispatchEntry->transform.tx(), - dispatchEntry->transform.ty(), + dispatchEntry->transform, motionEntry->xPrecision, motionEntry->yPrecision, motionEntry->xCursorPosition, @@ -3278,13 +3275,13 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { mLock.unlock(); MotionEvent event; + ui::Transform transform; event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC, args->action, args->actionButton, args->flags, args->edgeFlags, - args->metaState, args->buttonState, args->classification, 1 /*xScale*/, - 1 /*yScale*/, 0 /* xOffset */, 0 /* yOffset */, args->xPrecision, - args->yPrecision, args->xCursorPosition, args->yCursorPosition, - args->downTime, args->eventTime, args->pointerCount, - args->pointerProperties, args->pointerCoords); + args->metaState, args->buttonState, args->classification, transform, + args->xPrecision, args->yPrecision, args->xCursorPosition, + args->yCursorPosition, args->downTime, args->eventTime, + args->pointerCount, args->pointerProperties, args->pointerCoords); policyFlags |= POLICY_FLAG_FILTERED; if (!mPolicy->filterInputEvent(&event, policyFlags)) { diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 4cf4909e74..296201d8e0 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -433,10 +433,11 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { constexpr int32_t metaState = AMETA_NONE; constexpr MotionClassification classification = MotionClassification::NONE; + ui::Transform identityTransform; // Rejects undefined motion actions. event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, - /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, - 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, + identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, @@ -448,10 +449,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), - 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, - 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, - /*pointerCount*/ 1, pointerProperties, pointerCoords); + 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0, + AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, + ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, + pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) @@ -460,10 +461,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), - 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, - 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, - /*pointerCount*/ 1, pointerProperties, pointerCoords); + 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0, + AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, + ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, + pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) @@ -473,10 +474,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), - 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, - 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, - /*pointerCount*/ 1, pointerProperties, pointerCoords); + 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0, + AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, + ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, + pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) @@ -485,10 +486,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), - 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, - 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, - /*pointerCount*/ 1, pointerProperties, pointerCoords); + 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0, + AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, + ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, + pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0)) @@ -497,9 +498,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { // Rejects motion events with invalid number of pointers. event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, - 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -508,9 +508,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, - 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -521,9 +520,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { pointerProperties[0].id = -1; event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, - 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -533,9 +531,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { pointerProperties[0].id = MAX_POINTER_ID + 1; event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, - 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -547,9 +544,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { pointerProperties[1].id = 1; event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, - 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, @@ -810,7 +806,11 @@ public: void setFlags(Flags flags) { mInfo.flags = flags; } - void setWindowScale(float xScale, float yScale) { mInfo.transform.set(xScale, 0, 0, yScale); } + void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) { + mInfo.transform.set(dsdx, dtdx, dtdy, dsdy); + } + + void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); } void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) { consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, @@ -1025,13 +1025,13 @@ public: } MotionEvent event; + ui::Transform identityTransform; event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC, mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE, - mButtonState, MotionClassification::NONE, /* xScale */ 1, /* yScale */ 1, - /* xOffset */ 0, - /* yOffset */ 0, /* xPrecision */ 0, /* yPrecision */ 0, - mRawXCursorPosition, mRawYCursorPosition, mEventTime, mEventTime, - mPointers.size(), pointerProperties.data(), pointerCoords.data()); + mButtonState, MotionClassification::NONE, identityTransform, + /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition, + mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(), + pointerProperties.data(), pointerCoords.data()); return event; } @@ -2489,133 +2489,123 @@ protected: << ", got " << motionEvent.getY(i); } } + + void touchAndAssertPositions(int32_t action, std::vector touchedPoints, + std::vector expectedPoints) { + NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, touchedPoints); + mDispatcher->notifyMotion(&motionArgs); + + // Always consume from window1 since it's the window that has the InputReceiver + consumeMotionEvent(mWindow1, action, expectedPoints); + } }; TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) { // Touch Window 1 PointF touchedPoint = {10, 10}; PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint); - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint}); // Release touch on Window 1 - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); - // consume the UP event - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint}); + touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint}); // Touch Window 2 touchedPoint = {150, 150}; expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint); - - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); - - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint}); } -TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) { +TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) { + // Set scale value for window2 mWindow2->setWindowScale(0.5f, 0.5f); // Touch Window 1 PointF touchedPoint = {10, 10}; PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint); - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); - + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint}); // Release touch on Window 1 - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); - // consume the UP event - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint}); + touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint}); // Touch Window 2 touchedPoint = {150, 150}; expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint); + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint}); + touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint}); - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, {touchedPoint}); - mDispatcher->notifyMotion(&motionArgs); - - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); + // Update the transform so rotation is set + mWindow2->setWindowTransform(0, -1, 1, 0); + expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint); + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint}); } -TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) { +TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) { mWindow2->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector touchedPoints = {PointF{10, 10}}; std::vector expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - touchedPoints.emplace_back(PointF{150, 150}); - expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); + touchedPoints.push_back(PointF{150, 150}); + expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); + touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints); - motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); + // Release Window 2 + int32_t actionPointerUp = + AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints); + expectedPoints.pop_back(); - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); + // Update the transform so rotation is set for Window 2 + mWindow2->setWindowTransform(0, -1, 1, 0); + expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); + touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints); } -TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) { +TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) { mWindow2->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector touchedPoints = {PointF{10, 10}}; std::vector expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - touchedPoints.emplace_back(PointF{150, 150}); - expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); - - motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); + touchedPoints.push_back(PointF{150, 150}); + expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); + touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints); // Move both windows touchedPoints = {{20, 20}, {175, 175}}; expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); + touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints); + + // Release Window 2 + int32_t actionPointerUp = + AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints); + expectedPoints.pop_back(); + + // Touch Window 2 + mWindow2->setWindowTransform(0, -1, 1, 0); + expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); + touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints); + + // Move both windows + touchedPoints = {{20, 20}, {175, 175}}; + expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), + getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); + touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints); } TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) { @@ -2624,36 +2614,22 @@ TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithSc // Touch Window 1 std::vector touchedPoints = {PointF{10, 10}}; std::vector expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; - - NotifyMotionArgs motionArgs = - generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); + touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); - touchedPoints.emplace_back(PointF{150, 150}); - expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); + touchedPoints.push_back(PointF{150, 150}); + expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); - motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - - // Consuming from window1 since it's the window that has the InputReceiver - consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); + touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints); // Move both windows touchedPoints = {{20, 20}, {175, 175}}; expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; - motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, - ADISPLAY_ID_DEFAULT, touchedPoints); - mDispatcher->notifyMotion(&motionArgs); - - consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); + touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints); } class InputDispatcherSingleWindowAnr : public InputDispatcherTest { diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index d6543f2de7..02342c0fea 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -291,8 +291,8 @@ void InputFlingerServiceTest::SetUp() { mInfo.frameBottom = TestInfoFrameBottom; mInfo.surfaceInset = TestInfoSurfaceInset; mInfo.globalScaleFactor = TestInfoGlobalScaleFactor; - mInfo.transform.set(std::array{TestInfoWindowXScale, 0, TestInfoFrameLeft, 0, - TestInfoWindowYScale, TestInfoFrameTop, 0, 0, 1}); + mInfo.transform.set({TestInfoWindowXScale, 0, TestInfoFrameLeft, 0, TestInfoWindowYScale, + TestInfoFrameTop, 0, 0, 1}); mInfo.touchableRegion = TestInfoTouchableRegion; mInfo.visible = TestInfoVisible; mInfo.canReceiveKeys = TestInfoCanReceiveKeys; -- cgit v1.2.3-59-g8ed1b From 6c4243bfedc2ad66c92a7bc470be1470cf99b2f7 Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Wed, 22 Jul 2020 12:07:12 -0700 Subject: Use AIDL compiler to generate InputApplicationInfo class. Define parcelable structure in AIDL file to skip manual code of parcel read and write. Bug: 160178917 Test: atest libinput_tests Change-Id: Ic7a5a0b383fdb5784b9b8cdb0ee5acce30b89223 --- include/input/InputApplication.h | 24 ++-------- libs/gui/tests/EndToEndNativeInputTest.cpp | 3 +- libs/input/Android.bp | 2 +- libs/input/InputApplication.cpp | 55 ---------------------- libs/input/InputWindow.cpp | 14 +++--- libs/input/android/InputApplicationInfo.aidl | 23 +++++++++ libs/input/tests/InputWindow_test.cpp | 18 +++++++ .../benchmarks/InputDispatcher_benchmarks.cpp | 2 +- .../inputflinger/tests/InputDispatcher_test.cpp | 4 +- .../tests/InputFlingerService_test.cpp | 2 +- 10 files changed, 59 insertions(+), 88 deletions(-) delete mode 100644 libs/input/InputApplication.cpp create mode 100644 libs/input/android/InputApplicationInfo.aidl (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h index b6b935329b..d01d2d458f 100644 --- a/include/input/InputApplication.h +++ b/include/input/InputApplication.h @@ -19,6 +19,8 @@ #include +#include + #include #include #include @@ -28,22 +30,6 @@ #include namespace android { - -/* - * Describes the properties of an application that can receive input. - */ -struct InputApplicationInfo : public Parcelable { - sp token; - std::string name; - std::chrono::nanoseconds dispatchingTimeout; - - InputApplicationInfo() = default; - - status_t readFromParcel(const android::Parcel* parcel) override; - - status_t writeToParcel(android::Parcel* parcel) const override; -}; - /* * Handle for an application that can receive input. * @@ -62,7 +48,7 @@ public: inline std::chrono::nanoseconds getDispatchingTimeout( std::chrono::nanoseconds defaultValue) const { - return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue; + return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeoutNanos) : defaultValue; } inline sp getApplicationToken() const { @@ -81,8 +67,8 @@ public: virtual bool updateInfo() = 0; protected: - InputApplicationHandle(); - virtual ~InputApplicationHandle(); + InputApplicationHandle() = default; + virtual ~InputApplicationHandle() = default; InputApplicationInfo mInfo; }; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index cca8dddfe6..5b429d00c1 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -63,6 +63,7 @@ sp getInputFlinger() { // We use the top 10 layers as a way to haphazardly place ourselves above anything else. static const int LAYER_BASE = INT32_MAX - 10; +static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s; class InputSurface { public: @@ -206,7 +207,7 @@ private: InputApplicationInfo aInfo; aInfo.token = new BBinder(); aInfo.name = "Test app info"; - aInfo.dispatchingTimeout = 5s; + aInfo.dispatchingTimeoutNanos = DISPATCHING_TIMEOUT.count(); mInputInfo.applicationInfo = aInfo; } diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 7dd5276958..180700db0b 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -54,13 +54,13 @@ cc_library { target: { android: { srcs: [ - "InputApplication.cpp", "InputTransport.cpp", "InputWindow.cpp", "LatencyStatistics.cpp", "VelocityControl.cpp", "VelocityTracker.cpp", "android/FocusRequest.aidl", + "android/InputApplicationInfo.aidl", "android/os/IInputFlinger.aidl", "android/os/ISetInputWindowsListener.aidl", ], diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp deleted file mode 100644 index 41721a7344..0000000000 --- a/libs/input/InputApplication.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "InputApplication" - -#include - -#include - -namespace android { - -status_t InputApplicationInfo::readFromParcel(const android::Parcel* parcel) { - if (parcel == nullptr) { - ALOGE("%s: Null parcel", __func__); - return BAD_VALUE; - } - token = parcel->readStrongBinder(); - dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); - status_t status = parcel->readUtf8FromUtf16(&name); - - return status; -} - -status_t InputApplicationInfo::writeToParcel(android::Parcel* parcel) const { - if (parcel == nullptr) { - ALOGE("%s: Null parcel", __func__); - return BAD_VALUE; - } - status_t status = parcel->writeStrongBinder(token) - ?: parcel->writeInt64(dispatchingTimeout.count()) - ?: parcel->writeUtf8AsUtf16(name) ; - - return status; -} - -// --- InputApplicationHandle --- - -InputApplicationHandle::InputApplicationHandle() {} - -InputApplicationHandle::~InputApplicationHandle() {} - -} // namespace android diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 51190a0451..6db9ed5148 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -57,17 +57,15 @@ bool InputWindowInfo::operator==(const InputWindowInfo& info) const { 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.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay && - info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper && - info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) && + info.visible == visible && info.canReceiveKeys == canReceiveKeys && + info.trustedOverlay == trustedOverlay && info.hasFocus == hasFocus && + info.hasWallpaper == hasWallpaper && info.paused == paused && + info.ownerPid == ownerPid && info.ownerUid == ownerUid && info.inputFeatures == inputFeatures && info.displayId == displayId && info.portalToDisplayId == portalToDisplayId && info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && - info.applicationInfo.name == applicationInfo.name && - info.applicationInfo.token == applicationInfo.token && - info.applicationInfo.dispatchingTimeout == applicationInfo.dispatchingTimeout; + info.applicationInfo == applicationInfo; } status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { diff --git a/libs/input/android/InputApplicationInfo.aidl b/libs/input/android/InputApplicationInfo.aidl new file mode 100644 index 0000000000..d1161e1b12 --- /dev/null +++ b/libs/input/android/InputApplicationInfo.aidl @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android; + +parcelable InputApplicationInfo { + @nullable IBinder token; + @utf8InCpp String name; + long dispatchingTimeoutNanos; +} diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 1b5846023c..052222e428 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -66,6 +66,9 @@ TEST(InputWindowInfo, Parcelling) { i.portalToDisplayId = 2; i.replaceTouchableRegionWithCrop = true; i.touchableRegionCropHandle = touchableRegionCropHandle; + i.applicationInfo.name = "ApplicationFooBar"; + i.applicationInfo.token = new BBinder(); + i.applicationInfo.dispatchingTimeoutNanos = 0x12345678ABCD; Parcel p; i.writeToParcel(&p); @@ -97,6 +100,21 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.portalToDisplayId, i2.portalToDisplayId); ASSERT_EQ(i.replaceTouchableRegionWithCrop, i2.replaceTouchableRegionWithCrop); ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle); + ASSERT_EQ(i.applicationInfo, i2.applicationInfo); +} + +TEST(InputApplicationInfo, Parcelling) { + InputApplicationInfo i; + i.token = new BBinder(); + i.name = "ApplicationFooBar"; + i.dispatchingTimeoutNanos = 0x12345678ABCD; + + Parcel p; + ASSERT_EQ(i.writeToParcel(&p), OK); + p.setDataPosition(0); + InputApplicationInfo i2; + ASSERT_EQ(i2.readFromParcel(&p), OK); + ASSERT_EQ(i, i2); } } // namespace test diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 4e4af7e1e7..5ce9f23e82 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -94,7 +94,7 @@ public: virtual ~FakeApplicationHandle() {} virtual bool updateInfo() { - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; + mInfo.dispatchingTimeoutNanos = DISPATCHING_TIMEOUT.count(); return true; } }; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 296201d8e0..86d62d74ca 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -583,7 +583,7 @@ public: FakeApplicationHandle() { mInfo.name = "Fake Application"; mInfo.token = new BBinder(); - mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; + mInfo.dispatchingTimeoutNanos = DISPATCHING_TIMEOUT.count(); } virtual ~FakeApplicationHandle() {} @@ -592,7 +592,7 @@ public: } void setDispatchingTimeout(std::chrono::nanoseconds timeout) { - mInfo.dispatchingTimeout = timeout; + mInfo.dispatchingTimeoutNanos = timeout.count(); } }; diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index 02342c0fea..87e0fb5a3d 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -310,7 +310,7 @@ void InputFlingerServiceTest::SetUp() { mInfo.applicationInfo.name = TestAppInfoName; mInfo.applicationInfo.token = TestAppInfoToken; - mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout; + mInfo.applicationInfo.dispatchingTimeoutNanos = TestAppInfoDispatchingTimeout.count(); InitializeInputFlinger(); } -- cgit v1.2.3-59-g8ed1b From 47074b84da85b05912c911c6f12aecaa47b07142 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 14 Aug 2020 11:54:47 -0700 Subject: Rename InputWindowHandle hasFocus to focusable A window with hasFocus set to true, means the window can be focusable. The current name is confusing when mutliple windows set the field to true. Rename this to focusable and also remove canRecieveKeys field which is not used. Test: presubmit Bug: 151179149 Change-Id: I38f63dfd08300b6fc97388ee6d8bcbdddb89c4a1 --- include/input/InputWindow.h | 3 +- libs/gui/tests/EndToEndNativeInputTest.cpp | 3 +- libs/input/InputWindow.cpp | 18 +++---- libs/input/tests/InputWindow_test.cpp | 6 +-- .../benchmarks/InputDispatcher_benchmarks.cpp | 3 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 9 ++-- .../inputflinger/tests/InputDispatcher_test.cpp | 55 +++++++++++----------- .../tests/InputFlingerService_test.cpp | 7 ++- services/surfaceflinger/LayerProtoHelper.cpp | 3 +- services/surfaceflinger/layerproto/layers.proto | 4 +- 10 files changed, 51 insertions(+), 60 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 8a752c1e65..7372022078 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -167,8 +167,7 @@ struct InputWindowInfo : public Parcelable { */ Region touchableRegion; bool visible = false; - bool canReceiveKeys = false; - bool hasFocus = 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 diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index a68ec29d52..287a6f4ebb 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -192,8 +192,7 @@ private: mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; mInputInfo.dispatchingTimeout = 5s; mInputInfo.globalScaleFactor = 1.0; - mInputInfo.canReceiveKeys = true; - mInputInfo.hasFocus = true; + mInputInfo.focusable = true; mInputInfo.hasWallpaper = false; mInputInfo.paused = false; diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 6db9ed5148..885dc9b51e 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -58,10 +58,9 @@ bool InputWindowInfo::operator==(const InputWindowInfo& info) const { info.frameRight == frameRight && info.frameBottom == frameBottom && info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor && info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) && - info.visible == visible && info.canReceiveKeys == canReceiveKeys && - info.trustedOverlay == trustedOverlay && info.hasFocus == hasFocus && - info.hasWallpaper == hasWallpaper && info.paused == paused && - info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.visible == visible && info.trustedOverlay == trustedOverlay && + info.focusable == focusable && info.hasWallpaper == hasWallpaper && + info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && info.inputFeatures == inputFeatures && info.displayId == displayId && info.portalToDisplayId == portalToDisplayId && info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && @@ -79,6 +78,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { } parcel->writeInt32(1); + // clang-format off status_t status = parcel->writeStrongBinder(token) ?: parcel->writeInt64(dispatchingTimeout.count()) ?: parcel->writeInt32(id) ?: @@ -98,8 +98,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeFloat(transform.dsdy()) ?: parcel->writeFloat(transform.ty()) ?: parcel->writeBool(visible) ?: - parcel->writeBool(canReceiveKeys) ?: - parcel->writeBool(hasFocus) ?: + parcel->writeBool(focusable) ?: parcel->writeBool(hasWallpaper) ?: parcel->writeBool(paused) ?: parcel->writeBool(trustedOverlay) ?: @@ -112,7 +111,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->write(touchableRegion) ?: parcel->writeBool(replaceTouchableRegionWithCrop) ?: parcel->writeStrongBinder(touchableRegionCropHandle.promote()); - + // clang-format on return status; } @@ -135,6 +134,7 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { flags = Flags(parcel->readInt32()); type = static_cast(parcel->readInt32()); float dsdx, dtdx, tx, dtdy, dsdy, ty; + // clang-format off status = parcel->readInt32(&frameLeft) ?: parcel->readInt32(&frameTop) ?: parcel->readInt32(&frameRight) ?: @@ -148,13 +148,13 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readFloat(&dsdy) ?: parcel->readFloat(&ty) ?: parcel->readBool(&visible) ?: - parcel->readBool(&canReceiveKeys) ?: - parcel->readBool(&hasFocus) ?: + parcel->readBool(&focusable) ?: parcel->readBool(&hasWallpaper) ?: parcel->readBool(&paused) ?: parcel->readBool(&trustedOverlay) ?: parcel->readInt32(&ownerPid) ?: parcel->readInt32(&ownerUid); + // clang-format on if (status != OK) { return status; diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 7e3a40d7cc..65a7761aec 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -55,8 +55,7 @@ TEST(InputWindowInfo, Parcelling) { i.globalScaleFactor = 0.3; i.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); i.visible = false; - i.canReceiveKeys = false; - i.hasFocus = false; + i.focusable = false; i.hasWallpaper = false; i.paused = false; i.ownerPid = 19; @@ -89,8 +88,7 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor); ASSERT_EQ(i.transform, i2.transform); ASSERT_EQ(i.visible, i2.visible); - ASSERT_EQ(i.canReceiveKeys, i2.canReceiveKeys); - ASSERT_EQ(i.hasFocus, i2.hasFocus); + ASSERT_EQ(i.focusable, i2.focusable); ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper); ASSERT_EQ(i.paused, i2.paused); ASSERT_EQ(i.ownerPid, i2.ownerPid); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index f99fffe22b..b645d69267 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -171,8 +171,7 @@ public: mInfo.touchableRegion.clear(); mInfo.addTouchableRegion(mFrame); mInfo.visible = true; - mInfo.canReceiveKeys = true; - mInfo.hasFocus = true; + mInfo.focusable = true; mInfo.hasWallpaper = false; mInfo.paused = false; mInfo.ownerPid = INJECTOR_PID; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 5d716665af..078448f400 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3818,7 +3818,7 @@ void InputDispatcher::setInputWindowsLocked( bool foundHoveredWindow = false; for (const sp& windowHandle : getWindowHandlesLocked(displayId)) { // Set newFocusedWindowHandle to the top most focused window instead of the last one - if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus && + if (!newFocusedWindowHandle && windowHandle->getInfo()->focusable && windowHandle->getInfo()->visible) { newFocusedWindowHandle = windowHandle; } @@ -4221,18 +4221,17 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, " - "portalToDisplayId=%d, paused=%s, hasFocus=%s, " - "hasWallpaper=%s, visible=%s, canReceiveKeys=%s, " + "portalToDisplayId=%d, paused=%s, focusable=%s, " + "hasWallpaper=%s, visible=%s, " "flags=%s, type=0x%08x, " "frame=[%d,%d][%d,%d], globalScale=%f, " "touchableRegion=", i, windowInfo->name.c_str(), windowInfo->displayId, windowInfo->portalToDisplayId, toString(windowInfo->paused), - toString(windowInfo->hasFocus), + toString(windowInfo->focusable), toString(windowInfo->hasWallpaper), toString(windowInfo->visible), - toString(windowInfo->canReceiveKeys), windowInfo->flags.string().c_str(), static_cast(windowInfo->type), windowInfo->frameLeft, windowInfo->frameTop, diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index c7bb2ac382..da50af5c5f 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -777,8 +777,7 @@ public: mInfo.touchableRegion.clear(); mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT)); mInfo.visible = true; - mInfo.canReceiveKeys = true; - mInfo.hasFocus = false; + mInfo.focusable = false; mInfo.hasWallpaper = false; mInfo.paused = false; mInfo.ownerPid = INJECTOR_PID; @@ -788,7 +787,7 @@ public: virtual bool updateInfo() { return true; } - void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; } + void setFocusable(bool focusable) { mInfo.focusable = focusable; } void setDispatchingTimeout(std::chrono::nanoseconds timeout) { mInfo.dispatchingTimeout = timeout; @@ -1237,7 +1236,7 @@ TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) { mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); // Display should have only one focused window - windowSecond->setFocus(true); + windowSecond->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}}); windowSecond->consumeFocusEvent(true); @@ -1260,8 +1259,8 @@ TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) { mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first) - windowTop->setFocus(true); - windowSecond->setFocus(true); + windowTop->setFocusable(true); + windowSecond->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}}); windowTop->consumeFocusEvent(true); @@ -1284,8 +1283,8 @@ TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) { // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); - windowTop->setFocus(true); - windowSecond->setFocus(true); + windowTop->setFocusable(true); + windowSecond->setFocusable(true); // Release channel for window is no longer valid. windowTop->releaseChannel(); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}}); @@ -1521,7 +1520,7 @@ TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) { std::shared_ptr application = std::make_shared(); sp window = new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); - window->setFocus(true); + window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(true); @@ -1723,7 +1722,7 @@ TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) { sp window = new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); - window->setFocus(true); + window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(true); @@ -1831,7 +1830,7 @@ TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) { new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); - window->setFocus(true); + window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(true); @@ -1923,31 +1922,31 @@ TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) { // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); - window->setFocus(true); + window->setFocusable(true); SCOPED_TRACE("Check default value of touch mode"); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/); SCOPED_TRACE("Remove the window to trigger focus loss"); - window->setFocus(false); + window->setFocusable(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/); SCOPED_TRACE("Disable touch mode"); mDispatcher->setInTouchMode(false); - window->setFocus(true); + window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/); SCOPED_TRACE("Remove the window to trigger focus loss"); - window->setFocus(false); + window->setFocusable(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/); SCOPED_TRACE("Enable touch mode again"); mDispatcher->setInTouchMode(true); - window->setFocus(true); + window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/); @@ -1960,7 +1959,7 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) { new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); - window->setFocus(true); + window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/); @@ -2050,7 +2049,7 @@ protected: mApp = std::make_shared(); mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT); - mWindow->setFocus(true); + mWindow->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); mWindow->consumeFocusEvent(true); @@ -2140,7 +2139,7 @@ public: // Set focus window for primary display, but focused display would be second one. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1); - windowInPrimary->setFocus(true); + windowInPrimary->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}}); windowInPrimary->consumeFocusEvent(true); @@ -2152,7 +2151,7 @@ public: mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID); // Set focus window for second display. mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2); - windowInSecondary->setFocus(true); + windowInSecondary->setFocusable(true); mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); windowInSecondary->consumeFocusEvent(true); } @@ -2364,7 +2363,7 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); - mFocusedWindow->setFocus(true); + mFocusedWindow->setFocusable(true); // Expect one focus window exist in display. mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}}); @@ -2652,7 +2651,7 @@ class InputDispatcherSingleWindowAnr : public InputDispatcherTest { new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT); mWindow->setFrame(Rect(0, 0, 30, 30)); mWindow->setDispatchingTimeout(30ms); - mWindow->setFocus(true); + mWindow->setFocusable(true); // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this // window. mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL); @@ -2734,7 +2733,7 @@ TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) { // We have a focused application, but no focused window TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) { - mWindow->setFocus(false); + mWindow->setFocusable(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); mWindow->consumeFocusEvent(false); @@ -2762,7 +2761,7 @@ TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) { // If the policy wants to keep waiting on the focused window to be added, make sure // that this timeout extension is honored and ANR is raised again. TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) { - mWindow->setFocus(false); + mWindow->setFocusable(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); mWindow->consumeFocusEvent(false); const std::chrono::duration timeout = 5ms; @@ -2790,7 +2789,7 @@ TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) { // We have a focused application, but no focused window TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) { - mWindow->setFocus(false); + mWindow->setFocusable(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); mWindow->consumeFocusEvent(false); @@ -3050,7 +3049,7 @@ class InputDispatcherMultiWindowAnr : public InputDispatcherTest { // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication); - mFocusedWindow->setFocus(true); + mFocusedWindow->setFocusable(true); // Expect one focus window exist in display. mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}}); @@ -3247,8 +3246,8 @@ TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) { ASSERT_FALSE(keySequenceNum); // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there - mFocusedWindow->setFocus(false); - mUnfocusedWindow->setFocus(true); + mFocusedWindow->setFocusable(false); + mUnfocusedWindow->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}}); // Focus events should precede the key events diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index a4922faadc..99b96e9554 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -73,9 +73,8 @@ static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 450 /* bottom */}; static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect); static constexpr bool TestInfoVisible = false; -static constexpr bool TestInfoCanReceiveKeys = false; static constexpr bool TestInfoTrustedOverlay = true; -static constexpr bool TestInfoHasFocus = false; +static constexpr bool TestInfoFocusable = false; static constexpr bool TestInfoHasWallpaper = false; static constexpr bool TestInfoPaused = false; static constexpr int32_t TestInfoOwnerPid = 19; @@ -295,9 +294,9 @@ void InputFlingerServiceTest::SetUp() { TestInfoFrameTop, 0, 0, 1}); mInfo.touchableRegion = TestInfoTouchableRegion; mInfo.visible = TestInfoVisible; - mInfo.canReceiveKeys = TestInfoCanReceiveKeys; mInfo.trustedOverlay = TestInfoTrustedOverlay; - mInfo.hasFocus = TestInfoHasFocus; + mInfo.focusable = TestInfoFocusable; + mInfo.hasWallpaper = TestInfoHasWallpaper; mInfo.paused = TestInfoPaused; mInfo.ownerPid = TestInfoOwnerPid; diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 5d99908b77..59fad9bf0f 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -146,8 +146,7 @@ void LayerProtoHelper::writeToProto( proto->set_surface_inset(inputInfo.surfaceInset); proto->set_visible(inputInfo.visible); - proto->set_can_receive_keys(inputInfo.canReceiveKeys); - proto->set_has_focus(inputInfo.hasFocus); + proto->set_focusable(inputInfo.focusable); proto->set_has_wallpaper(inputInfo.hasWallpaper); proto->set_global_scale_factor(inputInfo.globalScaleFactor); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 41d6d08e11..f3f56265e0 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -193,8 +193,8 @@ message InputWindowInfoProto { uint32 surface_inset = 5; bool visible = 6; - bool can_receive_keys = 7; - bool has_focus = 8; + bool can_receive_keys = 7 [deprecated=true]; + bool focusable = 8; bool has_wallpaper = 9; float global_scale_factor = 10; -- cgit v1.2.3-59-g8ed1b From ea97d18b244d01edff2098848022d125af350140 Mon Sep 17 00:00:00 2001 From: Bernardo Rufino Date: Wed, 19 Aug 2020 14:43:14 +0100 Subject: Block untrusted touches in InputDispatcher With topic CL InputDispatcher now has the effect of each window for cross-UID touch occlusion rules: ALLOW, USE_OPACITY or BLOCK_UNTRUSTED. Check topic CL for exact meaning of each. USE_OPACITY is only used by SAWs for now. In this CL, InputDispatcher make use of that information for the stack of windows above the touch-consuming window to block a touch or not. The summary of the rules are: * If there is any visible untrusted window from a different UID (than the touch-consuming window UID) that has state BLOCK_UNTRUSTED, the touch is blocked. * Else, if there is any visible untrusted window from a different UID that has state USE_OPACITY, we compute the composed obscuring opacity by each stack of USE_OPACITY windows per UID of occluding window. We take maximum of those and compare with secure setting "maximum_obscuring_opacity_for_touch", if it's greater than the setting the touch is blocked. This means the remaining visibility on the touch-consuming window is not high enough to let the touch happen. * Else we don't block the touch. More details on go/cross-uid-touches. This doesn't interfere with existing flags FLAG_WINDOW_IS_OBSCURED and FLAG_WINDOW_IS_PARTIALLY_OBSCURED. To compute the opacity we also propagate the alpha of each window from SurfaceFlinger to InputDispatcher. Test: atest WindowUntrustedTouchTest Test: atest inputflinger_tests inputflinger_benchmarks libinput_tests Test: go/try-cross-uid-touches for manual testing Bug: 158002302 Change-Id: I673d7a5f16b19952311e8cb44a48af4349a4bd40 --- include/input/InputWindow.h | 9 ++ libs/input/Android.bp | 6 ++ libs/input/InputWindow.cpp | 20 +++- .../android/os/BlockUntrustedTouchesMode.aidl | 35 +++++++ libs/input/android/os/TouchOcclusionMode.aidl | 47 +++++++++ libs/input/tests/InputWindow_test.cpp | 6 ++ .../inputflinger/dispatcher/InputDispatcher.cpp | 110 +++++++++++++++++++++ services/inputflinger/dispatcher/InputDispatcher.h | 15 +++ .../dispatcher/include/InputDispatcherInterface.h | 18 ++++ services/surfaceflinger/Layer.cpp | 1 + 10 files changed, 262 insertions(+), 5 deletions(-) create mode 100644 libs/input/android/os/BlockUntrustedTouchesMode.aidl create mode 100644 libs/input/android/os/TouchOcclusionMode.aidl (limited to 'libs/input/InputWindow.cpp') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 7372022078..36097d6d65 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -17,6 +17,7 @@ #ifndef _UI_INPUT_WINDOW_H #define _UI_INPUT_WINDOW_H +#include #include #include #include @@ -30,6 +31,8 @@ #include "InputApplication.h" +using android::os::TouchOcclusionMode; + namespace android { /* @@ -158,6 +161,10 @@ struct InputWindowInfo : public Parcelable { // in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis. float globalScaleFactor = 1.0f; + // The opacity of this window, from 0.0 to 1.0 (inclusive). + // An alpha of 1.0 means fully opaque and 0.0 means fully transparent. + float alpha; + // Transform applied to individual windows. ui::Transform transform; @@ -176,8 +183,10 @@ struct InputWindowInfo : public Parcelable { * 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 inputFeatures; int32_t displayId = ADISPLAY_ID_NONE; int32_t portalToDisplayId = ADISPLAY_ID_NONE; diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 8f575a8cae..b442700138 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -18,6 +18,8 @@ filegroup { name: "inputconstants_aidl", srcs: [ "android/os/IInputConstants.aidl", + "android/os/TouchOcclusionMode.aidl", + "android/os/BlockUntrustedTouchesMode.aidl", ], } @@ -71,10 +73,14 @@ cc_library { "android/FocusRequest.aidl", "android/InputApplicationInfo.aidl", "android/os/IInputConstants.aidl", + "android/os/TouchOcclusionMode.aidl", + "android/os/BlockUntrustedTouchesMode.aidl", "android/os/IInputFlinger.aidl", "android/os/ISetInputWindowsListener.aidl", ], + export_shared_lib_headers: ["libbinder"], + shared_libs: [ "libutils", "libbinder", diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 885dc9b51e..8546bbbb43 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -59,10 +59,11 @@ bool InputWindowInfo::operator==(const InputWindowInfo& info) const { info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor && info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && info.trustedOverlay == trustedOverlay && - info.focusable == focusable && info.hasWallpaper == hasWallpaper && - info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && - info.inputFeatures == inputFeatures && info.displayId == displayId && - info.portalToDisplayId == portalToDisplayId && + info.focusable == focusable && info.touchOcclusionMode == touchOcclusionMode && + info.hasWallpaper == hasWallpaper && info.paused == paused && + info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.packageName == packageName && info.inputFeatures == inputFeatures && + info.displayId == displayId && info.portalToDisplayId == portalToDisplayId && info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && info.applicationInfo == applicationInfo; } @@ -91,6 +92,7 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeInt32(frameBottom) ?: parcel->writeInt32(surfaceInset) ?: parcel->writeFloat(globalScaleFactor) ?: + parcel->writeFloat(alpha) ?: parcel->writeFloat(transform.dsdx()) ?: parcel->writeFloat(transform.dtdx()) ?: parcel->writeFloat(transform.tx()) ?: @@ -102,8 +104,10 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeBool(hasWallpaper) ?: parcel->writeBool(paused) ?: parcel->writeBool(trustedOverlay) ?: + parcel->writeInt32(static_cast(touchOcclusionMode)) ?: parcel->writeInt32(ownerPid) ?: parcel->writeInt32(ownerUid) ?: + parcel->writeUtf8AsUtf16(packageName) ?: parcel->writeInt32(inputFeatures.get()) ?: parcel->writeInt32(displayId) ?: parcel->writeInt32(portalToDisplayId) ?: @@ -134,6 +138,7 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { flags = Flags(parcel->readInt32()); type = static_cast(parcel->readInt32()); float dsdx, dtdx, tx, dtdy, dsdy, ty; + int32_t touchOcclusionModeInt; // clang-format off status = parcel->readInt32(&frameLeft) ?: parcel->readInt32(&frameTop) ?: @@ -141,6 +146,7 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readInt32(&frameBottom) ?: parcel->readInt32(&surfaceInset) ?: parcel->readFloat(&globalScaleFactor) ?: + parcel->readFloat(&alpha) ?: parcel->readFloat(&dsdx) ?: parcel->readFloat(&dtdx) ?: parcel->readFloat(&tx) ?: @@ -152,14 +158,18 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readBool(&hasWallpaper) ?: parcel->readBool(&paused) ?: parcel->readBool(&trustedOverlay) ?: + parcel->readInt32(&touchOcclusionModeInt) ?: parcel->readInt32(&ownerPid) ?: - parcel->readInt32(&ownerUid); + parcel->readInt32(&ownerUid) ?: + parcel->readUtf8FromUtf16(&packageName); // clang-format on if (status != OK) { return status; } + touchOcclusionMode = static_cast(touchOcclusionModeInt); + inputFeatures = Flags(parcel->readInt32()); status = parcel->readInt32(&displayId) ?: parcel->readInt32(&portalToDisplayId) ?: diff --git a/libs/input/android/os/BlockUntrustedTouchesMode.aidl b/libs/input/android/os/BlockUntrustedTouchesMode.aidl new file mode 100644 index 0000000000..9504e993f8 --- /dev/null +++ b/libs/input/android/os/BlockUntrustedTouchesMode.aidl @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + + +/** + * Block untrusted touches feature mode. + * + * @hide + */ +@Backing(type="int") +enum BlockUntrustedTouchesMode { + /** Feature is off. */ + DISABLED, + + /** Untrusted touches are flagged but not blocked. */ + PERMISSIVE, + + /** Untrusted touches are blocked. */ + BLOCK +} diff --git a/libs/input/android/os/TouchOcclusionMode.aidl b/libs/input/android/os/TouchOcclusionMode.aidl new file mode 100644 index 0000000000..106f159a50 --- /dev/null +++ b/libs/input/android/os/TouchOcclusionMode.aidl @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + + +/** + * Touch occlusion modes: These modes represent how windows are taken into + * consideration in order to decide whether to block obscured touches or + * not. + * + * @hide + */ +@Backing(type="int") +enum TouchOcclusionMode { + /** + * Touches that pass through this window will be blocked if they are + * consumed by a different UID and this window is not trusted. + */ + BLOCK_UNTRUSTED, + + /** + * The window's opacity will be taken into consideration for touch + * occlusion rules if the touch passes through it and the window is not + * trusted. + */ + USE_OPACITY, + + /** + * The window won't count for touch occlusion rules if the touch passes + * through it. + */ + ALLOW +} diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 65a7761aec..c18a17f1ae 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -53,13 +53,16 @@ TEST(InputWindowInfo, Parcelling) { i.frameBottom = 19; i.surfaceInset = 17; 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 = InputWindowInfo::Feature::DISABLE_USER_ACTIVITY; i.displayId = 34; i.portalToDisplayId = 2; @@ -86,13 +89,16 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.frameBottom, i2.frameBottom); ASSERT_EQ(i.surfaceInset, i2.surfaceInset); 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.displayId, i2.displayId); ASSERT_EQ(i.portalToDisplayId, i2.portalToDisplayId); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 3ccb0c966e..ab0d340363 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -402,6 +402,7 @@ InputDispatcher::InputDispatcher(const sp& polic // To avoid leaking stack in case that call never comes, and for tests, // initialize it here anyways. mInTouchMode(true), + mMaximumObscuringOpacityForTouch(1.0f), mFocusedDisplayId(ADISPLAY_ID_DEFAULT) { mLooper = new Looper(false); mReporter = createInputReporter(); @@ -1708,6 +1709,22 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } } + // Drop events that can't be trusted due to occlusion + if (newTouchedWindowHandle != nullptr && + mBlockUntrustedTouchesMode != BlockUntrustedTouchesMode::DISABLED) { + TouchOcclusionInfo occlusionInfo = + computeTouchOcclusionInfoLocked(newTouchedWindowHandle, x, y); + // The order of the operands in the 'if' below is important because even if the feature + // is not BLOCK we want isTouchTrustedLocked() to execute in order to log details to + // logcat. + if (!isTouchTrustedLocked(occlusionInfo) && + mBlockUntrustedTouchesMode == BlockUntrustedTouchesMode::BLOCK) { + ALOGW("Dropping untrusted touch event due to %s/%d", + occlusionInfo.obscuringPackage.c_str(), occlusionInfo.obscuringUid); + newTouchedWindowHandle = nullptr; + } + } + // Also don't send the new touch event to unresponsive gesture monitors newGestureMonitors = selectResponsiveMonitorsLocked(newGestureMonitors); @@ -2121,6 +2138,84 @@ static bool canBeObscuredBy(const sp& windowHandle, return true; } +/** + * Returns touch occlusion information in the form of TouchOcclusionInfo. To check if the touch is + * untrusted, one should check: + * + * 1. If result.hasBlockingOcclusion is true. + * If it's, it means the touch should be blocked due to a window with occlusion mode of + * BLOCK_UNTRUSTED. + * + * 2. If result.obscuringOpacity > mMaximumObscuringOpacityForTouch. + * If it is (and 1 is false), then the touch should be blocked because a stack of windows + * (possibly only one) with occlusion mode of USE_OPACITY from one UID resulted in a composed + * obscuring opacity above the threshold. Note that if there was no window of occlusion mode + * USE_OPACITY, result.obscuringOpacity would've been 0 and since + * mMaximumObscuringOpacityForTouch >= 0, the condition above would never be true. + * + * If neither of those is true, then it means the touch can be allowed. + */ +InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked( + const sp& windowHandle, int32_t x, int32_t y) const { + int32_t displayId = windowHandle->getInfo()->displayId; + const std::vector>& windowHandles = getWindowHandlesLocked(displayId); + TouchOcclusionInfo info; + info.hasBlockingOcclusion = false; + info.obscuringOpacity = 0; + info.obscuringUid = -1; + std::map opacityByUid; + for (const sp& otherHandle : windowHandles) { + if (windowHandle == otherHandle) { + break; // All future windows are below us. Exit early. + } + const InputWindowInfo* otherInfo = otherHandle->getInfo(); + if (canBeObscuredBy(windowHandle, otherHandle) && + windowHandle->getInfo()->ownerUid != otherInfo->ownerUid && + otherInfo->frameContainsPoint(x, y)) { + // canBeObscuredBy() has returned true above, which means this window is untrusted, so + // we perform the checks below to see if the touch can be propagated or not based on the + // window's touch occlusion mode + if (otherInfo->touchOcclusionMode == TouchOcclusionMode::BLOCK_UNTRUSTED) { + info.hasBlockingOcclusion = true; + info.obscuringUid = otherInfo->ownerUid; + info.obscuringPackage = otherInfo->packageName; + break; + } + if (otherInfo->touchOcclusionMode == TouchOcclusionMode::USE_OPACITY) { + uint32_t uid = otherInfo->ownerUid; + float opacity = + (opacityByUid.find(uid) == opacityByUid.end()) ? 0 : opacityByUid[uid]; + // Given windows A and B: + // opacity(A, B) = 1 - [1 - opacity(A)] * [1 - opacity(B)] + opacity = 1 - (1 - opacity) * (1 - otherInfo->alpha); + opacityByUid[uid] = opacity; + if (opacity > info.obscuringOpacity) { + info.obscuringOpacity = opacity; + info.obscuringUid = uid; + info.obscuringPackage = otherInfo->packageName; + } + } + } + } + return info; +} + +bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const { + if (occlusionInfo.hasBlockingOcclusion) { + ALOGW("Untrusted touch due to occlusion by %s/%d", occlusionInfo.obscuringPackage.c_str(), + occlusionInfo.obscuringUid); + return false; + } + if (occlusionInfo.obscuringOpacity > mMaximumObscuringOpacityForTouch) { + ALOGW("Untrusted touch due to occlusion by %s/%d (obscuring opacity = " + "%.2f, maximum allowed = %.2f)", + occlusionInfo.obscuringPackage.c_str(), occlusionInfo.obscuringUid, + occlusionInfo.obscuringOpacity, mMaximumObscuringOpacityForTouch); + return false; + } + return true; +} + bool InputDispatcher::isWindowObscuredAtPointLocked(const sp& windowHandle, int32_t x, int32_t y) const { int32_t displayId = windowHandle->getInfo()->displayId; @@ -4060,6 +4155,21 @@ void InputDispatcher::setInTouchMode(bool inTouchMode) { mInTouchMode = inTouchMode; } +void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) { + if (opacity < 0 || opacity > 1) { + LOG_ALWAYS_FATAL("Maximum obscuring opacity for touch should be >= 0 and <= 1"); + return; + } + + std::scoped_lock lock(mLock); + mMaximumObscuringOpacityForTouch = opacity; +} + +void InputDispatcher::setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mode) { + std::scoped_lock lock(mLock); + mBlockUntrustedTouchesMode = mode; +} + bool InputDispatcher::transferTouchFocus(const sp& fromToken, const sp& toToken) { if (fromToken == toToken) { if (DEBUG_FOCUS) { diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 4fcdcc297e..d361b172e1 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -112,6 +112,8 @@ public: virtual void setInputDispatchMode(bool enabled, bool frozen) override; virtual void setInputFilterEnabled(bool enabled) override; virtual void setInTouchMode(bool inTouchMode) override; + virtual void setMaximumObscuringOpacityForTouch(float opacity) override; + virtual void setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mode) override; virtual bool transferTouchFocus(const sp& fromToken, const sp& toToken) override; @@ -296,6 +298,8 @@ private: bool mDispatchFrozen GUARDED_BY(mLock); bool mInputFilterEnabled GUARDED_BY(mLock); bool mInTouchMode GUARDED_BY(mLock); + float mMaximumObscuringOpacityForTouch GUARDED_BY(mLock); + BlockUntrustedTouchesMode mBlockUntrustedTouchesMode GUARDED_BY(mLock); std::unordered_map>> mWindowHandlesByDisplay GUARDED_BY(mLock); @@ -446,6 +450,17 @@ private: void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); bool checkInjectionPermission(const sp& windowHandle, const InjectionState* injectionState); + + struct TouchOcclusionInfo { + bool hasBlockingOcclusion; + float obscuringOpacity; + std::string obscuringPackage; + int32_t obscuringUid; + }; + + TouchOcclusionInfo computeTouchOcclusionInfoLocked(const sp& windowHandle, + int32_t x, int32_t y) const REQUIRES(mLock); + bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock); bool isWindowObscuredAtPointLocked(const sp& windowHandle, int32_t x, int32_t y) const REQUIRES(mLock); bool isWindowObscuredLocked(const sp& windowHandle) const REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 67d9a06108..65687c4c9b 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -20,12 +20,15 @@ #include #include #include +#include #include #include #include #include #include +using android::os::BlockUntrustedTouchesMode; + namespace android { /* @@ -145,6 +148,21 @@ public: */ virtual void setInTouchMode(bool inTouchMode) = 0; + /** + * Sets the maximum allowed obscuring opacity by UID to propagate touches. + * For certain window types (eg. SAWs), the decision of honoring + * FLAG_NOT_TOUCHABLE or not depends on the combined obscuring opacity of + * the windows above the touch-consuming window. + */ + virtual void setMaximumObscuringOpacityForTouch(float opacity) = 0; + + /** + * Sets the mode of the block untrusted touches feature. + * + * TODO(b/169067926): Clean-up feature modes. + */ + virtual void setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mode) = 0; + /* Transfers touch focus from one window to another window. * * Returns true on success. False if the window did not actually have touch focus. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 85046a4194..0127b31229 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2485,6 +2485,7 @@ InputWindowInfo Layer::fillInputInfo() { // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. info.visible = hasInputInfo() ? canReceiveInput() : isVisible(); + info.alpha = getAlpha(); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { -- cgit v1.2.3-59-g8ed1b From 44edce91b5253d325a2c3b225edf8008d14bb420 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Fri, 14 May 2021 18:09:55 -0700 Subject: Parcel/Unparcel displaysize in InputWindowInfo Somehow left this out causing compatraw to not work. Also converted some float displaySize to int to match the rest of displaySize uses. Bug: 179274888 Test: atest libinput_tests:InputWindowInfo Change-Id: I194f562e448d67d6fd8a04b86376e54c13933ae5 --- libs/input/InputWindow.cpp | 15 ++++++++++----- libs/input/tests/InputWindow_test.cpp | 4 ++++ services/inputflinger/dispatcher/Entry.cpp | 2 +- services/inputflinger/dispatcher/Entry.h | 4 ++-- services/inputflinger/dispatcher/InputDispatcher.cpp | 2 +- services/inputflinger/dispatcher/InputTarget.h | 2 +- 6 files changed, 19 insertions(+), 10 deletions(-) (limited to 'libs/input/InputWindow.cpp') diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 8546bbbb43..99477200db 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -57,11 +57,12 @@ bool InputWindowInfo::operator==(const InputWindowInfo& info) const { 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.transform == transform && info.displayWidth == displayWidth && + info.displayHeight == displayHeight && + 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 && info.displayId == displayId && info.portalToDisplayId == portalToDisplayId && info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && @@ -99,6 +100,8 @@ status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeFloat(transform.dtdy()) ?: parcel->writeFloat(transform.dsdy()) ?: parcel->writeFloat(transform.ty()) ?: + parcel->writeInt32(displayWidth) ?: + parcel->writeInt32(displayHeight) ?: parcel->writeBool(visible) ?: parcel->writeBool(focusable) ?: parcel->writeBool(hasWallpaper) ?: @@ -153,6 +156,8 @@ status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->readFloat(&dtdy) ?: parcel->readFloat(&dsdy) ?: parcel->readFloat(&ty) ?: + parcel->readInt32(&displayWidth) ?: + parcel->readInt32(&displayHeight) ?: parcel->readBool(&visible) ?: parcel->readBool(&focusable) ?: parcel->readBool(&hasWallpaper) ?: diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index c18a17f1ae..493f2f4495 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -55,6 +55,8 @@ TEST(InputWindowInfo, Parcelling) { i.globalScaleFactor = 0.3; i.alpha = 0.7; i.transform.set({0.4, -1, 100, 0.5, 0, 40, 0, 0, 1}); + i.displayWidth = 1000; + i.displayHeight = 2000; i.visible = false; i.focusable = false; i.hasWallpaper = false; @@ -91,6 +93,8 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor); ASSERT_EQ(i.alpha, i2.alpha); ASSERT_EQ(i.transform, i2.transform); + ASSERT_EQ(i.displayWidth, i2.displayWidth); + ASSERT_EQ(i.displayHeight, i2.displayHeight); ASSERT_EQ(i.visible, i2.visible); ASSERT_EQ(i.focusable, i2.focusable); ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper); diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index 6ed959306b..881024fc6e 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -296,7 +296,7 @@ std::string SensorEntry::getDescription() const { volatile int32_t DispatchEntry::sNextSeqAtomic; DispatchEntry::DispatchEntry(std::shared_ptr eventEntry, int32_t targetFlags, - ui::Transform transform, float globalScaleFactor, vec2 displaySize) + ui::Transform transform, float globalScaleFactor, int2 displaySize) : seq(nextSeq()), eventEntry(std::move(eventEntry)), targetFlags(targetFlags), diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 45c5e24395..b5d3571fcc 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -215,7 +215,7 @@ struct DispatchEntry { int32_t targetFlags; ui::Transform transform; float globalScaleFactor; - vec2 displaySize; + int2 displaySize; // Both deliveryTime and timeoutTime are only populated when the entry is sent to the app, // and will be undefined before that. nsecs_t deliveryTime; // time when the event was actually delivered @@ -228,7 +228,7 @@ struct DispatchEntry { int32_t resolvedFlags; DispatchEntry(std::shared_ptr eventEntry, int32_t targetFlags, - ui::Transform transform, float globalScaleFactor, vec2 displaySize); + ui::Transform transform, float globalScaleFactor, int2 displaySize); inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; } diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8bc877fd85..485a53a58e 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2385,7 +2385,7 @@ void InputDispatcher::addWindowTargetLocked(const sp& windowH inputTarget.flags = targetFlags; inputTarget.globalScaleFactor = windowInfo->globalScaleFactor; inputTarget.displaySize = - vec2(windowHandle->getInfo()->displayWidth, windowHandle->getInfo()->displayHeight); + int2(windowHandle->getInfo()->displayWidth, windowHandle->getInfo()->displayHeight); inputTargets.push_back(inputTarget); it = inputTargets.end() - 1; } diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h index 2543852788..1c4980b302 100644 --- a/services/inputflinger/dispatcher/InputTarget.h +++ b/services/inputflinger/dispatcher/InputTarget.h @@ -101,7 +101,7 @@ struct InputTarget { float globalScaleFactor = 1.0f; // Display-size in its natural rotation. Used for compatibility transform of raw coordinates. - vec2 displaySize = {AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE}; + int2 displaySize = {AMOTION_EVENT_INVALID_DISPLAY_SIZE, AMOTION_EVENT_INVALID_DISPLAY_SIZE}; // The subset of pointer ids to include in motion events dispatched to this input target // if FLAG_SPLIT is set. -- cgit v1.2.3-59-g8ed1b