From 00f511d329924824b1961e9472c3a06683fc2216 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Wed, 12 Jun 2019 16:55:40 -0700 Subject: Dispatch mouse events to window under the cursor. This CL adds cursor positions to NotifyMotionArgs, MotionEntry, InputMessage motion body and MotionEvent. Bug: 134788085 Test: The window under the cursor always responds to the gesture. Test: atest inputflinger_tests Test: atest libinput_tests Change-Id: I8ea460ed8738ffc3a5e997215685889cc1e1f2fe --- include/input/Input.h | 48 ++++++++++++++++++++++++------------------ include/input/InputTransport.h | 31 +++++++++------------------ 2 files changed, 37 insertions(+), 42 deletions(-) (limited to 'include/input') diff --git a/include/input/Input.h b/include/input/Input.h index 805957a5ca..a97624658c 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -24,12 +24,14 @@ */ #include +#include #include #include #include #include #include -#include + +#include /* * Additional private constants not defined in ndk/ui/input.h. @@ -246,6 +248,13 @@ enum class MotionClassification : uint8_t { */ const char* motionClassificationToString(MotionClassification classification); +/** + * Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't + * use it for direct comparison with any other value, because NaN isn't equal to itself according to + * IEEE 754. Use isnan() instead to check if a cursor position is valid. + */ +constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits::quiet_NaN(); + /* * Pointer coordinate data. */ @@ -459,6 +468,14 @@ public: inline float getYPrecision() const { return mYPrecision; } + inline float getRawXCursorPosition() const { return mXCursorPosition; } + + float getXCursorPosition() const; + + inline float getRawYCursorPosition() const { return mYCursorPosition; } + + float getYCursorPosition() const; + inline nsecs_t getDownTime() const { return mDownTime; } inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; } @@ -600,26 +617,13 @@ public: ssize_t findPointerIndex(int32_t pointerId) const; - void initialize( - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t actionButton, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - MotionClassification classification, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords); + void initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action, + int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, + int32_t buttonState, MotionClassification classification, float xOffset, + float yOffset, float xPrecision, float yPrecision, float mXCursorPosition, + float mYCursorPosition, nsecs_t downTime, nsecs_t eventTime, + size_t pointerCount, const PointerProperties* pointerProperties, + const PointerCoords* pointerCoords); void copyFrom(const MotionEvent* other, bool keepHistory); @@ -669,6 +673,8 @@ protected: float mYOffset; float mXPrecision; float mYPrecision; + float mXCursorPosition; + float mYCursorPosition; nsecs_t mDownTime; Vector mPointerProperties; Vector mSampleEventTimes; diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 63606e5911..df23f613c8 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -113,6 +113,8 @@ struct InputMessage { float yOffset; float xPrecision; float yPrecision; + float xCursorPosition; + float yCursorPosition; uint32_t pointerCount; uint32_t empty3; // Note that PointerCoords requires 8 byte alignment. @@ -261,27 +263,14 @@ public: * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS. * Other errors probably indicate that the channel is broken. */ - status_t publishMotionEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t actionButton, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - MotionClassification classification, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - uint32_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords); + status_t publishMotionEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId, + int32_t action, int32_t actionButton, int32_t flags, + int32_t edgeFlags, int32_t metaState, int32_t buttonState, + MotionClassification classification, 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); /* Receives the finished signal from the consumer in reply to the original dispatch signal. * If a signal was received, returns the message sequence number, -- cgit v1.2.3-59-g8ed1b From ab0ab9c57c8fa9d8c9648734fea74ee010e28e8c Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Wed, 10 Jul 2019 18:58:28 -0700 Subject: Address comments from a previous change. The original change is 00f511d329924824b1961e9472c3a06683fc2216. Bug: 134788085 Test: atest libinput_tests Change-Id: I1f3326067f94fe6a09850f4389483e60fa57a8d4 --- include/input/Input.h | 3 +++ libs/input/Input.cpp | 3 +-- libs/input/tests/InputEvent_test.cpp | 10 +++++++--- services/inputflinger/InputDispatcher.cpp | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) (limited to 'include/input') diff --git a/include/input/Input.h b/include/input/Input.h index a97624658c..ad8c233577 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -476,6 +477,8 @@ public: float getYCursorPosition() const; + static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); } + inline nsecs_t getDownTime() const { return mDownTime; } inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; } diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 3266b0740d..dc4978b836 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -17,7 +17,6 @@ #define LOG_TAG "Input" //#define LOG_NDEBUG 0 -#include #include #include @@ -434,7 +433,7 @@ void MotionEvent::transform(const float matrix[9]) { transformPoint(matrix, 0, 0, &originX, &originY); // Apply the transformation to cursor position. - if (!isnan(mXCursorPosition) && !isnan(mYCursorPosition)) { + if (isValidCursorPosition(mXCursorPosition, mYCursorPosition)) { float x = mXCursorPosition + oldXOffset; float y = mYCursorPosition + oldYOffset; transformPoint(matrix, x, y, &x, &y); diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index ec34f3e652..b879de6a74 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -603,9 +603,13 @@ TEST_F(MotionEventTest, Transform) { ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1); } - // Check cursor positions. - ASSERT_NEAR(sinf(PI_180 * (90 + ROTATION)) * RADIUS, event.getXCursorPosition(), 0.001); - ASSERT_NEAR(-cosf(PI_180 * (90 + ROTATION)) * RADIUS, event.getYCursorPosition(), 0.001); + // Check cursor positions. The original cursor position is at (3 + RADIUS, 2), where the center + // of the circle is (3, 2), so the cursor position is to the right of the center of the circle. + // The choice of triangular functions in this test defines the angle of rotation clockwise + // relative to the y-axis. Therefore the cursor position's angle is 90 degrees. Here we swap the + // triangular function so that we don't have to add the 90 degrees. + ASSERT_NEAR(cosf(PI_180 * ROTATION) * RADIUS, event.getXCursorPosition(), 0.001); + ASSERT_NEAR(sinf(PI_180 * ROTATION) * RADIUS, event.getYCursorPosition(), 0.001); // Applying the transformation should preserve the raw X and Y of the first point. ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001); diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp index be1370747c..1d8c365702 100644 --- a/services/inputflinger/InputDispatcher.cpp +++ b/services/inputflinger/InputDispatcher.cpp @@ -2766,7 +2766,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { ", policyFlags=0x%x, " "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, " "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, " - "mYCursorPosition=%f, downTime=%" PRId64, + "yCursorPosition=%f, downTime=%" PRId64, args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags, args->action, args->actionButton, args->flags, args->metaState, args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision, arg->xCursorPosition, -- cgit v1.2.3-59-g8ed1b From 937bb83a143631fcb25f0962aa95c1f850fdf023 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Thu, 25 Jul 2019 17:48:31 -0700 Subject: Add setCursorPosition. When source is updated we need to update their values. Also renamed mX/YCursorPosition to mRawX/YCursorPosition to indicate it stores raw values (w/o applying offset). Bug: 134788085 Test: atest libinput_tests Change-Id: I1533d79a7542291974ff572d3aeaf9924e3f0751 --- include/input/Input.h | 14 ++++++++------ libs/input/Input.cpp | 35 ++++++++++++++++++++--------------- libs/input/tests/InputEvent_test.cpp | 10 ++++++++++ 3 files changed, 38 insertions(+), 21 deletions(-) (limited to 'include/input') diff --git a/include/input/Input.h b/include/input/Input.h index ad8c233577..cbd1a412bf 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -469,14 +469,16 @@ public: inline float getYPrecision() const { return mYPrecision; } - inline float getRawXCursorPosition() const { return mXCursorPosition; } + inline float getRawXCursorPosition() const { return mRawXCursorPosition; } float getXCursorPosition() const; - inline float getRawYCursorPosition() const { return mYCursorPosition; } + inline float getRawYCursorPosition() const { return mRawYCursorPosition; } float getYCursorPosition() const; + void setCursorPosition(float x, float y); + static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); } inline nsecs_t getDownTime() const { return mDownTime; } @@ -623,8 +625,8 @@ public: void initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action, int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState, MotionClassification classification, float xOffset, - float yOffset, float xPrecision, float yPrecision, float mXCursorPosition, - float mYCursorPosition, nsecs_t downTime, nsecs_t eventTime, + float yOffset, float xPrecision, float yPrecision, float rawXCursorPosition, + float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime, size_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); @@ -676,8 +678,8 @@ protected: float mYOffset; float mXPrecision; float mYPrecision; - float mXCursorPosition; - float mYCursorPosition; + float mRawXCursorPosition; + float mRawYCursorPosition; nsecs_t mDownTime; Vector mPointerProperties; Vector mSampleEventTimes; diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index dc4978b836..34b305e548 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -238,8 +238,8 @@ void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState, MotionClassification classification, float xOffset, float yOffset, - float xPrecision, float yPrecision, float xCursorPosition, - float yCursorPosition, nsecs_t downTime, nsecs_t eventTime, + 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(deviceId, source, displayId); @@ -254,8 +254,8 @@ void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId mYOffset = yOffset; mXPrecision = xPrecision; mYPrecision = yPrecision; - mXCursorPosition = xCursorPosition; - mYCursorPosition = yCursorPosition; + mRawXCursorPosition = rawXCursorPosition; + mRawYCursorPosition = rawYCursorPosition; mDownTime = downTime; mPointerProperties.clear(); mPointerProperties.appendArray(pointerProperties, pointerCount); @@ -277,8 +277,8 @@ void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { mYOffset = other->mYOffset; mXPrecision = other->mXPrecision; mYPrecision = other->mYPrecision; - mXCursorPosition = other->mXCursorPosition; - mYCursorPosition = other->mYCursorPosition; + mRawXCursorPosition = other->mRawXCursorPosition; + mRawYCursorPosition = other->mRawYCursorPosition; mDownTime = other->mDownTime; mPointerProperties = other->mPointerProperties; @@ -313,6 +313,11 @@ float MotionEvent::getYCursorPosition() const { return rawY + mYOffset; } +void MotionEvent::setCursorPosition(float x, float y) { + mRawXCursorPosition = x - mXOffset; + mRawYCursorPosition = y - mYOffset; +} + const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; } @@ -433,12 +438,12 @@ void MotionEvent::transform(const float matrix[9]) { transformPoint(matrix, 0, 0, &originX, &originY); // Apply the transformation to cursor position. - if (isValidCursorPosition(mXCursorPosition, mYCursorPosition)) { - float x = mXCursorPosition + oldXOffset; - float y = mYCursorPosition + oldYOffset; + if (isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition)) { + float x = mRawXCursorPosition + oldXOffset; + float y = mRawYCursorPosition + oldYOffset; transformPoint(matrix, x, y, &x, &y); - mXCursorPosition = x - mXOffset; - mYCursorPosition = y - mYOffset; + mRawXCursorPosition = x - mXOffset; + mRawYCursorPosition = y - mYOffset; } // Apply the transformation to all samples. @@ -480,8 +485,8 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) { mYOffset = parcel->readFloat(); mXPrecision = parcel->readFloat(); mYPrecision = parcel->readFloat(); - mXCursorPosition = parcel->readFloat(); - mYCursorPosition = parcel->readFloat(); + mRawXCursorPosition = parcel->readFloat(); + mRawYCursorPosition = parcel->readFloat(); mDownTime = parcel->readInt64(); mPointerProperties.clear(); @@ -533,8 +538,8 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { parcel->writeFloat(mYOffset); parcel->writeFloat(mXPrecision); parcel->writeFloat(mYPrecision); - parcel->writeFloat(mXCursorPosition); - parcel->writeFloat(mYCursorPosition); + parcel->writeFloat(mRawXCursorPosition); + parcel->writeFloat(mRawYCursorPosition); parcel->writeInt64(mDownTime); for (size_t i = 0; i < pointerCount; i++) { diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index b879de6a74..b90857c99c 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -665,4 +665,14 @@ TEST_F(MotionEventTest, Initialize_SetsCursorPosition) { ASSERT_EQ(600, event.getYCursorPosition()); } +TEST_F(MotionEventTest, SetCursorPosition) { + MotionEvent event; + initializeEventWithHistory(&event); + event.setSource(AINPUT_SOURCE_MOUSE); + + event.setCursorPosition(3, 4); + ASSERT_EQ(3, event.getXCursorPosition()); + ASSERT_EQ(4, event.getYCursorPosition()); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From 8384682fd25b54921fd74288788f2a9299dd8dba Mon Sep 17 00:00:00 2001 From: Atif Niyaz Date: Thu, 18 Jul 2019 15:17:40 -0700 Subject: Seperate LatencyStatistics from InputReader Test: atest LatencyStatisticsTest Change-Id: I22a39cd5bef7fa9180bc1ee1fd9478a2cf872e83 --- include/input/LatencyStatistics.h | 59 +++++++++++++++++++ libs/input/Android.bp | 1 + libs/input/LatencyStatistics.cpp | 90 +++++++++++++++++++++++++++++ libs/input/tests/Android.bp | 1 + libs/input/tests/LatencyStatistics_test.cpp | 72 +++++++++++++++++++++++ services/inputflinger/InputReader.cpp | 21 +++---- services/inputflinger/InputReader.h | 72 ++--------------------- 7 files changed, 237 insertions(+), 79 deletions(-) create mode 100644 include/input/LatencyStatistics.h create mode 100644 libs/input/LatencyStatistics.cpp create mode 100644 libs/input/tests/LatencyStatistics_test.cpp (limited to 'include/input') diff --git a/include/input/LatencyStatistics.h b/include/input/LatencyStatistics.h new file mode 100644 index 0000000000..bd86266901 --- /dev/null +++ b/include/input/LatencyStatistics.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef _UI_INPUT_STATISTICS_H +#define _UI_INPUT_STATISTICS_H + +#include + +#include + +namespace android { + +class LatencyStatistics { +private: + /* Minimum sample recorded */ + float mMin; + /* Maximum sample recorded */ + float mMax; + /* Sum of all samples recorded */ + float mSum; + /* Sum of all the squares of samples recorded */ + float mSum2; + /* Count of all samples recorded */ + size_t mCount; + /* The last time statistics were reported */ + std::chrono::steady_clock::time_point mLastReportTime; + /* Statistics Report Frequency */ + const std::chrono::seconds mReportPeriod; + +public: + LatencyStatistics(std::chrono::seconds period); + + void addValue(float); + void reset(); + bool shouldReport(); + + float getMean(); + float getMin(); + float getMax(); + float getStDev(); + size_t getCount(); +}; + +} // namespace android + +#endif // _UI_INPUT_STATISTICS_H diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 2d788119cd..17138506e5 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -48,6 +48,7 @@ cc_library { "InputTransport.cpp", "InputWindow.cpp", "ISetInputWindowsListener.cpp", + "LatencyStatistics.cpp", "VelocityControl.cpp", "VelocityTracker.cpp", ], diff --git a/libs/input/LatencyStatistics.cpp b/libs/input/LatencyStatistics.cpp new file mode 100644 index 0000000000..e343578e00 --- /dev/null +++ b/libs/input/LatencyStatistics.cpp @@ -0,0 +1,90 @@ +/* + * 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 + +#include + +#include +#include + +namespace android { + +LatencyStatistics::LatencyStatistics(std::chrono::seconds period) : mReportPeriod(period) { + reset(); +} + +/** + * Add a raw value to the statistics + */ +void LatencyStatistics::addValue(float value) { + if (value < mMin) { + mMin = value; + } + if (value > mMax) { + mMax = value; + } + mSum += value; + mSum2 += value * value; + mCount++; +} + +/** + * Get the mean. Should not be called if no samples have been added. + */ +float LatencyStatistics::getMean() { + return mSum / mCount; +} + +/** + * Get the standard deviation. Should not be called if no samples have been added. + */ +float LatencyStatistics::getStDev() { + float mean = getMean(); + return sqrt(mSum2 / mCount - mean * mean); +} + +float LatencyStatistics::getMin() { + return mMin; +} + +float LatencyStatistics::getMax() { + return mMax; +} + +size_t LatencyStatistics::getCount() { + return mCount; +} + +/** + * Reset internal state. The variable 'when' is the time when the data collection started. + * Call this to start a new data collection window. + */ +void LatencyStatistics::reset() { + mMax = std::numeric_limits::lowest(); + mMin = std::numeric_limits::max(); + mSum = 0; + mSum2 = 0; + mCount = 0; + mLastReportTime = std::chrono::steady_clock::now(); +} + +bool LatencyStatistics::shouldReport() { + std::chrono::duration timeSinceReport = std::chrono::steady_clock::now() - mLastReportTime; + return mCount != 0 && timeSinceReport > mReportPeriod; +} + +} // namespace android diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index ade931e01a..c1c35e1b89 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -7,6 +7,7 @@ cc_test { "InputEvent_test.cpp", "InputPublisherAndConsumer_test.cpp", "InputWindow_test.cpp", + "LatencyStatistics_test.cpp", "TouchVideoFrame_test.cpp", "VelocityTracker_test.cpp", ], diff --git a/libs/input/tests/LatencyStatistics_test.cpp b/libs/input/tests/LatencyStatistics_test.cpp new file mode 100644 index 0000000000..6d1cab4187 --- /dev/null +++ b/libs/input/tests/LatencyStatistics_test.cpp @@ -0,0 +1,72 @@ +/* + * 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 +#include +#include +#include + +namespace android { +namespace test { + +TEST(LatencyStatisticsTest, ResetStats) { + LatencyStatistics stats{5min}; + stats.addValue(5.0); + stats.addValue(19.3); + stats.addValue(20); + stats.reset(); + + ASSERT_EQ(stats.getCount(), 0u); + ASSERT_EQ(std::isnan(stats.getStDev()), true); + ASSERT_EQ(std::isnan(stats.getMean()), true); +} + +TEST(LatencyStatisticsTest, AddStatsValue) { + LatencyStatistics stats{5min}; + stats.addValue(5.0); + + ASSERT_EQ(stats.getMin(), 5.0); + ASSERT_EQ(stats.getMax(), 5.0); + ASSERT_EQ(stats.getCount(), 1u); + ASSERT_EQ(stats.getMean(), 5.0); + ASSERT_EQ(stats.getStDev(), 0.0); +} + +TEST(LatencyStatisticsTest, AddMultipleStatsValue) { + LatencyStatistics stats{5min}; + stats.addValue(4.0); + stats.addValue(6.0); + stats.addValue(8.0); + stats.addValue(10.0); + + float stdev = stats.getStDev(); + + ASSERT_EQ(stats.getMin(), 4.0); + ASSERT_EQ(stats.getMax(), 10.0); + ASSERT_EQ(stats.getCount(), 4u); + ASSERT_EQ(stats.getMean(), 7.0); + ASSERT_EQ(stdev * stdev, 5.0); +} + +TEST(LatencyStatisticsTest, ShouldReportStats) { + LatencyStatistics stats{0min}; + stats.addValue(5.0); + + ASSERT_EQ(stats.shouldReport(), true); +} + +} // namespace test +} // namespace android \ No newline at end of file diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index eee49d5e2a..df5dcafec9 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -85,9 +85,6 @@ static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); // data. static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10); -// How often to report input event statistics -static constexpr nsecs_t STATISTICS_REPORT_FREQUENCY = seconds_to_nanoseconds(5 * 60); - // --- Static Functions --- template @@ -4314,16 +4311,14 @@ void TouchInputMapper::clearStylusDataPendingFlags() { } void TouchInputMapper::reportEventForStatistics(nsecs_t evdevTime) { - nsecs_t now = systemTime(CLOCK_MONOTONIC); - nsecs_t latency = now - evdevTime; - mStatistics.addValue(nanoseconds_to_microseconds(latency)); - nsecs_t timeSinceLastReport = now - mStatistics.lastReportTime; - if (timeSinceLastReport > STATISTICS_REPORT_FREQUENCY) { - android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, - mStatistics.min, mStatistics.max, - mStatistics.mean(), mStatistics.stdev(), mStatistics.count); - mStatistics.reset(now); - } + if (mStatistics.shouldReport()) { + android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mStatistics.getMin(), + mStatistics.getMax(), mStatistics.getMean(), + mStatistics.getStDev(), mStatistics.getCount()); + mStatistics.reset(); + } + nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime); + mStatistics.addValue(latency); } void TouchInputMapper::process(const RawEvent* rawEvent) { diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index 0c08e7da38..33763b6cdf 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -24,14 +24,15 @@ #include #include +#include #include #include #include -#include +#include #include +#include #include #include -#include #include #include @@ -569,69 +570,6 @@ struct CookedPointerData { } }; -/** - * Basic statistics information. - * Keep track of min, max, average, and standard deviation of the received samples. - * Used to report latency information about input events. - */ -struct LatencyStatistics { - float min; - float max; - // Sum of all samples - float sum; - // Sum of squares of all samples - float sum2; - // The number of samples - size_t count; - // The last time statistics were reported. - nsecs_t lastReportTime; - - LatencyStatistics() { - reset(systemTime(SYSTEM_TIME_MONOTONIC)); - } - - inline void addValue(float x) { - if (x < min) { - min = x; - } - if (x > max) { - max = x; - } - sum += x; - sum2 += x * x; - count++; - } - - // Get the average value. Should not be called if no samples have been added. - inline float mean() { - if (count == 0) { - return 0; - } - return sum / count; - } - - // Get the standard deviation. Should not be called if no samples have been added. - inline float stdev() { - if (count == 0) { - return 0; - } - float average = mean(); - return sqrt(sum2 / count - average * average); - } - - /** - * Reset internal state. The variable 'when' is the time when the data collection started. - * Call this to start a new data collection window. - */ - inline void reset(nsecs_t when) { - max = 0; - min = std::numeric_limits::max(); - sum = 0; - sum2 = 0; - count = 0; - lastReportTime = when; - } -}; /* Keeps track of the state of single-touch protocol. */ class SingleTouchMotionAccumulator { @@ -1571,8 +1509,10 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; + static constexpr std::chrono::duration STATS_REPORT_PERIOD = 5min; + // Latency statistics for touch events - struct LatencyStatistics mStatistics; + LatencyStatistics mStatistics{STATS_REPORT_PERIOD}; std::optional findViewport(); -- cgit v1.2.3-59-g8ed1b From 3d3fa52c8bbe481ffb87d75e24725444bef0b939 Mon Sep 17 00:00:00 2001 From: Atif Niyaz Date: Thu, 25 Jul 2019 11:12:39 -0700 Subject: Move LatencyStatistics collection from InputReader to InputTransport This move allows us to grab a bigger context of how much time a motion event is spent from the kernel to right before the event was published. Test: Modified LatencyStats to report ever 10 seconds. Utilized logs to check that logs were reporting every 10 seconds. Checked also using logs that data was being added and calculated correctly. Change-Id: Iee0f9a2155e93ae77de5a5cd8b9fd1506186c60f Signed-off-by: Atif Niyaz --- include/input/InputTransport.h | 12 ++++++++++-- libs/input/Android.bp | 3 ++- libs/input/InputTransport.cpp | 16 ++++++++++++++++ services/inputflinger/Android.bp | 1 - services/inputflinger/InputReader.cpp | 13 ------------- services/inputflinger/InputReader.h | 8 -------- 6 files changed, 28 insertions(+), 25 deletions(-) (limited to 'include/input') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index df23f613c8..690e0a11c8 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -31,13 +31,16 @@ #include +#include + #include #include +#include +#include #include -#include #include +#include #include -#include namespace android { class Parcel; @@ -286,7 +289,12 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: + static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min; + sp mChannel; + LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD}; + + void reportTouchEventForStatistics(nsecs_t evdevTime); }; /* diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 17138506e5..7749e66c4d 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -56,7 +56,8 @@ cc_library { shared_libs: [ "libutils", "libbinder", - "libui" + "libui", + "libstatslog", ], sanitize: { diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 904a6feb03..2ff301e270 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -34,6 +34,7 @@ #include #include +#include using android::base::StringPrintf; @@ -531,6 +532,10 @@ status_t InputPublisher::publishMotionEvent( msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]); msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]); } + + if (source == AINPUT_SOURCE_TOUCHSCREEN) { + reportTouchEventForStatistics(eventTime); + } return mChannel->sendMessage(&msg); } @@ -557,6 +562,17 @@ status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandle return OK; } +void InputPublisher::reportTouchEventForStatistics(nsecs_t evdevTime) { + if (mTouchStatistics.shouldReport()) { + android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(), + mTouchStatistics.getMax(), mTouchStatistics.getMean(), + mTouchStatistics.getStDev(), mTouchStatistics.getCount()); + mTouchStatistics.reset(); + } + nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime); + mTouchStatistics.addValue(latency); +} + // --- InputConsumer --- InputConsumer::InputConsumer(const sp& channel) : diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index 8dd4d1df63..bdee6fe043 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -88,7 +88,6 @@ cc_library_shared { "libui", "libutils", "libhardware_legacy", - "libstatslog", ], header_libs: [ diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index df5dcafec9..d565e3ab38 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -57,7 +57,6 @@ #include #include #include -#include #define INDENT " " #define INDENT2 " " @@ -4310,24 +4309,12 @@ void TouchInputMapper::clearStylusDataPendingFlags() { mExternalStylusFusionTimeout = LLONG_MAX; } -void TouchInputMapper::reportEventForStatistics(nsecs_t evdevTime) { - if (mStatistics.shouldReport()) { - android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mStatistics.getMin(), - mStatistics.getMax(), mStatistics.getMean(), - mStatistics.getStDev(), mStatistics.getCount()); - mStatistics.reset(); - } - nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime); - mStatistics.addValue(latency); -} - void TouchInputMapper::process(const RawEvent* rawEvent) { mCursorButtonAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { - reportEventForStatistics(rawEvent->when); sync(rawEvent->when); } } diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index 33763b6cdf..e434869996 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -1509,11 +1508,6 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; - static constexpr std::chrono::duration STATS_REPORT_PERIOD = 5min; - - // Latency statistics for touch events - LatencyStatistics mStatistics{STATS_REPORT_PERIOD}; - std::optional findViewport(); void resetExternalStylus(); @@ -1582,8 +1576,6 @@ private: static void assignPointerIds(const RawState* last, RawState* current); - void reportEventForStatistics(nsecs_t evdevTime); - const char* modeToString(DeviceMode deviceMode); }; -- cgit v1.2.3-59-g8ed1b From 2ccbe3a0359a1bd59d282400351f2e604d5aabb9 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Fri, 9 Aug 2019 14:35:36 -0700 Subject: InputTransport: store fd in a unique_fd. Use unique_fd to hold the file descriptor, so that it gets protected from being closed by someone else by fdsan. Test: atest libinput_tests inputflinger_tests Change-Id: I08df199294f9ddd7646c7bcd637b9c035e3c1e12 --- include/input/InputTransport.h | 14 +++--- libs/input/IInputFlinger.cpp | 6 +-- libs/input/InputTransport.cpp | 88 +++++++++++++++++----------------- libs/input/tests/InputChannel_test.cpp | 27 +++++++---- 4 files changed, 70 insertions(+), 65 deletions(-) (limited to 'include/input') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 690e0a11c8..28b8d80074 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -42,6 +42,8 @@ #include #include +#include + namespace android { class Parcel; @@ -166,8 +168,7 @@ protected: virtual ~InputChannel(); public: - InputChannel() = default; - InputChannel(const std::string& name, int fd); + static sp create(const std::string& name, android::base::unique_fd fd); /* Creates a pair of input channels. * @@ -177,7 +178,7 @@ public: sp& outServerChannel, sp& outClientChannel); inline std::string getName() const { return mName; } - inline int getFd() const { return mFd; } + inline int getFd() const { return mFd.get(); } /* Sends a message to the other endpoint. * @@ -208,16 +209,15 @@ public: sp dup() const; status_t write(Parcel& out) const; - status_t read(const Parcel& from); + static sp read(const Parcel& from); sp getToken() const; void setToken(const sp& token); private: - void setFd(int fd); - + InputChannel(const std::string& name, android::base::unique_fd fd); std::string mName; - int mFd = -1; + android::base::unique_fd mFd; sp mToken = nullptr; }; diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp index d6a73bfd27..90f6e09a69 100644 --- a/libs/input/IInputFlinger.cpp +++ b/libs/input/IInputFlinger.cpp @@ -92,15 +92,13 @@ status_t BnInputFlinger::onTransact( } case REGISTER_INPUT_CHANNEL_TRANSACTION: { CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = new InputChannel(); - channel->read(data); + sp channel = InputChannel::read(data); registerInputChannel(channel); break; } case UNREGISTER_INPUT_CHANNEL_TRANSACTION: { CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = new InputChannel(); - channel->read(data); + sp channel = InputChannel::read(data); unregisterInputChannel(channel); break; } diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 2ff301e270..7835651f11 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -227,35 +227,28 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { // --- InputChannel --- -InputChannel::InputChannel(const std::string& name, int fd) : - mName(name) { +sp InputChannel::create(const std::string& name, android::base::unique_fd fd) { + const int result = fcntl(fd, F_SETFL, O_NONBLOCK); + if (result != 0) { + LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(), + strerror(errno)); + return nullptr; + } + return new InputChannel(name, std::move(fd)); +} + +InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd) + : mName(name), mFd(std::move(fd)) { #if DEBUG_CHANNEL_LIFECYCLE ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), fd); #endif - - setFd(fd); } InputChannel::~InputChannel() { #if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel destroyed: name='%s', fd=%d", - mName.c_str(), mFd); + ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); #endif - - ::close(mFd); -} - -void InputChannel::setFd(int fd) { - if (mFd > 0) { - ::close(mFd); - } - mFd = fd; - if (mFd > 0) { - int result = fcntl(mFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket " - "non-blocking. errno=%d", mName.c_str(), errno); - } } status_t InputChannel::openInputChannelPair(const std::string& name, @@ -276,13 +269,13 @@ status_t InputChannel::openInputChannelPair(const std::string& name, setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); - std::string serverChannelName = name; - serverChannelName += " (server)"; - outServerChannel = new InputChannel(serverChannelName, sockets[0]); + std::string serverChannelName = name + " (server)"; + android::base::unique_fd serverFd(sockets[0]); + outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd)); - std::string clientChannelName = name; - clientChannelName += " (client)"; - outClientChannel = new InputChannel(clientChannelName, sockets[1]); + std::string clientChannelName = name + " (client)"; + android::base::unique_fd clientFd(sockets[1]); + outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd)); return OK; } @@ -292,7 +285,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { msg->getSanitizedCopy(&cleanMsg); ssize_t nWrite; do { - nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); + nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); } while (nWrite == -1 && errno == EINTR); if (nWrite < 0) { @@ -327,7 +320,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { status_t InputChannel::receiveMessage(InputMessage* msg) { ssize_t nRead; do { - nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT); + nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT); } while (nRead == -1 && errno == EINTR); if (nRead < 0) { @@ -365,39 +358,44 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { } sp InputChannel::dup() const { - int fd = ::dup(getFd()); - return fd >= 0 ? new InputChannel(getName(), fd) : nullptr; + android::base::unique_fd newFd(::dup(getFd())); + if (!newFd.ok()) { + ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), mName.c_str(), + strerror(errno)); + return nullptr; + } + return InputChannel::create(mName, std::move(newFd)); } - status_t InputChannel::write(Parcel& out) const { - status_t s = out.writeString8(String8(getName().c_str())); - + status_t s = out.writeCString(getName().c_str()); if (s != OK) { return s; } + s = out.writeStrongBinder(mToken); if (s != OK) { return s; } - s = out.writeDupFileDescriptor(getFd()); - + s = out.writeUniqueFileDescriptor(mFd); return s; } -status_t InputChannel::read(const Parcel& from) { - mName = from.readString8(); - mToken = from.readStrongBinder(); - - int rawFd = from.readFileDescriptor(); - setFd(::dup(rawFd)); - - if (mFd < 0) { - return BAD_VALUE; +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 OK; + sp channel = InputChannel::create(name, std::move(rawFd)); + if (channel != nullptr) { + channel->setToken(token); + } + return channel; } sp InputChannel::getToken() const { diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index f1675c0d36..af74edd65d 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -22,11 +22,12 @@ #include #include +#include #include #include -#include #include #include +#include namespace android { @@ -43,20 +44,28 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor // of a pipe and to check for EPIPE on the other end after the channel is destroyed. Pipe pipe; - sp inputChannel = new InputChannel("channel name", pipe.sendFd); + android::base::unique_fd sendFd(pipe.sendFd); + + sp inputChannel = InputChannel::create("channel name", std::move(sendFd)); + EXPECT_NE(inputChannel, nullptr) << "channel should be successfully created"; EXPECT_STREQ("channel name", inputChannel->getName().c_str()) << "channel should have provided name"; - EXPECT_EQ(pipe.sendFd, inputChannel->getFd()) - << "channel should have provided fd"; + EXPECT_NE(-1, inputChannel->getFd()) << "channel should have valid fd"; - inputChannel.clear(); // destroys input channel + // InputChannel should be the owner of the file descriptor now + ASSERT_FALSE(sendFd.ok()); +} - EXPECT_EQ(-EPIPE, pipe.readSignal()) - << "channel should have closed fd when destroyed"; +TEST_F(InputChannelTest, SetAndGetToken) { + Pipe pipe; + sp channel = + InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd)); + EXPECT_EQ(channel->getToken(), nullptr); - // clean up fds of Pipe endpoints that were closed so we don't try to close them again - pipe.sendFd = -1; + sp token = new BBinder(); + channel->setToken(token); + EXPECT_EQ(token, channel->getToken()); } TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { -- cgit v1.2.3-59-g8ed1b From 3578917f82c84ad1be334105624084c7b1c95b54 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Mon, 9 Sep 2019 16:50:14 -0700 Subject: Add SCROLL, RELATIVE_X and RELATIVE_Y axes labels. CTS tests then can use this to obtain axis value and sets them. Bug: 133368243 Test: We can obtain values of these axes. Change-Id: I2d94c9345639feb40c8486e07535bfd6fe059066 --- include/input/InputEventLabels.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/input') diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h index 59d16d15af..eaa562bb7b 100644 --- a/include/input/InputEventLabels.h +++ b/include/input/InputEventLabels.h @@ -359,6 +359,9 @@ static const InputEventLabel AXES[] = { DEFINE_AXIS(BRAKE), DEFINE_AXIS(DISTANCE), DEFINE_AXIS(TILT), + DEFINE_AXIS(SCROLL), + DEFINE_AXIS(RELATIVE_X), + DEFINE_AXIS(RELATIVE_Y), DEFINE_AXIS(GENERIC_1), DEFINE_AXIS(GENERIC_2), DEFINE_AXIS(GENERIC_3), -- cgit v1.2.3-59-g8ed1b From 6cbb97591535868d629a562dfd7d8e24865cf551 Mon Sep 17 00:00:00 2001 From: Arthur Hung Date: Thu, 5 Sep 2019 16:38:18 +0800 Subject: Revert "Fix drag and drop (2/3)" This reverts commit fbe5d9c4233dcd802a122f70ca5a3641fcd556ca. Bug: 137819199 Test: manual Change-Id: I7afec569519b9c69eb03225672db6db141b20241 --- include/input/IInputFlinger.h | 4 +-- libs/gui/tests/EndToEndNativeInputTest.cpp | 50 ------------------------------ libs/input/IInputFlinger.cpp | 17 ---------- services/inputflinger/InputManager.cpp | 4 --- services/inputflinger/InputManager.h | 1 - services/inputflinger/host/InputFlinger.h | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 15 +-------- services/surfaceflinger/SurfaceFlinger.h | 1 - 8 files changed, 2 insertions(+), 91 deletions(-) (limited to 'include/input') diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h index 4365a3c4e3..d23e3b7767 100644 --- a/include/input/IInputFlinger.h +++ b/include/input/IInputFlinger.h @@ -37,7 +37,6 @@ public: virtual void setInputWindows(const std::vector& inputHandles, const sp& setInputWindowsListener) = 0; - virtual void transferTouchFocus(const sp& fromToken, const sp& toToken) = 0; virtual void registerInputChannel(const sp& channel) = 0; virtual void unregisterInputChannel(const sp& channel) = 0; }; @@ -51,8 +50,7 @@ public: enum { SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, REGISTER_INPUT_CHANNEL_TRANSACTION, - UNREGISTER_INPUT_CHANNEL_TRANSACTION, - TRANSFER_TOUCH_FOCUS + UNREGISTER_INPUT_CHANNEL_TRANSACTION }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 386f731d23..f158e566e6 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -133,27 +133,6 @@ public: EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); } - void expectMotionEvent(int motionEventType, int x, int y) { - InputEvent *ev = consumeEvent(); - ASSERT_NE(ev, nullptr); - ASSERT_EQ(ev->getType(), AINPUT_EVENT_TYPE_MOTION); - MotionEvent *mev = static_cast(ev); - EXPECT_EQ(motionEventType, mev->getAction()); - EXPECT_EQ(x, mev->getX(0)); - EXPECT_EQ(y, mev->getY(0)); - } - - void expectNoMotionEvent(int motionEventType) { - InputEvent *ev = consumeEvent(); - if (ev == nullptr || ev->getType() != AINPUT_EVENT_TYPE_MOTION) { - // Didn't find an event or a motion event so assume action didn't occur. - return; - } - - MotionEvent *mev = static_cast(ev); - EXPECT_NE(motionEventType, mev->getAction()); - } - ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel); } @@ -278,15 +257,6 @@ void injectTap(int x, int y) { } } -void injectMotionEvent(std::string event, int x, int y) { - char *buf1, *buf2; - asprintf(&buf1, "%d", x); - asprintf(&buf2, "%d", y); - if (fork() == 0) { - execlp("input", "input", "motionevent", event.c_str(), buf1, buf2, NULL); - } -} - TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr surface = makeSurface(100, 100); surface->showAt(100, 100); @@ -504,26 +474,6 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { bgSurface->expectTap(1, 1); } -TEST_F(InputSurfacesTest, transfer_touch_focus) { - std::unique_ptr fromSurface = makeSurface(100, 100); - - fromSurface->showAt(10, 10); - injectMotionEvent("DOWN", 11, 11); - fromSurface->expectMotionEvent(AMOTION_EVENT_ACTION_DOWN, 1, 1); - - std::unique_ptr toSurface = makeSurface(100, 100); - toSurface->showAt(10, 10); - - sp fromToken = fromSurface->mServerChannel->getToken(); - sp toToken = toSurface->mServerChannel->getToken(); - SurfaceComposerClient::Transaction t; - t.transferTouchFocus(fromToken, toToken).apply(true); - - injectMotionEvent("UP", 11, 11); - toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1); - fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP); -} - TEST_F(InputSurfacesTest, input_respects_outscreen) { std::unique_ptr surface = makeSurface(100, 100); surface->showAt(-1, -1); diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp index 90f6e09a69..8ec51653a8 100644 --- a/libs/input/IInputFlinger.cpp +++ b/libs/input/IInputFlinger.cpp @@ -45,16 +45,6 @@ public: IBinder::FLAG_ONEWAY); } - virtual void transferTouchFocus(const sp& fromToken, const sp& toToken) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - - data.writeStrongBinder(fromToken); - data.writeStrongBinder(toToken); - remote()->transact(BnInputFlinger::TRANSFER_TOUCH_FOCUS, data, &reply, - IBinder::FLAG_ONEWAY); - } - virtual void registerInputChannel(const sp& channel) { Parcel data, reply; data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); @@ -102,13 +92,6 @@ status_t BnInputFlinger::onTransact( unregisterInputChannel(channel); break; } - case TRANSFER_TOUCH_FOCUS: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp fromToken = data.readStrongBinder(); - sp toToken = data.readStrongBinder(); - transferTouchFocus(fromToken, toToken); - break; - } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index 3996cca646..acb53be69e 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -117,10 +117,6 @@ void InputManager::setInputWindows(const std::vector& infos, } } -void InputManager::transferTouchFocus(const sp& fromToken, const sp& toToken) { - mDispatcher->transferTouchFocus(fromToken, toToken); -} - // Used by tests only. void InputManager::registerInputChannel(const sp& channel) { IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index e568df54df..32f7ae0058 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -96,7 +96,6 @@ public: virtual void setInputWindows(const std::vector& handles, const sp& setInputWindowsListener); - virtual void transferTouchFocus(const sp& fromToken, const sp& toToken); virtual void registerInputChannel(const sp& channel); virtual void unregisterInputChannel(const sp& channel); diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index d8b352cbc6..973b4f92fa 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -42,7 +42,6 @@ public: virtual status_t dump(int fd, const Vector& args); void setInputWindows(const std::vector&, const sp&) {} - void transferTouchFocus(const sp&, const sp&) {} void registerInputChannel(const sp&) {} void unregisterInputChannel(const sp&) {} diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3498419cdf..a35426e8d4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2606,7 +2606,7 @@ void SurfaceFlinger::updateInputFlinger() { setInputWindowsFinished(); } - executeInputWindowCommands(); + mInputWindowCommands.clear(); } void SurfaceFlinger::updateInputWindowInfo() { @@ -2630,19 +2630,6 @@ void SurfaceFlinger::commitInputWindowCommands() { mPendingInputWindowCommands.clear(); } -void SurfaceFlinger::executeInputWindowCommands() { - for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) { - if (transferTouchFocusCommand.fromToken != nullptr && - transferTouchFocusCommand.toToken != nullptr && - transferTouchFocusCommand.fromToken != transferTouchFocusCommand.toToken) { - mInputFlinger->transferTouchFocus(transferTouchFocusCommand.fromToken, - transferTouchFocusCommand.toToken); - } - } - - mInputWindowCommands.clear(); -} - void SurfaceFlinger::updateCursorAsync() { compositionengine::CompositionRefreshArgs refreshArgs; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f220c26bdf..e0259c80ec 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -551,7 +551,6 @@ private: void updateInputFlinger(); void updateInputWindowInfo(); void commitInputWindowCommands() REQUIRES(mStateLock); - void executeInputWindowCommands(); void setInputWindowsFinished(); void updateCursorAsync(); -- cgit v1.2.3-59-g8ed1b From de4bf150c5685643daa1fa17f697e8b1cf3ea9ec Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Fri, 16 Aug 2019 11:12:52 -0500 Subject: Do not report latency for injected events When reporting the latency of touch events, ensure that injected events are excluded. These events can have arbitrary timestamps, and would not result in meaningful data. Also do not report events for statistics if inputfilter is enabled. Move the statistics reporting from InputTransport to InputDispatcher. This ensures that there's only 1 instance of the mStatistics object. This also provides easy access to the inputfilterenabled state. Bug: 13894199 Test: Change the reporting period to 0 (to report every event immediately) Inject events in various ways and ensure they don't go to statsd $ m statsd_testdrive && ./out/host/linux-x86/bin/statsd_testdrive 34 $ adb shell input tap 100 100 $ adb shell monkey 1000 Next, relaunch the statsd_testdrive script and touch the screen Observe that events are reported. Change-Id: Ief8040599a347e084e75584ed3164c60a6dbc4ad --- include/input/InputTransport.h | 5 ---- libs/input/Android.bp | 1 - libs/input/InputTransport.cpp | 15 ----------- libs/input/LatencyStatistics.cpp | 2 +- services/inputflinger/Android.bp | 1 + services/inputflinger/dispatcher/Android.bp | 1 + services/inputflinger/dispatcher/Entry.h | 18 +++++++++++++ .../inputflinger/dispatcher/InputDispatcher.cpp | 30 ++++++++++++++++++++++ services/inputflinger/dispatcher/InputDispatcher.h | 5 ++++ services/inputflinger/dispatcher/InputState.h | 3 --- 10 files changed, 56 insertions(+), 25 deletions(-) (limited to 'include/input') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 28b8d80074..c056c972d2 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -289,12 +288,8 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: - static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min; sp mChannel; - LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD}; - - void reportTouchEventForStatistics(nsecs_t evdevTime); }; /* diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 7749e66c4d..8efaf3d90b 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -57,7 +57,6 @@ cc_library { "libutils", "libbinder", "libui", - "libstatslog", ], sanitize: { diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 8a2fc2a2d0..366c93cf1f 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -34,7 +34,6 @@ #include #include -#include using android::base::StringPrintf; @@ -538,9 +537,6 @@ status_t InputPublisher::publishMotionEvent( msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]); } - if (source == AINPUT_SOURCE_TOUCHSCREEN) { - reportTouchEventForStatistics(eventTime); - } return mChannel->sendMessage(&msg); } @@ -567,17 +563,6 @@ status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandle return OK; } -void InputPublisher::reportTouchEventForStatistics(nsecs_t evdevTime) { - if (mTouchStatistics.shouldReport()) { - android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(), - mTouchStatistics.getMax(), mTouchStatistics.getMean(), - mTouchStatistics.getStDev(), mTouchStatistics.getCount()); - mTouchStatistics.reset(); - } - nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime); - mTouchStatistics.addValue(latency); -} - // --- InputConsumer --- InputConsumer::InputConsumer(const sp& channel) : diff --git a/libs/input/LatencyStatistics.cpp b/libs/input/LatencyStatistics.cpp index e343578e00..394da22a62 100644 --- a/libs/input/LatencyStatistics.cpp +++ b/libs/input/LatencyStatistics.cpp @@ -84,7 +84,7 @@ void LatencyStatistics::reset() { bool LatencyStatistics::shouldReport() { std::chrono::duration timeSinceReport = std::chrono::steady_clock::now() - mLastReportTime; - return mCount != 0 && timeSinceReport > mReportPeriod; + return mCount != 0 && timeSinceReport >= mReportPeriod; } } // namespace android diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index 11578c393e..f6b5935bcf 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -44,6 +44,7 @@ cc_library_shared { "libhidlbase", "libinput", "liblog", + "libstatslog", "libutils", "libui", "server_configurable_flags", diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp index b8c3a808f1..9185e00272 100644 --- a/services/inputflinger/dispatcher/Android.bp +++ b/services/inputflinger/dispatcher/Android.bp @@ -34,6 +34,7 @@ cc_library_static { "libinputreporter", "libinputflinger_base", "liblog", + "libstatslog", "libui", "libutils", ], diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index a9e22f19f1..28c2799477 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -29,6 +29,9 @@ namespace android::inputdispatcher { +// Sequence number for synthesized or injected events. +constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0; + struct EventEntry { enum { TYPE_CONFIGURATION_CHANGED, TYPE_DEVICE_RESET, TYPE_KEY, TYPE_MOTION }; @@ -41,8 +44,23 @@ struct EventEntry { bool dispatchInProgress; // initially false, set to true while dispatching + /** + * Injected keys are events from an external (probably untrusted) application + * and are not related to real hardware state. They come in via + * InputDispatcher::injectInputEvent, which sets policy flag POLICY_FLAG_INJECTED. + */ inline bool isInjected() const { return injectionState != nullptr; } + /** + * Synthesized events are either injected events, or events that come + * from real hardware, but aren't directly attributable to a specific hardware event. + * Key repeat is a synthesized event, because it is related to an actual hardware state + * (a key is currently pressed), but the repeat itself is generated by the framework. + */ + inline bool isSynthesized() const { + return isInjected() || sequenceNum == SYNTHESIZED_EVENT_SEQUENCE_NUM; + } + void release(); virtual void appendDescription(std::string& msg) const = 0; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 039462e23b..2361867e62 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -2274,6 +2275,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, motionEntry->downTime, motionEntry->eventTime, motionEntry->pointerCount, motionEntry->pointerProperties, usingCoords); + reportTouchEventForStatistics(*motionEntry); break; } @@ -4478,6 +4480,34 @@ void InputDispatcher::updateDispatchStatistics(nsecs_t currentTime, const EventE // TODO Write some statistics about how long we spend waiting. } +/** + * Report the touch event latency to the statsd server. + * Input events are reported for statistics if: + * - This is a touchscreen event + * - InputFilter is not enabled + * - Event is not injected or synthesized + * + * Statistics should be reported before calling addValue, to prevent a fresh new sample + * from getting aggregated with the "old" data. + */ +void InputDispatcher::reportTouchEventForStatistics(const MotionEntry& motionEntry) + REQUIRES(mLock) { + const bool reportForStatistics = (motionEntry.source == AINPUT_SOURCE_TOUCHSCREEN) && + !(motionEntry.isSynthesized()) && !mInputFilterEnabled; + if (!reportForStatistics) { + return; + } + + if (mTouchStatistics.shouldReport()) { + android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(), + mTouchStatistics.getMax(), mTouchStatistics.getMean(), + mTouchStatistics.getStDev(), mTouchStatistics.getCount()); + mTouchStatistics.reset(); + } + const float latencyMicros = nanoseconds_to_microseconds(now() - motionEntry.eventTime); + mTouchStatistics.addValue(latencyMicros); +} + void InputDispatcher::traceInboundQueueLengthLocked() { if (ATRACE_ENABLED()) { ATRACE_INT("iq", mInboundQueue.size()); diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index f2c04028e4..0d9d6b0c15 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -455,6 +456,10 @@ private: void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); // Statistics gathering. + static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min; + LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD}; + + void reportTouchEventForStatistics(const MotionEntry& entry); void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry, int32_t injectionResult, nsecs_t timeSpentWaitingForApplication); void traceInboundQueueLengthLocked() REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h index bccef0fca3..47e9b36219 100644 --- a/services/inputflinger/dispatcher/InputState.h +++ b/services/inputflinger/dispatcher/InputState.h @@ -24,9 +24,6 @@ namespace android::inputdispatcher { -// Sequence number for synthesized or injected events. -constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0; - /* Tracks dispatched key and motion event state so that cancellation events can be * synthesized when events are dropped. */ class InputState { -- cgit v1.2.3-59-g8ed1b From 524027761e00c014fbe7e52741ca82bf6e6f1dca Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Tue, 22 Oct 2019 09:32:30 -0700 Subject: Use enum class for InputMessage type Using enum class helps with type safety, and allows compile-time detection of missing switch/case statements. Bug: 70668286 Test: compile-time only Change-Id: I5ae95cfbf2b38330fa34eca1c9f444a90190cd25 --- include/input/InputTransport.h | 10 +-- libs/input/InputTransport.cpp | 109 ++++++++++++++++----------------- libs/input/tests/InputChannel_test.cpp | 8 +-- 3 files changed, 63 insertions(+), 64 deletions(-) (limited to 'include/input') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index c056c972d2..1822e4a0db 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -60,14 +60,14 @@ class Parcel; * in StructLayout_test should be made. */ struct InputMessage { - enum { - TYPE_KEY = 1, - TYPE_MOTION = 2, - TYPE_FINISHED = 3, + enum class Type : uint32_t { + KEY, + MOTION, + FINISHED, }; struct Header { - uint32_t type; + Type type; // 4 bytes // We don't need this field in order to align the body below but we // leave it here because InputMessage::size() and other functions // compute the size of this structure as sizeof(Header) + sizeof(Body). diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 366c93cf1f..c4f7fe0bf2 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -93,13 +93,12 @@ inline static bool isPointerEvent(int32_t source) { bool InputMessage::isValid(size_t actualSize) const { if (size() == actualSize) { switch (header.type) { - case TYPE_KEY: - return true; - case TYPE_MOTION: - return body.motion.pointerCount > 0 - && body.motion.pointerCount <= MAX_POINTERS; - case TYPE_FINISHED: - return true; + case Type::KEY: + return true; + case Type::MOTION: + return body.motion.pointerCount > 0 && body.motion.pointerCount <= MAX_POINTERS; + case Type::FINISHED: + return true; } } return false; @@ -107,12 +106,12 @@ bool InputMessage::isValid(size_t actualSize) const { size_t InputMessage::size() const { switch (header.type) { - case TYPE_KEY: - return sizeof(Header) + body.key.size(); - case TYPE_MOTION: - return sizeof(Header) + body.motion.size(); - case TYPE_FINISHED: - return sizeof(Header) + body.finished.size(); + case Type::KEY: + return sizeof(Header) + body.key.size(); + case Type::MOTION: + return sizeof(Header) + body.motion.size(); + case Type::FINISHED: + return sizeof(Header) + body.finished.size(); } return sizeof(Header); } @@ -129,7 +128,7 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { // Write the body switch(header.type) { - case InputMessage::TYPE_KEY: { + case InputMessage::Type::KEY: { // uint32_t seq msg->body.key.seq = body.key.seq; // nsecs_t eventTime @@ -156,7 +155,7 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { msg->body.key.downTime = body.key.downTime; break; } - case InputMessage::TYPE_MOTION: { + case InputMessage::Type::MOTION: { // uint32_t seq msg->body.motion.seq = body.motion.seq; // nsecs_t eventTime @@ -212,7 +211,7 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { } break; } - case InputMessage::TYPE_FINISHED: { + case InputMessage::Type::FINISHED: { msg->body.finished.seq = body.finished.seq; msg->body.finished.handled = body.finished.handled; break; @@ -457,7 +456,7 @@ status_t InputPublisher::publishKeyEvent( } InputMessage msg; - msg.header.type = InputMessage::TYPE_KEY; + msg.header.type = InputMessage::Type::KEY; msg.body.key.seq = seq; msg.body.key.deviceId = deviceId; msg.body.key.source = source; @@ -511,7 +510,7 @@ status_t InputPublisher::publishMotionEvent( } InputMessage msg; - msg.header.type = InputMessage::TYPE_MOTION; + msg.header.type = InputMessage::Type::MOTION; msg.body.motion.seq = seq; msg.body.motion.deviceId = deviceId; msg.body.motion.source = source; @@ -553,7 +552,7 @@ status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandle *outHandled = false; return result; } - if (msg.header.type != InputMessage::TYPE_FINISHED) { + if (msg.header.type != InputMessage::Type::FINISHED) { ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer", mChannel->getName().c_str(), msg.header.type); return UNKNOWN_ERROR; @@ -614,59 +613,59 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, } switch (mMsg.header.type) { - case InputMessage::TYPE_KEY: { - KeyEvent* keyEvent = factory->createKeyEvent(); - if (!keyEvent) return NO_MEMORY; + case InputMessage::Type::KEY: { + KeyEvent* keyEvent = factory->createKeyEvent(); + if (!keyEvent) return NO_MEMORY; - initializeKeyEvent(keyEvent, &mMsg); - *outSeq = mMsg.body.key.seq; - *outEvent = keyEvent; + initializeKeyEvent(keyEvent, &mMsg); + *outSeq = mMsg.body.key.seq; + *outEvent = keyEvent; #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed key event, seq=%u", mChannel->getName().c_str(), *outSeq); #endif break; - } + } - case InputMessage::TYPE_MOTION: { - ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source); - if (batchIndex >= 0) { - Batch& batch = mBatches.editItemAt(batchIndex); - if (canAddSample(batch, &mMsg)) { - batch.samples.push(mMsg); + case InputMessage::Type::MOTION: { + ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source); + if (batchIndex >= 0) { + Batch& batch = mBatches.editItemAt(batchIndex); + if (canAddSample(batch, &mMsg)) { + batch.samples.push(mMsg); #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ appended to batch event", mChannel->getName().c_str()); #endif break; - } else if (isPointerEvent(mMsg.body.motion.source) && - mMsg.body.motion.action == AMOTION_EVENT_ACTION_CANCEL) { - // No need to process events that we are going to cancel anyways - const size_t count = batch.samples.size(); - for (size_t i = 0; i < count; i++) { - const InputMessage& msg = batch.samples.itemAt(i); - sendFinishedSignal(msg.body.motion.seq, false); - } - batch.samples.removeItemsAt(0, count); - mBatches.removeAt(batchIndex); - } else { - // We cannot append to the batch in progress, so we need to consume - // the previous batch right now and defer the new message until later. - mMsgDeferred = true; - status_t result = consumeSamples(factory, - batch, batch.samples.size(), outSeq, outEvent); - mBatches.removeAt(batchIndex); - if (result) { - return result; - } + } else if (isPointerEvent(mMsg.body.motion.source) && + mMsg.body.motion.action == AMOTION_EVENT_ACTION_CANCEL) { + // No need to process events that we are going to cancel anyways + const size_t count = batch.samples.size(); + for (size_t i = 0; i < count; i++) { + const InputMessage& msg = batch.samples.itemAt(i); + sendFinishedSignal(msg.body.motion.seq, false); + } + batch.samples.removeItemsAt(0, count); + mBatches.removeAt(batchIndex); + } else { + // We cannot append to the batch in progress, so we need to consume + // the previous batch right now and defer the new message until later. + mMsgDeferred = true; + status_t result = consumeSamples(factory, batch, batch.samples.size(), + outSeq, outEvent); + mBatches.removeAt(batchIndex); + if (result) { + return result; + } #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' consumer ~ consumed batch event and " "deferred current event, seq=%u", mChannel->getName().c_str(), *outSeq); #endif break; + } } - } // Start a new batch if needed. if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE @@ -694,7 +693,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, mChannel->getName().c_str(), *outSeq); #endif break; - } + } default: ALOGE("channel '%s' consumer ~ Received unexpected message of type %d", @@ -1074,7 +1073,7 @@ status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) { status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) { InputMessage msg; - msg.header.type = InputMessage::TYPE_FINISHED; + msg.header.type = InputMessage::Type::FINISHED; msg.body.finished.seq = seq; msg.body.finished.handled = handled; return mChannel->sendMessage(&msg); diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index af74edd65d..7c331e132d 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -86,7 +86,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { // Server->Client communication InputMessage serverMsg; memset(&serverMsg, 0, sizeof(InputMessage)); - serverMsg.header.type = InputMessage::TYPE_KEY; + serverMsg.header.type = InputMessage::Type::KEY; serverMsg.body.key.action = AKEY_EVENT_ACTION_DOWN; EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg)) << "server channel should be able to send message to client channel"; @@ -102,7 +102,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { // Client->Server communication InputMessage clientReply; memset(&clientReply, 0, sizeof(InputMessage)); - clientReply.header.type = InputMessage::TYPE_FINISHED; + clientReply.header.type = InputMessage::Type::FINISHED; clientReply.body.finished.seq = 0x11223344; clientReply.body.finished.handled = true; EXPECT_EQ(OK, clientChannel->sendMessage(&clientReply)) @@ -161,7 +161,7 @@ TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) { serverChannel.clear(); // close server channel InputMessage msg; - msg.header.type = InputMessage::TYPE_KEY; + msg.header.type = InputMessage::Type::KEY; EXPECT_EQ(DEAD_OBJECT, clientChannel->sendMessage(&msg)) << "sendMessage should have returned DEAD_OBJECT"; } @@ -180,7 +180,7 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { }; InputMessage serverMsg = {}, clientMsg; - serverMsg.header.type = InputMessage::TYPE_MOTION; + serverMsg.header.type = InputMessage::Type::MOTION; serverMsg.body.motion.seq = 1; serverMsg.body.motion.pointerCount = 1; -- cgit v1.2.3-59-g8ed1b From 26d3cfb571a5cc1567f53c4550fbf9ed7a5d501f Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Tue, 15 Oct 2019 17:02:32 -0700 Subject: Remove InputChannel::setToken The token is now assigned in the constructor. It is read-only. When you open inputchannelpair, the same token is assigned to both server and client side channels. Bug: 142581626 Test: presubmit Change-Id: I603603844b41f478e244b89dcdd1dab7e6260347 --- include/input/InputTransport.h | 47 ++++++++++++++-------- libs/gui/tests/EndToEndNativeInputTest.cpp | 3 +- libs/input/InputTransport.cpp | 47 +++++++++------------- libs/input/tests/InputChannel_test.cpp | 11 +++-- .../inputflinger/dispatcher/InputDispatcher.cpp | 40 +++++++++--------- .../inputflinger/tests/InputDispatcher_test.cpp | 4 +- 6 files changed, 78 insertions(+), 74 deletions(-) (limited to 'include/input') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 1822e4a0db..94d90ad30b 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -167,11 +167,15 @@ protected: virtual ~InputChannel(); public: - static sp create(const std::string& name, android::base::unique_fd fd); + static sp create(const std::string& name, android::base::unique_fd fd, + sp token); - /* Creates a pair of input channels. + /** + * Create a pair of input channels. + * The two returned input channels are equivalent, and are labeled as "server" and "client" + * for convenience. The two input channels share the same token. * - * Returns OK on success. + * Return OK on success. */ static status_t openInputChannelPair(const std::string& name, sp& outServerChannel, sp& outClientChannel); @@ -179,46 +183,57 @@ public: inline std::string getName() const { return mName; } inline int getFd() const { return mFd.get(); } - /* Sends a message to the other endpoint. + /* Send a message to the other endpoint. * * If the channel is full then the message is guaranteed not to have been sent at all. * Try again after the consumer has sent a finished signal indicating that it has * consumed some of the pending messages from the channel. * - * Returns OK on success. - * Returns WOULD_BLOCK if the channel is full. - * Returns DEAD_OBJECT if the channel's peer has been closed. + * Return OK on success. + * Return WOULD_BLOCK if the channel is full. + * Return DEAD_OBJECT if the channel's peer has been closed. * Other errors probably indicate that the channel is broken. */ status_t sendMessage(const InputMessage* msg); - /* Receives a message sent by the other endpoint. + /* Receive a message sent by the other endpoint. * * If there is no message present, try again after poll() indicates that the fd * is readable. * - * Returns OK on success. - * Returns WOULD_BLOCK if there is no message present. - * Returns DEAD_OBJECT if the channel's peer has been closed. + * Return OK on success. + * Return WOULD_BLOCK if there is no message present. + * Return DEAD_OBJECT if the channel's peer has been closed. * Other errors probably indicate that the channel is broken. */ status_t receiveMessage(InputMessage* msg); - /* Returns a new object that has a duplicate of this channel's fd. */ + /* 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); - sp getToken() const; - void setToken(const sp& token); + /** + * The connection token is used to identify the input connection, i.e. + * the pair of input channels that were created simultaneously. Input channels + * are always created in pairs, and the token can be used to find the server-side + * input channel from the client-side input channel, and vice versa. + * + * Do not use connection token to check equality of a specific input channel object + * to another, because two different (client and server) input channels will share the + * same connection token. + * + * Return the token that identifies this connection. + */ + sp getConnectionToken() const; private: - InputChannel(const std::string& name, android::base::unique_fd fd); + InputChannel(const std::string& name, android::base::unique_fd fd, sp token); std::string mName; android::base::unique_fd mFd; - sp mToken = nullptr; + sp mToken; }; /* diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 03b9cd75db..8d36ba7b70 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -69,7 +69,6 @@ public: mSurfaceControl = sc; InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); - mServerChannel->setToken(new BBinder()); mInputFlinger = getInputFlinger(); mInputFlinger->registerInputChannel(mServerChannel); @@ -165,7 +164,7 @@ private: } void populateInputInfo(int width, int height) { - mInputInfo.token = mServerChannel->getToken(); + mInputInfo.token = mServerChannel->getConnectionToken(); mInputInfo.name = "Test info"; mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION; diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index c4f7fe0bf2..a5dd3c0544 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -11,7 +11,7 @@ #define DEBUG_CHANNEL_MESSAGES 0 // Log debug messages whenever InputChannel objects are created/destroyed -#define DEBUG_CHANNEL_LIFECYCLE 0 +static constexpr bool DEBUG_CHANNEL_LIFECYCLE = false; // Log debug messages about transport actions #define DEBUG_TRANSPORT_ACTIONS 0 @@ -225,28 +225,28 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { // --- InputChannel --- -sp InputChannel::create(const std::string& name, android::base::unique_fd fd) { +sp InputChannel::create(const std::string& name, android::base::unique_fd fd, + sp token) { const int result = fcntl(fd, F_SETFL, O_NONBLOCK); if (result != 0) { LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(), strerror(errno)); return nullptr; } - return new InputChannel(name, std::move(fd)); + return new InputChannel(name, std::move(fd), token); } -InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd) - : mName(name), mFd(std::move(fd)) { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel constructed: name='%s', fd=%d", - mName.c_str(), fd); -#endif +InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp token) + : mName(name), mFd(std::move(fd)), mToken(token) { + if (DEBUG_CHANNEL_LIFECYCLE) { + ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), mFd.get()); + } } InputChannel::~InputChannel() { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); -#endif + if (DEBUG_CHANNEL_LIFECYCLE) { + ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); + } } status_t InputChannel::openInputChannelPair(const std::string& name, @@ -267,13 +267,15 @@ status_t InputChannel::openInputChannelPair(const std::string& name, setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); + sp token = new BBinder(); + std::string serverChannelName = name + " (server)"; android::base::unique_fd serverFd(sockets[0]); - outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd)); + outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token); std::string clientChannelName = name + " (client)"; android::base::unique_fd clientFd(sockets[1]); - outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd)); + outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token); return OK; } @@ -369,7 +371,7 @@ sp InputChannel::dup() const { getName().c_str()); return nullptr; } - return InputChannel::create(mName, std::move(newFd)); + return InputChannel::create(mName, std::move(newFd), mToken); } status_t InputChannel::write(Parcel& out) const { @@ -396,24 +398,13 @@ sp InputChannel::read(const Parcel& from) { return nullptr; } - sp channel = InputChannel::create(name, std::move(rawFd)); - if (channel != nullptr) { - channel->setToken(token); - } - return channel; + return InputChannel::create(name, std::move(rawFd), token); } -sp InputChannel::getToken() const { +sp InputChannel::getConnectionToken() const { return mToken; } -void InputChannel::setToken(const sp& token) { - if (mToken != nullptr) { - ALOGE("Assigning InputChannel (%s) a second handle?", mName.c_str()); - } - mToken = token; -} - // --- InputPublisher --- InputPublisher::InputPublisher(const sp& channel) : diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index 7c331e132d..ada275d014 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -46,7 +46,8 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor android::base::unique_fd sendFd(pipe.sendFd); - sp inputChannel = InputChannel::create("channel name", std::move(sendFd)); + sp inputChannel = + InputChannel::create("channel name", std::move(sendFd), new BBinder()); EXPECT_NE(inputChannel, nullptr) << "channel should be successfully created"; EXPECT_STREQ("channel name", inputChannel->getName().c_str()) @@ -59,13 +60,11 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor TEST_F(InputChannelTest, SetAndGetToken) { Pipe pipe; + sp token = new BBinder(); sp channel = - InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd)); - EXPECT_EQ(channel->getToken(), nullptr); + InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd), token); - sp token = new BBinder(); - channel->setToken(token); - EXPECT_EQ(token, channel->getToken()); + EXPECT_EQ(token, channel->getConnectionToken()); } TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 24b27b9f15..58a5b3c8d3 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1038,7 +1038,8 @@ void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* event pokeUserActivityLocked(*eventEntry); for (const InputTarget& inputTarget : inputTargets) { - sp connection = getConnectionLocked(inputTarget.inputChannel->getToken()); + sp connection = + getConnectionLocked(inputTarget.inputChannel->getConnectionToken()); if (connection != nullptr) { prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget); } else { @@ -2142,7 +2143,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp& connectio } dispatchPointerDownOutsideFocus(motionEntry.source, dispatchEntry->resolvedAction, - inputTarget->inputChannel->getToken()); + inputTarget->inputChannel->getConnectionToken()); break; } @@ -2472,7 +2473,7 @@ void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked( void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked( const sp& channel, const CancelationOptions& options) { - sp connection = getConnectionLocked(channel->getToken()); + sp connection = getConnectionLocked(channel->getConnectionToken()); if (connection == nullptr) { return; } @@ -2514,7 +2515,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( InputTarget target; sp windowHandle = - getWindowHandleLocked(connection->inputChannel->getToken()); + getWindowHandleLocked(connection->inputChannel->getConnectionToken()); if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); target.xOffset = -windowInfo->frameLeft; @@ -3866,7 +3867,7 @@ status_t InputDispatcher::registerInputChannel(const sp& inputChan { // acquire lock std::scoped_lock _l(mLock); - sp existingConnection = getConnectionLocked(inputChannel->getToken()); + sp existingConnection = getConnectionLocked(inputChannel->getConnectionToken()); if (existingConnection != nullptr) { ALOGW("Attempted to register already registered input channel '%s'", inputChannel->getName().c_str()); @@ -3877,7 +3878,7 @@ status_t InputDispatcher::registerInputChannel(const sp& inputChan int fd = inputChannel->getFd(); mConnectionsByFd[fd] = connection; - mInputChannelsByToken[inputChannel->getToken()] = inputChannel; + mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel; mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); } // release lock @@ -3897,7 +3898,7 @@ status_t InputDispatcher::registerInputMonitor(const sp& inputChan return BAD_VALUE; } - if (inputChannel->getToken() == nullptr) { + if (inputChannel->getConnectionToken() == nullptr) { ALOGW("Attempted to register input monitor without an identifying token."); return BAD_VALUE; } @@ -3906,7 +3907,7 @@ status_t InputDispatcher::registerInputMonitor(const sp& inputChan const int fd = inputChannel->getFd(); mConnectionsByFd[fd] = connection; - mInputChannelsByToken[inputChannel->getToken()] = inputChannel; + mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel; auto& monitorsByDisplay = isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay; @@ -3941,7 +3942,7 @@ status_t InputDispatcher::unregisterInputChannel(const sp& inputCh status_t InputDispatcher::unregisterInputChannelLocked(const sp& inputChannel, bool notify) { - sp connection = getConnectionLocked(inputChannel->getToken()); + sp connection = getConnectionLocked(inputChannel->getConnectionToken()); if (connection == nullptr) { ALOGW("Attempted to unregister already unregistered input channel '%s'", inputChannel->getName().c_str()); @@ -3950,7 +3951,7 @@ status_t InputDispatcher::unregisterInputChannelLocked(const sp& i [[maybe_unused]] const bool removed = removeByValue(mConnectionsByFd, connection); ALOG_ASSERT(removed); - mInputChannelsByToken.erase(inputChannel->getToken()); + mInputChannelsByToken.erase(inputChannel->getConnectionToken()); if (connection->monitor) { removeMonitorChannelLocked(inputChannel); @@ -4010,7 +4011,7 @@ status_t InputDispatcher::pilferPointers(const sp& token) { TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex); std::optional foundDeviceId; for (const TouchedMonitor& touchedMonitor : state.gestureMonitors) { - if (touchedMonitor.monitor.inputChannel->getToken() == token) { + if (touchedMonitor.monitor.inputChannel->getConnectionToken() == token) { foundDeviceId = state.deviceId; } } @@ -4041,7 +4042,7 @@ std::optional InputDispatcher::findGestureMonitorDisplayByTokenLocked( for (const auto& it : mGestureMonitorsByDisplay) { const std::vector& monitors = it.second; for (const Monitor& monitor : monitors) { - if (monitor.inputChannel->getToken() == token) { + if (monitor.inputChannel->getConnectionToken() == token) { return it.first; } } @@ -4056,7 +4057,7 @@ sp InputDispatcher::getConnectionLocked(const sp& inputConn for (const auto& pair : mConnectionsByFd) { const sp& connection = pair.second; - if (connection->inputChannel->getToken() == inputConnectionToken) { + if (connection->inputChannel->getConnectionToken() == inputConnectionToken) { return connection; } } @@ -4149,7 +4150,7 @@ void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(CommandEntry if (connection->status != Connection::STATUS_ZOMBIE) { mLock.unlock(); - mPolicy->notifyInputChannelBroken(connection->inputChannel->getToken()); + mPolicy->notifyInputChannelBroken(connection->inputChannel->getConnectionToken()); mLock.lock(); } @@ -4165,7 +4166,7 @@ void InputDispatcher::doNotifyFocusChangedLockedInterruptible(CommandEntry* comm void InputDispatcher::doNotifyANRLockedInterruptible(CommandEntry* commandEntry) { sp token = - commandEntry->inputChannel ? commandEntry->inputChannel->getToken() : nullptr; + commandEntry->inputChannel ? commandEntry->inputChannel->getConnectionToken() : nullptr; mLock.unlock(); nsecs_t newTimeout = @@ -4186,7 +4187,7 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( android::base::Timer t; sp token = commandEntry->inputChannel != nullptr - ? commandEntry->inputChannel->getToken() + ? commandEntry->inputChannel->getConnectionToken() : nullptr; nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token, &event, entry->policyFlags); if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) { @@ -4305,7 +4306,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp& con mLock.unlock(); - mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(), &event, + mPolicy->dispatchUnhandledKey(connection->inputChannel->getConnectionToken(), &event, keyEntry->policyFlags, &event); mLock.lock(); @@ -4346,8 +4347,9 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp& con mLock.unlock(); - bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(), &event, - keyEntry->policyFlags, &event); + bool fallback = + mPolicy->dispatchUnhandledKey(connection->inputChannel->getConnectionToken(), + &event, keyEntry->policyFlags, &event); mLock.lock(); diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 7d69854868..b706a749fe 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -470,7 +470,6 @@ public: const sp& dispatcher, const std::string name, int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId), mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) { - mServerChannel->setToken(new BBinder()); mDispatcher->registerInputChannel(mServerChannel); inputApplicationHandle->updateInfo(); @@ -478,7 +477,7 @@ public: } virtual bool updateInfo() { - mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr; + mInfo.token = mServerChannel ? mServerChannel->getConnectionToken() : nullptr; mInfo.name = mName; mInfo.layoutParamsFlags = mLayoutParamFlags; mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; @@ -859,7 +858,6 @@ public: FakeMonitorReceiver(const sp& dispatcher, const std::string name, int32_t displayId, bool isGestureMonitor = false) : FakeInputReceiver(dispatcher, name, displayId) { - mServerChannel->setToken(new BBinder()); mDispatcher->registerInputMonitor(mServerChannel, displayId, isGestureMonitor); } }; -- cgit v1.2.3-59-g8ed1b From c0d3c4b24ec64e2fdef7b7a9133db8672a5df923 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 1 May 2019 14:49:39 -0700 Subject: Removing support for menu key from status bar Bug: 131763491 Test: Verified that menu key doesn't show up for legacy apps Change-Id: I1a93c2552945788331fdda376785647e7978da07 --- include/input/InputWindow.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/input') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 916af699e0..f852cd0540 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -63,7 +63,6 @@ struct InputWindowInfo { FLAG_DISMISS_KEYGUARD = 0x00400000, FLAG_SPLIT_TOUCH = 0x00800000, FLAG_SLIPPERY = 0x20000000, - FLAG_NEEDS_MENU_KEY = 0x40000000, }; // Window types from WindowManager.LayoutParams -- cgit v1.2.3-59-g8ed1b From 727a44e37ee5ac778fc3abf0fcd849847f5d7c29 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Sat, 23 Nov 2019 12:59:16 -0800 Subject: Use queue and unique_ptr for pooled events Currently, we are doing some manual memory management for pooled events. Refactor to use queue and unique_ptr Bug: 70668286 Test: presubmit Change-Id: Ia3f39a841a84b76243e4a68cb2cf8005e0a48ce3 --- include/input/Input.h | 14 +++++++------- libs/input/Input.cpp | 30 ++++++++++++------------------ 2 files changed, 19 insertions(+), 25 deletions(-) (limited to 'include/input') diff --git a/include/input/Input.h b/include/input/Input.h index cbd1a412bf..a7e706ed18 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -31,8 +31,8 @@ #include #include #include - #include +#include /* * Additional private constants not defined in ndk/ui/input.h. @@ -709,8 +709,8 @@ public: PreallocatedInputEventFactory() { } virtual ~PreallocatedInputEventFactory() { } - virtual KeyEvent* createKeyEvent() { return & mKeyEvent; } - virtual MotionEvent* createMotionEvent() { return & mMotionEvent; } + virtual KeyEvent* createKeyEvent() override { return &mKeyEvent; } + virtual MotionEvent* createMotionEvent() override { return &mMotionEvent; } private: KeyEvent mKeyEvent; @@ -725,16 +725,16 @@ public: explicit PooledInputEventFactory(size_t maxPoolSize = 20); virtual ~PooledInputEventFactory(); - virtual KeyEvent* createKeyEvent(); - virtual MotionEvent* createMotionEvent(); + virtual KeyEvent* createKeyEvent() override; + virtual MotionEvent* createMotionEvent() override; void recycle(InputEvent* event); private: const size_t mMaxPoolSize; - Vector mKeyEventPool; - Vector mMotionEventPool; + std::queue> mKeyEventPool; + std::queue> mMotionEventPool; }; } // namespace android diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 34b305e548..c7303efd13 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -595,43 +595,37 @@ PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) : } PooledInputEventFactory::~PooledInputEventFactory() { - for (size_t i = 0; i < mKeyEventPool.size(); i++) { - delete mKeyEventPool.itemAt(i); - } - for (size_t i = 0; i < mMotionEventPool.size(); i++) { - delete mMotionEventPool.itemAt(i); - } } KeyEvent* PooledInputEventFactory::createKeyEvent() { - if (!mKeyEventPool.isEmpty()) { - KeyEvent* event = mKeyEventPool.top(); - mKeyEventPool.pop(); - return event; + if (mKeyEventPool.empty()) { + return new KeyEvent(); } - return new KeyEvent(); + KeyEvent* event = mKeyEventPool.front().release(); + mKeyEventPool.pop(); + return event; } MotionEvent* PooledInputEventFactory::createMotionEvent() { - if (!mMotionEventPool.isEmpty()) { - MotionEvent* event = mMotionEventPool.top(); - mMotionEventPool.pop(); - return event; + if (mMotionEventPool.empty()) { + return new MotionEvent(); } - return new MotionEvent(); + MotionEvent* event = mMotionEventPool.front().release(); + mMotionEventPool.pop(); + return event; } void PooledInputEventFactory::recycle(InputEvent* event) { switch (event->getType()) { case AINPUT_EVENT_TYPE_KEY: if (mKeyEventPool.size() < mMaxPoolSize) { - mKeyEventPool.push(static_cast(event)); + mKeyEventPool.push(std::unique_ptr(static_cast(event))); return; } break; case AINPUT_EVENT_TYPE_MOTION: if (mMotionEventPool.size() < mMaxPoolSize) { - mMotionEventPool.push(static_cast(event)); + mMotionEventPool.push(std::unique_ptr(static_cast(event))); return; } break; -- cgit v1.2.3-59-g8ed1b From 10fe676bf6423dfb17104e8f1fdacdaf1d1983da Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 25 Nov 2019 11:44:11 -0800 Subject: Add static asserts for InputMessage sizes We currently don't test the total size of InputMessage. But that's still important, to ensure it doesn't extend further than expected. Add asserts for the sizes of Header and Body. Bug: none Test: presubmit Change-Id: I2dbda2136186b22a9247fde058a9c356b07c808d --- include/input/InputTransport.h | 11 ++++++++--- libs/input/InputTransport.cpp | 4 ++-- libs/input/tests/StructLayout_test.cpp | 16 ++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'include/input') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 94d90ad30b..d39ee250a5 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -121,11 +121,16 @@ struct InputMessage { float yCursorPosition; uint32_t pointerCount; uint32_t empty3; - // Note that PointerCoords requires 8 byte alignment. + /** + * The "pointers" field must be the last field of the struct InputMessage. + * When we send the struct InputMessage across the socket, we are not + * writing the entire "pointers" array, but only the pointerCount portion + * of it as an optimization. Adding a field after "pointers" would break this. + */ struct Pointer { PointerProperties properties; PointerCoords coords; - } pointers[MAX_POINTERS]; + } pointers[MAX_POINTERS] __attribute__((aligned(8))); int32_t getActionId() const { uint32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) @@ -141,7 +146,7 @@ struct InputMessage { struct Finished { uint32_t seq; - bool handled; + uint32_t handled; // actually a bool, but we must maintain 8-byte alignment inline size_t size() const { return sizeof(Finished); diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 8d1dd639bb..b7937dc95e 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -547,7 +547,7 @@ status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandle return UNKNOWN_ERROR; } *outSeq = msg.body.finished.seq; - *outHandled = msg.body.finished.handled; + *outHandled = msg.body.finished.handled == 1; return OK; } @@ -1065,7 +1065,7 @@ status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) InputMessage msg; msg.header.type = InputMessage::Type::FINISHED; msg.body.finished.seq = seq; - msg.body.finished.handled = handled; + msg.body.finished.handled = handled ? 1 : 0; return mChannel->sendMessage(&msg); } diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index 8d8cf06c91..0fb6cfc204 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -73,4 +73,20 @@ void TestInputMessageAlignment() { CHECK_OFFSET(InputMessage::Body::Finished, handled, 4); } +void TestHeaderSize() { + static_assert(sizeof(InputMessage::Header) == 8); +} + +/** + * We cannot use the Body::size() method here because it is not static for + * the Motion type, where "pointerCount" variable affects the size and can change at runtime. + */ +void TestBodySize() { + static_assert(sizeof(InputMessage::Body::Key) == 64); + static_assert(sizeof(InputMessage::Body::Motion) == + offsetof(InputMessage::Body::Motion, pointers) + + sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS); + static_assert(sizeof(InputMessage::Body::Finished) == 8); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From 7feb2eaf82d88bd4d903f43776860015806274ce Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 25 Nov 2019 15:11:23 -0800 Subject: Add FocusEvent and InputMessage::Type::FOCUS FocusEvents will be consumed by InputConsumer on the app side. They will be used to notify app that focus has been gained / lost. They will also carry information about the current state of touch mode. Also add a new type of InputMessage with type FOCUS. This new data structure will be used to pass focus events to the apps from input across the socket. Bug: 70668286 Test: presubmit Change-Id: I88582c64ee41ecb49623b9b7f5c149eafa694788 --- include/android/input.h | 5 +- include/input/Input.h | 29 ++++++++++ include/input/InputTransport.h | 34 ++++++++--- libs/input/Input.cpp | 45 +++++++++++++++ libs/input/InputTransport.cpp | 67 +++++++++++++++++----- .../input/tests/InputPublisherAndConsumer_test.cpp | 43 ++++++++++++++ libs/input/tests/StructLayout_test.cpp | 5 ++ .../inputflinger/dispatcher/InputDispatcher.cpp | 2 +- .../inputflinger/tests/InputDispatcher_test.cpp | 4 +- 9 files changed, 209 insertions(+), 25 deletions(-) (limited to 'include/input') diff --git a/include/android/input.h b/include/android/input.h index ce439c6d75..f51cd79504 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -158,7 +158,10 @@ enum { AINPUT_EVENT_TYPE_KEY = 1, /** Indicates that the input event is a motion event. */ - AINPUT_EVENT_TYPE_MOTION = 2 + AINPUT_EVENT_TYPE_MOTION = 2, + + /** Focus event */ + AINPUT_EVENT_TYPE_FOCUS = 3, }; /** diff --git a/include/input/Input.h b/include/input/Input.h index a7e706ed18..f8718479f9 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -167,6 +167,8 @@ namespace android { class Parcel; #endif +const char* inputEventTypeToString(int32_t type); + /* * Flags that flow alongside events in the input dispatch system to help with certain * policy decisions such as waking from device sleep. @@ -686,6 +688,28 @@ protected: Vector mSamplePointerCoords; }; +/* + * Focus events. + */ +class FocusEvent : public InputEvent { +public: + virtual ~FocusEvent() {} + + virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_FOCUS; } + + inline bool getHasFocus() const { return mHasFocus; } + + inline bool getInTouchMode() const { return mInTouchMode; } + + void initialize(bool hasFocus, bool inTouchMode); + + void initialize(const FocusEvent& from); + +protected: + bool mHasFocus; + bool mInTouchMode; +}; + /* * Input event factory. */ @@ -698,6 +722,7 @@ public: virtual KeyEvent* createKeyEvent() = 0; virtual MotionEvent* createMotionEvent() = 0; + virtual FocusEvent* createFocusEvent() = 0; }; /* @@ -711,10 +736,12 @@ public: virtual KeyEvent* createKeyEvent() override { return &mKeyEvent; } virtual MotionEvent* createMotionEvent() override { return &mMotionEvent; } + virtual FocusEvent* createFocusEvent() override { return &mFocusEvent; } private: KeyEvent mKeyEvent; MotionEvent mMotionEvent; + FocusEvent mFocusEvent; }; /* @@ -727,6 +754,7 @@ public: virtual KeyEvent* createKeyEvent() override; virtual MotionEvent* createMotionEvent() override; + virtual FocusEvent* createFocusEvent() override; void recycle(InputEvent* event); @@ -735,6 +763,7 @@ private: std::queue> mKeyEventPool; std::queue> mMotionEventPool; + std::queue> mFocusEventPool; }; } // namespace android diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index d39ee250a5..ae47438ac8 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -64,6 +64,7 @@ struct InputMessage { KEY, MOTION, FINISHED, + FOCUS, }; struct Header { @@ -92,9 +93,7 @@ struct InputMessage { uint32_t empty2; nsecs_t downTime __attribute__((aligned(8))); - inline size_t size() const { - return sizeof(Key); - } + inline size_t size() const { return sizeof(Key); } } key; struct Motion { @@ -110,7 +109,7 @@ struct InputMessage { int32_t metaState; int32_t buttonState; MotionClassification classification; // base type: uint8_t - uint8_t empty2[3]; + uint8_t empty2[3]; // 3 bytes to fill gap created by classification int32_t edgeFlags; nsecs_t downTime __attribute__((aligned(8))); float xOffset; @@ -148,10 +147,17 @@ struct InputMessage { uint32_t seq; uint32_t handled; // actually a bool, but we must maintain 8-byte alignment - inline size_t size() const { - return sizeof(Finished); - } + inline size_t size() const { return sizeof(Finished); } } finished; + + struct Focus { + uint32_t seq; + // The following two fields take up 4 bytes total + uint16_t hasFocus; // actually a bool + uint16_t inTouchMode; // actually a bool, but we must maintain 8-byte alignment + + inline size_t size() const { return sizeof(Focus); } + } focus; } __attribute__((aligned(8))) body; bool isValid(size_t actualSize) const; @@ -294,6 +300,15 @@ public: uint32_t pointerCount, const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); + /* Publishes a focus event to the input channel. + * + * Returns OK on success. + * Returns WOULD_BLOCK if the channel is full. + * Returns DEAD_OBJECT if the channel's peer has been closed. + * Other errors probably indicate that the channel is broken. + */ + status_t publishFocusEvent(uint32_t seq, bool hasFocus, bool inTouchMode); + /* Receives the finished signal from the consumer in reply to the original dispatch signal. * If a signal was received, returns the message sequence number, * and whether the consumer handled the message. @@ -349,8 +364,8 @@ public: * Returns NO_MEMORY if the event could not be created. * Other errors probably indicate that the channel is broken. */ - status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent); + status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, nsecs_t frameTime, + uint32_t* outSeq, InputEvent** outEvent); /* Sends a finished signal to the publisher to inform it that the message * with the specified sequence number has finished being process and whether @@ -521,6 +536,7 @@ private: static void rewriteMessage(TouchState& state, InputMessage& msg); static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg); static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg); + static void initializeFocusEvent(FocusEvent* event, const InputMessage* msg); static void addSample(MotionEvent* event, const InputMessage* msg); static bool canAddSample(const Batch& batch, const InputMessage* msg); static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time); diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index c7303efd13..8ccbc7f650 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #ifdef __ANDROID__ @@ -41,6 +42,21 @@ const char* motionClassificationToString(MotionClassification classification) { // --- InputEvent --- +const char* inputEventTypeToString(int32_t type) { + switch (type) { + case AINPUT_EVENT_TYPE_KEY: { + return "KEY"; + } + case AINPUT_EVENT_TYPE_MOTION: { + return "MOTION"; + } + case AINPUT_EVENT_TYPE_FOCUS: { + return "FOCUS"; + } + } + return "UNKNOWN"; +} + void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId) { mDeviceId = deviceId; mSource = source; @@ -587,6 +603,20 @@ int32_t MotionEvent::getAxisFromLabel(const char* label) { return getAxisByLabel(label); } +// --- FocusEvent --- + +void FocusEvent::initialize(bool hasFocus, bool inTouchMode) { + InputEvent::initialize(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN, + ADISPLAY_ID_NONE); + mHasFocus = hasFocus; + mInTouchMode = inTouchMode; +} + +void FocusEvent::initialize(const FocusEvent& from) { + InputEvent::initialize(from); + mHasFocus = from.mHasFocus; + mInTouchMode = from.mInTouchMode; +} // --- PooledInputEventFactory --- @@ -615,6 +645,15 @@ MotionEvent* PooledInputEventFactory::createMotionEvent() { return event; } +FocusEvent* PooledInputEventFactory::createFocusEvent() { + if (mFocusEventPool.empty()) { + return new FocusEvent(); + } + FocusEvent* event = mFocusEventPool.front().release(); + mFocusEventPool.pop(); + return event; +} + void PooledInputEventFactory::recycle(InputEvent* event) { switch (event->getType()) { case AINPUT_EVENT_TYPE_KEY: @@ -629,6 +668,12 @@ void PooledInputEventFactory::recycle(InputEvent* event) { return; } break; + case AINPUT_EVENT_TYPE_FOCUS: + if (mFocusEventPool.size() < mMaxPoolSize) { + mFocusEventPool.push(std::unique_ptr(static_cast(event))); + return; + } + break; } delete event; } diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index b7937dc95e..200e1f39d9 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -103,6 +103,8 @@ bool InputMessage::isValid(size_t actualSize) const { return body.motion.pointerCount > 0 && body.motion.pointerCount <= MAX_POINTERS; case Type::FINISHED: return true; + case Type::FOCUS: + return true; } } return false; @@ -116,6 +118,8 @@ size_t InputMessage::size() const { return sizeof(Header) + body.motion.size(); case Type::FINISHED: return sizeof(Header) + body.finished.size(); + case Type::FOCUS: + return sizeof(Header) + body.focus.size(); } return sizeof(Header); } @@ -220,6 +224,12 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { msg->body.finished.handled = body.finished.handled; break; } + case InputMessage::Type::FOCUS: { + msg->body.focus.seq = body.focus.seq; + msg->body.focus.hasFocus = body.focus.hasFocus; + msg->body.focus.inTouchMode = body.focus.inTouchMode; + break; + } } } @@ -529,6 +539,23 @@ status_t InputPublisher::publishMotionEvent( return mChannel->sendMessage(&msg); } +status_t InputPublisher::publishFocusEvent(uint32_t seq, bool hasFocus, bool inTouchMode) { + if (ATRACE_ENABLED()) { + std::string message = + StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s, inTouchMode=%s)", + mChannel->getName().c_str(), toString(hasFocus), + toString(inTouchMode)); + ATRACE_NAME(message.c_str()); + } + + InputMessage msg; + msg.header.type = InputMessage::Type::FOCUS; + msg.body.focus.seq = seq; + msg.body.focus.hasFocus = hasFocus ? 1 : 0; + msg.body.focus.inTouchMode = inTouchMode ? 1 : 0; + return mChannel->sendMessage(&msg); +} + status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) { if (DEBUG_TRANSPORT_ACTIONS) { ALOGD("channel '%s' publisher ~ receiveFinishedSignal", mChannel->getName().c_str()); @@ -565,8 +592,8 @@ bool InputConsumer::isTouchResamplingEnabled() { return property_get_bool(PROPERTY_RESAMPLING_ENABLED, true); } -status_t InputConsumer::consume(InputEventFactoryInterface* factory, - bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) { +status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches, + nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) { if (DEBUG_TRANSPORT_ACTIONS) { ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64, mChannel->getName().c_str(), toString(consumeBatches), frameTime); @@ -669,19 +696,19 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, break; } - MotionEvent* motionEvent = factory->createMotionEvent(); - if (! motionEvent) return NO_MEMORY; + MotionEvent* motionEvent = factory->createMotionEvent(); + if (!motionEvent) return NO_MEMORY; - updateTouchState(mMsg); - initializeMotionEvent(motionEvent, &mMsg); - *outSeq = mMsg.body.motion.seq; - *outEvent = motionEvent; + updateTouchState(mMsg); + initializeMotionEvent(motionEvent, &mMsg); + *outSeq = mMsg.body.motion.seq; + *outEvent = motionEvent; - if (DEBUG_TRANSPORT_ACTIONS) { - ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u", - mChannel->getName().c_str(), *outSeq); - } - break; + if (DEBUG_TRANSPORT_ACTIONS) { + ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u", + mChannel->getName().c_str(), *outSeq); + } + break; } case InputMessage::Type::FINISHED: { @@ -689,6 +716,16 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, "InputConsumer!"); break; } + + case InputMessage::Type::FOCUS: { + FocusEvent* focusEvent = factory->createFocusEvent(); + if (!focusEvent) return NO_MEMORY; + + initializeFocusEvent(focusEvent, &mMsg); + *outSeq = mMsg.body.focus.seq; + *outEvent = focusEvent; + break; + } } } return OK; @@ -1113,6 +1150,10 @@ void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) msg->body.key.eventTime); } +void InputConsumer::initializeFocusEvent(FocusEvent* event, const InputMessage* msg) { + event->initialize(msg->body.focus.hasFocus == 1, msg->body.focus.inTouchMode == 1); +} + void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) { uint32_t pointerCount = msg->body.motion.pointerCount; PointerProperties pointerProperties[pointerCount]; diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index a362f3281d..2fc77e97a0 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -60,6 +60,7 @@ protected: void PublishAndConsumeKeyEvent(); void PublishAndConsumeMotionEvent(); + void PublishAndConsumeFocusEvent(); }; TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) { @@ -256,6 +257,43 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { << "publisher receiveFinishedSignal should have set handled to consumer's reply"; } +void InputPublisherAndConsumerTest::PublishAndConsumeFocusEvent() { + status_t status; + + constexpr uint32_t seq = 15; + constexpr bool hasFocus = true; + constexpr bool inTouchMode = true; + + status = mPublisher->publishFocusEvent(seq, hasFocus, inTouchMode); + ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK"; + + uint32_t consumeSeq; + InputEvent* event; + status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event); + ASSERT_EQ(OK, status) << "consumer consume should return OK"; + + ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event"; + ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType()) + << "consumer should have returned a focus event"; + + FocusEvent* focusEvent = static_cast(event); + EXPECT_EQ(seq, consumeSeq); + EXPECT_EQ(hasFocus, focusEvent->getHasFocus()); + EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode()); + + status = mConsumer->sendFinishedSignal(seq, true); + ASSERT_EQ(OK, status) << "consumer sendFinishedSignal should return OK"; + + uint32_t finishedSeq = 0; + bool handled = false; + status = mPublisher->receiveFinishedSignal(&finishedSeq, &handled); + ASSERT_EQ(OK, status) << "publisher receiveFinishedSignal should return OK"; + ASSERT_EQ(seq, finishedSeq) + << "publisher receiveFinishedSignal should have returned the original sequence number"; + ASSERT_TRUE(handled) + << "publisher receiveFinishedSignal should have set handled to consumer's reply"; +} + TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_EndToEnd) { ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); } @@ -264,6 +302,10 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_EndToEnd) { ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); } +TEST_F(InputPublisherAndConsumerTest, PublishFocusEvent_EndToEnd) { + ASSERT_NO_FATAL_FAILURE(PublishAndConsumeFocusEvent()); +} + TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) { status_t status; const size_t pointerCount = 1; @@ -322,6 +364,7 @@ TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) { ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); + ASSERT_NO_FATAL_FAILURE(PublishAndConsumeFocusEvent()); ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); } diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index 0fb6cfc204..9ab0dba08d 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -69,6 +69,10 @@ void TestInputMessageAlignment() { CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 88); CHECK_OFFSET(InputMessage::Body::Motion, pointers, 96); + CHECK_OFFSET(InputMessage::Body::Focus, seq, 0); + CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4); + CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 6); + CHECK_OFFSET(InputMessage::Body::Finished, seq, 0); CHECK_OFFSET(InputMessage::Body::Finished, handled, 4); } @@ -87,6 +91,7 @@ void TestBodySize() { offsetof(InputMessage::Body::Motion, pointers) + sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS); static_assert(sizeof(InputMessage::Body::Finished) == 8); + static_assert(sizeof(InputMessage::Body::Focus) == 8); } } // namespace android diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 746908ba40..9c0e08e297 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3036,7 +3036,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec } default: - ALOGW("Cannot inject event of type %d", event->getType()); + ALOGW("Cannot inject %s events", inputEventTypeToString(event->getType())); return INPUT_EVENT_INJECTION_FAILED; } diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index ebce47f1e7..4f282611d5 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -410,7 +411,8 @@ public: ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event."; ASSERT_EQ(expectedEventType, event->getType()) - << mName.c_str() << ": event type should match."; + << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType) + << " event, got " << inputEventTypeToString(event->getType()) << " event"; EXPECT_EQ(expectedDisplayId, event->getDisplayId()); -- cgit v1.2.3-59-g8ed1b From d041c5d9e162fbac4ef92c1d84a1bcd035fb8455 Mon Sep 17 00:00:00 2001 From: Powei Feng Date: Fri, 3 May 2019 17:11:33 -0700 Subject: Default TV remote keys to no-wake For Android TV, we want the default behavior of keys to not wake up the device. We want to be able to whitelist keys if wake is desired. This differs from the behavior on mobile where the default is to wake the device unless its a media key. We separate by means of the idc file. Specifying "keyboard.doNotWakeByDefault=1" in the idc would indicate the device is a TV remote and should go through corresponding path. Bug: 144979700 Test: Change idc/kl files. Rebuild and examine 'dumpsys input' on key presses. atest inputflinger_tests Change-Id: I4168c4c21fd901ca0402e0211f636b06234b9a85 --- include/input/InputEventLabels.h | 11 ++- .../reader/mapper/KeyboardInputMapper.cpp | 11 ++- .../reader/mapper/KeyboardInputMapper.h | 1 + services/inputflinger/tests/InputReader_test.cpp | 78 ++++++++++++++++++++++ 4 files changed, 92 insertions(+), 9 deletions(-) (limited to 'include/input') diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h index eaa562bb7b..b327d76b1c 100644 --- a/include/input/InputEventLabels.h +++ b/include/input/InputEventLabels.h @@ -405,13 +405,12 @@ static const InputEventLabel LEDS[] = { { nullptr, 0 } }; -static const InputEventLabel FLAGS[] = { - DEFINE_FLAG(VIRTUAL), - DEFINE_FLAG(FUNCTION), - DEFINE_FLAG(GESTURE), +static const InputEventLabel FLAGS[] = {DEFINE_FLAG(VIRTUAL), + DEFINE_FLAG(FUNCTION), + DEFINE_FLAG(GESTURE), + DEFINE_FLAG(WAKE), - { nullptr, 0 } -}; + {nullptr, 0}}; static int lookupValueByLabel(const char* literal, const InputEventLabel *list) { while (list->literal) { diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index f51d4a0d4a..348a7ada0e 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -183,6 +183,9 @@ void KeyboardInputMapper::configureParameters() { mParameters.handlesKeyRepeat = false; config.tryGetProperty(String8("keyboard.handlesKeyRepeat"), mParameters.handlesKeyRepeat); + + mParameters.doNotWakeByDefault = false; + config.tryGetProperty(String8("keyboard.doNotWakeByDefault"), mParameters.doNotWakeByDefault); } void KeyboardInputMapper::dumpParameters(std::string& dump) { @@ -331,10 +334,12 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, // Key down on external an keyboard should wake the device. // We don't do this for internal keyboards to prevent them from waking up in your pocket. - // For internal keyboards, the key layout file should specify the policy flags for - // each wake key individually. + // For internal keyboards and devices for which the default wake behavior is explicitly + // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each + // wake key individually. // TODO: Use the input device configuration to control this behavior more finely. - if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) { + if (down && getDevice()->isExternal() && !mParameters.doNotWakeByDefault && + !isMediaKey(keyCode)) { policyFlags |= POLICY_FLAG_WAKE; } diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h index de2a377e9a..badbcb26cf 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h @@ -73,6 +73,7 @@ private: struct Parameters { bool orientationAware; bool handlesKeyRepeat; + bool doNotWakeByDefault; } mParameters; void configureParameters(); diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index d6624c9f5a..1fc8217df8 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -2580,6 +2580,84 @@ TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) { AKEYCODE_DPAD_LEFT, newDisplayId)); } +TEST_F(KeyboardInputMapperTest, ExternalDevice_WakeBehavior) { + // For external devices, non-media keys will trigger wake on key down. Media keys need to be + // marked as WAKE in the keylayout file to trigger wake. + mDevice->setExternal(true); + + mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE, POLICY_FLAG_WAKE); + + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, + AINPUT_KEYBOARD_TYPE_ALPHABETIC); + addMapperAndConfigure(mapper); + + process(mapper, ARBITRARY_TIME, EV_KEY, KEY_HOME, 1); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); + + process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_HOME, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(uint32_t(0), args.policyFlags); + + process(mapper, ARBITRARY_TIME, EV_KEY, KEY_PLAY, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(uint32_t(0), args.policyFlags); + + process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_PLAY, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(uint32_t(0), args.policyFlags); + + process(mapper, ARBITRARY_TIME, EV_KEY, KEY_PLAYPAUSE, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); + + process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_PLAYPAUSE, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); +} + +TEST_F(KeyboardInputMapperTest, ExternalDevice_DoNotWakeByDefaultBehavior) { + // Tv Remote key's wake behavior is prescribed by the keylayout file. + mDevice->setExternal(true); + + mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); + mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE); + + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, + AINPUT_KEYBOARD_TYPE_ALPHABETIC); + addConfigurationProperty("keyboard.doNotWakeByDefault", "1"); + addMapperAndConfigure(mapper); + + process(mapper, ARBITRARY_TIME, EV_KEY, KEY_HOME, 1); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); + + process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_HOME, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); + + process(mapper, ARBITRARY_TIME, EV_KEY, KEY_DOWN, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(uint32_t(0), args.policyFlags); + + process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_DOWN, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(uint32_t(0), args.policyFlags); + + process(mapper, ARBITRARY_TIME, EV_KEY, KEY_PLAY, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); + + process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_PLAY, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); +} + // --- CursorInputMapperTest --- class CursorInputMapperTest : public InputMapperTest { -- cgit v1.2.3-59-g8ed1b From af87b3e09141558215e28f84d954590b5e7f2f16 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 1 Oct 2019 16:59:28 -0700 Subject: Added input support for cloned layers This was done with a few changes: 1. Added a layerId in the input info so the InputInfo objects can be uniquely identified as per layer 2. When setting input info in InputDispatcher, compare InputInfo objects using layer id instead of input token. 3. Updated the crop region for layers based on the cloned hierarchy so the input is cropped to the correct region. Bug: 140756730 Test: InputDispatcherMultiWindowSameTokenTests Change-Id: I980f5d29d091fecb407f5cd6a289615505800927 --- include/input/InputWindow.h | 6 + libs/input/InputWindow.cpp | 2 + libs/input/tests/InputWindow_test.cpp | 2 + .../inputflinger/dispatcher/InputDispatcher.cpp | 22 ++- .../inputflinger/tests/InputDispatcher_test.cpp | 149 +++++++++++++++++++++ services/surfaceflinger/BufferLayer.cpp | 15 ++- services/surfaceflinger/Layer.cpp | 63 ++++++--- services/surfaceflinger/Layer.h | 7 +- 8 files changed, 239 insertions(+), 27 deletions(-) (limited to 'include/input') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index f852cd0540..cbd64d520e 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -119,7 +119,11 @@ struct InputWindowInfo { /* These values are filled in by the WM and passed through SurfaceFlinger * unless specified otherwise. */ + // This value should NOT be used to uniquely identify the window. There may be different + // input windows that have the same token. sp token; + // This uniquely identifies the input window. + int32_t id = 0; std::string name; int32_t layoutParamsFlags; int32_t layoutParamsType; @@ -203,6 +207,8 @@ public: sp getToken() const; + int32_t getId() const { return mInfo.id; } + sp getApplicationToken() { return mInfo.applicationInfo.token; } diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index ec28757933..74a05055eb 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -73,6 +73,7 @@ status_t InputWindowInfo::write(Parcel& output) const { status_t s = output.writeStrongBinder(token); if (s != OK) return s; + output.writeInt32(id); output.writeString8(String8(name.c_str())); output.writeInt32(layoutParamsFlags); output.writeInt32(layoutParamsType); @@ -116,6 +117,7 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) { } ret.token = token; + ret.id = from.readInt32(); ret.name = from.readString8().c_str(); ret.layoutParamsFlags = from.readInt32(); ret.layoutParamsType = from.readInt32(); diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 6db18abacf..cdc81d2f04 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -40,6 +40,7 @@ TEST(InputWindowInfo, Parcelling) { sp touchableRegionCropHandle = new BBinder(); InputWindowInfo i; i.token = new BBinder(); + i.id = 1; i.name = "Foobar"; i.layoutParamsFlags = 7; i.layoutParamsType = 39; @@ -72,6 +73,7 @@ TEST(InputWindowInfo, Parcelling) { p.setDataPosition(0); InputWindowInfo i2 = InputWindowInfo::read(p); 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); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 5a49b5e16a..116625c03e 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -240,6 +240,18 @@ static bool removeByValue(std::unordered_map& map, const V& value) { return removed; } +static bool haveSameToken(const sp& first, const sp& second) { + if (first == second) { + return true; + } + + if (first == nullptr || second == nullptr) { + return false; + } + + return first->getToken() == second->getToken(); +} + // --- InputDispatcherThread --- class InputDispatcher::InputDispatcherThread : public Thread { @@ -3278,9 +3290,9 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked( // Since we compare the pointer of input window handles across window updates, we need // to make sure the handle object for the same window stays unchanged across updates. const std::vector>& oldHandles = getWindowHandlesLocked(displayId); - std::unordered_map, sp, IBinderHash> oldHandlesByTokens; + std::unordered_map> oldHandlesById; for (const sp& handle : oldHandles) { - oldHandlesByTokens[handle->getToken()] = handle; + oldHandlesById[handle->getId()] = handle; } std::vector> newHandles; @@ -3311,8 +3323,8 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked( continue; } - if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) { - const sp oldHandle = oldHandlesByTokens.at(handle->getToken()); + if (oldHandlesById.find(handle->getId()) != oldHandlesById.end()) { + const sp& oldHandle = oldHandlesById.at(handle->getId()); oldHandle->updateFrom(handle); newHandles.push_back(oldHandle); } else { @@ -3370,7 +3382,7 @@ void InputDispatcher::setInputWindows(const std::vector>& sp oldFocusedWindowHandle = getValueByKey(mFocusedWindowHandlesByDisplay, displayId); - if (oldFocusedWindowHandle != newFocusedWindowHandle) { + if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) { if (oldFocusedWindowHandle != nullptr) { if (DEBUG_FOCUS) { ALOGD("Focus left window: %s in display %" PRId32, diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index b4d7608770..c25122c72b 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -526,6 +526,7 @@ public: mInfo.applicationInfo = *inputApplicationHandle->getInfo(); mInfo.token = token; + mInfo.id = 0; mInfo.name = name; mInfo.layoutParamsFlags = 0; mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; @@ -564,6 +565,13 @@ public: void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; } + void setId(int32_t id) { mInfo.id = id; } + + void setWindowScale(float xScale, float yScale) { + mInfo.windowXScale = xScale; + mInfo.windowYScale = yScale; + } + void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) { consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags); @@ -586,12 +594,21 @@ public: expectedFlags); } + InputEvent* consume() { + if (mInputReceiver == nullptr) { + return nullptr; + } + return mInputReceiver->consume(); + } + void assertNoEvents() { ASSERT_NE(mInputReceiver, nullptr) << "Call 'assertNoEvents' on a window with an InputReceiver"; mInputReceiver->assertNoEvents(); } + sp getToken() { return mInfo.token; } + private: std::unique_ptr mInputReceiver; }; @@ -667,6 +684,10 @@ static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLA static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId, const std::vector& points) { size_t pointerCount = points.size(); + if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) { + EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer"; + } + PointerProperties pointerProperties[pointerCount]; PointerCoords pointerCoords[pointerCount]; @@ -1291,4 +1312,132 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, mFakePolicy->assertOnPointerDownWasNotCalled(); } +// These tests ensures we can send touch events to a single client when there are multiple input +// windows that point to the same client token. +class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest { + virtual void SetUp() override { + InputDispatcherTest::SetUp(); + + sp application = new FakeApplicationHandle(); + mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1", + 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->setId(0); + 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->setId(1); + mWindow2->setFrame(Rect(100, 100, 200, 200)); + + mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT); + } + +protected: + sp mWindow1; + sp mWindow2; + + // 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}; + } + + void consumeMotionEvent(const sp& window, int32_t expectedAction, + const std::vector& points) { + std::string name = window->mName; + InputEvent* event = window->consume(); + + ASSERT_NE(nullptr, event) << name.c_str() + << ": consumer should have returned non-NULL event."; + + ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) + << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION) + << " event, got " << inputEventTypeToString(event->getType()) << " event"; + + const MotionEvent& motionEvent = static_cast(*event); + EXPECT_EQ(expectedAction, motionEvent.getAction()); + + for (size_t i = 0; i < points.size(); i++) { + float expectedX = points[i].x; + float expectedY = points[i].y; + + EXPECT_EQ(expectedX, motionEvent.getX(i)) + << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str() + << ", got " << motionEvent.getX(i); + EXPECT_EQ(expectedY, motionEvent.getY(i)) + << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str() + << ", got " << motionEvent.getY(i); + } + } +}; + +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}); + + // 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}); + + // 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}); +} + +TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) { + 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}); + + // 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}); + + // 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}); +} + } // namespace android::inputdispatcher diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 054acc5069..bdecdb78d0 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -770,17 +770,20 @@ void BufferLayer::updateCloneBufferInfo() { // After buffer info is updated, the drawingState from the real layer needs to be copied into // the cloned. This is because some properties of drawingState can change when latchBuffer is - // called. However, copying the drawingState would also overwrite the cloned layer's relatives. - // Therefore, temporarily store the relatives so they can be set in the cloned drawingState - // again. + // called. However, copying the drawingState would also overwrite the cloned layer's relatives + // and touchableRegionCrop. Therefore, temporarily store the relatives so they can be set in + // the cloned drawingState again. wp tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf; SortedVector> tmpZOrderRelatives = mDrawingState.zOrderRelatives; + wp tmpTouchableRegionCrop = mDrawingState.touchableRegionCrop; + InputWindowInfo tmpInputInfo = mDrawingState.inputInfo; + mDrawingState = clonedFrom->mDrawingState; - // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple - // InputWindows per client token yet. - mDrawingState.inputInfo.token = nullptr; + + mDrawingState.touchableRegionCrop = tmpTouchableRegionCrop; mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf; mDrawingState.zOrderRelatives = tmpZOrderRelatives; + mDrawingState.inputInfo = tmpInputInfo; } } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 35fc4be056..e7572f0054 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2025,6 +2025,7 @@ bool Layer::isRemovedFromCurrentState() const { InputWindowInfo Layer::fillInputInfo() { InputWindowInfo info = mDrawingState.inputInfo; + info.id = sequence; if (info.displayId == ADISPLAY_ID_NONE) { info.displayId = getLayerStack(); @@ -2081,9 +2082,29 @@ InputWindowInfo Layer::fillInputInfo() { info.touchableRegion = info.touchableRegion.intersect(Rect{cropLayer->mScreenBounds}); } + // If the layer is a clone, we need to crop the input region to cloned root to prevent + // touches from going outside the cloned area. + if (isClone()) { + sp clonedRoot = getClonedRoot(); + if (clonedRoot != nullptr) { + Rect rect(clonedRoot->mScreenBounds); + info.touchableRegion = info.touchableRegion.intersect(rect); + } + } + return info; } +sp Layer::getClonedRoot() { + if (mClonedChild != nullptr) { + return this; + } + if (mDrawingParent == nullptr || mDrawingParent.promote() == nullptr) { + return nullptr; + } + return mDrawingParent.promote()->getClonedRoot(); +} + bool Layer::hasInput() const { return mDrawingState.inputInfo.token != nullptr; } @@ -2119,10 +2140,6 @@ void Layer::setInitialValuesForClone(const sp& clonedFrom) { // copy drawing state from cloned layer mDrawingState = clonedFrom->mDrawingState; mClonedFrom = clonedFrom; - - // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple - // InputWindows per client token yet. - mDrawingState.inputInfo.token = nullptr; } void Layer::updateMirrorInfo() { @@ -2157,9 +2174,6 @@ void Layer::updateClonedDrawingState(std::map, sp>& clonedLayer if (isClonedFromAlive()) { sp clonedFrom = getClonedFrom(); mDrawingState = clonedFrom->mDrawingState; - // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple - // InputWindows per client token yet. - mDrawingState.inputInfo.token = nullptr; clonedLayersMap.emplace(clonedFrom, this); } @@ -2198,7 +2212,24 @@ void Layer::updateClonedChildren(const sp& mirrorRoot, } } -void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap) { +void Layer::updateClonedInputInfo(const std::map, sp>& clonedLayersMap) { + auto cropLayer = mDrawingState.touchableRegionCrop.promote(); + if (cropLayer != nullptr) { + if (clonedLayersMap.count(cropLayer) == 0) { + // Real layer had a crop layer but it's not in the cloned hierarchy. Just set to + // self as crop layer to avoid going outside bounds. + mDrawingState.touchableRegionCrop = this; + } else { + const sp& clonedCropLayer = clonedLayersMap.at(cropLayer); + mDrawingState.touchableRegionCrop = clonedCropLayer; + } + } + // 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; +} + +void Layer::updateClonedRelatives(const std::map, sp>& clonedLayersMap) { mDrawingState.zOrderRelativeOf = nullptr; mDrawingState.zOrderRelatives.clear(); @@ -2206,11 +2237,11 @@ void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap return; } - sp clonedFrom = getClonedFrom(); + const sp& clonedFrom = getClonedFrom(); for (wp& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) { - sp relative = relativeWeak.promote(); - auto clonedRelative = clonedLayersMap[relative]; - if (clonedRelative != nullptr) { + const sp& relative = relativeWeak.promote(); + if (clonedLayersMap.count(relative) > 0) { + auto& clonedRelative = clonedLayersMap.at(relative); mDrawingState.zOrderRelatives.add(clonedRelative); } } @@ -2220,12 +2251,14 @@ void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap // In that case, we treat the layer as if the relativeOf has been removed. This way, it will // still traverse the children, but the layer with the missing relativeOf will not be shown // on screen. - sp relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); - sp clonedRelativeOf = clonedLayersMap[relativeOf]; - if (clonedRelativeOf != nullptr) { + const sp& relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); + if (clonedLayersMap.count(relativeOf) > 0) { + const sp& clonedRelativeOf = clonedLayersMap.at(relativeOf); mDrawingState.zOrderRelativeOf = clonedRelativeOf; } + updateClonedInputInfo(clonedLayersMap); + for (sp& child : mDrawingChildren) { child->updateClonedRelatives(clonedLayersMap); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 843d3ae88e..d697a6a182 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -497,8 +497,9 @@ protected: void updateClonedDrawingState(std::map, sp>& clonedLayersMap); void updateClonedChildren(const sp& mirrorRoot, std::map, sp>& clonedLayersMap); - void updateClonedRelatives(std::map, sp> clonedLayersMap); + void updateClonedRelatives(const std::map, sp>& clonedLayersMap); void addChildToDrawing(const sp& layer); + void updateClonedInputInfo(const std::map, sp>& clonedLayersMap); public: /* @@ -972,6 +973,10 @@ private: // Returns true if the layer can draw shadows on its border. virtual bool canDrawShadows() const { return true; } + + // Find the root of the cloned hierarchy, this means the first non cloned parent. + // This will return null if first non cloned parent is not found. + sp getClonedRoot(); }; } // namespace android -- cgit v1.2.3-59-g8ed1b From cb9232108322f4e74583feaf27c44c5331e4fa35 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 30 Dec 2019 14:05:11 -0800 Subject: Remove layer from window handle since it's no longer used Fixes: 146671630 Test: Builds and runs Change-Id: I095228a361ecdda8e1abd48c6d32b085b0dd20cf --- include/input/InputWindow.h | 1 - libs/input/InputWindow.cpp | 2 -- libs/input/tests/InputWindow_test.cpp | 2 -- .../benchmarks/InputDispatcher_benchmarks.cpp | 1 - services/inputflinger/dispatcher/InputDispatcher.cpp | 17 +++++++---------- services/inputflinger/tests/InputDispatcher_test.cpp | 1 - 6 files changed, 7 insertions(+), 17 deletions(-) (limited to 'include/input') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index cbd64d520e..c44db514d2 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -161,7 +161,6 @@ struct InputWindowInfo { bool hasFocus; bool hasWallpaper; bool paused; - int32_t layer; int32_t ownerPid; int32_t ownerUid; int32_t inputFeatures; diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 74a05055eb..03ca459fb9 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -91,7 +91,6 @@ status_t InputWindowInfo::write(Parcel& output) const { output.writeBool(hasFocus); output.writeBool(hasWallpaper); output.writeBool(paused); - output.writeInt32(layer); output.writeInt32(ownerPid); output.writeInt32(ownerUid); output.writeInt32(inputFeatures); @@ -135,7 +134,6 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) { ret.hasFocus = from.readBool(); ret.hasWallpaper = from.readBool(); ret.paused = from.readBool(); - ret.layer = from.readInt32(); ret.ownerPid = from.readInt32(); ret.ownerUid = from.readInt32(); ret.inputFeatures = from.readInt32(); diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index cdc81d2f04..d1cb527a57 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -58,7 +58,6 @@ TEST(InputWindowInfo, Parcelling) { i.hasFocus = false; i.hasWallpaper = false; i.paused = false; - i.layer = 7; i.ownerPid = 19; i.ownerUid = 24; i.inputFeatures = 29; @@ -91,7 +90,6 @@ TEST(InputWindowInfo, Parcelling) { ASSERT_EQ(i.hasFocus, i2.hasFocus); ASSERT_EQ(i.hasWallpaper, i2.hasWallpaper); ASSERT_EQ(i.paused, i2.paused); - ASSERT_EQ(i.layer, i2.layer); ASSERT_EQ(i.ownerPid, i2.ownerPid); ASSERT_EQ(i.ownerUid, i2.ownerUid); ASSERT_EQ(i.inputFeatures, i2.inputFeatures); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 9686ceaf2f..0d3c821215 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -170,7 +170,6 @@ public: mInfo.hasFocus = true; mInfo.hasWallpaper = false; mInfo.paused = false; - mInfo.layer = 0; mInfo.ownerPid = INJECTOR_PID; mInfo.ownerUid = INJECTOR_UID; mInfo.inputFeatures = 0; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 116625c03e..4766bcefed 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3793,12 +3793,10 @@ 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, layer=%d, " + "hasWallpaper=%s, visible=%s, canReceiveKeys=%s, " + "flags=0x%08x, type=0x%08x, " "frame=[%d,%d][%d,%d], globalScale=%f, " - "windowScale=(%f,%f), " - "touchableRegion=", + "windowScale=(%f,%f), touchableRegion=", i, windowInfo->name.c_str(), windowInfo->displayId, windowInfo->portalToDisplayId, toString(windowInfo->paused), @@ -3807,11 +3805,10 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { toString(windowInfo->visible), toString(windowInfo->canReceiveKeys), windowInfo->layoutParamsFlags, - windowInfo->layoutParamsType, windowInfo->layer, - windowInfo->frameLeft, windowInfo->frameTop, - windowInfo->frameRight, windowInfo->frameBottom, - windowInfo->globalScaleFactor, windowInfo->windowXScale, - windowInfo->windowYScale); + windowInfo->layoutParamsType, 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(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index c25122c72b..5ffc89d210 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -543,7 +543,6 @@ public: mInfo.hasFocus = false; mInfo.hasWallpaper = false; mInfo.paused = false; - mInfo.layer = 0; mInfo.ownerPid = INJECTOR_PID; mInfo.ownerUid = INJECTOR_UID; mInfo.inputFeatures = 0; -- cgit v1.2.3-59-g8ed1b From 718f9601c611f657fd872f84f27d5cc9aec533b4 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Sat, 9 Nov 2019 20:01:35 -0800 Subject: ui: Deduplicate rotation types Introduce ui::Rotation, replacing ISurfaceComposer::Rotation as well as DISPLAY_ORIENTATION_* and DisplayState::eOrientation* constants. libinput has widespread use of int32_t for orientation, so move DISPLAY_ORIENTATION_* to input/DisplayViewport.h for now. Bug: 144601064 Test: go/wm-smoke Test: screencap Change-Id: Ic4b8494e37c9d79c00d5b4be5eb88585f09efebf --- cmds/surfacereplayer/replayer/Replayer.cpp | 2 +- include/input/DisplayViewport.h | 13 +- include/input/TouchVideoFrame.h | 1 - libs/gui/ISurfaceComposer.cpp | 9 +- libs/gui/LayerState.cpp | 5 +- libs/gui/SurfaceComposerClient.cpp | 39 +++-- libs/gui/include/gui/ISurfaceComposer.h | 22 +-- libs/gui/include/gui/LayerState.h | 12 +- libs/gui/include/gui/SurfaceComposerClient.h | 33 ++-- libs/gui/tests/BLASTBufferQueue_test.cpp | 10 +- libs/gui/tests/Surface_test.cpp | 9 +- libs/input/TouchVideoFrame.cpp | 1 + libs/input/tests/TouchVideoFrame_test.cpp | 1 + libs/ui/include/ui/DisplayInfo.h | 11 +- libs/ui/include/ui/Rotation.h | 57 +++++++ libs/ui/include/ui/Transform.h | 39 +++-- libs/ui/include_vndk/ui/Rotation.h | 1 + opengl/tests/lib/WindowSurface.cpp | 3 +- services/surfaceflinger/BufferLayer.cpp | 6 +- services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 75 +++------ services/surfaceflinger/DisplayDevice.h | 169 +++++++++------------ services/surfaceflinger/LayerRejecter.cpp | 2 +- services/surfaceflinger/RegionSamplingThread.cpp | 14 +- services/surfaceflinger/RenderArea.h | 16 +- services/surfaceflinger/SurfaceFlinger.cpp | 101 ++++++------ services/surfaceflinger/SurfaceFlinger.h | 10 +- services/surfaceflinger/SurfaceInterceptor.cpp | 8 +- services/surfaceflinger/tests/Credentials_test.cpp | 3 +- .../tests/LayerRenderTypeTransaction_test.cpp | 4 +- .../surfaceflinger/tests/LayerTransaction_test.cpp | 2 +- .../tests/unittests/DisplayTransactionTest.cpp | 12 +- .../tests/unittests/TestableSurfaceFlinger.h | 1 - 33 files changed, 329 insertions(+), 364 deletions(-) create mode 100644 libs/ui/include/ui/Rotation.h create mode 120000 libs/ui/include_vndk/ui/Rotation.h (limited to 'include/input') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 0d6c31ee2f..675aad6f81 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -606,7 +606,7 @@ void Replayer::setDisplayProjection(SurfaceComposerClient::Transaction& t, pc.viewport().bottom()); Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom()); - t.setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame); + t.setDisplayProjection(mDisplays[id], ui::toRotation(pc.orientation()), viewport, frame); } status_t Replayer::createSurfaceControl( diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index fa456bb213..610062697c 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -17,16 +17,23 @@ #ifndef _LIBINPUT_DISPLAY_VIEWPORT_H #define _LIBINPUT_DISPLAY_VIEWPORT_H +#include +#include + #include -#include #include -#include -#include using android::base::StringPrintf; namespace android { +enum { + DISPLAY_ORIENTATION_0 = 0, + DISPLAY_ORIENTATION_90 = 1, + DISPLAY_ORIENTATION_180 = 2, + DISPLAY_ORIENTATION_270 = 3 +}; + /** * Describes the different type of viewports supported by input flinger. * Keep in sync with values in InputManagerService.java. diff --git a/include/input/TouchVideoFrame.h b/include/input/TouchVideoFrame.h index b49c623204..4fa2f86dc1 100644 --- a/include/input/TouchVideoFrame.h +++ b/include/input/TouchVideoFrame.h @@ -19,7 +19,6 @@ #include #include -#include #include namespace android { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ab4d51e3cb..d34fe3b0ba 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -110,10 +110,10 @@ public: } virtual status_t captureScreen(const sp& display, sp* outBuffer, - bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation, bool captureSecureLayers) { + ui::Rotation rotation, bool captureSecureLayers) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -1214,8 +1214,7 @@ status_t BnSurfaceComposer::onTransact( bool capturedSecureLayers = false; status_t res = captureScreen(display, &outBuffer, capturedSecureLayers, reqDataspace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, - useIdentityTransform, - static_cast(rotation), + useIdentityTransform, ui::toRotation(rotation), captureSecureLayers); reply->writeInt32(res); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e033f93286..a7c4f4670a 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -203,7 +203,6 @@ status_t ComposerState::read(const Parcel& input) { DisplayState::DisplayState() : what(0), layerStack(0), - orientation(eOrientationDefault), viewport(Rect::EMPTY_RECT), frame(Rect::EMPTY_RECT), width(0), @@ -215,7 +214,7 @@ status_t DisplayState::write(Parcel& output) const { output.writeStrongBinder(IInterface::asBinder(surface)); output.writeUint32(what); output.writeUint32(layerStack); - output.writeUint32(orientation); + output.writeUint32(toRotationInt(orientation)); output.write(viewport); output.write(frame); output.writeUint32(width); @@ -228,7 +227,7 @@ status_t DisplayState::read(const Parcel& input) { surface = interface_cast(input.readStrongBinder()); what = input.readUint32(); layerStack = input.readUint32(); - orientation = input.readUint32(); + orientation = ui::toRotation(input.readUint32()); input.read(viewport); input.read(frame); width = input.readUint32(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index f378fc5ef6..1dac70a950 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1399,9 +1399,9 @@ void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp& } void SurfaceComposerClient::Transaction::setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect) { + ui::Rotation orientation, + const Rect& layerStackRect, + const Rect& displayRect) { DisplayState& s(getDisplayState(token)); s.orientation = orientation; s.viewport = layerStackRect; @@ -1773,28 +1773,26 @@ status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColo // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, +status_t ScreenshotClient::capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, bool captureSecureLayers, + ui::Rotation rotation, bool captureSecureLayers, sp* outBuffer, bool& outCapturedSecureLayers) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; - status_t ret = - s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace, - reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, - static_cast(rotation), - captureSecureLayers); + status_t ret = s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace, + reqPixelFormat, sourceCrop, reqWidth, reqHeight, + useIdentityTransform, rotation, captureSecureLayers); if (ret != NO_ERROR) { return ret; } return ret; } -status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, +status_t ScreenshotClient::capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, sp* outBuffer) { + ui::Rotation rotation, sp* outBuffer) { bool ignored; return capture(display, reqDataSpace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation, false, outBuffer, ignored); @@ -1807,9 +1805,8 @@ status_t ScreenshotClient::capture(uint64_t displayOrLayerStack, ui::Dataspace* return s->captureScreen(displayOrLayerStack, outDataspace, outBuffer); } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, - const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, +status_t ScreenshotClient::captureLayers(const sp& layerHandle, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; @@ -1819,8 +1816,8 @@ status_t ScreenshotClient::captureLayers(const sp& layerHandle, } status_t ScreenshotClient::captureChildLayers( - const sp& layerHandle, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + const sp& layerHandle, ui::Dataspace reqDataSpace, ui::PixelFormat reqPixelFormat, + const Rect& sourceCrop, const std::unordered_set, ISurfaceComposer::SpHash>& excludeHandles, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); @@ -1830,5 +1827,5 @@ status_t ScreenshotClient::captureChildLayers( excludeHandles, frameScale, true /* childrenOnly */); return ret; } -// ---------------------------------------------------------------------------- -}; // namespace android + +} // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 998973c4dc..9804c92d0c 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -81,13 +82,6 @@ public: eEarlyWakeup = 0x04 }; - enum Rotation { - eRotateNone = 0, - eRotate90 = 1, - eRotate180 = 2, - eRotate270 = 3 - }; - enum VsyncSource { eVsyncSourceApp = 0, eVsyncSourceSurfaceFlinger = 1 @@ -249,10 +243,10 @@ public: * it) around its center. */ virtual status_t captureScreen(const sp& display, sp* outBuffer, - bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - Rotation rotation = eRotateNone, + ui::Rotation rotation = ui::ROTATION_0, bool captureSecureLayers = false) = 0; /** * Capture the specified screen. This requires READ_FRAME_BUFFER @@ -276,8 +270,9 @@ public: * it) around its center. */ virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, Rotation rotation = eRotateNone) { + const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + bool useIdentityTransform, + ui::Rotation rotation = ui::ROTATION_0) { bool outIgnored; return captureScreen(display, outBuffer, outIgnored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, sourceCrop, reqWidth, reqHeight, @@ -301,8 +296,7 @@ public: */ virtual status_t captureLayers( const sp& layerHandleBinder, sp* outBuffer, - const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat, - const Rect& sourceCrop, + ui::Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, const std::unordered_set, SpHash>& excludeHandles, float frameScale = 1.0, bool childrenOnly = false) = 0; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index c2b5119242..fb186396a6 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace android { @@ -217,15 +218,6 @@ struct ComposerState { }; struct DisplayState { - enum { - eOrientationDefault = 0, - eOrientation90 = 1, - eOrientation180 = 2, - eOrientation270 = 3, - eOrientationUnchanged = 4, - eOrientationSwapMask = 0x01 - }; - enum { eSurfaceChanged = 0x01, eLayerStackChanged = 0x02, @@ -252,7 +244,7 @@ struct DisplayState { // 0, layers will be scaled by a factor of 2 and translated by (20, 10). // When orientation is 1, layers will be additionally rotated by 90 // degrees around the origin clockwise and translated by (W, 0). - uint32_t orientation; + ui::Rotation orientation = ui::ROTATION_0; Rect viewport; Rect frame; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 86468a49f3..44f29eaa6f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -531,10 +532,8 @@ public: * mapped to. displayRect is specified post-orientation, that is * it uses the orientation seen by the end-user. */ - void setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect); + void setDisplayProjection(const sp& token, ui::Rotation orientation, + const Rect& layerStackRect, const Rect& displayRect); void setDisplaySize(const sp& token, uint32_t width, uint32_t height); void setAnimationTransaction(); void setEarlyWakeup(); @@ -548,10 +547,8 @@ public: static status_t getHdrCapabilities(const sp& display, HdrCapabilities* outCapabilities); - static void setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect); + static void setDisplayProjection(const sp& token, ui::Rotation orientation, + const Rect& layerStackRect, const Rect& displayRect); inline sp getClient() { return mClient; } @@ -583,23 +580,23 @@ class ScreenshotClient { public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + static status_t capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, bool captureSecureLayers, + ui::Rotation rotation, bool captureSecureLayers, sp* outBuffer, bool& outCapturedSecureLayers); - static status_t capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + static status_t capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, sp* outBuffer); + ui::Rotation rotation, sp* outBuffer); static status_t capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp* outBuffer); - static status_t captureLayers(const sp& layerHandle, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + static status_t captureLayers(const sp& layerHandle, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, float frameScale, sp* outBuffer); static status_t captureChildLayers( - const sp& layerHandle, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + const sp& layerHandle, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, const std::unordered_set, ISurfaceComposer::SpHash>& excludeHandles, float frameScale, sp* outBuffer); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 0f618f181c..85cf62f44f 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -127,7 +127,7 @@ protected: ASSERT_EQ(NO_ERROR, igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &qbOutput)); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); producer = igbProducer; } @@ -266,7 +266,7 @@ TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) { NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); @@ -349,7 +349,7 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); // capture screen and verify that it is red @@ -410,7 +410,7 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { NATIVE_WINDOW_SCALING_MODE_SCALE_CROP, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); // capture screen and verify that it is red @@ -456,7 +456,7 @@ public: NATIVE_WINDOW_SCALING_MODE_FREEZE, tr, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); bool capturedSecureLayers; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 0445755ade..f9540b2a41 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -742,11 +742,10 @@ public: status_t setActiveColorMode(const sp& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, sp* /*outBuffer*/, - bool& /* outCapturedSecureLayers */, - const ui::Dataspace /*reqDataspace*/, - const ui::PixelFormat /*reqPixelFormat*/, Rect /*sourceCrop*/, + bool& /*outCapturedSecureLayers*/, ui::Dataspace /*reqDataspace*/, + ui::PixelFormat /*reqPixelFormat*/, const Rect& /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, - bool /*useIdentityTransform*/, Rotation /*rotation*/, + bool /*useIdentityTransform*/, ui::Rotation, bool /*captureSecureLayers*/) override { return NO_ERROR; } @@ -766,7 +765,7 @@ public: } virtual status_t captureLayers( const sp& /*parentHandle*/, sp* /*outBuffer*/, - const ui::Dataspace /*reqDataspace*/, const ui::PixelFormat /*reqPixelFormat*/, + ui::Dataspace /*reqDataspace*/, ui::PixelFormat /*reqPixelFormat*/, const Rect& /*sourceCrop*/, const std::unordered_set, ISurfaceComposer::SpHash>& /*excludeHandles*/, diff --git a/libs/input/TouchVideoFrame.cpp b/libs/input/TouchVideoFrame.cpp index 8a4298a36f..145b4ae03b 100644 --- a/libs/input/TouchVideoFrame.cpp +++ b/libs/input/TouchVideoFrame.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include namespace android { diff --git a/libs/input/tests/TouchVideoFrame_test.cpp b/libs/input/tests/TouchVideoFrame_test.cpp index 815424ee31..1ec935859d 100644 --- a/libs/input/tests/TouchVideoFrame_test.cpp +++ b/libs/input/tests/TouchVideoFrame_test.cpp @@ -16,6 +16,7 @@ #include +#include #include namespace android { diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h index 07722104de..38f8d6be02 100644 --- a/libs/ui/include/ui/DisplayInfo.h +++ b/libs/ui/include/ui/DisplayInfo.h @@ -20,6 +20,7 @@ #include #include +#include #include namespace android { @@ -33,7 +34,7 @@ struct DisplayInfo { float ydpi{0}; float fps{0}; float density{0}; - uint8_t orientation{0}; + ui::Rotation orientation{ui::ROTATION_0}; bool secure{false}; nsecs_t appVsyncOffset{0}; nsecs_t presentationDeadline{0}; @@ -42,14 +43,6 @@ struct DisplayInfo { uint32_t layerStack{NO_LAYER_STACK}; }; -/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */ -enum { - DISPLAY_ORIENTATION_0 = 0, - DISPLAY_ORIENTATION_90 = 1, - DISPLAY_ORIENTATION_180 = 2, - DISPLAY_ORIENTATION_270 = 3 -}; - } // namespace android #endif // ANDROID_COMPOSER_DISPLAY_INFO_H diff --git a/libs/ui/include/ui/Rotation.h b/libs/ui/include/ui/Rotation.h new file mode 100644 index 0000000000..89008f6694 --- /dev/null +++ b/libs/ui/include/ui/Rotation.h @@ -0,0 +1,57 @@ +/* + * Copyright 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 + +namespace android::ui { + +enum class Rotation { Rotation0 = 0, Rotation90 = 1, Rotation180 = 2, Rotation270 = 3 }; + +// Equivalent to Surface.java constants. +constexpr auto ROTATION_0 = Rotation::Rotation0; +constexpr auto ROTATION_90 = Rotation::Rotation90; +constexpr auto ROTATION_180 = Rotation::Rotation180; +constexpr auto ROTATION_270 = Rotation::Rotation270; + +constexpr auto toRotation(std::underlying_type_t rotation) { + return static_cast(rotation); +} + +constexpr auto toRotationInt(Rotation rotation) { + return static_cast>(rotation); +} + +constexpr Rotation operator+(Rotation lhs, Rotation rhs) { + constexpr auto N = toRotationInt(ROTATION_270) + 1; + return toRotation((toRotationInt(lhs) + toRotationInt(rhs)) % N); +} + +constexpr const char* toCString(Rotation rotation) { + switch (rotation) { + case ROTATION_0: + return "ROTATION_0"; + case ROTATION_90: + return "ROTATION_90"; + case ROTATION_180: + return "ROTATION_180"; + case ROTATION_270: + return "ROTATION_270"; + } +} + +} // namespace android::ui diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h index de07684d79..c6bb598d7f 100644 --- a/libs/ui/include/ui/Transform.h +++ b/libs/ui/include/ui/Transform.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef ANDROID_TRANSFORM_H -#define ANDROID_TRANSFORM_H +#pragma once #include #include @@ -28,6 +27,7 @@ #include #include #include +#include namespace android { @@ -42,13 +42,13 @@ public: explicit Transform(uint32_t orientation, int w = 0, int h = 0); ~Transform(); - enum orientation_flags { - ROT_0 = 0x00000000, - FLIP_H = HAL_TRANSFORM_FLIP_H, - FLIP_V = HAL_TRANSFORM_FLIP_V, - ROT_90 = HAL_TRANSFORM_ROT_90, - ROT_180 = FLIP_H|FLIP_V, - ROT_270 = ROT_180|ROT_90, + enum RotationFlags : uint32_t { + ROT_0 = 0, + FLIP_H = HAL_TRANSFORM_FLIP_H, + FLIP_V = HAL_TRANSFORM_FLIP_V, + ROT_90 = HAL_TRANSFORM_ROT_90, + ROT_180 = FLIP_H | FLIP_V, + ROT_270 = ROT_180 | ROT_90, ROT_INVALID = 0x80 }; @@ -100,6 +100,8 @@ public: void dump(std::string& result, const char* name) const; void dump(const char* name) const; + static RotationFlags toRotationFlags(Rotation); + private: struct mat33 { vec3 v[3]; @@ -117,13 +119,26 @@ private: mutable uint32_t mType; }; -static inline void PrintTo(const Transform& t, ::std::ostream* os) { +inline void PrintTo(const Transform& t, ::std::ostream* os) { std::string out; t.dump(out, "ui::Transform"); *os << out; } +inline Transform::RotationFlags Transform::toRotationFlags(Rotation rotation) { + switch (rotation) { + case ROTATION_0: + return ROT_0; + case ROTATION_90: + return ROT_90; + case ROTATION_180: + return ROT_180; + case ROTATION_270: + return ROT_270; + default: + return ROT_INVALID; + } +} + } // namespace ui } // namespace android - -#endif /* ANDROID_TRANSFORM_H */ diff --git a/libs/ui/include_vndk/ui/Rotation.h b/libs/ui/include_vndk/ui/Rotation.h new file mode 120000 index 0000000000..d84fb4b46b --- /dev/null +++ b/libs/ui/include_vndk/ui/Rotation.h @@ -0,0 +1 @@ +../../include/ui/Rotation.h \ No newline at end of file diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp index a0bd4e2409..4dcc1ca4db 100644 --- a/opengl/tests/lib/WindowSurface.cpp +++ b/opengl/tests/lib/WindowSurface.cpp @@ -48,8 +48,7 @@ WindowSurface::WindowSurface() { } uint32_t width, height; - if (mainDpyInfo.orientation != DISPLAY_ORIENTATION_0 && - mainDpyInfo.orientation != DISPLAY_ORIENTATION_180) { + if (mainDpyInfo.orientation != ui::ROTATION_0 && mainDpyInfo.orientation != ui::ROTATION_180) { // rotated width = mainDpyInfo.h; height = mainDpyInfo.w; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index bdecdb78d0..3b1b796076 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -207,7 +207,7 @@ std::optional BufferLayer::prepareClientComposition * the code below applies the primary display's inverse transform to * the texture transform */ - uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t transform = DisplayDevice::getPrimaryDisplayRotationFlags(); mat4 tr = inverseOrientation(transform); /** @@ -622,7 +622,7 @@ Rect BufferLayer::getBufferSize(const State& s) const { } if (getTransformToDisplayInverse()) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -658,7 +658,7 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const } if (getTransformToDisplayInverse()) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 1e471e53ff..170956ca80 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -468,7 +468,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } if (s.transformToDisplayInverse) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufferWidth, bufferHeight); } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 84ec597d2f..e0dc3e7751 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -41,12 +41,7 @@ namespace android { using android::base::StringAppendF; -/* - * Initialize the display to the specified values. - * - */ - -uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0; +ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0; DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(const sp& flinger, const wp& displayToken, @@ -57,13 +52,11 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) : mFlinger(args.flinger), mDisplayToken(args.displayToken), mSequenceId(args.sequenceId), - mDisplayInstallOrientation(args.displayInstallOrientation), + mIsVirtual(args.isVirtual), mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay( compositionengine::DisplayCreationArgs{args.isVirtual, args.displayId, args.powerAdvisor})}, - mIsVirtual(args.isVirtual), - mOrientation(), - mActiveConfig(0), + mPhysicalOrientation(args.physicalOrientation), mIsPrimary(args.isPrimary) { mCompositionDisplay->editState().isSecure = args.isSecure; mCompositionDisplay->createRenderSurface( @@ -88,7 +81,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) setPowerMode(args.initialPowerMode); // initialize the display orientation transform. - setProjection(DisplayState::eOrientationDefault, Rect::INVALID_RECT, Rect::INVALID_RECT); + setProjection(ui::ROTATION_0, Rect::INVALID_RECT, Rect::INVALID_RECT); } DisplayDevice::~DisplayDevice() = default; @@ -131,7 +124,6 @@ bool DisplayDevice::isPoweredOn() const { return mPowerMode != HWC_POWER_MODE_OFF; } -// ---------------------------------------------------------------------------- void DisplayDevice::setActiveConfig(HwcConfigIndexType mode) { mActiveConfig = mode; } @@ -140,53 +132,19 @@ HwcConfigIndexType DisplayDevice::getActiveConfig() const { return mActiveConfig; } -// ---------------------------------------------------------------------------- - ui::Dataspace DisplayDevice::getCompositionDataSpace() const { return mCompositionDisplay->getState().dataspace; } -// ---------------------------------------------------------------------------- - void DisplayDevice::setLayerStack(uint32_t stack) { mCompositionDisplay->setLayerStackFilter(stack, isPrimary()); } -// ---------------------------------------------------------------------------- - -uint32_t DisplayDevice::displayStateOrientationToTransformOrientation(int orientation) { - switch (orientation) { - case DisplayState::eOrientationDefault: - return ui::Transform::ROT_0; - case DisplayState::eOrientation90: - return ui::Transform::ROT_90; - case DisplayState::eOrientation180: - return ui::Transform::ROT_180; - case DisplayState::eOrientation270: - return ui::Transform::ROT_270; - default: - return ui::Transform::ROT_INVALID; - } -} - -status_t DisplayDevice::orientationToTransfrom(int orientation, int w, int h, ui::Transform* tr) { - uint32_t flags = displayStateOrientationToTransformOrientation(orientation); - if (flags == ui::Transform::ROT_INVALID) { - return BAD_VALUE; - } - tr->set(flags, w, h); - return NO_ERROR; -} - void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) { mCompositionDisplay->setBounds(ui::Size(newWidth, newHeight)); } -void DisplayDevice::setProjection(int orientation, - const Rect& newViewport, const Rect& newFrame) { - Rect viewport(newViewport); - Rect frame(newFrame); - +void DisplayDevice::setProjection(ui::Rotation orientation, Rect viewport, Rect frame) { mOrientation = orientation; const Rect& displayBounds = getCompositionDisplay()->getState().bounds; @@ -194,7 +152,10 @@ void DisplayDevice::setProjection(int orientation, const int h = displayBounds.height(); ui::Transform R; - DisplayDevice::orientationToTransfrom(orientation, w, h, &R); + if (const auto flags = ui::Transform::toRotationFlags(orientation); + flags != ui::Transform::ROT_INVALID) { + R.set(flags, w, h); + } if (!frame.isValid()) { // the destination frame can be invalid if it has never been set, @@ -236,9 +197,10 @@ void DisplayDevice::setProjection(int orientation, // need to take care of primary display rotation for globalTransform // for case if the panel is not installed aligned with device orientation if (isPrimary()) { - DisplayDevice::orientationToTransfrom( - (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1), - w, h, &R); + if (const auto flags = ui::Transform::toRotationFlags(orientation + mPhysicalOrientation); + flags != ui::Transform::ROT_INVALID) { + R.set(flags, w, h); + } } // The viewport and frame are both in the logical orientation. @@ -258,19 +220,18 @@ void DisplayDevice::setProjection(int orientation, uint32_t transformOrientation; if (isPrimary()) { - sPrimaryDisplayOrientation = displayStateOrientationToTransformOrientation(orientation); - transformOrientation = displayStateOrientationToTransformOrientation( - (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1)); + sPrimaryDisplayRotationFlags = ui::Transform::toRotationFlags(orientation); + transformOrientation = ui::Transform::toRotationFlags(orientation + mPhysicalOrientation); } else { - transformOrientation = displayStateOrientationToTransformOrientation(orientation); + transformOrientation = ui::Transform::toRotationFlags(orientation); } getCompositionDisplay()->setProjection(globalTransform, transformOrientation, frame, viewport, scissor, needsFiltering); } -uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() { - return sPrimaryDisplayOrientation; +ui::Transform::RotationFlags DisplayDevice::getPrimaryDisplayRotationFlags() { + return sPrimaryDisplayRotationFlags; } std::string DisplayDevice::getDebugName() const { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 79a118571e..605e7c8ab4 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef ANDROID_DISPLAY_DEVICE_H -#define ANDROID_DISPLAY_DEVICE_H +#pragma once #include @@ -83,14 +82,17 @@ public: int getWidth() const; int getHeight() const; - int getInstallOrientation() const { return mDisplayInstallOrientation; } void setLayerStack(uint32_t stack); void setDisplaySize(const int newWidth, const int newHeight); - void setProjection(int orientation, const Rect& viewport, const Rect& frame); - int getOrientation() const { return mOrientation; } - static uint32_t getPrimaryDisplayOrientationTransform(); + void setProjection(ui::Rotation orientation, Rect viewport, Rect frame); + + ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; } + ui::Rotation getOrientation() const { return mOrientation; } + + static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags(); + const ui::Transform& getTransform() const; const Rect& getViewport() const; const Rect& getFrame() const; @@ -156,37 +158,21 @@ public: void dump(std::string& result) const; private: - /* - * Constants, set during initialization - */ const sp mFlinger; const wp mDisplayToken; const int32_t mSequenceId; + const bool mIsVirtual; - const int mDisplayInstallOrientation; const std::shared_ptr mCompositionDisplay; std::string mDisplayName; - const bool mIsVirtual; - /* - * Can only accessed from the main thread, these members - * don't need synchronization. - */ - - /* - * Transaction state - */ - static uint32_t displayStateOrientationToTransformOrientation(int orientation); - static status_t orientationToTransfrom(int orientation, - int w, int h, ui::Transform* tr); + const ui::Rotation mPhysicalOrientation; + ui::Rotation mOrientation = ui::ROTATION_0; - int mOrientation; - static uint32_t sPrimaryDisplayOrientation; + static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags; - // Current power mode - int mPowerMode; - // Current active config + int mPowerMode = HWC_POWER_MODE_OFF; HwcConfigIndexType mActiveConfig; // TODO(b/74619554): Remove special cases for primary display. @@ -202,7 +188,7 @@ struct DisplayDeviceState { uint32_t layerStack = NO_LAYER_STACK; Rect viewport; Rect frame; - uint8_t orientation = 0; + ui::Rotation orientation = ui::ROTATION_0; uint32_t width = 0; uint32_t height = 0; std::string displayName; @@ -227,7 +213,7 @@ struct DisplayDeviceCreationArgs { bool isSecure{false}; sp nativeWindow; sp displaySurface; - int displayInstallOrientation{DisplayState::eOrientationDefault}; + ui::Rotation physicalOrientation{ui::ROTATION_0}; bool hasWideColorGamut{false}; HdrCapabilities hdrCapabilities; int32_t supportedPerFrameMetadata{0}; @@ -239,31 +225,33 @@ struct DisplayDeviceCreationArgs { class DisplayRenderArea : public RenderArea { public: - DisplayRenderArea(const sp device, - ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) - : DisplayRenderArea(device, device->getBounds(), device->getWidth(), device->getHeight(), - device->getCompositionDataSpace(), rotation) {} - DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, ui::Dataspace reqDataSpace, - ui::Transform::orientation_flags rotation, bool allowSecureLayers = true) + DisplayRenderArea(const sp& display, + RotationFlags rotation = ui::Transform::ROT_0) + : DisplayRenderArea(display, display->getBounds(), display->getWidth(), + display->getHeight(), display->getCompositionDataSpace(), rotation) {} + + DisplayRenderArea(sp display, const Rect& sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation, + bool allowSecureLayers = true) : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace, - device->getViewport(), - getDisplayRotation(rotation, device->getInstallOrientation())), - mDevice(device), + display->getViewport(), + applyInversePhysicalOrientation(rotation, + display->getPhysicalOrientation())), + mDisplay(std::move(display)), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} - const ui::Transform& getTransform() const override { return mDevice->getTransform(); } - Rect getBounds() const override { return mDevice->getBounds(); } - int getHeight() const override { return mDevice->getHeight(); } - int getWidth() const override { return mDevice->getWidth(); } - bool isSecure() const override { return mAllowSecureLayers && mDevice->isSecure(); } - const sp getDisplayDevice() const override { return mDevice; } + const ui::Transform& getTransform() const override { return mDisplay->getTransform(); } + Rect getBounds() const override { return mDisplay->getBounds(); } + int getHeight() const override { return mDisplay->getHeight(); } + int getWidth() const override { return mDisplay->getWidth(); } + bool isSecure() const override { return mAllowSecureLayers && mDisplay->isSecure(); } + sp getDisplayDevice() const override { return mDisplay; } bool needsFiltering() const override { // check if the projection from the logical display to the physical // display needs filtering - if (mDevice->needsFiltering()) { + if (mDisplay->needsFiltering()) { return true; } @@ -281,7 +269,7 @@ public: Rect getSourceCrop() const override { // use the projected display viewport by default. if (mSourceCrop.isEmpty()) { - return mDevice->getScissor(); + return mDisplay->getScissor(); } // Recompute the device transformation for the source crop. @@ -289,27 +277,13 @@ public: ui::Transform translatePhysical; ui::Transform translateLogical; ui::Transform scale; - const Rect& viewport = mDevice->getViewport(); - const Rect& scissor = mDevice->getScissor(); - const Rect& frame = mDevice->getFrame(); - - const int orientation = mDevice->getInstallOrientation(); - // Install orientation is transparent to the callers. Apply it now. - uint32_t flags = 0x00; - switch (orientation) { - case DisplayState::eOrientation90: - flags = ui::Transform::ROT_90; - break; - case DisplayState::eOrientation180: - flags = ui::Transform::ROT_180; - break; - case DisplayState::eOrientation270: - flags = ui::Transform::ROT_270; - break; - default: - break; - } + const Rect& viewport = mDisplay->getViewport(); + const Rect& scissor = mDisplay->getScissor(); + const Rect& frame = mDisplay->getFrame(); + + const auto flags = ui::Transform::toRotationFlags(mDisplay->getPhysicalOrientation()); rotation.set(flags, getWidth(), getHeight()); + translateLogical.set(-viewport.left, -viewport.top); translatePhysical.set(scissor.left, scissor.top); scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0, @@ -320,49 +294,44 @@ public: } private: - // Install orientation is transparent to the callers. We need to cancel - // it out by modifying rotation flags. - static ui::Transform::orientation_flags getDisplayRotation( - ui::Transform::orientation_flags rotation, int orientation) { - if (orientation == DisplayState::eOrientationDefault) { - return rotation; - } - - // convert hw orientation into flag presentation - // here inverse transform needed - uint8_t hw_rot_90 = 0x00; - uint8_t hw_flip_hv = 0x00; - switch (orientation) { - case DisplayState::eOrientation90: - hw_rot_90 = ui::Transform::ROT_90; - hw_flip_hv = ui::Transform::ROT_180; + static RotationFlags applyInversePhysicalOrientation(RotationFlags orientation, + ui::Rotation physicalOrientation) { + uint32_t inverseRotate90 = 0; + uint32_t inverseReflect = 0; + + switch (physicalOrientation) { + case ui::ROTATION_0: + return orientation; + + case ui::ROTATION_90: + inverseRotate90 = ui::Transform::ROT_90; + inverseReflect = ui::Transform::ROT_180; break; - case DisplayState::eOrientation180: - hw_flip_hv = ui::Transform::ROT_180; + + case ui::ROTATION_180: + inverseReflect = ui::Transform::ROT_180; break; - case DisplayState::eOrientation270: - hw_rot_90 = ui::Transform::ROT_90; + + case ui::ROTATION_270: + inverseRotate90 = ui::Transform::ROT_90; break; } - // transform flags operation - // 1) flip H V if both have ROT_90 flag - // 2) XOR these flags - uint8_t rotation_rot_90 = rotation & ui::Transform::ROT_90; - uint8_t rotation_flip_hv = rotation & ui::Transform::ROT_180; - if (rotation_rot_90 & hw_rot_90) { - rotation_flip_hv = (~rotation_flip_hv) & ui::Transform::ROT_180; + const uint32_t rotate90 = orientation & ui::Transform::ROT_90; + uint32_t reflect = orientation & ui::Transform::ROT_180; + + // Apply reflection for double rotation. + if (rotate90 & inverseRotate90) { + reflect = ~reflect & ui::Transform::ROT_180; } - return static_cast( - (rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv)); + return static_cast((rotate90 ^ inverseRotate90) | + (reflect ^ inverseReflect)); } - const sp mDevice; + const sp mDisplay; const Rect mSourceCrop; const bool mAllowSecureLayers; }; -}; // namespace android - -#endif // ANDROID_DISPLAY_DEVICE_H +} // namespace android diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 1a60f1ed08..412f9779c8 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -49,7 +49,7 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) } if (mTransformToDisplayInverse) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index a484373caa..73de4f8b78 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -337,19 +337,7 @@ void RegionSamplingThread::captureSample() { } const auto device = mFlinger.getDefaultDisplayDevice(); - const auto orientation = [](uint32_t orientation) { - switch (orientation) { - default: - case DisplayState::eOrientationDefault: - return ui::Transform::ROT_0; - case DisplayState::eOrientation90: - return ui::Transform::ROT_90; - case DisplayState::eOrientation180: - return ui::Transform::ROT_180; - case DisplayState::eOrientation270: - return ui::Transform::ROT_270; - } - }(device->getOrientation()); + const auto orientation = ui::Transform::toRotationFlags(device->getOrientation()); std::vector descriptors; Region sampleRegion; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 532572f766..a7a6dd5fc1 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -17,13 +17,15 @@ class DisplayDevice; // physical render area. class RenderArea { public: + using RotationFlags = ui::Transform::RotationFlags; + enum class CaptureFill {CLEAR, OPAQUE}; static float getCaptureFillValue(CaptureFill captureFill); RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill, ui::Dataspace reqDataSpace, const Rect& displayViewport, - ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) + RotationFlags rotation = ui::Transform::ROT_0) : mReqWidth(reqWidth), mReqHeight(reqHeight), mReqDataSpace(reqDataSpace), @@ -66,20 +68,20 @@ public: virtual Rect getSourceCrop() const = 0; // Returns the rotation of the source crop and the layers. - ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; + RotationFlags getRotationFlags() const { return mRotationFlags; } // Returns the size of the physical render area. - int getReqWidth() const { return mReqWidth; }; - int getReqHeight() const { return mReqHeight; }; + int getReqWidth() const { return mReqWidth; } + int getReqHeight() const { return mReqHeight; } // Returns the composition data space of the render area. ui::Dataspace getReqDataSpace() const { return mReqDataSpace; } // Returns the fill color of the physical render area. Regions not // covered by any rendered layer should be filled with this color. - CaptureFill getCaptureFill() const { return mCaptureFill; }; + CaptureFill getCaptureFill() const { return mCaptureFill; } - virtual const sp getDisplayDevice() const = 0; + virtual sp getDisplayDevice() const = 0; // Returns the source display viewport. const Rect& getDisplayViewport() const { return mDisplayViewport; } @@ -89,7 +91,7 @@ private: const uint32_t mReqHeight; const ui::Dataspace mReqDataSpace; const CaptureFill mCaptureFill; - const ui::Transform::orientation_flags mRotationFlags; + const RotationFlags mRotationFlags; const Rect mDisplayViewport; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8c1d168cdb..92f40ff00f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,21 +163,6 @@ bool isWideColorMode(const ColorMode colorMode) { return false; } -ui::Transform::orientation_flags fromSurfaceComposerRotation(ISurfaceComposer::Rotation rotation) { - switch (rotation) { - case ISurfaceComposer::eRotateNone: - return ui::Transform::ROT_0; - case ISurfaceComposer::eRotate90: - return ui::Transform::ROT_90; - case ISurfaceComposer::eRotate180: - return ui::Transform::ROT_180; - case ISurfaceComposer::eRotate270: - return ui::Transform::ROT_270; - } - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - return ui::Transform::ROT_0; -} - #pragma clang diagnostic pop class ConditionalLock { @@ -215,7 +200,7 @@ bool SurfaceFlinger::hasSyncFramework; bool SurfaceFlinger::useVrFlinger; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; bool SurfaceFlinger::hasWideColorDisplay; -int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault; +ui::Rotation SurfaceFlinger::internalDisplayOrientation = ui::ROTATION_0; bool SurfaceFlinger::useColorManagement; bool SurfaceFlinger::useContextPriority; Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB; @@ -298,23 +283,21 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI useContextPriority = use_context_priority(true); - auto tmpPrimaryDisplayOrientation = primary_display_orientation( - SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_0); - switch (tmpPrimaryDisplayOrientation) { - case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_90: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation90; + using Values = SurfaceFlingerProperties::primary_display_orientation_values; + switch (primary_display_orientation(Values::ORIENTATION_0)) { + case Values::ORIENTATION_0: break; - case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_180: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation180; + case Values::ORIENTATION_90: + internalDisplayOrientation = ui::ROTATION_90; break; - case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_270: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation270; + case Values::ORIENTATION_180: + internalDisplayOrientation = ui::ROTATION_180; break; - default: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault; + case Values::ORIENTATION_270: + internalDisplayOrientation = ui::ROTATION_270; break; } - ALOGV("Primary Display Orientation is set to %2d.", SurfaceFlinger::primaryDisplayOrientation); + ALOGV("Internal Display Orientation: %s", toCString(internalDisplayOrientation)); mInternalDisplayPrimaries = sysprop::getDisplayNativePrimaries(); @@ -789,9 +772,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, } info.density = density; - // TODO: this needs to go away (currently needed only by webkit) const auto display = getDefaultDisplayDeviceLocked(); - info.orientation = display ? display->getOrientation() : 0; + info.orientation = display->getOrientation(); // This is for screenrecord const Rect viewport = display->getViewport(); @@ -804,7 +786,6 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, // TODO: where should this value come from? static const int TV_DENSITY = 213; info.density = TV_DENSITY / 160.0f; - info.orientation = 0; const auto display = getDisplayDeviceLocked(displayToken); info.layerStack = display->getLayerStack(); @@ -835,7 +816,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, info.secure = true; if (displayId == getInternalDisplayIdLocked() && - primaryDisplayOrientation & DisplayState::eOrientationSwapMask) { + (internalDisplayOrientation == ui::ROTATION_90 || + internalDisplayOrientation == ui::ROTATION_270)) { std::swap(info.w, info.h); } @@ -2279,8 +2261,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( nativeWindow->setSwapInterval(nativeWindow.get(), 0); } - creationArgs.displayInstallOrientation = - isInternalDisplay ? primaryDisplayOrientation : DisplayState::eOrientationDefault; + creationArgs.physicalOrientation = + isInternalDisplay ? internalDisplayOrientation : ui::ROTATION_0; // virtual displays are always considered enabled creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; @@ -3817,7 +3799,7 @@ void SurfaceFlinger::onInitializeDisplays() { DisplayState::eLayerStackChanged; d.token = token; d.layerStack = 0; - d.orientation = DisplayState::eOrientationDefault; + d.orientation = ui::ROTATION_0; d.frame.makeInvalid(); d.viewport.makeInvalid(); d.width = 0; @@ -4426,8 +4408,8 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co if (const auto display = getDefaultDisplayDeviceLocked()) { display->getCompositionDisplay()->getState().undefinedRegion.dump(result, "undefinedRegion"); - StringAppendF(&result, " orientation=%d, isPoweredOn=%d\n", display->getOrientation(), - display->isPoweredOn()); + StringAppendF(&result, " orientation=%s, isPoweredOn=%d\n", + toCString(display->getOrientation()), display->isPoweredOn()); } StringAppendF(&result, " transaction-flags : %08x\n" @@ -5004,17 +4986,19 @@ private: status_t SurfaceFlinger::captureScreen(const sp& displayToken, sp* outBuffer, bool& outCapturedSecureLayers, - const Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, - ISurfaceComposer::Rotation rotation, - bool captureSecureLayers) { + Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, + const Rect& sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, bool useIdentityTransform, + ui::Rotation rotation, bool captureSecureLayers) { ATRACE_CALL(); if (!displayToken) return BAD_VALUE; - auto renderAreaRotation = fromSurfaceComposerRotation(rotation); + auto renderAreaRotation = ui::Transform::toRotationFlags(rotation); + if (renderAreaRotation == ui::Transform::ROT_INVALID) { + ALOGE("%s: Invalid rotation: %s", __FUNCTION__, toCString(rotation)); + renderAreaRotation = ui::Transform::ROT_0; + } sp display; { @@ -5076,7 +5060,7 @@ status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* sp display; uint32_t width; uint32_t height; - ui::Transform::orientation_flags captureOrientation; + ui::Transform::RotationFlags captureOrientation; { Mutex::Autolock _l(mStateLock); display = getDisplayByIdOrLayerStack(displayOrLayerStack); @@ -5087,12 +5071,25 @@ status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* width = uint32_t(display->getViewport().width()); height = uint32_t(display->getViewport().height()); - captureOrientation = fromSurfaceComposerRotation( - static_cast(display->getOrientation())); - if (captureOrientation == ui::Transform::orientation_flags::ROT_90) { - captureOrientation = ui::Transform::orientation_flags::ROT_270; - } else if (captureOrientation == ui::Transform::orientation_flags::ROT_270) { - captureOrientation = ui::Transform::orientation_flags::ROT_90; + const auto orientation = display->getOrientation(); + captureOrientation = ui::Transform::toRotationFlags(orientation); + + switch (captureOrientation) { + case ui::Transform::ROT_90: + captureOrientation = ui::Transform::ROT_270; + break; + + case ui::Transform::ROT_270: + captureOrientation = ui::Transform::ROT_90; + break; + + case ui::Transform::ROT_INVALID: + ALOGE("%s: Invalid orientation: %s", __FUNCTION__, toCString(orientation)); + captureOrientation = ui::Transform::ROT_0; + break; + + default: + break; } *outDataspace = pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode); @@ -5140,7 +5137,7 @@ status_t SurfaceFlinger::captureLayers( } bool isSecure() const override { return false; } bool needsFiltering() const override { return mNeedsFiltering; } - const sp getDisplayDevice() const override { return nullptr; } + sp getDisplayDevice() const override { return nullptr; } Rect getSourceCrop() const override { if (mCrop.isEmpty()) { return getBounds(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2f84b138d2..61876b2b36 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -229,7 +229,7 @@ public: // found on devices with wide color gamut (e.g. Display-P3) display. static bool hasWideColorDisplay; - static int primaryDisplayOrientation; + static ui::Rotation internalDisplayOrientation; // Indicate if device wants color management on its display. static bool useColorManagement; @@ -415,10 +415,10 @@ private: ISurfaceComposer::ConfigChanged configChanged = ISurfaceComposer::eConfigChangedSuppress) override; status_t captureScreen(const sp& displayToken, sp* outBuffer, - bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation, bool captureSecureLayers) override; + bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, + ui::Rotation rotation, bool captureSecureLayers) override; status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp* outBuffer) override; status_t captureLayers( diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 5e8910a3c5..8e0462ab52 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -137,8 +137,8 @@ void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, addDisplaySurfaceLocked(transaction, display.sequenceId, display.surface); addDisplayLayerStackLocked(transaction, display.sequenceId, display.layerStack); addDisplaySizeLocked(transaction, display.sequenceId, display.width, display.height); - addDisplayProjectionLocked(transaction, display.sequenceId, display.orientation, - display.viewport, display.frame); + addDisplayProjectionLocked(transaction, display.sequenceId, toRotationInt(display.orientation), + display.viewport, display.frame); } status_t SurfaceInterceptor::writeProtoFileLocked() { @@ -467,8 +467,8 @@ void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction, addDisplaySizeLocked(transaction, sequenceId, state.width, state.height); } if (state.what & DisplayState::eDisplayProjectionChanged) { - addDisplayProjectionLocked(transaction, sequenceId, state.orientation, state.viewport, - state.frame); + addDisplayProjectionLocked(transaction, sequenceId, toRotationInt(state.orientation), + state.viewport, state.frame); } } diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index b1bb7fdef9..f6188738b2 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -23,7 +23,6 @@ using ui::ColorMode; namespace { const String8 DISPLAY_NAME("Credentials Display Test"); const String8 SURFACE_NAME("Test Surface Name"); -const uint32_t ROTATION = 0; const float FRAME_SCALE = 1.0f; } // namespace @@ -262,7 +261,7 @@ TEST_F(CredentialsTest, CaptureTest) { sp outBuffer; return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/, - 0 /*reqHeight*/, false, ROTATION, &outBuffer); + 0 /*reqHeight*/, false, ui::ROTATION_0, &outBuffer); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, PERMISSION_DENIED)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 627de7a12e..92698f0142 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -189,12 +189,12 @@ TEST_P(LayerRenderTypeTransactionTest, SetSizeWithScaleToWindow_BufferQueue) { } TEST_P(LayerRenderTypeTransactionTest, CreateLayer_BufferState) { - uint32_t transformHint = ui::Transform::orientation_flags::ROT_INVALID; + uint32_t transformHint = ui::Transform::ROT_INVALID; sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState, /*parent*/ nullptr, &transformHint)); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, transformHint); } void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) { diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp index 35c51e1915..7816c667bb 100644 --- a/services/surfaceflinger/tests/LayerTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp @@ -53,7 +53,7 @@ TEST_F(LayerTransactionTest, SetFlagsSecureEUidSystem) { ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0, - 0, false, ISurfaceComposer::eRotateNone, true)); + 0, false, ui::ROTATION_0, true)); ASSERT_EQ(true, outCapturedSecureLayers); ScreenCapture sc(outBuffer); sc.expectColor(Rect(0, 0, 32, 32), Color::RED); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 76e8171255..55c3ab8b22 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -2040,8 +2040,8 @@ TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackChanges) { TEST_F(HandleTransactionLockedTest, processesDisplayTransformChanges) { using Case = NonHwcVirtualDisplayCase; - constexpr int oldTransform = 0; - constexpr int newTransform = 2; + constexpr ui::Rotation oldTransform = ui::ROTATION_0; + constexpr ui::Rotation newTransform = ui::ROTATION_180; // -------------------------------------------------------------------- // Preconditions @@ -2414,7 +2414,7 @@ TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfLayerStackCh TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) { using Case = SimplePrimaryDisplayCase; - constexpr int initialOrientation = 180; + constexpr ui::Rotation initialOrientation = ui::ROTATION_180; const Rect initialFrame = {1, 2, 3, 4}; const Rect initialViewport = {5, 6, 7, 8}; @@ -2458,8 +2458,8 @@ TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfProjectionDidNo TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfOrientationChanged) { using Case = SimplePrimaryDisplayCase; - constexpr int initialOrientation = 90; - constexpr int desiredOrientation = 180; + constexpr ui::Rotation initialOrientation = ui::ROTATION_90; + constexpr ui::Rotation desiredOrientation = ui::ROTATION_180; // -------------------------------------------------------------------- // Preconditions @@ -2721,7 +2721,7 @@ TEST_F(DisplayTransactionTest, onInitializeDisplaysSetsUpPrimaryDisplay) { // The layer stack state should be set to zero EXPECT_EQ(0u, primaryDisplayState.layerStack); // The orientation state should be set to zero - EXPECT_EQ(0, primaryDisplayState.orientation); + EXPECT_EQ(ui::ROTATION_0, primaryDisplayState.orientation); // The frame state should be set to INVALID EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.frame); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index b5245e2579..9728c80888 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -371,7 +371,6 @@ public: */ auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; } - auto& mutablePrimaryDisplayOrientation() { return SurfaceFlinger::primaryDisplayOrientation; } auto& mutableUseColorManagement() { return SurfaceFlinger::useColorManagement; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } -- cgit v1.2.3-59-g8ed1b From 9c858ac6573d32a98d24cc0da0722592873ae3ec Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 23 Jan 2020 14:20:11 -0600 Subject: Add hmac to InputEvent and scale to MotionEvent We need to pass some additional data to the app to be able to construct the MotionEvent. For proper support of getRawX/getRawY, add the xScale and yScale to MotionEvent. For the verification of input events, add hmac to InputEvent. Bug: 134977432 Bug: 140786233 Test: atest libinput_tests inputflinger_tests Change-Id: Ia3400ebbd9698549aad4d97a3b789ab7e10f6b65 --- include/input/Input.h | 40 ++++---- include/input/InputTransport.h | 31 +++--- libs/input/Input.cpp | 60 +++++++----- libs/input/InputTransport.cpp | 76 +++++++-------- libs/input/KeyCharacterMap.cpp | 6 +- libs/input/tests/InputEvent_test.cpp | 69 ++++++++------ .../input/tests/InputPublisherAndConsumer_test.cpp | 64 ++++++++----- libs/input/tests/StructLayout_test.cpp | 52 +++++----- libs/input/tests/VelocityTracker_test.cpp | 10 +- .../benchmarks/InputDispatcher_benchmarks.cpp | 3 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 26 ++--- .../inputflinger/tests/InputDispatcher_test.cpp | 106 +++++++++++---------- 12 files changed, 300 insertions(+), 243 deletions(-) (limited to 'include/input') diff --git a/include/input/Input.h b/include/input/Input.h index f8718479f9..1cf58efcaf 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -258,6 +259,11 @@ const char* motionClassificationToString(MotionClassification classification); */ constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits::quiet_NaN(); +/** + * Invalid value of HMAC - SHA256. Any events with this HMAC value will be marked as not verified. + */ +constexpr std::array INVALID_HMAC = {0}; + /* * Pointer coordinate data. */ @@ -356,14 +362,17 @@ public: inline void setDisplayId(int32_t displayId) { mDisplayId = displayId; } + inline std::array getHmac() const { return mHmac; } protected: - void initialize(int32_t deviceId, int32_t source, int32_t displayId); + void initialize(int32_t deviceId, int32_t source, int32_t displayId, + std::array hmac); void initialize(const InputEvent& from); int32_t mDeviceId; int32_t mSource; int32_t mDisplayId; + std::array mHmac; }; /* @@ -396,18 +405,10 @@ public: static const char* getLabel(int32_t keyCode); static int32_t getKeyCodeFromLabel(const char* label); - void initialize( - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime); + void initialize(int32_t deviceId, int32_t source, int32_t displayId, + std::array hmac, int32_t action, int32_t flags, int32_t keyCode, + int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime, + nsecs_t eventTime); void initialize(const KeyEvent& from); protected: @@ -463,6 +464,10 @@ public: inline void setActionButton(int32_t button) { mActionButton = button; } + inline float getXScale() const { return mXScale; } + + inline float getYScale() const { return mYScale; } + inline float getXOffset() const { return mXOffset; } inline float getYOffset() const { return mYOffset; } @@ -624,9 +629,10 @@ public: ssize_t findPointerIndex(int32_t pointerId) const; - void initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action, - int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, - int32_t buttonState, MotionClassification classification, float xOffset, + void initialize(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 rawXCursorPosition, float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime, size_t pointerCount, const PointerProperties* pointerProperties, @@ -676,6 +682,8 @@ protected: int32_t mMetaState; int32_t mButtonState; MotionClassification mClassification; + float mXScale; + float mYScale; float mXOffset; float mYOffset; float mXPrecision; diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index ae47438ac8..06fd3bb364 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -76,6 +76,9 @@ struct InputMessage { } header; // Body *must* be 8 byte aligned. + // For keys and motions, rely on the fact that std::array takes up exactly as much space + // as the underlying data. This is not guaranteed by C++, but it simplifies the conversions. + static_assert(sizeof(std::array) == 32); union Body { struct Key { uint32_t seq; @@ -84,6 +87,7 @@ struct InputMessage { int32_t deviceId; int32_t source; int32_t displayId; + std::array hmac; int32_t action; int32_t flags; int32_t keyCode; @@ -103,6 +107,7 @@ struct InputMessage { int32_t deviceId; int32_t source; int32_t displayId; + std::array hmac; int32_t action; int32_t actionButton; int32_t flags; @@ -112,6 +117,8 @@ 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 xPrecision; @@ -269,19 +276,10 @@ public: * Returns BAD_VALUE if seq is 0. * Other errors probably indicate that the channel is broken. */ - status_t publishKeyEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime); + status_t publishKeyEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId, + std::array hmac, int32_t action, int32_t flags, + int32_t keyCode, int32_t scanCode, int32_t metaState, + int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime); /* Publishes a motion event to the input channel. * @@ -292,9 +290,10 @@ public: * Other errors probably indicate that the channel is broken. */ status_t publishMotionEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId, - int32_t action, int32_t actionButton, int32_t flags, - int32_t edgeFlags, int32_t metaState, int32_t buttonState, - MotionClassification classification, float xOffset, float yOffset, + 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, diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 8ccbc7f650..bff1b97769 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -57,16 +57,19 @@ const char* inputEventTypeToString(int32_t type) { return "UNKNOWN"; } -void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId) { +void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, + std::array hmac) { mDeviceId = deviceId; mSource = source; mDisplayId = displayId; + mHmac = hmac; } void InputEvent::initialize(const InputEvent& from) { mDeviceId = from.mDeviceId; mSource = from.mSource; mDisplayId = from.mDisplayId; + mHmac = from.mHmac; } // --- KeyEvent --- @@ -79,19 +82,11 @@ int32_t KeyEvent::getKeyCodeFromLabel(const char* label) { return getKeyCodeByLabel(label); } -void KeyEvent::initialize( - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime) { - InputEvent::initialize(deviceId, source, displayId); +void KeyEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, + std::array hmac, int32_t action, int32_t flags, + int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount, + nsecs_t downTime, nsecs_t eventTime) { + InputEvent::initialize(deviceId, source, displayId, hmac); mAction = action; mFlags = flags; mKeyCode = keyCode; @@ -250,15 +245,16 @@ void PointerProperties::copyFrom(const PointerProperties& other) { // --- MotionEvent --- -void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, int32_t action, - int32_t actionButton, int32_t flags, int32_t edgeFlags, - int32_t metaState, int32_t buttonState, - MotionClassification classification, float xOffset, float yOffset, - float xPrecision, float yPrecision, float rawXCursorPosition, - float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime, - size_t pointerCount, const PointerProperties* pointerProperties, +void MotionEvent::initialize(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 rawXCursorPosition, float rawYCursorPosition, + nsecs_t downTime, nsecs_t eventTime, size_t pointerCount, + const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) { - InputEvent::initialize(deviceId, source, displayId); + InputEvent::initialize(deviceId, source, displayId, hmac); mAction = action; mActionButton = actionButton; mFlags = flags; @@ -266,6 +262,8 @@ void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId mMetaState = metaState; mButtonState = buttonState; mClassification = classification; + mXScale = xScale; + mYScale = yScale; mXOffset = xOffset; mYOffset = yOffset; mXPrecision = xPrecision; @@ -281,7 +279,7 @@ void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId } void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { - InputEvent::initialize(other->mDeviceId, other->mSource, other->mDisplayId); + InputEvent::initialize(other->mDeviceId, other->mSource, other->mDisplayId, other->mHmac); mAction = other->mAction; mActionButton = other->mActionButton; mFlags = other->mFlags; @@ -289,6 +287,8 @@ 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; mXPrecision = other->mXPrecision; @@ -490,6 +490,12 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) { mDeviceId = parcel->readInt32(); mSource = parcel->readInt32(); mDisplayId = parcel->readInt32(); + std::vector hmac; + status_t result = parcel->readByteVector(&hmac); + if (result != OK || hmac.size() != 32) { + return BAD_VALUE; + } + std::move(hmac.begin(), hmac.begin() + hmac.size(), mHmac.begin()); mAction = parcel->readInt32(); mActionButton = parcel->readInt32(); mFlags = parcel->readInt32(); @@ -497,6 +503,8 @@ 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(); mXPrecision = parcel->readFloat(); @@ -543,6 +551,8 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { parcel->writeInt32(mDeviceId); parcel->writeInt32(mSource); parcel->writeInt32(mDisplayId); + std::vector hmac(mHmac.begin(), mHmac.end()); + parcel->writeByteVector(hmac); parcel->writeInt32(mAction); parcel->writeInt32(mActionButton); parcel->writeInt32(mFlags); @@ -550,6 +560,8 @@ 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); parcel->writeFloat(mXPrecision); @@ -607,7 +619,7 @@ int32_t MotionEvent::getAxisFromLabel(const char* label) { void FocusEvent::initialize(bool hasFocus, bool inTouchMode) { InputEvent::initialize(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN, - ADISPLAY_ID_NONE); + ADISPLAY_ID_NONE, INVALID_HMAC); mHasFocus = hasFocus; mInTouchMode = inTouchMode; } diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index d53a557b28..d25a5cc0ef 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -147,6 +147,8 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { msg->body.key.source = body.key.source; // int32_t displayId msg->body.key.displayId = body.key.displayId; + // std::array hmac + msg->body.key.hmac = body.key.hmac; // int32_t action msg->body.key.action = body.key.action; // int32_t flags @@ -174,6 +176,8 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { msg->body.motion.source = body.motion.source; // int32_t displayId msg->body.motion.displayId = body.motion.displayId; + // std::array hmac + msg->body.motion.hmac = body.motion.hmac; // int32_t action msg->body.motion.action = body.motion.action; // int32_t actionButton @@ -190,6 +194,10 @@ 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 @@ -424,19 +432,11 @@ InputPublisher::InputPublisher(const sp& channel) : InputPublisher::~InputPublisher() { } -status_t InputPublisher::publishKeyEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime) { +status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t deviceId, int32_t source, + int32_t displayId, std::array hmac, + int32_t action, int32_t flags, int32_t keyCode, + int32_t scanCode, int32_t metaState, int32_t repeatCount, + nsecs_t downTime, nsecs_t eventTime) { if (ATRACE_ENABLED()) { std::string message = StringPrintf("publishKeyEvent(inputChannel=%s, keyCode=%" PRId32 ")", mChannel->getName().c_str(), keyCode); @@ -461,6 +461,7 @@ status_t InputPublisher::publishKeyEvent( msg.body.key.deviceId = deviceId; msg.body.key.source = source; msg.body.key.displayId = displayId; + msg.body.key.hmac = hmac; msg.body.key.action = action; msg.body.key.flags = flags; msg.body.key.keyCode = keyCode; @@ -473,11 +474,12 @@ status_t InputPublisher::publishKeyEvent( } status_t InputPublisher::publishMotionEvent( - uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId, int32_t action, - int32_t actionButton, int32_t flags, int32_t edgeFlags, int32_t metaState, - int32_t buttonState, MotionClassification classification, float xOffset, float yOffset, - float xPrecision, float yPrecision, float xCursorPosition, float yCursorPosition, - nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount, + uint32_t seq, 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) { if (ATRACE_ENABLED()) { std::string message = StringPrintf( @@ -489,13 +491,14 @@ status_t InputPublisher::publishMotionEvent( 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, xOffset=%f, yOffset=%f, " + "metaState=0x%x, buttonState=0x%x, classification=%s, xScale=%.1f, yScale=%.1f, " + "xOffset=%.1f, yOffset=%.1f, " "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", " "pointerCount=%" PRIu32, mChannel->getName().c_str(), seq, deviceId, source, displayId, action, actionButton, flags, edgeFlags, metaState, buttonState, - motionClassificationToString(classification), xOffset, yOffset, xPrecision, - yPrecision, downTime, eventTime, pointerCount); + motionClassificationToString(classification), xScale, yScale, xOffset, yOffset, + xPrecision, yPrecision, downTime, eventTime, pointerCount); } if (!seq) { @@ -515,6 +518,7 @@ status_t InputPublisher::publishMotionEvent( msg.body.motion.deviceId = deviceId; msg.body.motion.source = source; msg.body.motion.displayId = displayId; + msg.body.motion.hmac = hmac; msg.body.motion.action = action; msg.body.motion.actionButton = actionButton; msg.body.motion.flags = flags; @@ -522,6 +526,8 @@ 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.xPrecision = xPrecision; @@ -1136,18 +1142,10 @@ ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const { } void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) { - event->initialize( - msg->body.key.deviceId, - msg->body.key.source, - msg->body.key.displayId, - msg->body.key.action, - msg->body.key.flags, - msg->body.key.keyCode, - msg->body.key.scanCode, - msg->body.key.metaState, - msg->body.key.repeatCount, - msg->body.key.downTime, - msg->body.key.eventTime); + event->initialize(msg->body.key.deviceId, msg->body.key.source, msg->body.key.displayId, + msg->body.key.hmac, msg->body.key.action, msg->body.key.flags, + msg->body.key.keyCode, msg->body.key.scanCode, msg->body.key.metaState, + msg->body.key.repeatCount, msg->body.key.downTime, msg->body.key.eventTime); } void InputConsumer::initializeFocusEvent(FocusEvent* event, const InputMessage* msg) { @@ -1164,15 +1162,15 @@ void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage } event->initialize(msg->body.motion.deviceId, msg->body.motion.source, - msg->body.motion.displayId, msg->body.motion.action, + 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.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.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); } void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) { diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index e189d20e28..6f9b162986 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -487,9 +487,9 @@ void KeyCharacterMap::addKey(Vector& outEvents, int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) { outEvents.push(); KeyEvent& event = outEvents.editTop(); - event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, - down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, - 0, keyCode, 0, metaState, 0, time, time); + event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, + down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode, 0, metaState, + 0, time, time); } void KeyCharacterMap::addMetaKeys(Vector& outEvents, diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index b90857c99c..8c6890f542 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -26,7 +26,12 @@ namespace android { // Default display id. static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT; -class BaseTest : public testing::Test { }; +class BaseTest : public testing::Test { +protected: + static constexpr std::array HMAC = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +}; // --- PointerCoordsTest --- @@ -176,16 +181,17 @@ TEST_F(KeyEventTest, Properties) { KeyEvent event; // Initialize and get properties. - const nsecs_t ARBITRARY_DOWN_TIME = 1; - const nsecs_t ARBITRARY_EVENT_TIME = 2; - event.initialize(2, AINPUT_SOURCE_GAMEPAD, DISPLAY_ID, AKEY_EVENT_ACTION_DOWN, - AKEY_EVENT_FLAG_FROM_SYSTEM, AKEYCODE_BUTTON_X, 121, - AMETA_ALT_ON, 1, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME); + constexpr nsecs_t ARBITRARY_DOWN_TIME = 1; + constexpr nsecs_t ARBITRARY_EVENT_TIME = 2; + event.initialize(2, AINPUT_SOURCE_GAMEPAD, DISPLAY_ID, HMAC, AKEY_EVENT_ACTION_DOWN, + AKEY_EVENT_FLAG_FROM_SYSTEM, AKEYCODE_BUTTON_X, 121, AMETA_ALT_ON, 1, + ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME); ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType()); ASSERT_EQ(2, event.getDeviceId()); ASSERT_EQ(static_cast(AINPUT_SOURCE_GAMEPAD), event.getSource()); ASSERT_EQ(DISPLAY_ID, event.getDisplayId()); + EXPECT_EQ(HMAC, event.getHmac()); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction()); ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags()); ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode()); @@ -210,19 +216,17 @@ TEST_F(KeyEventTest, Properties) { class MotionEventTest : public BaseTest { protected: - static const nsecs_t ARBITRARY_DOWN_TIME; - static const nsecs_t ARBITRARY_EVENT_TIME; - static const float X_OFFSET; - static const float Y_OFFSET; + static constexpr nsecs_t ARBITRARY_DOWN_TIME = 1; + static constexpr nsecs_t ARBITRARY_EVENT_TIME = 2; + static constexpr float X_SCALE = 2.0; + static constexpr float Y_SCALE = 3.0; + static constexpr float X_OFFSET = 1; + static constexpr float Y_OFFSET = 1.1; void initializeEventWithHistory(MotionEvent* event); void assertEqualsEventWithHistory(const MotionEvent* event); }; -const nsecs_t MotionEventTest::ARBITRARY_DOWN_TIME = 1; -const nsecs_t MotionEventTest::ARBITRARY_EVENT_TIME = 2; -const float MotionEventTest::X_OFFSET = 1.0f; -const float MotionEventTest::Y_OFFSET = 1.1f; void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { PointerProperties pointerProperties[2]; @@ -254,12 +258,13 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27); pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28); - event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0, + event->initialize(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_OFFSET, Y_OFFSET, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_DOWN_TIME, - ARBITRARY_EVENT_TIME, 2, pointerProperties, pointerCoords); + X_SCALE, Y_SCALE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f, + AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, + ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, pointerProperties, + pointerCoords); pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110); pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111); @@ -308,12 +313,15 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { ASSERT_EQ(2, event->getDeviceId()); ASSERT_EQ(static_cast(AINPUT_SOURCE_TOUCHSCREEN), event->getSource()); ASSERT_EQ(DISPLAY_ID, event->getDisplayId()); + EXPECT_EQ(HMAC, event->getHmac()); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags()); ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags()); 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()); ASSERT_EQ(X_OFFSET, event->getXOffset()); ASSERT_EQ(Y_OFFSET, event->getYOffset()); ASSERT_EQ(2.0f, event->getXPrecision()); @@ -570,12 +578,13 @@ TEST_F(MotionEventTest, Transform) { pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle); } MotionEvent event; - event.initialize(0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, - 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, - 0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/, 0 /*yOffset*/, - 0 /*xPrecision*/, 0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/, - 2 /*yCursorPosition*/, 0 /*downTime*/, 0 /*eventTime*/, pointerCount, - pointerProperties, pointerCoords); + event.initialize(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); float originalRawX = 0 + 3; float originalRawY = -RADIUS + 2; @@ -634,9 +643,10 @@ TEST_F(MotionEventTest, Initialize_SetsClassification) { } for (MotionClassification classification : classifications) { - event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, + event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, - 0, classification, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, + 0, classification, 1 /*xScale*/, 1 /*yScale*/, 0, 0, 0, 0, + AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(classification, event.getClassification()); @@ -654,9 +664,10 @@ TEST_F(MotionEventTest, Initialize_SetsCursorPosition) { pointerCoords[i].clear(); } - event.initialize(0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, - 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE, 0, - 0, 0, 0, 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/, + event.initialize(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*/, 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 2fc77e97a0..1e51ea8b2f 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -75,6 +75,9 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { constexpr int32_t deviceId = 1; constexpr int32_t source = AINPUT_SOURCE_KEYBOARD; constexpr int32_t displayId = ADISPLAY_ID_DEFAULT; + constexpr std::array hmac = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; constexpr int32_t action = AKEY_EVENT_ACTION_DOWN; constexpr int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM; constexpr int32_t keyCode = AKEYCODE_ENTER; @@ -84,8 +87,9 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { constexpr nsecs_t downTime = 3; constexpr nsecs_t eventTime = 4; - status = mPublisher->publishKeyEvent(seq, deviceId, source, displayId, action, flags, - keyCode, scanCode, metaState, repeatCount, downTime, eventTime); + status = mPublisher->publishKeyEvent(seq, deviceId, source, displayId, hmac, action, flags, + keyCode, scanCode, metaState, repeatCount, downTime, + eventTime); ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK"; @@ -105,6 +109,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { EXPECT_EQ(deviceId, keyEvent->getDeviceId()); EXPECT_EQ(source, keyEvent->getSource()); EXPECT_EQ(displayId, keyEvent->getDisplayId()); + EXPECT_EQ(hmac, keyEvent->getHmac()); EXPECT_EQ(action, keyEvent->getAction()); EXPECT_EQ(flags, keyEvent->getFlags()); EXPECT_EQ(keyCode, keyEvent->getKeyCode()); @@ -136,6 +141,9 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { constexpr int32_t deviceId = 1; constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN; constexpr int32_t displayId = ADISPLAY_ID_DEFAULT; + constexpr std::array hmac = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; constexpr int32_t action = AMOTION_EVENT_ACTION_MOVE; constexpr int32_t actionButton = 0; constexpr int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; @@ -143,6 +151,8 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; constexpr int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY; constexpr MotionClassification classification = MotionClassification::AMBIGUOUS_GESTURE; + constexpr float xScale = 2; + constexpr float yScale = 3; constexpr float xOffset = -10; constexpr float yOffset = -20; constexpr float xPrecision = 0.25; @@ -171,12 +181,12 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i); } - status = - mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton, - flags, edgeFlags, metaState, buttonState, classification, - xOffset, yOffset, xPrecision, yPrecision, - xCursorPosition, yCursorPosition, downTime, eventTime, - pointerCount, pointerProperties, pointerCoords); + status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, hmac, action, + actionButton, flags, edgeFlags, metaState, buttonState, + classification, xScale, yScale, xOffset, yOffset, + xPrecision, yPrecision, xCursorPosition, + yCursorPosition, downTime, eventTime, pointerCount, + pointerProperties, pointerCoords); ASSERT_EQ(OK, status) << "publisher publishMotionEvent should return OK"; @@ -196,12 +206,17 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { EXPECT_EQ(deviceId, motionEvent->getDeviceId()); EXPECT_EQ(source, motionEvent->getSource()); EXPECT_EQ(displayId, motionEvent->getDisplayId()); + EXPECT_EQ(hmac, motionEvent->getHmac()); EXPECT_EQ(action, motionEvent->getAction()); EXPECT_EQ(flags, motionEvent->getFlags()); EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags()); 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(xOffset, motionEvent->getXOffset()); + EXPECT_EQ(yOffset, motionEvent->getYOffset()); EXPECT_EQ(xPrecision, motionEvent->getXPrecision()); EXPECT_EQ(yPrecision, motionEvent->getYPrecision()); EXPECT_EQ(xCursorPosition, motionEvent->getRawXCursorPosition()); @@ -316,11 +331,12 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZer pointerCoords[i].clear(); } - status = - mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE, - 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, - pointerCount, pointerProperties, pointerCoords); + status = mPublisher->publishMotionEvent(0, 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, + AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, + pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE"; } @@ -331,11 +347,12 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha PointerProperties pointerProperties[pointerCount]; PointerCoords pointerCoords[pointerCount]; - status = - mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE, - 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, - pointerCount, pointerProperties, pointerCoords); + status = mPublisher->publishMotionEvent(1, 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, + AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, + pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE"; } @@ -351,11 +368,12 @@ TEST_F(InputPublisherAndConsumerTest, pointerCoords[i].clear(); } - status = - mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, MotionClassification::NONE, - 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, - AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, - pointerCount, pointerProperties, pointerCoords); + status = mPublisher->publishMotionEvent(1, 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, + AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0, + pointerCount, pointerProperties, pointerCoords); ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE"; } diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index 9ab0dba08d..aa8a2d488f 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -39,35 +39,39 @@ void TestInputMessageAlignment() { CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16); CHECK_OFFSET(InputMessage::Body::Key, source, 20); CHECK_OFFSET(InputMessage::Body::Key, displayId, 24); - CHECK_OFFSET(InputMessage::Body::Key, action, 28); - CHECK_OFFSET(InputMessage::Body::Key, flags, 32); - CHECK_OFFSET(InputMessage::Body::Key, keyCode, 36); - CHECK_OFFSET(InputMessage::Body::Key, scanCode, 40); - CHECK_OFFSET(InputMessage::Body::Key, metaState, 44); - CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 48); - CHECK_OFFSET(InputMessage::Body::Key, downTime, 56); + CHECK_OFFSET(InputMessage::Body::Key, hmac, 28); + CHECK_OFFSET(InputMessage::Body::Key, action, 60); + CHECK_OFFSET(InputMessage::Body::Key, flags, 64); + CHECK_OFFSET(InputMessage::Body::Key, keyCode, 68); + CHECK_OFFSET(InputMessage::Body::Key, scanCode, 72); + CHECK_OFFSET(InputMessage::Body::Key, metaState, 76); + CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 80); + CHECK_OFFSET(InputMessage::Body::Key, downTime, 88); CHECK_OFFSET(InputMessage::Body::Motion, seq, 0); CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8); CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16); CHECK_OFFSET(InputMessage::Body::Motion, source, 20); CHECK_OFFSET(InputMessage::Body::Motion, displayId, 24); - CHECK_OFFSET(InputMessage::Body::Motion, action, 28); - CHECK_OFFSET(InputMessage::Body::Motion, actionButton, 32); - CHECK_OFFSET(InputMessage::Body::Motion, flags, 36); - CHECK_OFFSET(InputMessage::Body::Motion, metaState, 40); - CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 44); - CHECK_OFFSET(InputMessage::Body::Motion, classification, 48); - CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 52); - CHECK_OFFSET(InputMessage::Body::Motion, downTime, 56); - CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 64); - CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 68); - CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 72); - CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76); - CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 80); - CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 84); - CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 88); - CHECK_OFFSET(InputMessage::Body::Motion, pointers, 96); + CHECK_OFFSET(InputMessage::Body::Motion, hmac, 28); + CHECK_OFFSET(InputMessage::Body::Motion, action, 60); + CHECK_OFFSET(InputMessage::Body::Motion, actionButton, 64); + CHECK_OFFSET(InputMessage::Body::Motion, flags, 68); + CHECK_OFFSET(InputMessage::Body::Motion, metaState, 72); + CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 76); + 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::Focus, seq, 0); CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4); @@ -86,7 +90,7 @@ void TestHeaderSize() { * the Motion type, where "pointerCount" variable affects the size and can change at runtime. */ void TestBodySize() { - static_assert(sizeof(InputMessage::Body::Key) == 64); + static_assert(sizeof(InputMessage::Body::Key) == 96); static_assert(sizeof(InputMessage::Body::Motion) == offsetof(InputMessage::Body::Motion, pointers) + sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS); diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp index 968e2fa6bc..731eb6a000 100644 --- a/libs/input/tests/VelocityTracker_test.cpp +++ b/libs/input/tests/VelocityTracker_test.cpp @@ -176,11 +176,11 @@ static std::vector createMotionEventStream( EXPECT_EQ(pointerIndex, pointerCount); MotionEvent event; - event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, action, - 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, - 0 /*buttonState*/, MotionClassification::NONE, 0 /*xOffset*/, - 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/, - AMOTION_EVENT_INVALID_CURSOR_POSITION, + event.initialize(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, AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, entry.eventTime.count(), pointerCount, properties, coords); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 246e735330..9a6ef21724 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -203,9 +203,10 @@ static MotionEvent generateMotionEvent() { const nsecs_t currentTime = now(); MotionEvent event; - event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + event.initialize(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, /* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, currentTime, diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 30fdf906fc..d8e91cc6ad 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2410,7 +2410,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, status = connection->inputPublisher .publishKeyEvent(dispatchEntry->seq, keyEntry->deviceId, keyEntry->source, keyEntry->displayId, - dispatchEntry->resolvedAction, + INVALID_HMAC, dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, keyEntry->keyCode, keyEntry->scanCode, keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime, @@ -2457,12 +2457,14 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, status = connection->inputPublisher .publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId, motionEntry->source, motionEntry->displayId, - dispatchEntry->resolvedAction, + INVALID_HMAC, dispatchEntry->resolvedAction, motionEntry->actionButton, dispatchEntry->resolvedFlags, motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState, - motionEntry->classification, xOffset, yOffset, + motionEntry->classification, + dispatchEntry->windowXScale, + dispatchEntry->windowYScale, xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision, motionEntry->xCursorPosition, @@ -2930,8 +2932,9 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState); KeyEvent event; - event.initialize(args->deviceId, args->source, args->displayId, args->action, flags, keyCode, - args->scanCode, metaState, repeatCount, args->downTime, args->eventTime); + event.initialize(args->deviceId, args->source, args->displayId, INVALID_HMAC, args->action, + flags, keyCode, args->scanCode, metaState, repeatCount, args->downTime, + args->eventTime); android::base::Timer t; mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); @@ -3024,9 +3027,10 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { mLock.unlock(); MotionEvent event; - event.initialize(args->deviceId, args->source, args->displayId, args->action, - args->actionButton, args->flags, args->edgeFlags, args->metaState, - args->buttonState, args->classification, 0, 0, args->xPrecision, + event.initialize(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); @@ -3126,7 +3130,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injec accelerateMetaShortcuts(keyEvent.getDeviceId(), action, /*byref*/ keyCode, /*byref*/ metaState); keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(), - keyEvent.getDisplayId(), action, flags, keyCode, + keyEvent.getDisplayId(), INVALID_HMAC, action, flags, keyCode, keyEvent.getScanCode(), metaState, keyEvent.getRepeatCount(), keyEvent.getDownTime(), keyEvent.getEventTime()); @@ -4682,8 +4686,8 @@ void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* comman KeyEvent InputDispatcher::createKeyEvent(const KeyEntry& entry) { KeyEvent event; - event.initialize(entry.deviceId, entry.source, entry.displayId, entry.action, entry.flags, - entry.keyCode, entry.scanCode, entry.metaState, entry.repeatCount, + event.initialize(entry.deviceId, entry.source, entry.displayId, INVALID_HMAC, entry.action, + entry.flags, entry.keyCode, entry.scanCode, entry.metaState, entry.repeatCount, entry.downTime, entry.eventTime); return event; } diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 98ebf50819..094452a0c0 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -225,18 +225,18 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) { KeyEvent event; // Rejects undefined key actions. - event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, - /*action*/ -1, 0, - AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); + event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, + /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, + ARBITRARY_TIME); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject key events with undefined action."; // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API. - event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, - AKEY_EVENT_ACTION_MULTIPLE, 0, - AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); + event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, + AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, + ARBITRARY_TIME, ARBITRARY_TIME); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) @@ -260,10 +260,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { constexpr MotionClassification classification = MotionClassification::NONE; // Rejects undefined motion actions. - event.initialize(DEVICE_ID, source, DISPLAY_ID, - /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + event.initialize(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, + AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, @@ -271,24 +271,24 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { << "Should reject motion events with undefined action."; // Rejects pointer down with invalid index. - event.initialize(DEVICE_ID, source, DISPLAY_ID, + event.initialize(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, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + 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); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer down index too large."; - event.initialize(DEVICE_ID, source, DISPLAY_ID, + event.initialize(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, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + 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); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, @@ -296,24 +296,24 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { << "Should reject motion events with pointer down index too small."; // Rejects pointer up with invalid index. - event.initialize(DEVICE_ID, source, DISPLAY_ID, + event.initialize(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, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + 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); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with pointer up index too large."; - event.initialize(DEVICE_ID, source, DISPLAY_ID, + event.initialize(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, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + 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); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, @@ -321,20 +321,20 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { << "Should reject motion events with pointer up index too small."; // Rejects motion events with invalid number of pointers. - event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, - metaState, 0, classification, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + event.initialize(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, /*pointerCount*/ 0, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) << "Should reject motion events with 0 pointers."; - event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, - metaState, 0, classification, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + event.initialize(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, /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, @@ -343,10 +343,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { // Rejects motion events with invalid pointer ids. pointerProperties[0].id = -1; - event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, - metaState, 0, classification, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + event.initialize(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, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, @@ -354,10 +354,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { << "Should reject motion events with pointer ids less than 0."; pointerProperties[0].id = MAX_POINTER_ID + 1; - event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, - metaState, 0, classification, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + event.initialize(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, /*pointerCount*/ 1, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, @@ -367,10 +367,10 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { // Rejects motion events with duplicate pointer ids. pointerProperties[0].id = 1; pointerProperties[1].id = 1; - event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, - metaState, 0, classification, 0, 0, 0, 0, - AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, - ARBITRARY_TIME, ARBITRARY_TIME, + event.initialize(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, /*pointerCount*/ 2, pointerProperties, pointerCoords); ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( &event, @@ -645,9 +645,9 @@ static int32_t injectKeyDown(const sp& dispatcher, nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid key down event. - event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, - AKEY_EVENT_ACTION_DOWN, /* flags */ 0, - AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime); + event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, INVALID_HMAC, + AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE, + /* repeatCount */ 0, currentTime, currentTime); // Inject event until dispatch out. return dispatcher->injectInputEvent( @@ -674,10 +674,12 @@ static int32_t injectMotionEvent(const sp& dispatcher, int32_t nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid motion down event. - event.initialize(DEVICE_ID, source, displayId, action, /* actionButton */ 0, /* flags */ 0, + event.initialize(DEVICE_ID, source, displayId, INVALID_HMAC, action, /* actionButton */ 0, + /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE, - /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0, - /* yPrecision */ 0, xCursorPosition, yCursorPosition, currentTime, currentTime, + /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0, + /* xPrecision */ 0, /* yPrecision */ 0, xCursorPosition, yCursorPosition, + currentTime, currentTime, /*pointerCount*/ 1, pointerProperties, pointerCoords); // Inject event until dispatch out. -- cgit v1.2.3-59-g8ed1b From 3826d47fa79b505683c20317fa1b8dafb0c8bd39 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 27 Jan 2020 10:44:40 -0600 Subject: Use uint32_t for input source The input source type originates from EventHub as an unsigned integer. But later, it somehow becomes a signed value. Even the InputListeners specify the source as uint32_t. To maintain the consistency prior to adding new API that would again use source, convert the source to uint32_t. This also helps remove some static_casts, as well as ensures that the order of input arguments is harder to confuse. Bug: 134977432 Test: atest libinput_tests inputflinger_tests inputflinger_benchmarks Change-Id: Iba10da08ee3a1004d50827785f570dab72a919d1 --- include/input/Input.h | 14 +++++++------- libs/input/Input.cpp | 12 ++++++------ libs/input/tests/InputEvent_test.cpp | 8 ++++---- libs/input/tests/InputPublisherAndConsumer_test.cpp | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'include/input') diff --git a/include/input/Input.h b/include/input/Input.h index 1cf58efcaf..cf0814cf2f 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -354,9 +354,9 @@ public: inline int32_t getDeviceId() const { return mDeviceId; } - inline int32_t getSource() const { return mSource; } + inline uint32_t getSource() const { return mSource; } - inline void setSource(int32_t source) { mSource = source; } + inline void setSource(uint32_t source) { mSource = source; } inline int32_t getDisplayId() const { return mDisplayId; } @@ -365,12 +365,12 @@ public: inline std::array getHmac() const { return mHmac; } protected: - void initialize(int32_t deviceId, int32_t source, int32_t displayId, + void initialize(int32_t deviceId, uint32_t source, int32_t displayId, std::array hmac); void initialize(const InputEvent& from); int32_t mDeviceId; - int32_t mSource; + uint32_t mSource; int32_t mDisplayId; std::array mHmac; }; @@ -405,7 +405,7 @@ public: static const char* getLabel(int32_t keyCode); static int32_t getKeyCodeFromLabel(const char* label); - void initialize(int32_t deviceId, int32_t source, int32_t displayId, + void initialize(int32_t deviceId, uint32_t source, int32_t displayId, std::array hmac, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime); @@ -629,7 +629,7 @@ public: ssize_t findPointerIndex(int32_t pointerId) const; - void initialize(int32_t deviceId, int32_t source, int32_t displayId, + void initialize(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, @@ -657,7 +657,7 @@ public: status_t writeToParcel(Parcel* parcel) const; #endif - static bool isTouchEvent(int32_t source, int32_t action); + static bool isTouchEvent(uint32_t source, int32_t action); inline bool isTouchEvent() const { return isTouchEvent(mSource, mAction); } diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index bff1b97769..3a5fc7fe6e 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -57,7 +57,7 @@ const char* inputEventTypeToString(int32_t type) { return "UNKNOWN"; } -void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, +void InputEvent::initialize(int32_t deviceId, uint32_t source, int32_t displayId, std::array hmac) { mDeviceId = deviceId; mSource = source; @@ -82,7 +82,7 @@ int32_t KeyEvent::getKeyCodeFromLabel(const char* label) { return getKeyCodeByLabel(label); } -void KeyEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, +void KeyEvent::initialize(int32_t deviceId, uint32_t source, int32_t displayId, std::array hmac, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime) { @@ -245,7 +245,7 @@ void PointerProperties::copyFrom(const PointerProperties& other) { // --- MotionEvent --- -void MotionEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId, +void MotionEvent::initialize(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, @@ -488,7 +488,7 @@ status_t MotionEvent::readFromParcel(Parcel* parcel) { } mDeviceId = parcel->readInt32(); - mSource = parcel->readInt32(); + mSource = parcel->readUint32(); mDisplayId = parcel->readInt32(); std::vector hmac; status_t result = parcel->readByteVector(&hmac); @@ -549,7 +549,7 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { parcel->writeInt32(sampleCount); parcel->writeInt32(mDeviceId); - parcel->writeInt32(mSource); + parcel->writeUint32(mSource); parcel->writeInt32(mDisplayId); std::vector hmac(mHmac.begin(), mHmac.end()); parcel->writeByteVector(hmac); @@ -590,7 +590,7 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const { } #endif -bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { +bool MotionEvent::isTouchEvent(uint32_t source, int32_t action) { if (source & AINPUT_SOURCE_CLASS_POINTER) { // Specifically excludes HOVER_MOVE and SCROLL. switch (action & AMOTION_EVENT_ACTION_MASK) { diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index 8c6890f542..3d7c34e542 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -189,7 +189,7 @@ TEST_F(KeyEventTest, Properties) { ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType()); ASSERT_EQ(2, event.getDeviceId()); - ASSERT_EQ(static_cast(AINPUT_SOURCE_GAMEPAD), event.getSource()); + ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource()); ASSERT_EQ(DISPLAY_ID, event.getDisplayId()); EXPECT_EQ(HMAC, event.getHmac()); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction()); @@ -203,7 +203,7 @@ TEST_F(KeyEventTest, Properties) { // Set source. event.setSource(AINPUT_SOURCE_JOYSTICK); - ASSERT_EQ(static_cast(AINPUT_SOURCE_JOYSTICK), event.getSource()); + ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource()); // Set display id. constexpr int32_t newDisplayId = 2; @@ -311,7 +311,7 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { // Check properties. ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()); ASSERT_EQ(2, event->getDeviceId()); - ASSERT_EQ(static_cast(AINPUT_SOURCE_TOUCHSCREEN), event->getSource()); + ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource()); ASSERT_EQ(DISPLAY_ID, event->getDisplayId()); EXPECT_EQ(HMAC, event->getHmac()); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); @@ -448,7 +448,7 @@ TEST_F(MotionEventTest, Properties) { // Set source. event.setSource(AINPUT_SOURCE_JOYSTICK); - ASSERT_EQ(static_cast(AINPUT_SOURCE_JOYSTICK), event.getSource()); + ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource()); // Set displayId. constexpr int32_t newDisplayId = 2; diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index 1e51ea8b2f..b002893c43 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -73,7 +73,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { constexpr uint32_t seq = 15; constexpr int32_t deviceId = 1; - constexpr int32_t source = AINPUT_SOURCE_KEYBOARD; + constexpr uint32_t source = AINPUT_SOURCE_KEYBOARD; constexpr int32_t displayId = ADISPLAY_ID_DEFAULT; constexpr std::array hmac = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, @@ -139,7 +139,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { constexpr uint32_t seq = 15; constexpr int32_t deviceId = 1; - constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN; + constexpr uint32_t source = AINPUT_SOURCE_TOUCHSCREEN; constexpr int32_t displayId = ADISPLAY_ID_DEFAULT; constexpr std::array hmac = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, -- cgit v1.2.3-59-g8ed1b From 54d3e189009e4138ec5074b0ac79f56ce322daed Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 15 Jan 2020 17:38:38 -0800 Subject: Add verifyInputEvent api to InputDispatcher Now InputDispatcher will be able to check whether a certain InputEvent is legitimate. Use the 'verifyInputEvent' api to determine if a given 'InputEvent' actually came from InputDispatcher. Bug: 134977432 Test: atest VerifiedKeyEventTest VerifiedMotionEventTest libinput_tests inputflinger_tests Change-Id: I8e7fa9bfa3c14b0b0d949fb5e28b43ff7583398f --- include/input/Input.h | 62 +++++++++++ libs/input/Input.cpp | 24 +++++ libs/input/tests/Android.bp | 2 +- libs/input/tests/InputEvent_test.cpp | 1 - .../input/tests/InputPublisherAndConsumer_test.cpp | 1 + libs/input/tests/StructLayout_test.cpp | 30 ++++++ libs/input/tests/VerifiedInputEvent_test.cpp | 116 +++++++++++++++++++++ .../inputflinger/dispatcher/InputDispatcher.cpp | 4 + services/inputflinger/dispatcher/InputDispatcher.h | 2 + .../dispatcher/include/InputDispatcherInterface.h | 7 ++ 10 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 libs/input/tests/VerifiedInputEvent_test.cpp (limited to 'include/input') diff --git a/include/input/Input.h b/include/input/Input.h index cf0814cf2f..14a7288d19 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -73,6 +73,19 @@ enum { AMOTION_EVENT_FLAG_TAINTED = 0x80000000, }; +/** + * Allowed VerifiedKeyEvent flags. All other flags from KeyEvent do not get verified. + * These values must be kept in sync with VerifiedKeyEvent.java + */ +constexpr int32_t VERIFIED_KEY_EVENT_FLAGS = AKEY_EVENT_FLAG_CANCELED; + +/** + * Allowed VerifiedMotionEventFlags. All other flags from MotionEvent do not get verified. + * These values must be kept in sync with VerifiedMotionEvent.java + */ +constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS = + AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED; + enum { /* Used when a motion event is not associated with any display. * Typically used for non-pointer events. */ @@ -718,6 +731,55 @@ protected: bool mInTouchMode; }; +/** + * Base class for verified events. + * Do not create a VerifiedInputEvent explicitly. + * Use helper functions to create them from InputEvents. + */ +struct __attribute__((__packed__)) VerifiedInputEvent { + enum class Type : int32_t { + KEY = AINPUT_EVENT_TYPE_KEY, + MOTION = AINPUT_EVENT_TYPE_MOTION, + }; + + Type type; + int32_t deviceId; + nsecs_t eventTimeNanos; + uint32_t source; + int32_t displayId; +}; + +/** + * Same as KeyEvent, but only contains the data that can be verified. + * If you update this class, you must also update VerifiedKeyEvent.java + */ +struct __attribute__((__packed__)) VerifiedKeyEvent : public VerifiedInputEvent { + int32_t action; + nsecs_t downTimeNanos; + int32_t flags; + int32_t keyCode; + int32_t scanCode; + int32_t metaState; + int32_t repeatCount; +}; + +/** + * Same as MotionEvent, but only contains the data that can be verified. + * If you update this class, you must also update VerifiedMotionEvent.java + */ +struct __attribute__((__packed__)) VerifiedMotionEvent : public VerifiedInputEvent { + float rawX; + float rawY; + int32_t actionMasked; + nsecs_t downTimeNanos; + int32_t flags; + int32_t metaState; + int32_t buttonState; +}; + +VerifiedKeyEvent verifiedKeyEventFromKeyEvent(const KeyEvent& event); +VerifiedMotionEvent verifiedMotionEventFromMotionEvent(const MotionEvent& event); + /* * Input event factory. */ diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 85b0fd0ec7..2a73dc0149 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -57,6 +57,30 @@ const char* inputEventTypeToString(int32_t type) { return "UNKNOWN"; } +VerifiedKeyEvent verifiedKeyEventFromKeyEvent(const KeyEvent& event) { + return {{VerifiedInputEvent::Type::KEY, event.getDeviceId(), event.getEventTime(), + event.getSource(), event.getDisplayId()}, + event.getAction(), + event.getDownTime(), + event.getFlags() & VERIFIED_KEY_EVENT_FLAGS, + event.getKeyCode(), + event.getScanCode(), + event.getMetaState(), + event.getRepeatCount()}; +} + +VerifiedMotionEvent verifiedMotionEventFromMotionEvent(const MotionEvent& event) { + return {{VerifiedInputEvent::Type::MOTION, event.getDeviceId(), event.getEventTime(), + event.getSource(), event.getDisplayId()}, + event.getRawX(0), + event.getRawY(0), + event.getActionMasked(), + event.getDownTime(), + event.getFlags() & VERIFIED_MOTION_EVENT_FLAGS, + event.getMetaState(), + event.getButtonState()}; +} + void InputEvent::initialize(int32_t deviceId, uint32_t source, int32_t displayId, std::array hmac) { mDeviceId = deviceId; diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index c1c35e1b89..fb21d5e3b1 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -10,12 +10,12 @@ cc_test { "LatencyStatistics_test.cpp", "TouchVideoFrame_test.cpp", "VelocityTracker_test.cpp", + "VerifiedInputEvent_test.cpp", ], cflags: [ "-Wall", "-Wextra", "-Werror", - "-Wno-unused-variable", ], shared_libs: [ "libinput", diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp index dce1f29124..d0f761887a 100644 --- a/libs/input/tests/InputEvent_test.cpp +++ b/libs/input/tests/InputEvent_test.cpp @@ -46,7 +46,6 @@ TEST_F(PointerCoordsTest, ClearSetsBitsToZero) { } TEST_F(PointerCoordsTest, AxisValues) { - float* valuePtr; PointerCoords coords; coords.clear(); diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index d4bbf6c6ac..885196f3f3 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -38,6 +38,7 @@ protected: virtual void SetUp() { status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); + ASSERT_EQ(OK, result); mPublisher = new InputPublisher(serverChannel); mConsumer = new InputConsumer(clientChannel); diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index aa8a2d488f..dd127fcabd 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -98,4 +98,34 @@ void TestBodySize() { static_assert(sizeof(InputMessage::Body::Focus) == 8); } +// --- VerifiedInputEvent --- +// Ensure that VerifiedInputEvent, VerifiedKeyEvent, VerifiedMotionEvent are packed. +// We will treat them as byte collections when signing them. There should not be any uninitialized +// data in-between fields. Otherwise, the padded data will affect the hmac value and verifications +// will fail. + +void TestVerifiedEventSize() { + // VerifiedInputEvent + constexpr size_t VERIFIED_INPUT_EVENT_SIZE = sizeof(VerifiedInputEvent::type) + + sizeof(VerifiedInputEvent::deviceId) + sizeof(VerifiedInputEvent::eventTimeNanos) + + sizeof(VerifiedInputEvent::source) + sizeof(VerifiedInputEvent::displayId); + static_assert(sizeof(VerifiedInputEvent) == VERIFIED_INPUT_EVENT_SIZE); + + // VerifiedKeyEvent + constexpr size_t VERIFIED_KEY_EVENT_SIZE = VERIFIED_INPUT_EVENT_SIZE + + sizeof(VerifiedKeyEvent::action) + sizeof(VerifiedKeyEvent::downTimeNanos) + + sizeof(VerifiedKeyEvent::flags) + sizeof(VerifiedKeyEvent::keyCode) + + sizeof(VerifiedKeyEvent::scanCode) + sizeof(VerifiedKeyEvent::metaState) + + sizeof(VerifiedKeyEvent::repeatCount); + static_assert(sizeof(VerifiedKeyEvent) == VERIFIED_KEY_EVENT_SIZE); + + // VerifiedMotionEvent + constexpr size_t VERIFIED_MOTION_EVENT_SIZE = VERIFIED_INPUT_EVENT_SIZE + + sizeof(VerifiedMotionEvent::rawX) + sizeof(VerifiedMotionEvent::rawY) + + sizeof(VerifiedMotionEvent::actionMasked) + sizeof(VerifiedMotionEvent::downTimeNanos) + + sizeof(VerifiedMotionEvent::flags) + sizeof(VerifiedMotionEvent::metaState) + + sizeof(VerifiedMotionEvent::buttonState); + static_assert(sizeof(VerifiedMotionEvent) == VERIFIED_MOTION_EVENT_SIZE); +} + } // namespace android diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp new file mode 100644 index 0000000000..a59dbe5987 --- /dev/null +++ b/libs/input/tests/VerifiedInputEvent_test.cpp @@ -0,0 +1,116 @@ +/* + * 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