Merge "Skip caching if any layer has protected contents" into sc-dev am: 963026b842
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/15053550
Change-Id: Ia99c5ec624a6581b4032b493d0a8d0d7b64c4134
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index 3798ba7..29d4409 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -100,6 +100,10 @@
required uint32 layer_stack = 1;
}
+message DisplayFlagsChange {
+ required uint32 flags = 1;
+}
+
message HiddenFlagChange {
required bool hidden_flag = 1;
}
@@ -120,6 +124,7 @@
LayerStackChange layer_stack = 3;
SizeChange size = 4;
ProjectionChange projection = 5;
+ DisplayFlagsChange flags = 6;
}
}
@@ -212,4 +217,4 @@
message Origin {
required int32 pid = 1;
required int32 uid = 2;
-}
\ No newline at end of file
+}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e65c721..d102e07 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -315,6 +315,7 @@
DisplayState::DisplayState()
: what(0),
layerStack(0),
+ flags(0),
layerStackSpaceRect(Rect::EMPTY_RECT),
orientedDisplaySpaceRect(Rect::EMPTY_RECT),
width(0),
@@ -325,6 +326,7 @@
SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(surface));
SAFE_PARCEL(output.writeUint32, what);
SAFE_PARCEL(output.writeUint32, layerStack);
+ SAFE_PARCEL(output.writeUint32, flags);
SAFE_PARCEL(output.writeUint32, toRotationInt(orientation));
SAFE_PARCEL(output.write, layerStackSpaceRect);
SAFE_PARCEL(output.write, orientedDisplaySpaceRect);
@@ -341,6 +343,7 @@
SAFE_PARCEL(input.readUint32, &what);
SAFE_PARCEL(input.readUint32, &layerStack);
+ SAFE_PARCEL(input.readUint32, &flags);
uint32_t tmpUint = 0;
SAFE_PARCEL(input.readUint32, &tmpUint);
orientation = ui::toRotation(tmpUint);
@@ -361,6 +364,10 @@
what |= eLayerStackChanged;
layerStack = other.layerStack;
}
+ if (other.what & eFlagsChanged) {
+ what |= eFlagsChanged;
+ flags = other.flags;
+ }
if (other.what & eDisplayProjectionChanged) {
what |= eDisplayProjectionChanged;
orientation = other.orientation;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index fd78309..38d6fef 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1738,6 +1738,12 @@
s.what |= DisplayState::eLayerStackChanged;
}
+void SurfaceComposerClient::Transaction::setDisplayFlags(const sp<IBinder>& token, uint32_t flags) {
+ DisplayState& s(getDisplayState(token));
+ s.flags = flags;
+ s.what |= DisplayState::eFlagsChanged;
+}
+
void SurfaceComposerClient::Transaction::setDisplayProjection(const sp<IBinder>& token,
ui::Rotation orientation,
const Rect& layerStackRect,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 16430b3..869c082 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -247,7 +247,8 @@
eSurfaceChanged = 0x01,
eLayerStackChanged = 0x02,
eDisplayProjectionChanged = 0x04,
- eDisplaySizeChanged = 0x08
+ eDisplaySizeChanged = 0x08,
+ eFlagsChanged = 0x10
};
DisplayState();
@@ -257,6 +258,7 @@
sp<IBinder> token;
sp<IGraphicBufferProducer> surface;
uint32_t layerStack;
+ uint32_t flags;
// These states define how layers are projected onto the physical display.
//
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 13994fd..e99bb7d 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -564,6 +564,8 @@
void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
+ void setDisplayFlags(const sp<IBinder>& token, uint32_t flags);
+
/* setDisplayProjection() defines the projection of layer stacks
* to a given display.
*
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 70ed438..266d7a3 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -91,6 +91,19 @@
return xy;
}
+vec2 applyTransformWithoutTranslation(const ui::Transform& transform, float x, float y) {
+ const vec2 transformedXy = transform.transform(x, y);
+ const vec2 transformedOrigin = transform.transform(0, 0);
+ return transformedXy - transformedOrigin;
+}
+
+bool shouldDisregardWindowTranslation(uint32_t source) {
+ // Pointer events are the only type of events that refer to absolute coordinates on the display,
+ // so we should apply the entire window transform. For other types of events, we should make
+ // sure to not apply the window translation/offset.
+ return (source & AINPUT_SOURCE_CLASS_POINTER) == 0;
+}
+
} // namespace
const char* motionClassificationToString(MotionClassification classification) {
@@ -305,6 +318,8 @@
scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, globalScaleFactor);
scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, globalScaleFactor);
scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, globalScaleFactor);
+ scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_X, windowXScale);
+ scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_Y, windowYScale);
}
void PointerCoords::scale(float globalScaleFactor) {
@@ -373,6 +388,15 @@
setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
+ if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_X) ||
+ BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_RELATIVE_Y)) {
+ const ui::Transform rotation(transform.getOrientation());
+ const vec2 relativeXy = rotation.transform(getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
+ setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, relativeXy.x);
+ setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y);
+ }
+
if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_ORIENTATION)) {
const float val = getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, val));
@@ -509,25 +533,48 @@
if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
// For compatibility, convert raw coordinates into "oriented screen space". Once app
// developers are educated about getRaw, we can consider removing this.
- const vec2 xy = rotatePoint(mTransform, coords->getX(), coords->getY(), mDisplayWidth,
- mDisplayHeight);
+ const vec2 xy = shouldDisregardWindowTranslation(mSource)
+ ? rotatePoint(mTransform, coords->getX(), coords->getY())
+ : rotatePoint(mTransform, coords->getX(), coords->getY(), mDisplayWidth,
+ mDisplayHeight);
static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
return xy[axis];
}
+ if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
+ // For compatibility, since we convert raw coordinates into "oriented screen space", we
+ // need to convert the relative axes into the same orientation for consistency.
+ const vec2 relativeXy =
+ rotatePoint(mTransform, coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
+ return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
+ }
+
return coords->getAxisValue(axis);
}
float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
- size_t historicalIndex) const {
+ size_t historicalIndex) const {
const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex);
if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
- const vec2 xy = mTransform.transform(coords->getXYValue());
+ const vec2 xy = shouldDisregardWindowTranslation(mSource)
+ ? applyTransformWithoutTranslation(mTransform, coords->getX(), coords->getY())
+ : mTransform.transform(coords->getXYValue());
static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
return xy[axis];
}
+ if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
+ const vec2 relativeXy =
+ applyTransformWithoutTranslation(mTransform,
+ coords->getAxisValue(
+ AMOTION_EVENT_AXIS_RELATIVE_X),
+ coords->getAxisValue(
+ AMOTION_EVENT_AXIS_RELATIVE_Y));
+ return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
+ }
+
return coords->getAxisValue(axis);
}
@@ -583,6 +630,13 @@
// Apply the transformation to all samples.
std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(),
[&transform](PointerCoords& c) { c.transform(transform); });
+
+ if (mRawXCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION &&
+ mRawYCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) {
+ const vec2 cursor = transform.transform(mRawXCursorPosition, mRawYCursorPosition);
+ mRawXCursorPosition = cursor.x;
+ mRawYCursorPosition = cursor.y;
+ }
}
#ifdef __linux__
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 32b72ba..cfb5986 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -588,7 +588,7 @@
}
MotionEvent event;
ui::Transform identityTransform;
- event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID,
+ event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,
@@ -636,13 +636,16 @@
ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
}
-MotionEvent createTouchDownEvent(int x, int y, ui::Transform transform) {
+MotionEvent createTouchDownEvent(float x, float y, float dx, float dy,
+ const ui::Transform& transform) {
std::vector<PointerProperties> pointerProperties;
pointerProperties.push_back(PointerProperties{/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER});
std::vector<PointerCoords> pointerCoords;
pointerCoords.emplace_back().clear();
pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, x);
pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, dx);
+ pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, dy);
nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
MotionEvent event;
event.initialize(InputEvent::nextId(), /* deviceId */ 1, AINPUT_SOURCE_TOUCHSCREEN,
@@ -661,26 +664,56 @@
ui::Transform identity;
ui::Transform xform(ui::Transform::ROT_90, 800, 400);
xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, xform);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);
ASSERT_EQ(700, event.getRawX(0));
ASSERT_EQ(60, event.getRawY(0));
ASSERT_NE(event.getRawX(0), event.getX(0));
ASSERT_NE(event.getRawY(0), event.getY(0));
+ // Relative values should be rotated but not translated.
+ ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
+ ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- MotionEvent changedEvent = createTouchDownEvent(60, 100, identity);
+ MotionEvent changedEvent = createTouchDownEvent(60, 100, 42, 96, identity);
const std::array<float, 9> rowMajor{xform[0][0], xform[1][0], xform[2][0],
xform[0][1], xform[1][1], xform[2][1],
xform[0][2], xform[1][2], xform[2][2]};
changedEvent.applyTransform(rowMajor);
// transformContent effectively rotates the raw coordinates, so those should now include
- // both rotation AND offset
+ // both rotation AND offset.
ASSERT_EQ(720, changedEvent.getRawX(0));
ASSERT_EQ(100, changedEvent.getRawY(0));
+ // Relative values should be rotated but not translated.
+ ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
+ ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- // The transformed output should be the same then
+ // The transformed output should be the same then.
ASSERT_NEAR(event.getX(0), changedEvent.getX(0), 0.001);
ASSERT_NEAR(event.getY(0), changedEvent.getY(0), 0.001);
+ ASSERT_NEAR(event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0),
+ changedEvent.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0), 0.001);
+ ASSERT_NEAR(event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0),
+ changedEvent.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0), 0.001);
+}
+
+TEST_F(MotionEventTest, NonPointerSourcesAreNotTranslated) {
+ constexpr static auto NON_POINTER_SOURCES = {AINPUT_SOURCE_TRACKBALL,
+ AINPUT_SOURCE_MOUSE_RELATIVE,
+ AINPUT_SOURCE_JOYSTICK};
+ for (uint32_t source : NON_POINTER_SOURCES) {
+ // Create a rotate-90 transform with an offset (like a window which isn't fullscreen).
+ ui::Transform xform(ui::Transform::ROT_90, 800, 400);
+ xform.set(xform.tx() + 20, xform.ty() + 40);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);
+ event.setSource(source);
+
+ // Since this event comes from a non-pointer source, it should include rotation but not
+ // translation/offset.
+ ASSERT_EQ(-100, event.getX(0));
+ ASSERT_EQ(60, event.getY(0));
+ ASSERT_EQ(event.getRawX(0), event.getX(0));
+ ASSERT_EQ(event.getRawY(0), event.getY(0));
+ }
}
TEST_F(MotionEventTest, RawCompatTransform) {
@@ -688,11 +721,14 @@
// Make sure raw is raw regardless of transform translation.
ui::Transform xform;
xform.set(20, 40);
- MotionEvent event = createTouchDownEvent(60, 100, xform);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);
ASSERT_EQ(60, event.getRawX(0));
ASSERT_EQ(100, event.getRawY(0));
ASSERT_NE(event.getRawX(0), event.getX(0));
ASSERT_NE(event.getRawY(0), event.getY(0));
+ // Relative values should not be modified.
+ ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
+ ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
}
// Next check that getRaw contains rotation (for compatibility) but otherwise is still
@@ -701,29 +737,38 @@
// Create a rotate-90 transform with an offset (like a window which isn't fullscreen).
ui::Transform xform(ui::Transform::ROT_90, 800, 400);
xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, xform);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);
ASSERT_EQ(700, event.getRawX(0));
ASSERT_EQ(60, event.getRawY(0));
ASSERT_NE(event.getRawX(0), event.getX(0));
ASSERT_NE(event.getRawY(0), event.getY(0));
+ // Relative values should be rotated but not translated.
+ ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
+ ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
}
{
// Same as above, but check rotate-180.
ui::Transform xform(ui::Transform::ROT_180, 400, 800);
xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, xform);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);
ASSERT_EQ(340, event.getRawX(0));
ASSERT_EQ(700, event.getRawY(0));
+ // Relative values should be rotated but not translated.
+ ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
+ ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
}
{
// Same as above, but check rotate-270.
ui::Transform xform(ui::Transform::ROT_270, 800, 400);
xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, xform);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);
ASSERT_EQ(100, event.getRawX(0));
ASSERT_EQ(340, event.getRawY(0));
+ // Relative values should be rotated but not translated.
+ ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
+ ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
}
}
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 6612a93..24d186c 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -73,6 +73,7 @@
"libui",
"lib-platform-compat-native-api",
"server_configurable_flags",
+ "InputFlingerProperties",
],
static_libs: [
"libattestation",
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 1b3888b..7c7a16b 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -67,6 +67,7 @@
"libutils",
"lib-platform-compat-native-api",
"server_configurable_flags",
+ "InputFlingerProperties",
],
static_libs: [
"libattestation",
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index c0010ab..6b8cf74 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -47,6 +47,7 @@
// Log debug messages about hover events.
#define DEBUG_HOVER 0
+#include <InputFlingerProperties.sysprop.h>
#include <android-base/chrono_utils.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -93,7 +94,8 @@
// coordinates and SurfaceFlinger includes the display rotation in the input window transforms.
static bool isPerWindowInputRotationEnabled() {
static const bool PER_WINDOW_INPUT_ROTATION =
- base::GetBoolProperty("persist.debug.per_window_input_rotation", false);
+ sysprop::InputFlingerProperties::per_window_input_rotation().value_or(false);
+
return PER_WINDOW_INPUT_ROTATION;
}
@@ -319,11 +321,11 @@
int32_t inputTargetFlags) {
if (eventEntry->type == EventEntry::Type::MOTION) {
const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry);
- if ((motionEntry.source & AINPUT_SOURCE_CLASS_POINTER) == 0) {
+ if ((motionEntry.source & AINPUT_SOURCE_CLASS_JOYSTICK) ||
+ (motionEntry.source & AINPUT_SOURCE_CLASS_POSITION)) {
const ui::Transform identityTransform;
- // Use identity transform for events that are not pointer events because their axes
- // values do not represent on-screen coordinates, so they should not have any window
- // transformations applied to them.
+ // Use identity transform for joystick and position-based (touchpad) events because they
+ // don't depend on the window transform.
return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, identityTransform,
1.0f /*globalScaleFactor*/,
inputTarget.displaySize);
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 7db32e3..ee7b392 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -71,6 +71,7 @@
"libstatslog",
"libui",
"libutils",
+ "InputFlingerProperties",
],
static_libs: [
"libc++fs",
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
index da0fea4..4c5ff63 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
@@ -17,7 +17,7 @@
#ifndef _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
#define _UI_INPUTREADER_TOUCH_CURSOR_INPUT_MAPPER_COMMON_H
-#include <android-base/properties.h>
+#include <InputFlingerProperties.sysprop.h>
#include <input/DisplayViewport.h>
#include <stdint.h>
@@ -34,7 +34,7 @@
// un-rotated coordinate space.
static bool isPerWindowInputRotationEnabled() {
static const bool PER_WINDOW_INPUT_ROTATION =
- base::GetBoolProperty("persist.debug.per_window_input_rotation", false);
+ sysprop::InputFlingerProperties::per_window_input_rotation().value_or(false);
return PER_WINDOW_INPUT_ROTATION;
}
diff --git a/services/inputflinger/sysprop/Android.bp b/services/inputflinger/sysprop/Android.bp
new file mode 100644
index 0000000..b9d65ee
--- /dev/null
+++ b/services/inputflinger/sysprop/Android.bp
@@ -0,0 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+sysprop_library {
+ name: "InputFlingerProperties",
+ srcs: ["*.sysprop"],
+ api_packages: ["android.sysprop"],
+ property_owner: "Platform",
+}
diff --git a/services/inputflinger/sysprop/InputFlingerProperties.sysprop b/services/inputflinger/sysprop/InputFlingerProperties.sysprop
new file mode 100644
index 0000000..1c7e724
--- /dev/null
+++ b/services/inputflinger/sysprop/InputFlingerProperties.sysprop
@@ -0,0 +1,27 @@
+# Copyright (C) 2021 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.
+
+module: "android.sysprop.InputFlingerProperties"
+owner: Platform
+
+# When per-window-input-rotation is enabled, InputReader works in the un-rotated
+# display coordinate space, and the display rotation is encoded as part of the
+# input window transform that is sent from SurfaceFlinger to InputDispatcher.
+prop {
+ api_name: "per_window_input_rotation"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ prop_name: "persist.debug.per_window_input_rotation"
+}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 77ca12c..09b6a79 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2432,7 +2432,7 @@
EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
}
-TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) {
+TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
@@ -2452,20 +2452,19 @@
// Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
window->consumeFocusEvent(true);
- constexpr const std::array nonPointerSources = {AINPUT_SOURCE_TRACKBALL,
- AINPUT_SOURCE_MOUSE_RELATIVE,
- AINPUT_SOURCE_JOYSTICK};
- for (const int source : nonPointerSources) {
- // Notify motion with a non-pointer source.
- NotifyMotionArgs motionArgs =
- generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, source, ADISPLAY_ID_DEFAULT);
+ constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD,
+ AMOTION_EVENT_ACTION_DOWN),
+ std::pair(AINPUT_SOURCE_JOYSTICK,
+ AMOTION_EVENT_ACTION_MOVE)};
+ for (const auto& [source, action] : nonTransformedSources) {
+ const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);
mDispatcher->notifyMotion(&motionArgs);
MotionEvent* event = window->consumeMotion();
ASSERT_NE(event, nullptr);
const MotionEvent& motionEvent = *event;
- EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, motionEvent.getAction());
+ EXPECT_EQ(action, motionEvent.getAction());
EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
float expectedX = motionArgs.pointerCoords[0].getX();
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index ca4b6ab..c391901 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -220,6 +220,10 @@
mCompositionDisplay->setLayerStackFilter(stack, isPrimary());
}
+void DisplayDevice::setFlags(uint32_t flags) {
+ mFlags = flags;
+}
+
void DisplayDevice::setDisplaySize(int width, int height) {
LOG_FATAL_IF(!isVirtual(), "Changing the display size is supported only for virtual displays.");
mCompositionDisplay->setDisplaySize(ui::Size(width, height));
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 7e4d923..70dcc1e 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -64,6 +64,7 @@
public:
constexpr static float sDefaultMinLumiance = 0.0;
constexpr static float sDefaultMaxLumiance = 500.0;
+ enum { eReceivesInput = 0x01 };
explicit DisplayDevice(DisplayDeviceCreationArgs& args);
@@ -90,6 +91,7 @@
void setLayerStack(ui::LayerStack);
void setDisplaySize(int width, int height);
void setProjection(ui::Rotation orientation, Rect viewport, Rect frame);
+ void setFlags(uint32_t flags);
ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; }
ui::Rotation getOrientation() const { return mOrientation; }
@@ -102,6 +104,7 @@
const Rect& getOrientedDisplaySpaceRect() const;
bool needsFiltering() const;
ui::LayerStack getLayerStack() const;
+ bool receivesInput() const { return mFlags & eReceivesInput; }
DisplayId getId() const;
@@ -227,6 +230,8 @@
// TODO(b/74619554): Remove special cases for primary display.
const bool mIsPrimary;
+ uint32_t mFlags = 0;
+
std::optional<DeviceProductInfo> mDeviceProductInfo;
std::vector<ui::Hdr> mOverrideHdrTypes;
@@ -252,6 +257,7 @@
std::optional<Physical> physical;
sp<IGraphicBufferProducer> surface;
ui::LayerStack layerStack = ui::NO_LAYER_STACK;
+ uint32_t flags = 0;
Rect layerStackSpaceRect;
Rect orientedDisplaySpaceRect;
ui::Rotation orientation = ui::ROTATION_0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e2f3ebb..84c0c7e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2851,6 +2851,9 @@
if (currentState.layerStack != drawingState.layerStack) {
display->setLayerStack(currentState.layerStack);
}
+ if (currentState.flags != drawingState.flags) {
+ display->setFlags(currentState.flags);
+ }
if ((currentState.orientation != drawingState.orientation) ||
(currentState.layerStackSpaceRect != drawingState.layerStackSpaceRect) ||
(currentState.orientedDisplaySpaceRect != drawingState.orientedDisplaySpaceRect)) {
@@ -3059,18 +3062,9 @@
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (!layer->needsInputInfo()) return;
- sp<DisplayDevice> display;
- if (enablePerWindowInputRotation()) {
- for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
- const auto& displayDevice = pair.second;
- if (!displayDevice->getCompositionDisplay()
- ->belongsInOutput(layer->getLayerStack(),
- layer->getPrimaryDisplayOnly())) {
- continue;
- }
- display = displayDevice;
- }
- }
+ sp<DisplayDevice> display = enablePerWindowInputRotation()
+ ? ON_MAIN_THREAD(getDisplayWithInputByLayer(layer))
+ : nullptr;
// When calculating the screen bounds we ignore the transparent region since it may
// result in an unwanted offset.
inputInfos.push_back(layer->fillInputInfo(display));
@@ -3825,6 +3819,12 @@
flags |= eDisplayTransactionNeeded;
}
}
+ if (what & DisplayState::eFlagsChanged) {
+ if (state.flags != s.flags) {
+ state.flags = s.flags;
+ flags |= eDisplayTransactionNeeded;
+ }
+ }
if (what & DisplayState::eDisplayProjectionChanged) {
if (state.orientation != s.orientation) {
state.orientation = s.orientation;
@@ -4492,6 +4492,26 @@
static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); }));
}
+sp<DisplayDevice> SurfaceFlinger::getDisplayWithInputByLayer(Layer* layer) const {
+ sp<DisplayDevice> display;
+ for (const auto& pair : mDisplays) {
+ const auto& displayDevice = pair.second;
+ if (!displayDevice->receivesInput() ||
+ !displayDevice->getCompositionDisplay()
+ ->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
+ continue;
+ }
+ // Don't return immediately so that we can log duplicates.
+ if (display) {
+ ALOGE("Multiple display devices claim to accept input for the same layerstack: %d",
+ layer->getLayerStack());
+ continue;
+ }
+ display = displayDevice;
+ }
+ return display;
+}
+
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {
if (display->isVirtual()) {
ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f33df86..ecb6907 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -984,6 +984,8 @@
// region of all screens presenting this layer stack.
void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
+ sp<DisplayDevice> getDisplayWithInputByLayer(Layer* layer) const REQUIRES(mStateLock);
+
/*
* H/W composer
*/
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 8ca241e..2084bb6 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -160,6 +160,7 @@
addDisplaySurfaceLocked(transaction, display.sequenceId, display.surface);
addDisplayLayerStackLocked(transaction, display.sequenceId, display.layerStack);
+ addDisplayFlagsLocked(transaction, display.sequenceId, display.flags);
addDisplaySizeLocked(transaction, display.sequenceId, display.width, display.height);
addDisplayProjectionLocked(transaction, display.sequenceId, toRotationInt(display.orientation),
display.layerStackSpaceRect, display.orientedDisplaySpaceRect);
@@ -474,6 +475,9 @@
if (state.what & DisplayState::eLayerStackChanged) {
addDisplayLayerStackLocked(transaction, sequenceId, state.layerStack);
}
+ if (state.what & DisplayState::eFlagsChanged) {
+ addDisplayFlagsLocked(transaction, sequenceId, state.flags);
+ }
if (state.what & DisplayState::eDisplaySizeChanged) {
addDisplaySizeLocked(transaction, sequenceId, state.width, state.height);
}
@@ -565,6 +569,13 @@
layerStackChange->set_layer_stack(layerStack);
}
+void SurfaceInterceptor::addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId,
+ uint32_t flags) {
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId));
+ DisplayFlagsChange* flagsChange(dispChange->mutable_flags());
+ flagsChange->set_flags(flags);
+}
+
void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId,
uint32_t w, uint32_t h)
{
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 30aca83..e498e7d 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -184,6 +184,7 @@
const sp<const IGraphicBufferProducer>& surface);
void addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId,
uint32_t layerStack);
+ void addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId, uint32_t flags);
void addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId, uint32_t w,
uint32_t h);
void addDisplayProjectionLocked(Transaction* transaction, int32_t sequenceId,
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
index be01984..fc40818 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
@@ -224,6 +224,74 @@
EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
}
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfFlagsNotChanged) {
+ using Case = SimplePrimaryDisplayCase;
+
+ // --------------------------------------------------------------------
+ // Preconditions
+
+ // A display is set up
+ auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+ display.inject();
+
+ // The display has flags set
+ display.mutableCurrentDisplayState().flags = 1u;
+
+ // The incoming request sets a different layer stack
+ DisplayState state;
+ state.what = DisplayState::eFlagsChanged;
+ state.token = display.token();
+ state.flags = 1u;
+
+ // --------------------------------------------------------------------
+ // Invocation
+
+ uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+ // --------------------------------------------------------------------
+ // Postconditions
+
+ // The returned flags are empty
+ EXPECT_EQ(0u, flags);
+
+ // The desired display state has been set to the new value.
+ EXPECT_EQ(1u, display.getCurrentDisplayState().flags);
+}
+
+TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfFlagsChanged) {
+ using Case = SimplePrimaryDisplayCase;
+
+ // --------------------------------------------------------------------
+ // Preconditions
+
+ // A display is set up
+ auto display = Case::Display::makeFakeExistingDisplayInjector(this);
+ display.inject();
+
+ // The display has a layer stack set
+ display.mutableCurrentDisplayState().flags = 0u;
+
+ // The incoming request sets a different layer stack
+ DisplayState state;
+ state.what = DisplayState::eFlagsChanged;
+ state.token = display.token();
+ state.flags = 1u;
+
+ // --------------------------------------------------------------------
+ // Invocation
+
+ uint32_t flags = mFlinger.setDisplayStateLocked(state);
+
+ // --------------------------------------------------------------------
+ // Postconditions
+
+ // The returned flags indicate a transaction is needed
+ EXPECT_EQ(eDisplayTransactionNeeded, flags);
+
+ // The desired display state has been set to the new value.
+ EXPECT_EQ(1u, display.getCurrentDisplayState().flags);
+}
+
TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) {
using Case = SimplePrimaryDisplayCase;
constexpr ui::Rotation initialOrientation = ui::ROTATION_180;