Merge "Add tracing thread for RenderEngine's fences" into udc-dev
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 3a1e600..ed69100 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1796,12 +1796,14 @@
auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
auto startTimeNanos = static_cast<int64_t>(va_arg(args, int64_t));
+ auto useForRefreshRateSelection = static_cast<bool>(va_arg(args, int32_t));
ALOGV("Surface::%s", __func__);
FrameTimelineInfo ftlInfo;
ftlInfo.vsyncId = frameTimelineVsyncId;
ftlInfo.inputEventId = inputEventId;
ftlInfo.startTimeNanos = startTimeNanos;
+ ftlInfo.useForRefreshRateSelection = useForRefreshRateSelection;
return setFrameTimelineInfo(frameNumber, ftlInfo);
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1b13ec1..c6c7367 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2245,11 +2245,13 @@
t.vsyncId = other.vsyncId;
t.inputEventId = other.inputEventId;
t.startTimeNanos = other.startTimeNanos;
+ t.useForRefreshRateSelection = other.useForRefreshRateSelection;
}
} else if (t.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
t.vsyncId = other.vsyncId;
t.inputEventId = other.inputEventId;
t.startTimeNanos = other.startTimeNanos;
+ t.useForRefreshRateSelection = other.useForRefreshRateSelection;
}
}
@@ -2258,6 +2260,7 @@
t.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID;
t.inputEventId = os::IInputConstants::INVALID_INPUT_EVENT_ID;
t.startTimeNanos = 0;
+ t.useForRefreshRateSelection = false;
}
SurfaceComposerClient::Transaction&
diff --git a/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl b/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
index 6ffe466..6a86c6a 100644
--- a/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
+++ b/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
@@ -33,4 +33,8 @@
// The current time in nanoseconds the application started to render the frame.
long startTimeNanos = 0;
+
+ // Whether this vsyncId should be used to heuristically select the display refresh rate
+ // TODO(b/281695725): Clean this up once TextureView use setFrameRate API
+ boolean useForRefreshRateSelection = false;
}
diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp
index af9ce3a..9a459b1 100644
--- a/libs/input/VirtualInputDevice.cpp
+++ b/libs/input/VirtualInputDevice.cpp
@@ -49,11 +49,10 @@
std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(eventTime);
std::chrono::microseconds microseconds =
std::chrono::duration_cast<std::chrono::microseconds>(eventTime - seconds);
- struct input_event ev = {.type = type,
- .code = code,
- .value = value,
- .input_event_sec = static_cast<time_t>(seconds.count()),
- .input_event_usec = static_cast<suseconds_t>(microseconds.count())};
+ struct input_event ev = {.type = type, .code = code, .value = value};
+ ev.input_event_sec = static_cast<decltype(ev.input_event_sec)>(seconds.count());
+ ev.input_event_usec = static_cast<decltype(ev.input_event_usec)>(microseconds.count());
+
return TEMP_FAILURE_RETRY(write(mFd, &ev, sizeof(struct input_event))) == sizeof(ev);
}
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 6c54635..0fee3c1 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1066,13 +1066,12 @@
(int)compatibility, (int)changeFrameRateStrategy);
}
-static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window,
- uint64_t frameNumber,
- int64_t frameTimelineVsyncId,
- int32_t inputEventId,
- int64_t startTimeNanos) {
+static inline int native_window_set_frame_timeline_info(
+ struct ANativeWindow* window, uint64_t frameNumber, int64_t frameTimelineVsyncId,
+ int32_t inputEventId, int64_t startTimeNanos, int32_t useForRefreshRateSelection) {
return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO, frameNumber,
- frameTimelineVsyncId, inputEventId, startTimeNanos);
+ frameTimelineVsyncId, inputEventId, startTimeNanos,
+ useForRefreshRateSelection);
}
// ------------------------------------------------------------------------------------------------
diff --git a/libs/permission/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp
index baa9d75..6959274 100644
--- a/libs/permission/AppOpsManager.cpp
+++ b/libs/permission/AppOpsManager.cpp
@@ -146,6 +146,14 @@
}
}
+void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName, int32_t flags,
+ const sp<IAppOpsCallback>& callback) {
+ sp<IAppOpsService> service = getService();
+ if (service != nullptr) {
+ service->startWatchingModeWithFlags(op, packageName, flags, callback);
+ }
+}
+
void AppOpsManager::stopWatchingMode(const sp<IAppOpsCallback>& callback) {
sp<IAppOpsService> service = getService();
if (service != nullptr) {
diff --git a/libs/permission/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp
index d59f445..7f235a4 100644
--- a/libs/permission/IAppOpsService.cpp
+++ b/libs/permission/IAppOpsService.cpp
@@ -166,6 +166,17 @@
}
return reply.readBool();
}
+
+ virtual void startWatchingModeWithFlags(int32_t op, const String16& packageName,
+ int32_t flags, const sp<IAppOpsCallback>& callback) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+ data.writeInt32(op);
+ data.writeString16(packageName);
+ data.writeInt32(flags);
+ data.writeStrongBinder(IInterface::asBinder(callback));
+ remote()->transact(START_WATCHING_MODE_WITH_FLAGS_TRANSACTION, data, &reply);
+ }
};
IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService")
diff --git a/libs/permission/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
index abcd527..243532b 100644
--- a/libs/permission/include/binder/AppOpsManager.h
+++ b/libs/permission/include/binder/AppOpsManager.h
@@ -151,6 +151,10 @@
_NUM_OP = 117
};
+ enum {
+ WATCH_FOREGROUND_CHANGES = 1 << 0
+ };
+
AppOpsManager();
int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
@@ -174,6 +178,8 @@
const std::optional<String16>& attributionTag);
void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback);
+ void startWatchingMode(int32_t op, const String16& packageName, int32_t flags,
+ const sp<IAppOpsCallback>& callback);
void stopWatchingMode(const sp<IAppOpsCallback>& callback);
int32_t permissionToOpCode(const String16& permission);
void setCameraAudioRestriction(int32_t mode);
diff --git a/libs/permission/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
index 22f056b..918fcdb 100644
--- a/libs/permission/include/binder/IAppOpsService.h
+++ b/libs/permission/include/binder/IAppOpsService.h
@@ -52,6 +52,8 @@
const String16& packageName) = 0;
virtual void setCameraAudioRestriction(int32_t mode) = 0;
virtual bool shouldCollectNotes(int32_t opCode) = 0;
+ virtual void startWatchingModeWithFlags(int32_t op, const String16& packageName,
+ int32_t flags, const sp<IAppOpsCallback>& callback) = 0;
enum {
CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -64,6 +66,7 @@
CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
SHOULD_COLLECT_NOTES_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8,
SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+9,
+ START_WATCHING_MODE_WITH_FLAGS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+10,
};
enum {
diff --git a/libs/ultrahdr/jpegr.cpp b/libs/ultrahdr/jpegr.cpp
index 0f7aa27..ef927e3 100644
--- a/libs/ultrahdr/jpegr.cpp
+++ b/libs/ultrahdr/jpegr.cpp
@@ -534,7 +534,7 @@
if (mQueuedAllJobs) {
return false;
} else {
- mCv.wait(lock);
+ mCv.wait_for(lock, std::chrono::milliseconds(100));
}
} else {
auto it = mJobs.begin();
@@ -557,6 +557,8 @@
void JobQueue::markQueueForEnd() {
std::unique_lock<std::mutex> lock{mMutex};
mQueuedAllJobs = true;
+ lock.unlock();
+ mCv.notify_all();
}
void JobQueue::reset() {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 326ca87..f3ada8e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2476,7 +2476,8 @@
newTouchedWindowHandle = nullptr;
}
- if (!haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
+ if (newTouchedWindowHandle != nullptr &&
+ !haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
oldTouchedWindowHandle->getName().c_str(),
newTouchedWindowHandle->getName().c_str(), displayId);
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index b86906b..3f6d557 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -203,7 +203,7 @@
using Change = InputReaderConfiguration::Change;
- if (!isIgnored()) {
+ if (!changes.any() || !isIgnored()) {
// Full configuration should happen the first time configure is called
// and when the device type is changed. Changing a device type can
// affect various other parameters so should result in a
@@ -446,17 +446,17 @@
// Switch-like devices.
if (classes.test(InputDeviceClass::SWITCH)) {
- mappers.push_back(std::make_unique<SwitchInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<SwitchInputMapper>(contextPtr, readerConfig));
}
// Scroll wheel-like devices.
if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {
- mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<RotaryEncoderInputMapper>(contextPtr, readerConfig));
}
// Vibrator-like devices.
if (classes.test(InputDeviceClass::VIBRATOR)) {
- mappers.push_back(std::make_unique<VibratorInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<VibratorInputMapper>(contextPtr, readerConfig));
}
// Battery-like devices or light-containing devices.
@@ -488,7 +488,7 @@
// Cursor-like devices.
if (classes.test(InputDeviceClass::CURSOR)) {
- mappers.push_back(std::make_unique<CursorInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<CursorInputMapper>(contextPtr, readerConfig));
}
// Touchscreens and touchpad devices.
@@ -501,26 +501,26 @@
(identifier.product == 0x05c4 || identifier.product == 0x09cc);
if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) {
- mappers.push_back(std::make_unique<TouchpadInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<TouchpadInputMapper>(contextPtr, readerConfig));
} else if (classes.test(InputDeviceClass::TOUCH_MT)) {
- mappers.push_back(std::make_unique<MultiTouchInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<MultiTouchInputMapper>(contextPtr, readerConfig));
} else if (classes.test(InputDeviceClass::TOUCH)) {
- mappers.push_back(std::make_unique<SingleTouchInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<SingleTouchInputMapper>(contextPtr, readerConfig));
}
// Joystick-like devices.
if (classes.test(InputDeviceClass::JOYSTICK)) {
- mappers.push_back(std::make_unique<JoystickInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<JoystickInputMapper>(contextPtr, readerConfig));
}
// Motion sensor enabled devices.
if (classes.test(InputDeviceClass::SENSOR)) {
- mappers.push_back(std::make_unique<SensorInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<SensorInputMapper>(contextPtr, readerConfig));
}
// External stylus-like devices.
if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) {
- mappers.push_back(std::make_unique<ExternalStylusInputMapper>(contextPtr, readerConfig));
+ mappers.push_back(createInputMapper<ExternalStylusInputMapper>(contextPtr, readerConfig));
}
return mappers;
}
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 6303546..0b8a608 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -149,6 +149,16 @@
return *mapper;
}
+ template <class T, typename... Args>
+ T& constructAndAddMapper(int32_t eventHubId, Args... args) {
+ // create mapper
+ auto& devicePair = mDevices[eventHubId];
+ auto& deviceContext = devicePair.first;
+ auto& mappers = devicePair.second;
+ mappers.push_back(createInputMapper<T>(*deviceContext, args...));
+ return static_cast<T&>(*mappers.back());
+ }
+
// construct and add a controller to the input device
template <class T>
T& addController(int32_t eventHubId) {
diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
index dab4661..061c6a3 100644
--- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
+++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp
@@ -199,6 +199,29 @@
}
}
+ // Send BUTTON_RELEASE events. (This has to happen before any UP events to avoid sending
+ // BUTTON_RELEASE events without any pointers.)
+ uint32_t newButtonState;
+ if (coords.size() - upSlots.size() + downSlots.size() == 0) {
+ // If there won't be any pointers down after this evdev sync, we won't be able to send
+ // button updates on their own, as motion events without pointers are invalid. To avoid
+ // erroneously reporting buttons being held for long periods, send BUTTON_RELEASE events for
+ // all pressed buttons when the last pointer is lifted.
+ //
+ // This also prevents us from sending BUTTON_PRESS events too early in the case of touchpads
+ // which report a button press one evdev sync before reporting a touch going down.
+ newButtonState = 0;
+ } else {
+ newButtonState = mCursorButtonAccumulator.getButtonState();
+ }
+ for (uint32_t button = 1; button <= AMOTION_EVENT_BUTTON_FORWARD; button <<= 1) {
+ if (!(newButtonState & button) && mButtonState & button) {
+ mButtonState &= ~button;
+ out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ coords, properties, /*actionButton=*/button));
+ }
+ }
+
// For any touches that were lifted, send UP or POINTER_UP events.
for (size_t slotNumber : upSlots) {
const size_t indexToRemove = coordsIndexForSlotNumber.at(slotNumber);
@@ -240,16 +263,11 @@
out.push_back(makeMotionArgs(when, readTime, action, coords, properties));
}
- const uint32_t newButtonState = mCursorButtonAccumulator.getButtonState();
for (uint32_t button = 1; button <= AMOTION_EVENT_BUTTON_FORWARD; button <<= 1) {
if (newButtonState & button && !(mButtonState & button)) {
mButtonState |= button;
out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_PRESS, coords,
properties, /*actionButton=*/button));
- } else if (!(newButtonState & button) && mButtonState & button) {
- mButtonState &= ~button;
- out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- coords, properties, /*actionButton=*/button));
}
}
return out;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 8ef5ff6..c684ed4 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -71,9 +71,7 @@
CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
const InputReaderConfiguration& readerConfig)
: InputMapper(deviceContext, readerConfig),
- mLastEventTime(std::numeric_limits<nsecs_t>::min()) {
- configureWithZeroChanges(readerConfig);
-}
+ mLastEventTime(std::numeric_limits<nsecs_t>::min()) {}
CursorInputMapper::~CursorInputMapper() {
if (mPointerController != nullptr) {
@@ -142,46 +140,51 @@
ConfigurationChanges changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, readerConfig, changes);
- if (!changes.any()) {
- configureWithZeroChanges(readerConfig);
- return out;
+ if (!changes.any()) { // first time only
+ configureBasicParams();
}
- const bool configurePointerCapture = mParameters.mode != Parameters::Mode::NAVIGATION &&
- changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE);
+ const bool configurePointerCapture = !changes.any() ||
+ (mParameters.mode != Parameters::Mode::NAVIGATION &&
+ changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE));
if (configurePointerCapture) {
configureOnPointerCapture(readerConfig);
out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
}
- if (changes.test(InputReaderConfiguration::Change::POINTER_SPEED) || configurePointerCapture) {
+ if (!changes.any() || changes.test(InputReaderConfiguration::Change::POINTER_SPEED) ||
+ configurePointerCapture) {
configureOnChangePointerSpeed(readerConfig);
}
- if (changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) {
+ if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) ||
+ configurePointerCapture) {
configureOnChangeDisplayInfo(readerConfig);
}
return out;
}
-void CursorInputMapper::configureParameters() {
- mParameters.mode = Parameters::Mode::POINTER;
- const PropertyMap& config = getDeviceContext().getConfiguration();
+CursorInputMapper::Parameters CursorInputMapper::computeParameters(
+ const InputDeviceContext& deviceContext) {
+ Parameters parameters;
+ parameters.mode = Parameters::Mode::POINTER;
+ const PropertyMap& config = deviceContext.getConfiguration();
std::optional<std::string> cursorModeString = config.getString("cursor.mode");
if (cursorModeString.has_value()) {
if (*cursorModeString == "navigation") {
- mParameters.mode = Parameters::Mode::NAVIGATION;
+ parameters.mode = Parameters::Mode::NAVIGATION;
} else if (*cursorModeString != "pointer" && *cursorModeString != "default") {
ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString->c_str());
}
}
- mParameters.orientationAware = config.getBool("cursor.orientationAware").value_or(false);
+ parameters.orientationAware = config.getBool("cursor.orientationAware").value_or(false);
- mParameters.hasAssociatedDisplay = false;
- if (mParameters.mode == Parameters::Mode::POINTER || mParameters.orientationAware) {
- mParameters.hasAssociatedDisplay = true;
+ parameters.hasAssociatedDisplay = false;
+ if (parameters.mode == Parameters::Mode::POINTER || parameters.orientationAware) {
+ parameters.hasAssociatedDisplay = true;
}
+ return parameters;
}
void CursorInputMapper::dumpParameters(std::string& dump) {
@@ -424,22 +427,11 @@
return mDisplayId;
}
-void CursorInputMapper::configureWithZeroChanges(const InputReaderConfiguration& readerConfig) {
- // Configuration with zero changes
- configureBasicParams();
- if (mParameters.mode != Parameters::Mode::NAVIGATION &&
- readerConfig.pointerCaptureRequest.enable) {
- configureOnPointerCapture(readerConfig);
- }
- configureOnChangePointerSpeed(readerConfig);
- configureOnChangeDisplayInfo(readerConfig);
-}
-
void CursorInputMapper::configureBasicParams() {
mCursorScrollAccumulator.configure(getDeviceContext());
// Configure basic parameters.
- configureParameters();
+ mParameters = computeParameters(getDeviceContext());
// Configure device mode.
switch (mParameters.mode) {
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index caf2e5a..b879bfd 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -53,8 +53,10 @@
class CursorInputMapper : public InputMapper {
public:
- explicit CursorInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~CursorInputMapper();
virtual uint32_t getSources() const override;
@@ -125,15 +127,17 @@
nsecs_t mDownTime;
nsecs_t mLastEventTime;
- void configureParameters();
+ explicit CursorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
void dumpParameters(std::string& dump);
- void configureWithZeroChanges(const InputReaderConfiguration& readerConfig);
void configureBasicParams();
void configureOnPointerCapture(const InputReaderConfiguration& config);
void configureOnChangePointerSpeed(const InputReaderConfiguration& config);
void configureOnChangeDisplayInfo(const InputReaderConfiguration& config);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime);
+
+ static Parameters computeParameters(const InputDeviceContext& deviceContext);
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
index 841c437..97df02b 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h
@@ -26,8 +26,10 @@
class ExternalStylusInputMapper : public InputMapper {
public:
- explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~ExternalStylusInputMapper() = default;
uint32_t getSources() const override;
@@ -46,6 +48,8 @@
StylusState mStylusState;
+ explicit ExternalStylusInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when);
};
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index f017317..06de4c2 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -25,6 +25,20 @@
#include "VibrationElement.h"
namespace android {
+/**
+ * This is the factory method that must be used to create any InputMapper
+ */
+template <class T, class... Args>
+std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig, Args... args) {
+ // Using `new` to access non-public constructors.
+ std::unique_ptr<T> mapper(new T(deviceContext, readerConfig, args...));
+ // We need to reset and configure the mapper to ensure it is ready to process event
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ std::list<NotifyArgs> unused = mapper->reset(now);
+ unused += mapper->reconfigure(now, readerConfig, /*changes=*/{});
+ return mapper;
+}
/* An input mapper transforms raw input events into cooked event data.
* A single input device can have multiple associated input mappers in order to interpret
@@ -39,8 +53,15 @@
*/
class InputMapper {
public:
- explicit InputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ /**
+ * Subclasses must either provide a public constructor
+ * or must be-friend the factory method.
+ */
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
+
virtual ~InputMapper();
inline int32_t getDeviceId() { return mDeviceContext.getId(); }
@@ -102,6 +123,9 @@
protected:
InputDeviceContext& mDeviceContext;
+ explicit InputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
void bumpGeneration();
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.h b/services/inputflinger/reader/mapper/JoystickInputMapper.h
index 49673a2..313f092 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.h
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.h
@@ -22,8 +22,10 @@
class JoystickInputMapper : public InputMapper {
public:
- explicit JoystickInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~JoystickInputMapper();
virtual uint32_t getSources() const override;
@@ -87,6 +89,9 @@
}
};
+ explicit JoystickInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
static Axis createAxis(const AxisInfo& AxisInfo, const RawAbsoluteAxisInfo& rawAxisInfo,
bool explicitlyMapped);
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index a617420..1d788df 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -23,8 +23,11 @@
class MultiTouchInputMapper : public TouchInputMapper {
public:
- explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
+
~MultiTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
@@ -36,6 +39,8 @@
bool hasStylus() const override;
private:
+ explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
// simulate_stylus_with_touch is a debug mode that converts all finger pointers reported by this
// mapper's touchscreen into stylus pointers, and adds SOURCE_STYLUS to the input device.
// It is used to simulate stylus events for debugging and testing on a device that does not
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
index d3dcbe1..9e2e8c4 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -25,8 +25,10 @@
class RotaryEncoderInputMapper : public InputMapper {
public:
- explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~RotaryEncoderInputMapper();
virtual uint32_t getSources() const override;
@@ -45,6 +47,8 @@
float mScalingFactor;
ui::Rotation mOrientation;
+ explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime);
};
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h
index 1f82559..a55dcd1 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.h
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.h
@@ -27,8 +27,10 @@
class SensorInputMapper : public InputMapper {
public:
- explicit SensorInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
~SensorInputMapper() override;
uint32_t getSources() const override;
@@ -106,6 +108,9 @@
}
};
+ explicit SensorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
static Axis createAxis(const AxisInfo& AxisInfo, const RawAbsoluteAxisInfo& rawAxisInfo);
// Axes indexed by raw ABS_* axis index.
diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
index 9341007..7726bfb 100644
--- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.h
@@ -23,8 +23,11 @@
class SingleTouchInputMapper : public TouchInputMapper {
public:
- explicit SingleTouchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
+
~SingleTouchInputMapper() override;
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
@@ -37,6 +40,8 @@
private:
SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
+ explicit SingleTouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.h b/services/inputflinger/reader/mapper/SwitchInputMapper.h
index 7ec282b..2fb48bb 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.h
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.h
@@ -22,8 +22,10 @@
class SwitchInputMapper : public InputMapper {
public:
- explicit SwitchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~SwitchInputMapper();
virtual uint32_t getSources() const override;
@@ -36,6 +38,8 @@
uint32_t mSwitchValues;
uint32_t mUpdatedSwitchMask;
+ explicit SwitchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
void processSwitch(int32_t switchCode, int32_t switchValue);
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when);
};
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index c72a263..f4d50b8 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -125,8 +125,7 @@
const InputReaderConfiguration& readerConfig)
: InputMapper(deviceContext, readerConfig),
mTouchButtonAccumulator(deviceContext),
- mConfig(readerConfig),
- mParameters(computeParameters(deviceContext)) {}
+ mConfig(readerConfig) {}
TouchInputMapper::~TouchInputMapper() {}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 7141924..d8b59ca 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -146,8 +146,6 @@
class TouchInputMapper : public InputMapper {
public:
- explicit TouchInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
~TouchInputMapper() override;
uint32_t getSources() const override;
@@ -358,25 +356,28 @@
nsecs_t mExternalStylusFusionTimeout;
bool mExternalStylusDataPending;
// A subset of the buttons in mCurrentRawState that came from an external stylus.
- int32_t mExternalStylusButtonsApplied;
+ int32_t mExternalStylusButtonsApplied{0};
// True if we sent a HOVER_ENTER event.
- bool mSentHoverEnter;
+ bool mSentHoverEnter{false};
// Have we assigned pointer IDs for this stream
- bool mHavePointerIds;
+ bool mHavePointerIds{false};
// Is the current stream of direct touch events aborted
- bool mCurrentMotionAborted;
+ bool mCurrentMotionAborted{false};
// The time the primary pointer last went down.
- nsecs_t mDownTime;
+ nsecs_t mDownTime{0};
// The pointer controller, or null if the device is not a pointer.
std::shared_ptr<PointerControllerInterface> mPointerController;
std::vector<VirtualKey> mVirtualKeys;
+ explicit TouchInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
+
virtual void dumpParameters(std::string& dump);
virtual void configureRawPointerAxes();
virtual void dumpRawPointerAxes(std::string& dump);
@@ -513,7 +514,7 @@
STYLUS,
MOUSE,
};
- PointerUsage mPointerUsage;
+ PointerUsage mPointerUsage{PointerUsage::NONE};
struct PointerGesture {
enum class Mode {
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 3128d18..23d0fd3 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -40,8 +40,10 @@
class TouchpadInputMapper : public InputMapper {
public:
- explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
~TouchpadInputMapper();
uint32_t getSources() const override;
@@ -58,6 +60,8 @@
private:
void resetGestureInterpreter(nsecs_t when);
+ explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> sendHardwareState(nsecs_t when, nsecs_t readTime,
SelfContainedHardwareState schs);
[[nodiscard]] std::list<NotifyArgs> processGestures(nsecs_t when, nsecs_t readTime);
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.h b/services/inputflinger/reader/mapper/VibratorInputMapper.h
index 384c075..9079c73 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.h
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.h
@@ -22,8 +22,10 @@
class VibratorInputMapper : public InputMapper {
public:
- explicit VibratorInputMapper(InputDeviceContext& deviceContext,
- const InputReaderConfiguration& readerConfig);
+ template <class T, class... Args>
+ friend std::unique_ptr<T> createInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig,
+ Args... args);
virtual ~VibratorInputMapper();
virtual uint32_t getSources() const override;
@@ -46,6 +48,8 @@
ssize_t mIndex;
nsecs_t mNextStepTime;
+ explicit VibratorInputMapper(InputDeviceContext& deviceContext,
+ const InputReaderConfiguration& readerConfig);
[[nodiscard]] std::list<NotifyArgs> nextStep();
[[nodiscard]] NotifyVibratorStateArgs stopVibrating();
};
diff --git a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
index 3dc5152..99a6a1f 100644
--- a/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
+++ b/services/inputflinger/tests/CapturedTouchpadEventConverter_test.cpp
@@ -781,4 +781,175 @@
WithPointerId(/*index=*/1, /*id=*/0)));
}
+// Motion events without any pointers are invalid, so when a button press is reported in the same
+// frame as a touch down, the button press must be reported second. Similarly with a button release
+// and a touch lift.
+TEST_F(CapturedTouchpadEventConverterTest,
+ ButtonPressedAndReleasedInSameFrameAsTouch_ReportedWithPointers) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 1);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)));
+
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 0);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 0);
+ args = processSync(conv);
+ ASSERT_EQ(3u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(0)));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_UP));
+}
+
+// Some touchpads sometimes report a button press before they report the finger touching the pad. In
+// that case we need to wait until the touch comes to report the button press.
+TEST_F(CapturedTouchpadEventConverterTest, ButtonPressedBeforeTouch_ReportedOnceTouchOccurs) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+ ASSERT_EQ(0u, processSync(conv).size());
+
+ processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 1);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
+
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)));
+}
+
+// When all fingers are lifted from a touchpad, we should release any buttons that are down, since
+// we won't be able to report them being lifted later if no pointers are present.
+TEST_F(CapturedTouchpadEventConverterTest, ButtonReleasedAfterTouchLifts_ReportedWithLift) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 1);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 0);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 0);
+ args = processSync(conv);
+ ASSERT_EQ(3u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithPointerCount(1u),
+ WithCoords(50, 100), WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(0)));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_UP));
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 0);
+ ASSERT_EQ(0u, processSync(conv).size());
+}
+
+TEST_F(CapturedTouchpadEventConverterTest, MultipleButtonsPressedDuringTouch_ReportedCorrectly) {
+ CapturedTouchpadEventConverter conv = createConverter();
+
+ processAxis(conv, EV_ABS, ABS_MT_SLOT, 0);
+ processAxis(conv, EV_ABS, ABS_MT_TRACKING_ID, 1);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_X, 50);
+ processAxis(conv, EV_ABS, ABS_MT_POSITION_Y, 100);
+ processAxis(conv, EV_KEY, BTN_TOUCH, 1);
+ processAxis(conv, EV_KEY, BTN_TOOL_FINGER, 1);
+
+ EXPECT_THAT(processSyncAndExpectSingleMotionArg(conv),
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 1);
+ std::list<NotifyArgs> args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY)));
+
+ processAxis(conv, EV_KEY, BTN_RIGHT, 1);
+ args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY |
+ AMOTION_EVENT_BUTTON_SECONDARY)));
+
+ processAxis(conv, EV_KEY, BTN_LEFT, 0);
+ args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
+ WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY)));
+
+ processAxis(conv, EV_KEY, BTN_RIGHT, 0);
+ args = processSync(conv);
+ ASSERT_EQ(2u, args.size());
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
+ args.pop_front();
+ EXPECT_THAT(std::get<NotifyMotionArgs>(args.front()),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
+ WithActionButton(AMOTION_EVENT_BUTTON_SECONDARY), WithButtonState(0)));
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index a6cdee5..f6f02d8 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -5535,6 +5535,46 @@
AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
}
+/**
+ * Two windows, one on the left and another on the right. The left window is slippery. The right
+ * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
+ * touch moves from the left window into the right window, the gesture should continue to go to the
+ * left window. Touch shouldn't slip because the right window can't receive touches. This test
+ * reproduces a crash.
+ */
+TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+
+ sp<FakeWindowHandle> leftSlipperyWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
+ leftSlipperyWindow->setSlippery(true);
+ leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
+
+ sp<FakeWindowHandle> rightDropTouchesWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
+ rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
+ rightDropTouchesWindow->setDropInput(true);
+
+ mDispatcher->setInputWindows(
+ {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
+
+ // Start touch in the left window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .build());
+ leftSlipperyWindow->consumeMotionDown();
+
+ // And move it into the right window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+ .build());
+
+ // Since the right window isn't eligible to receive input, touch does not slip.
+ // The left window continues to receive the gesture.
+ leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ rightDropTouchesWindow->assertNoEvents();
+}
+
class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
protected:
static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index d969034..2b6655c 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -73,6 +73,17 @@
return mapper;
}
+ template <class T, typename... Args>
+ T& constructAndAddMapper(Args... args) {
+ // ensure a device entry exists for this eventHubId
+ mDevice->addEmptyEventHubDevice(EVENTHUB_ID);
+ // configure the empty device
+ configureDevice(/*changes=*/{});
+
+ return mDevice->constructAndAddMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ args...);
+ }
+
void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
ui::Rotation orientation, const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index d56db11..9fbe762 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -2603,13 +2603,13 @@
};
TEST_F(SwitchInputMapperTest, GetSources) {
- SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>();
+ SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper.getSources());
}
TEST_F(SwitchInputMapperTest, GetSwitchState) {
- SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>();
+ SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
@@ -2619,7 +2619,7 @@
}
TEST_F(SwitchInputMapperTest, Process) {
- SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>();
+ SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
std::list<NotifyArgs> out;
out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1);
ASSERT_TRUE(out.empty());
@@ -2645,13 +2645,13 @@
};
TEST_F(VibratorInputMapperTest, GetSources) {
- VibratorInputMapper& mapper = addMapperAndConfigure<VibratorInputMapper>();
+ VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
}
TEST_F(VibratorInputMapperTest, GetVibratorIds) {
- VibratorInputMapper& mapper = addMapperAndConfigure<VibratorInputMapper>();
+ VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
}
@@ -2659,7 +2659,7 @@
TEST_F(VibratorInputMapperTest, Vibrate) {
constexpr uint8_t DEFAULT_AMPLITUDE = 192;
constexpr int32_t VIBRATION_TOKEN = 100;
- VibratorInputMapper& mapper = addMapperAndConfigure<VibratorInputMapper>();
+ VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
VibrationElement pattern(2);
VibrationSequence sequence(2);
@@ -2784,7 +2784,7 @@
}
TEST_F(SensorInputMapperTest, GetSources) {
- SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>();
+ SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
}
@@ -2792,7 +2792,7 @@
TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
setAccelProperties();
prepareAccelAxes();
- SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>();
+ SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
std::chrono::microseconds(10000),
@@ -2822,7 +2822,7 @@
TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
setGyroProperties();
prepareGyroAxes();
- SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>();
+ SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
std::chrono::microseconds(10000),
@@ -3862,21 +3862,21 @@
TEST_F(CursorInputMapperTest, WhenModeIsPointer_GetSources_ReturnsMouse) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
}
TEST_F(CursorInputMapperTest, WhenModeIsNavigation_GetSources_ReturnsTrackball) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper.getSources());
}
TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeFromPointerController) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
@@ -3906,7 +3906,7 @@
TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsScaledRange) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
@@ -3924,7 +3924,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -4012,7 +4012,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyMotionArgs args;
@@ -4036,7 +4036,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyMotionArgs args;
@@ -4065,7 +4065,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
addConfigurationProperty("cursor.mode", "navigation");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyMotionArgs args;
@@ -4114,7 +4114,7 @@
// InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
// need to be rotated.
addConfigurationProperty("cursor.orientationAware", "1");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
prepareDisplay(ui::ROTATION_90);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
@@ -4132,7 +4132,7 @@
addConfigurationProperty("cursor.mode", "navigation");
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
clearViewports();
prepareDisplay(ui::ROTATION_0);
@@ -4181,7 +4181,7 @@
TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
mFakePointerController->setPosition(100, 200);
@@ -4435,7 +4435,7 @@
TEST_F(CursorInputMapperTest, Process_WhenModeIsPointer_ShouldMoveThePointerAround) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
mFakePointerController->setPosition(100, 200);
@@ -4456,7 +4456,7 @@
TEST_F(CursorInputMapperTest, Process_PointerCapture) {
addConfigurationProperty("cursor.mode", "pointer");
mFakePolicy->setPointerCapture(true);
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
@@ -4548,7 +4548,7 @@
const VelocityControlParameters testParams(/*scale=*/5.f, /*low threshold=*/0.f,
/*high threshold=*/100.f, /*acceleration=*/10.f);
mFakePolicy->setVelocityControlParams(testParams);
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
@@ -4589,7 +4589,7 @@
TEST_F(CursorInputMapperTest, PointerCaptureDisablesOrientationChanges) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
@@ -4630,7 +4630,7 @@
}
TEST_F(CursorInputMapperTest, ConfigureDisplayId_NoAssociatedViewport) {
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
// Set up the default display.
prepareDisplay(ui::ROTATION_90);
@@ -4656,7 +4656,7 @@
}
TEST_F(CursorInputMapperTest, ConfigureDisplayId_WithAssociatedViewport) {
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
// Set up the default display.
prepareDisplay(ui::ROTATION_90);
@@ -4682,7 +4682,7 @@
}
TEST_F(CursorInputMapperTest, ConfigureDisplayId_IgnoresEventsForMismatchedPointerDisplay) {
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
// Set up the default display as the display on which the pointer should be shown.
prepareDisplay(ui::ROTATION_90);
@@ -4715,7 +4715,7 @@
TEST_F(BluetoothCursorInputMapperTest, TimestampSmoothening) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
nsecs_t kernelEventTime = ARBITRARY_TIME;
nsecs_t expectedEventTime = ARBITRARY_TIME;
@@ -4742,7 +4742,7 @@
TEST_F(BluetoothCursorInputMapperTest, TimestampSmootheningIsCapped) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
nsecs_t expectedEventTime = ARBITRARY_TIME;
process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 1);
@@ -4779,7 +4779,7 @@
TEST_F(BluetoothCursorInputMapperTest, TimestampSmootheningNotUsed) {
addConfigurationProperty("cursor.mode", "pointer");
- CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ CursorInputMapper& mapper = constructAndAddMapper<CursorInputMapper>();
nsecs_t kernelEventTime = ARBITRARY_TIME;
nsecs_t expectedEventTime = ARBITRARY_TIME;
@@ -5069,7 +5069,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
}
@@ -5078,7 +5078,7 @@
prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
}
@@ -5089,7 +5089,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Unknown key.
ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
@@ -5117,7 +5117,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Unknown key.
ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
@@ -5145,7 +5145,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
uint8_t flags[2] = { 0, 0 };
ASSERT_TRUE(
@@ -5160,7 +5160,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5210,7 +5210,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5331,7 +5331,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5406,7 +5406,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5502,7 +5502,7 @@
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -5592,7 +5592,7 @@
prepareAxes(POSITION);
// InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
// need to be rotated. Touchscreens are orientation-aware by default.
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5617,7 +5617,7 @@
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5686,7 +5686,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_0");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 0.
@@ -5710,7 +5710,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_90");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 90.
@@ -5734,7 +5734,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_180");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 180.
@@ -5758,7 +5758,7 @@
addConfigurationProperty("touch.orientation", "ORIENTATION_270");
clearViewports();
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
// Orientation 270.
@@ -5782,7 +5782,7 @@
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
addConfigurationProperty("touch.orientation", "ORIENTATION_90");
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5849,7 +5849,7 @@
prepareAxes(POSITION);
addConfigurationProperty("touch.orientationAware", "1");
prepareDisplay(ui::ROTATION_0);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Set a physical frame in the display viewport.
auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
@@ -5903,7 +5903,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -5948,7 +5948,7 @@
prepareLocationCalibration();
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
int32_t rawX = 100;
int32_t rawY = 200;
@@ -5970,7 +5970,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
NotifyKeyArgs keyArgs;
@@ -6213,7 +6213,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6349,7 +6349,7 @@
prepareButtons();
prepareAxes(POSITION);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6420,7 +6420,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6491,7 +6491,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Touch down.
processDown(mapper, 100, 200);
@@ -6513,7 +6513,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Set the initial state for the touch pointer.
mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
@@ -6541,7 +6541,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Down.
@@ -6569,7 +6569,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
NotifyMotionArgs motionArgs;
@@ -6629,7 +6629,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Press a stylus button.
@@ -6670,7 +6670,7 @@
mFakePolicy->setStylusButtonMotionEventsEnabled(false);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Press a stylus button.
@@ -6707,7 +6707,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mapper.getSources());
@@ -6723,7 +6723,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(true);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
processKey(mapper, BTN_TOOL_PEN, 1);
processMove(mapper, 100, 200);
@@ -6747,7 +6747,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(false);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
processKey(mapper, BTN_TOOL_PEN, 1);
processMove(mapper, 100, 200);
@@ -6765,7 +6765,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Ensure that the device is created as a touchscreen, not touch navigation.
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
@@ -6799,7 +6799,7 @@
mFakePolicy->updateViewport(*viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Hovering inside the physical frame produces events.
processKey(mapper, BTN_TOOL_PEN, 1);
@@ -6905,7 +6905,7 @@
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6940,7 +6940,7 @@
prepareButtons();
prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -7069,7 +7069,7 @@
addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
prepareDisplay(ui::ROTATION_0);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
// orientations of either 90 or 270) this means the display's natural resolution will be
@@ -7121,7 +7121,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(displayRotation);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
const auto& expectedPoints = kMappedCorners.at(displayRotation);
@@ -7159,7 +7159,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.orientation", "ORIENTATION_270");
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
// Ori 270, so width and height swapped
const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
@@ -7195,7 +7195,7 @@
prepareDisplay(displayRotation);
__attribute__((unused)) SingleTouchInputMapper& mapper =
- addMapperAndConfigure<SingleTouchInputMapper>();
+ constructAndAddMapper<SingleTouchInputMapper>();
const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
// MotionRanges use display pixels as their units
@@ -7240,7 +7240,7 @@
prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
- auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+ auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
mStylusState.when = ARBITRARY_TIME;
mStylusState.pressure = 0.f;
@@ -7729,7 +7729,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION);
prepareVirtualKeys();
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -8013,7 +8013,7 @@
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
/*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// X and Y axes
assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
@@ -8037,7 +8037,7 @@
// We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Touch major and minor
assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
@@ -8052,7 +8052,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID);
prepareVirtualKeys();
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -8223,7 +8223,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
prepareVirtualKeys();
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
@@ -8388,7 +8388,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -8438,7 +8438,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL | MINOR);
addConfigurationProperty("touch.size.calibration", "geometric");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -8478,7 +8478,7 @@
addConfigurationProperty("touch.size.scale", "10");
addConfigurationProperty("touch.size.bias", "160");
addConfigurationProperty("touch.size.isSummed", "1");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
// Note: We only provide a single common touch/tool value because the device is assumed
@@ -8528,7 +8528,7 @@
addConfigurationProperty("touch.size.calibration", "area");
addConfigurationProperty("touch.size.scale", "43");
addConfigurationProperty("touch.size.bias", "3");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// These calculations are based on the input device calibration documentation.
int32_t rawX = 100;
@@ -8560,7 +8560,7 @@
prepareAxes(POSITION | PRESSURE);
addConfigurationProperty("touch.pressure.calibration", "amplitude");
addConfigurationProperty("touch.pressure.scale", "0.01");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
InputDeviceInfo info;
mapper.populateDeviceInfo(info);
@@ -8592,7 +8592,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
NotifyKeyArgs keyArgs;
@@ -8835,7 +8835,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
@@ -8892,7 +8892,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9043,7 +9043,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9113,7 +9113,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9194,7 +9194,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
mFakePolicy->addInputPortAssociation(usb2, hdmi2);
@@ -9224,7 +9224,7 @@
TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
@@ -9253,7 +9253,7 @@
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Check source is mouse that would obtain the PointerController.
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
@@ -9273,7 +9273,7 @@
TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
prepareDisplay(ui::ROTATION_0);
process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
@@ -9304,7 +9304,7 @@
/*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
processPosition(mapper, 100, 100);
@@ -9324,7 +9324,7 @@
/*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
processPosition(mapper, 100, 100);
@@ -9346,7 +9346,7 @@
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Finger down
int32_t x = 100, y = 100;
@@ -9389,7 +9389,7 @@
// Setup the first touch screen device.
prepareAxes(POSITION | ID | SLOT);
addConfigurationProperty("touch.deviceType", "touchScreen");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Create the second touch screen device, and enable multi fingers.
const std::string USB2 = "USB2";
@@ -9413,9 +9413,9 @@
String8("touchScreen"));
// Setup the second touch screen device.
- MultiTouchInputMapper& mapper2 =
- device2->addMapper<MultiTouchInputMapper>(SECOND_EVENTHUB_ID,
- mFakePolicy->getReaderConfiguration());
+ device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
+ MultiTouchInputMapper& mapper2 = device2->constructAndAddMapper<
+ MultiTouchInputMapper>(SECOND_EVENTHUB_ID, mFakePolicy->getReaderConfiguration());
std::list<NotifyArgs> unused =
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
/*changes=*/{});
@@ -9480,7 +9480,7 @@
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Unrotated video frame
@@ -9504,7 +9504,7 @@
TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frame
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
NotifyMotionArgs motionArgs;
@@ -9529,7 +9529,7 @@
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frame
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
NotifyMotionArgs motionArgs;
@@ -9560,7 +9560,7 @@
TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frames. There's no rule that they must all have the same dimensions,
// so mix these.
TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
@@ -9583,7 +9583,7 @@
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
addConfigurationProperty("touch.orientationAware", "0");
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// Unrotated video frames. There's no rule that they must all have the same dimensions,
// so mix these.
TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
@@ -9620,7 +9620,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_EQ(mDevice->isEnabled(), false);
@@ -9641,7 +9641,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9686,7 +9686,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9734,7 +9734,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9809,7 +9809,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9907,7 +9907,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9979,7 +9979,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -10036,7 +10036,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// First finger down.
processId(mapper, FIRST_TRACKING_ID);
@@ -10077,7 +10077,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// First finger touches down and releases.
processId(mapper, FIRST_TRACKING_ID);
@@ -10105,7 +10105,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
@@ -10160,7 +10160,7 @@
std::make_shared<FakePointerController>();
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(true);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
processId(mapper, FIRST_TRACKING_ID);
processPressure(mapper, RAW_PRESSURE_MIN);
@@ -10187,7 +10187,7 @@
std::make_shared<FakePointerController>();
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setStylusPointerIconEnabled(false);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
processId(mapper, FIRST_TRACKING_ID);
processPressure(mapper, RAW_PRESSURE_MIN);
@@ -10215,7 +10215,7 @@
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
@@ -10250,7 +10250,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerCapture(true);
mFakePolicy->setPointerController(fakePointerController);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// captured touchpad should be a touchpad source
NotifyDeviceResetArgs resetArgs;
@@ -10398,7 +10398,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// run uncaptured pointer tests - pushes out generic events
// FINGER 0 DOWN
processId(mapper, 3);
@@ -10459,7 +10459,7 @@
mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
mFakePolicy->setPointerCapture(false);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
// uncaptured touchpad should be a pointer device
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
@@ -10483,7 +10483,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
nsecs_t kernelEventTime = ARBITRARY_TIME;
nsecs_t expectedEventTime = ARBITRARY_TIME;
@@ -10570,7 +10570,7 @@
// which is greater than fraction of the diagnal length of the touchpad (349).
// Thus, MaxSwipWidth is 750.
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Two fingers down at once.
@@ -10630,7 +10630,7 @@
// which is greater than fraction of the diagnal length of the touchpad (349).
// Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Two fingers down at once.
@@ -10686,7 +10686,7 @@
*/
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -10781,7 +10781,7 @@
TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
// Place two fingers down.
@@ -10828,7 +10828,7 @@
TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
// Start a stylus gesture.
@@ -10904,7 +10904,7 @@
TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) {
prepareAxes();
- JoystickInputMapper& mapper = addMapperAndConfigure<JoystickInputMapper>();
+ JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>();
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h
index 84ac0fd..b992928 100644
--- a/services/inputflinger/tests/fuzzers/FuzzContainer.h
+++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h
@@ -75,9 +75,12 @@
template <class T, typename... Args>
T& getMapper(Args... args) {
- T& mapper = mFuzzDevice->addMapper<T>(mFdp->ConsumeIntegral<int32_t>(), args...);
+ int32_t eventhubId = mFdp->ConsumeIntegral<int32_t>();
+ // ensure a device entry exists for this eventHubId
+ mFuzzDevice->addEmptyEventHubDevice(eventhubId);
configureDevice();
- return mapper;
+
+ return mFuzzDevice->template constructAndAddMapper<T>(eventhubId, args...);
}
};
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 20f4de1..f6ca9e2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -50,8 +50,6 @@
namespace hal = hardware::graphics::composer::hal;
-ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0;
-
DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(
const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay)
@@ -282,10 +280,6 @@
Rect orientedDisplaySpaceRect) {
mOrientation = orientation;
- if (isPrimary()) {
- sPrimaryDisplayRotationFlags = ui::Transform::toRotationFlags(orientation);
- }
-
// We need to take care of display rotation for globalTransform for case if the panel is not
// installed aligned with device orientation.
const auto transformOrientation = orientation + mPhysicalOrientation;
@@ -326,10 +320,6 @@
return mStagedBrightness;
}
-ui::Transform::RotationFlags DisplayDevice::getPrimaryDisplayRotationFlags() {
- return sPrimaryDisplayRotationFlags;
-}
-
void DisplayDevice::dump(utils::Dumper& dumper) const {
using namespace std::string_view_literals;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 51876e7..dc5f8a8 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -109,8 +109,6 @@
ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; }
ui::Rotation getOrientation() const { return mOrientation; }
- static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags();
-
std::optional<float> getStagedBrightness() const REQUIRES(kMainThreadContext);
ui::Transform::RotationFlags getTransformHint() const;
const ui::Transform& getTransform() const;
@@ -274,8 +272,6 @@
const ui::Rotation mPhysicalOrientation;
ui::Rotation mOrientation = ui::ROTATION_0;
- static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags;
-
// Allow nullopt as initial power mode.
using TracedPowerMode = TracedOrdinal<hardware::graphics::composer::hal::PowerMode>;
std::optional<TracedPowerMode> mPowerMode;
diff --git a/services/surfaceflinger/FrontEnd/DisplayInfo.h b/services/surfaceflinger/FrontEnd/DisplayInfo.h
index 76b36fe..218a64a 100644
--- a/services/surfaceflinger/FrontEnd/DisplayInfo.h
+++ b/services/surfaceflinger/FrontEnd/DisplayInfo.h
@@ -28,7 +28,7 @@
ui::Transform transform;
bool receivesInput;
bool isSecure;
- // TODO(b/238781169) can eliminate once sPrimaryDisplayRotationFlags is removed.
+ // TODO(b/259407931): can eliminate once SurfaceFlinger::sActiveDisplayRotationFlags is removed.
bool isPrimary;
bool isVirtual;
ui::Transform::RotationFlags rotationFlags;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index ce7d37e..985c6f9 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -667,6 +667,7 @@
snapshot.relativeLayerMetadata.mMap.clear();
}
+// TODO (b/259407931): Remove.
uint32_t getPrimaryDisplayRotationFlags(
const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
for (auto& [_, display] : displays) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3371ae2..f12aab7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -254,7 +254,8 @@
mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
}
if (mHadClonedChild) {
- mFlinger->mNumClones--;
+ auto& roots = mFlinger->mLayerMirrorRoots;
+ roots.erase(std::remove(roots.begin(), roots.end(), this), roots.end());
}
if (hasTrustedPresentationListener()) {
mFlinger->mNumTrustedPresentationListeners--;
@@ -1649,8 +1650,8 @@
void Layer::dumpOffscreenDebugInfo(std::string& result) const {
std::string hasBuffer = hasBufferOrSidebandStream() ? " (contains buffer)" : "";
- StringAppendF(&result, "Layer %s%s pid:%d uid:%d\n", getName().c_str(), hasBuffer.c_str(),
- mOwnerPid, mOwnerUid);
+ StringAppendF(&result, "Layer %s%s pid:%d uid:%d%s\n", getName().c_str(), hasBuffer.c_str(),
+ mOwnerPid, mOwnerUid, isHandleAlive() ? " handleAlive" : "");
}
void Layer::onDisconnect() {
@@ -2594,7 +2595,7 @@
mDrawingState.inputInfo = tmpInputInfo;
}
-void Layer::updateMirrorInfo() {
+bool Layer::updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates) {
if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) {
// If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false,
// it means that there is a clone, but the layer it was cloned from has been destroyed. In
@@ -2602,7 +2603,7 @@
// destroyed. The root, this layer, will still be around since the client can continue
// to hold a reference, but no cloned layers will be displayed.
mClonedChild = nullptr;
- return;
+ return true;
}
std::map<sp<Layer>, sp<Layer>> clonedLayersMap;
@@ -2617,6 +2618,13 @@
mClonedChild->updateClonedDrawingState(clonedLayersMap);
mClonedChild->updateClonedChildren(sp<Layer>::fromExisting(this), clonedLayersMap);
mClonedChild->updateClonedRelatives(clonedLayersMap);
+
+ for (Layer* root : cloneRootsPendingUpdates) {
+ if (clonedLayersMap.find(sp<Layer>::fromExisting(root)) != clonedLayersMap.end()) {
+ return false;
+ }
+ }
+ return true;
}
void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
@@ -2764,7 +2772,7 @@
void Layer::setClonedChild(const sp<Layer>& clonedChild) {
mClonedChild = clonedChild;
mHadClonedChild = true;
- mFlinger->mNumClones++;
+ mFlinger->mLayerMirrorRoots.push_back(this);
}
bool Layer::setDropInputMode(gui::DropInputMode mode) {
@@ -2977,7 +2985,7 @@
if (mDrawingState.bufferTransform & ui::Transform::ROT_90) {
std::swap(bufferWidth, bufferHeight);
}
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ uint32_t invTransform = SurfaceFlinger::getActiveDisplayRotationFlags();
if (mDrawingState.transformToDisplayInverse) {
if (invTransform & ui::Transform::ROT_90) {
std::swap(bufferWidth, bufferHeight);
@@ -3077,6 +3085,7 @@
mDrawingState.desiredPresentTime = desiredPresentTime;
mDrawingState.isAutoTimestamp = isAutoTimestamp;
mDrawingState.latchedVsyncId = info.vsyncId;
+ mDrawingState.useVsyncIdForRefreshRateSelection = info.useForRefreshRateSelection;
mDrawingState.modified = true;
if (!buffer) {
resetDrawingStateBufferInfo();
@@ -3139,15 +3148,31 @@
}
void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps) {
+ ATRACE_CALL();
const nsecs_t presentTime = [&] {
- if (!mDrawingState.isAutoTimestamp) return mDrawingState.desiredPresentTime;
+ if (!mDrawingState.isAutoTimestamp) {
+ ATRACE_FORMAT_INSTANT("desiredPresentTime");
+ return mDrawingState.desiredPresentTime;
+ }
- const auto prediction = mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(
- mDrawingState.latchedVsyncId);
- if (prediction.has_value()) return prediction->presentTime;
+ if (mDrawingState.useVsyncIdForRefreshRateSelection) {
+ const auto prediction =
+ mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(
+ mDrawingState.latchedVsyncId);
+ if (prediction.has_value()) {
+ ATRACE_FORMAT_INSTANT("predictedPresentTime");
+ return prediction->presentTime;
+ }
+ }
return static_cast<nsecs_t>(0);
}();
+
+ if (ATRACE_ENABLED() && presentTime > 0) {
+ const auto presentIn = TimePoint::fromNs(presentTime) - TimePoint::now();
+ ATRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str());
+ }
+
mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime,
scheduler::LayerHistory::LayerUpdateType::Buffer);
}
@@ -3287,7 +3312,7 @@
}
if (getTransformToDisplayInverse()) {
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ uint32_t invTransform = SurfaceFlinger::getActiveDisplayRotationFlags();
if (invTransform & ui::Transform::ROT_90) {
std::swap(bufWidth, bufHeight);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2640c92..38590e6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -234,6 +234,7 @@
float desiredHdrSdrRatio = 1.f;
gui::CachingHint cachingHint = gui::CachingHint::Enabled;
int64_t latchedVsyncId = 0;
+ bool useVsyncIdForRefreshRateSelection = false;
};
explicit Layer(const LayerCreationArgs& args);
@@ -651,7 +652,7 @@
gui::WindowInfo::Type getWindowType() const { return mWindowType; }
- void updateMirrorInfo();
+ bool updateMirrorInfo(const std::deque<Layer*>& cloneRootsPendingUpdates);
/*
* doTransaction - process the transaction. This is a good place to figure
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index e713263..f855f27 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -25,8 +25,8 @@
#include <system/window.h>
#include <utils/Log.h>
-#include "DisplayDevice.h"
#include "LayerFE.h"
+#include "SurfaceFlinger.h"
namespace android {
@@ -260,7 +260,7 @@
* the code below applies the primary display's inverse transform to
* the texture transform
*/
- uint32_t transform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ uint32_t transform = SurfaceFlinger::getActiveDisplayRotationFlags();
mat4 tr = inverseOrientation(transform);
/**
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index f6b5afc..d606cff 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -85,7 +85,7 @@
// If layer is offscreen, update mirroring info if it exists
if (mLayer->isRemovedFromCurrentState()) {
mLayer->traverse(LayerVector::StateSet::Drawing,
- [&](Layer* layer) { layer->updateMirrorInfo(); });
+ [&](Layer* layer) { layer->updateMirrorInfo({}); });
mLayer->traverse(LayerVector::StateSet::Drawing,
[&](Layer* layer) { layer->updateCloneBufferInfo(); });
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dfe8c72..b05838b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -356,6 +356,8 @@
PermissionCache::checkPermission(permission, pid, uid);
}
+ui::Transform::RotationFlags SurfaceFlinger::sActiveDisplayRotationFlags = ui::Transform::ROT_0;
+
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
: mFactory(factory),
mPid(getpid()),
@@ -2619,7 +2621,7 @@
refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) || mVisibleRegionsDirty;
- refreshArgs.internalDisplayRotationFlags = DisplayDevice::getPrimaryDisplayRotationFlags();
+ refreshArgs.internalDisplayRotationFlags = getActiveDisplayRotationFlags();
if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
@@ -3563,6 +3565,8 @@
currentState.orientedDisplaySpaceRect);
if (display->getId() == mActiveDisplayId) {
mActiveDisplayTransformHint = display->getTransformHint();
+ sActiveDisplayRotationFlags =
+ ui::Transform::toRotationFlags(display->getOrientation());
}
}
if (currentState.width != drawingState.width ||
@@ -4025,8 +4029,24 @@
}
commitOffscreenLayers();
- if (mNumClones > 0) {
- mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
+ if (mLayerMirrorRoots.size() > 0) {
+ std::deque<Layer*> pendingUpdates;
+ pendingUpdates.insert(pendingUpdates.end(), mLayerMirrorRoots.begin(),
+ mLayerMirrorRoots.end());
+ std::vector<Layer*> needsUpdating;
+ for (Layer* cloneRoot : mLayerMirrorRoots) {
+ pendingUpdates.pop_front();
+ if (cloneRoot->isRemovedFromCurrentState()) {
+ continue;
+ }
+ if (cloneRoot->updateMirrorInfo(pendingUpdates)) {
+ } else {
+ needsUpdating.push_back(cloneRoot);
+ }
+ }
+ for (Layer* cloneRoot : needsUpdating) {
+ cloneRoot->updateMirrorInfo({});
+ }
}
}
@@ -4133,7 +4153,7 @@
mBootStage = BootStage::BOOTANIMATION;
}
- if (mNumClones > 0) {
+ if (mLayerMirrorRoots.size() > 0) {
mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });
}
@@ -4158,8 +4178,8 @@
leakingParentLayerFound = true;
sp<Layer> parent = sp<Layer>::fromExisting(layer);
while (parent) {
- ALOGE("Parent Layer: %s handleIsAlive: %s", parent->getName().c_str(),
- std::to_string(parent->isHandleAlive()).c_str());
+ ALOGE("Parent Layer: %s%s", parent->getName().c_str(),
+ (parent->isHandleAlive() ? "handleAlive" : ""));
parent = parent->getParent();
}
// Sample up to 100 layers
@@ -4174,21 +4194,28 @@
}
});
- ALOGE("Dumping random sampling of on-screen layers: ");
+ int numLayers = 0;
+ mDrawingState.traverse([&](Layer* layer) { numLayers++; });
+
+ ALOGE("Dumping random sampling of on-screen layers total(%u):", numLayers);
mDrawingState.traverse([&](Layer* layer) {
// Aim to dump about 200 layers to avoid totally trashing
// logcat. On the other hand, if there really are 4096 layers
// something has gone totally wrong its probably the most
// useful information in logcat.
if (rand() % 20 == 13) {
- ALOGE("Layer: %s", layer->getName().c_str());
+ ALOGE("Layer: %s%s", layer->getName().c_str(),
+ (layer->isHandleAlive() ? "handleAlive" : ""));
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
});
ALOGE("Dumping random sampling of off-screen layers total(%zu): ",
mOffscreenLayers.size());
for (Layer* offscreenLayer : mOffscreenLayers) {
if (rand() % 20 == 13) {
- ALOGE("Offscreen-layer: %s", offscreenLayer->getName().c_str());
+ ALOGE("Offscreen-layer: %s%s", offscreenLayer->getName().c_str(),
+ (offscreenLayer->isHandleAlive() ? "handleAlive" : ""));
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
}));
@@ -5474,14 +5501,19 @@
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
}
- // Keep uclamp in a separate syscall and set it before changing to RT due to b/190237315.
- // We can merge the syscall later.
- if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
- ALOGW("Couldn't set uclamp.min on display on: %s\n", strerror(errno));
+ if (displayId == mActiveDisplayId) {
+ // TODO(b/281692563): Merge the syscalls. For now, keep uclamp in a separate syscall and
+ // set it before SCHED_FIFO due to b/190237315.
+ if (setSchedAttr(true) != NO_ERROR) {
+ ALOGW("Failed to set uclamp.min after powering on active display: %s",
+ strerror(errno));
+ }
+ if (setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Failed to set SCHED_FIFO after powering on active display: %s",
+ strerror(errno));
+ }
}
- if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
- ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
- }
+
getHwComposer().setPowerMode(displayId, mode);
if (displayId == mActiveDisplayId && mode != hal::PowerMode::DOZE_SUSPEND) {
setHWCVsyncEnabled(displayId,
@@ -5495,15 +5527,21 @@
scheduleComposite(FrameHint::kActive);
} else if (mode == hal::PowerMode::OFF) {
// Turn off the display
- if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
- ALOGW("Couldn't set SCHED_OTHER on display off: %s\n", strerror(errno));
- }
- if (SurfaceFlinger::setSchedAttr(false) != NO_ERROR) {
- ALOGW("Couldn't set uclamp.min on display off: %s\n", strerror(errno));
- }
- if (displayId == mActiveDisplayId && *currentModeOpt != hal::PowerMode::DOZE_SUSPEND) {
- mScheduler->disableHardwareVsync(displayId, true);
- mScheduler->enableSyntheticVsync();
+
+ if (displayId == mActiveDisplayId) {
+ if (setSchedFifo(false) != NO_ERROR) {
+ ALOGW("Failed to set SCHED_OTHER after powering off active display: %s",
+ strerror(errno));
+ }
+ if (setSchedAttr(false) != NO_ERROR) {
+ ALOGW("Failed set uclamp.min after powering off active display: %s",
+ strerror(errno));
+ }
+
+ if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) {
+ mScheduler->disableHardwareVsync(displayId, true);
+ mScheduler->enableSyntheticVsync();
+ }
}
// Make sure HWVsync is disabled before turning off the display
@@ -7943,6 +7981,7 @@
onActiveDisplaySizeChanged(activeDisplay);
mActiveDisplayTransformHint = activeDisplay.getTransformHint();
+ sActiveDisplayRotationFlags = ui::Transform::toRotationFlags(activeDisplay.getOrientation());
// The policy of the new active/pacesetter display may have changed while it was inactive. In
// that case, its preferred mode has not been propagated to HWC (via setDesiredActiveMode). In
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d92ec7a..1182b84 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -296,8 +296,7 @@
// the client can no longer modify this layer directly.
void onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32_t layerId);
- // TODO: Remove atomic if move dtor to main thread CL lands
- std::atomic<uint32_t> mNumClones;
+ std::vector<Layer*> mLayerMirrorRoots;
TransactionCallbackInvoker& getTransactionCallbackInvoker() {
return mTransactionCallbackInvoker;
@@ -332,6 +331,14 @@
const DisplayDevice* getDisplayFromLayerStack(ui::LayerStack)
REQUIRES(mStateLock, kMainThreadContext);
+ // TODO (b/259407931): Remove.
+ // TODO (b/281857977): This should be annotated with REQUIRES(kMainThreadContext), but this
+ // would require thread safety annotations throughout the frontend (in particular Layer and
+ // LayerFE).
+ static ui::Transform::RotationFlags getActiveDisplayRotationFlags() {
+ return sActiveDisplayRotationFlags;
+ }
+
protected:
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -1390,6 +1397,10 @@
std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint;
+ // Must only be accessed on the main thread.
+ // TODO (b/259407931): Remove.
+ static ui::Transform::RotationFlags sActiveDisplayRotationFlags;
+
bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) {
return hasDisplay(
[](const auto& display) { return display.isRefreshRateOverlayEnabled(); });
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 0495678..cf23169 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -91,7 +91,7 @@
// Set uclamp.min setting on all threads, maybe an overkill but we want
// to cover important threads like RenderEngine.
if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
- ALOGW("Couldn't set uclamp.min: %s\n", strerror(errno));
+ ALOGW("Failed to set uclamp.min during boot: %s", strerror(errno));
}
// The binder threadpool we start will inherit sched policy and priority
@@ -155,7 +155,7 @@
startDisplayService(); // dependency on SF getting registered above
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
- ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
+ ALOGW("Failed to set SCHED_FIFO during boot: %s", strerror(errno));
}
// run surface flinger in this thread
diff --git a/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp b/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp
new file mode 100644
index 0000000..7077523
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include "DisplayTransactionTestHelpers.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace {
+
+struct ActiveDisplayRotationFlagsTest : DisplayTransactionTest {
+ static constexpr bool kWithMockScheduler = false;
+ ActiveDisplayRotationFlagsTest() : DisplayTransactionTest(kWithMockScheduler) {}
+
+ void SetUp() override {
+ injectMockScheduler(kInnerDisplayId);
+
+ // Inject inner and outer displays with uninitialized power modes.
+ constexpr bool kInitPowerMode = false;
+ {
+ InnerDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
+ auto injector = InnerDisplayVariant::makeFakeExistingDisplayInjector(this);
+ injector.setPowerMode(std::nullopt);
+ injector.setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector());
+ mInnerDisplay = injector.inject();
+ }
+ {
+ OuterDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
+ auto injector = OuterDisplayVariant::makeFakeExistingDisplayInjector(this);
+ injector.setPowerMode(std::nullopt);
+ mOuterDisplay = injector.inject();
+ }
+
+ mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
+ mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
+
+ // The flags are a static variable, so by modifying them in the test, we
+ // are modifying the real ones used by SurfaceFlinger. Save the original
+ // flags so we can restore them on teardown. This isn't perfect - the
+ // phone may have been rotated during the test, so we're restoring the
+ // wrong flags. But if the phone is rotated, this may also fail the test.
+ mOldRotationFlags = mFlinger.mutableActiveDisplayRotationFlags();
+
+ // Reset to the expected default state.
+ mFlinger.mutableActiveDisplayRotationFlags() = ui::Transform::ROT_0;
+ }
+
+ void TearDown() override { mFlinger.mutableActiveDisplayRotationFlags() = mOldRotationFlags; }
+
+ static inline PhysicalDisplayId kInnerDisplayId = InnerDisplayVariant::DISPLAY_ID::get();
+ static inline PhysicalDisplayId kOuterDisplayId = OuterDisplayVariant::DISPLAY_ID::get();
+
+ sp<DisplayDevice> mInnerDisplay, mOuterDisplay;
+ ui::Transform::RotationFlags mOldRotationFlags;
+};
+
+TEST_F(ActiveDisplayRotationFlagsTest, defaultRotation) {
+ ASSERT_EQ(ui::Transform::ROT_0, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotate90) {
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_90;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_90, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotate90_inactive) {
+ auto displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_90;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_0, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotateBoth_innerActive) {
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_180;
+
+ displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_270;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_180, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotateBoth_outerActive) {
+ mFlinger.mutableActiveDisplayId() = kOuterDisplayId;
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_180;
+
+ displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_270;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_270, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, onActiveDisplayChanged) {
+ auto displayToken = mInnerDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_180;
+
+ displayToken = mOuterDisplay->getDisplayToken().promote();
+ mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+ mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+ ui::ROTATION_270;
+
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ ASSERT_EQ(ui::Transform::ROT_180, SurfaceFlinger::getActiveDisplayRotationFlags());
+
+ mFlinger.onActiveDisplayChanged(mInnerDisplay.get(), *mOuterDisplay);
+ ASSERT_EQ(ui::Transform::ROT_270, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 55705ca..70f8a83 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -70,6 +70,7 @@
":libsurfaceflinger_mock_sources",
":libsurfaceflinger_sources",
"libsurfaceflinger_unittest_main.cpp",
+ "ActiveDisplayRotationFlagsTest.cpp",
"CompositionTest.cpp",
"DisplayIdGeneratorTest.cpp",
"DisplayTransactionTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index a189c00..8e18a3f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -600,6 +600,10 @@
auto& mutablePrimaryHwcDisplayId() { return getHwComposer().mPrimaryHwcDisplayId; }
auto& mutableActiveDisplayId() { return mFlinger->mActiveDisplayId; }
+ auto& mutableActiveDisplayRotationFlags() {
+ return SurfaceFlinger::sActiveDisplayRotationFlags;
+ }
+
auto fromHandle(const sp<IBinder>& handle) { return LayerHandle::getLayer(handle); }
~TestableSurfaceFlinger() {