summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/dumpstate/dumpstate.cpp6
-rw-r--r--cmds/installd/otapreopt_script.sh6
-rw-r--r--data/etc/Android.bp6
-rw-r--r--include/input/Input.h20
-rw-r--r--libs/binder/Parcel.cpp4
-rw-r--r--libs/binder/tests/parcel_fuzzer/binder.cpp8
-rw-r--r--libs/input/Input.cpp12
-rw-r--r--libs/input/tests/InputEvent_test.cpp18
-rw-r--r--libs/input/tests/InputPublisherAndConsumer_test.cpp6
-rw-r--r--libs/math/include/math/mat4.h8
-rw-r--r--libs/renderengine/skia/SkiaVkRenderEngine.cpp7
-rw-r--r--services/inputflinger/PointerChoreographer.cpp139
-rw-r--r--services/inputflinger/PointerChoreographer.h8
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp21
-rw-r--r--services/inputflinger/include/PointerChoreographerPolicyInterface.h6
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateSelector.cpp6
-rw-r--r--services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp148
17 files changed, 343 insertions, 86 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 8d37aac0cb..826a8dbc2c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -3280,6 +3280,12 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
// duration is logged into MYLOG instead.
PrintHeader();
+ bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
+ if (options_->use_predumped_ui_data && !system_trace_exists) {
+ MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
+ options_->use_predumped_ui_data = false;
+ }
+
std::future<std::string> snapshot_system_trace;
bool is_dumpstate_restricted =
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index 28bd7932a2..ae7d8e04d4 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -50,6 +50,12 @@ else
exit 1
fi
+if pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
+ # Handled by Pre-reboot Dexopt.
+ exit 0
+fi
+echo "Pre-reboot Dexopt not enabled. Fall back to otapreopt."
+
if [ "$(/system/bin/otapreopt_chroot --version)" != 2 ]; then
# We require an updated chroot wrapper that reads dexopt commands from stdin.
# Even if we kept compat with the old binary, the OTA preopt wouldn't work due
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 8b2842a3ae..eedf1410a1 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -353,6 +353,12 @@ prebuilt_etc {
}
prebuilt_etc {
+ name: "android.software.contextualsearch.prebuilt.xml",
+ src: "android.software.contextualsearch.xml",
+ defaults: ["frameworks_native_data_etc_defaults"],
+}
+
+prebuilt_etc {
name: "android.software.device_id_attestation.prebuilt.xml",
src: "android.software.device_id_attestation.xml",
defaults: ["frameworks_native_data_etc_defaults"],
diff --git a/include/input/Input.h b/include/input/Input.h
index 374254fc84..ddc376809e 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -662,10 +662,6 @@ public:
inline void setActionButton(int32_t button) { mActionButton = button; }
- inline float getXOffset() const { return mTransform.tx(); }
-
- inline float getYOffset() const { return mTransform.ty(); }
-
inline const ui::Transform& getTransform() const { return mTransform; }
std::optional<ui::Rotation> getSurfaceRotation() const;
@@ -880,6 +876,22 @@ public:
void offsetLocation(float xOffset, float yOffset);
+ /**
+ * Get the X offset of this motion event relative to the origin of the raw coordinate space.
+ *
+ * In practice, this is the delta that was added to the raw screen coordinates (i.e. in logical
+ * display space) to adjust for the absolute position of the containing windows and views.
+ */
+ float getRawXOffset() const;
+
+ /**
+ * Get the Y offset of this motion event relative to the origin of the raw coordinate space.
+ *
+ * In practice, this is the delta that was added to the raw screen coordinates (i.e. in logical
+ * display space) to adjust for the absolute position of the containing windows and views.
+ */
+ float getRawYOffset() const;
+
void scale(float globalScaleFactor);
// Set 3x3 perspective matrix transformation.
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2dd310e9ca..35cea8132d 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2976,14 +2976,14 @@ status_t Parcel::restartWrite(size_t desired)
return continueWrite(desired);
}
+ releaseObjects();
+
uint8_t* data = reallocZeroFree(mData, mDataCapacity, desired, mDeallocZero);
if (!data && desired > mDataCapacity) {
mError = NO_MEMORY;
return NO_MEMORY;
}
- releaseObjects();
-
if (data || desired == 0) {
LOG_ALLOC("Parcel %p: restart from %zu to %zu capacity", this, mDataCapacity, desired);
if (mDataCapacity > desired) {
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 5c280f4b2c..e378b864f7 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -115,6 +115,14 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
p.setDataPosition(pos);
FUZZ_LOG() << "setDataPosition done";
},
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
+ size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024);
+ std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(len);
+ FUZZ_LOG() << "about to setData: " <<(bytes.data() ? HexString(bytes.data(), bytes.size()) : "null");
+ // TODO: allow all read and write operations
+ (*const_cast<::android::Parcel*>(&p)).setData(bytes.data(), bytes.size());
+ FUZZ_LOG() << "setData done";
+ },
PARCEL_READ_NO_STATUS(size_t, allowFds),
PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors),
PARCEL_READ_NO_STATUS(std::vector<android::sp<android::IBinder>>, debugReadAllStrongBinders),
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index d58fb42f05..ff9d9a94c9 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -751,6 +751,18 @@ void MotionEvent::offsetLocation(float xOffset, float yOffset) {
mTransform.set(currXOffset + xOffset, currYOffset + yOffset);
}
+float MotionEvent::getRawXOffset() const {
+ // This is equivalent to the x-coordinate of the point that the origin of the raw coordinate
+ // space maps to.
+ return (mTransform * mRawTransform.inverse()).tx();
+}
+
+float MotionEvent::getRawYOffset() const {
+ // This is equivalent to the y-coordinate of the point that the origin of the raw coordinate
+ // space maps to.
+ return (mTransform * mRawTransform.inverse()).ty();
+}
+
void MotionEvent::scale(float globalScaleFactor) {
mTransform.set(mTransform.tx() * globalScaleFactor, mTransform.ty() * globalScaleFactor);
mRawTransform.set(mRawTransform.tx() * globalScaleFactor,
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 540766d66c..0df06b790e 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -371,8 +371,10 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
ASSERT_EQ(MotionClassification::NONE, event->getClassification());
EXPECT_EQ(mTransform, event->getTransform());
- ASSERT_EQ(X_OFFSET, event->getXOffset());
- ASSERT_EQ(Y_OFFSET, event->getYOffset());
+ ASSERT_NEAR((-RAW_X_OFFSET / RAW_X_SCALE) * X_SCALE + X_OFFSET, event->getRawXOffset(),
+ EPSILON);
+ ASSERT_NEAR((-RAW_Y_OFFSET / RAW_Y_SCALE) * Y_SCALE + Y_OFFSET, event->getRawYOffset(),
+ EPSILON);
ASSERT_EQ(2.0f, event->getXPrecision());
ASSERT_EQ(2.1f, event->getYPrecision());
ASSERT_EQ(ARBITRARY_DOWN_TIME, event->getDownTime());
@@ -709,22 +711,26 @@ TEST_F(MotionEventTest, SplitPointerMove) {
TEST_F(MotionEventTest, OffsetLocation) {
MotionEvent event;
initializeEventWithHistory(&event);
+ const float xOffset = event.getRawXOffset();
+ const float yOffset = event.getRawYOffset();
event.offsetLocation(5.0f, -2.0f);
- ASSERT_EQ(X_OFFSET + 5.0f, event.getXOffset());
- ASSERT_EQ(Y_OFFSET - 2.0f, event.getYOffset());
+ ASSERT_EQ(xOffset + 5.0f, event.getRawXOffset());
+ ASSERT_EQ(yOffset - 2.0f, event.getRawYOffset());
}
TEST_F(MotionEventTest, Scale) {
MotionEvent event;
initializeEventWithHistory(&event);
const float unscaledOrientation = event.getOrientation(0);
+ const float unscaledXOffset = event.getRawXOffset();
+ const float unscaledYOffset = event.getRawYOffset();
event.scale(2.0f);
- ASSERT_EQ(X_OFFSET * 2, event.getXOffset());
- ASSERT_EQ(Y_OFFSET * 2, event.getYOffset());
+ ASSERT_EQ(unscaledXOffset * 2, event.getRawXOffset());
+ ASSERT_EQ(unscaledYOffset * 2, event.getRawYOffset());
ASSERT_NEAR((RAW_X_OFFSET + 210 * RAW_X_SCALE) * 2, event.getRawX(0), EPSILON);
ASSERT_NEAR((RAW_Y_OFFSET + 211 * RAW_Y_SCALE) * 2, event.getRawY(0), EPSILON);
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 35430207f9..30f9a42519 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -135,8 +135,10 @@ void verifyArgsEqualToEvent(const PublishMotionArgs& args, const MotionEvent& mo
EXPECT_EQ(args.buttonState, motionEvent.getButtonState());
EXPECT_EQ(args.classification, motionEvent.getClassification());
EXPECT_EQ(args.transform, motionEvent.getTransform());
- EXPECT_EQ(args.xOffset, motionEvent.getXOffset());
- EXPECT_EQ(args.yOffset, motionEvent.getYOffset());
+ EXPECT_NEAR((-args.rawXOffset / args.rawXScale) * args.xScale + args.xOffset,
+ motionEvent.getRawXOffset(), EPSILON);
+ EXPECT_NEAR((-args.rawYOffset / args.rawYScale) * args.yScale + args.yOffset,
+ motionEvent.getRawYOffset(), EPSILON);
EXPECT_EQ(args.xPrecision, motionEvent.getXPrecision());
EXPECT_EQ(args.yPrecision, motionEvent.getYPrecision());
EXPECT_NEAR(args.xCursorPosition, motionEvent.getRawXCursorPosition(), EPSILON);
diff --git a/libs/math/include/math/mat4.h b/libs/math/include/math/mat4.h
index 6119ba7f68..c630d972b2 100644
--- a/libs/math/include/math/mat4.h
+++ b/libs/math/include/math/mat4.h
@@ -34,6 +34,14 @@
#define CONSTEXPR
#endif
+#ifdef _WIN32
+// windows.h contains obsolete defines of 'near' and 'far' for systems using
+// legacy 16 bit pointers. Undefine them to avoid conflicting with the usage of
+// 'near' and 'far' in this file.
+#undef near
+#undef far
+#endif
+
namespace android {
// -------------------------------------------------------------------------------------
namespace details {
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index eb7a9d5bfa..feb76a1ccd 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -25,6 +25,7 @@
#include <GrContextOptions.h>
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>
+#include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
#include <include/gpu/ganesh/vk/GrVkDirectContext.h>
#include <android-base/stringprintf.h>
@@ -766,8 +767,7 @@ void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd
base::unique_fd fenceDup(dupedFd);
VkSemaphore waitSemaphore =
getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
- GrBackendSemaphore beSemaphore;
- beSemaphore.initVulkan(waitSemaphore);
+ GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore);
grContext->wait(1, &beSemaphore, true /* delete after wait */);
}
@@ -775,8 +775,7 @@ base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
VulkanInterface& vi = getVulkanInterface(isProtected());
VkSemaphore semaphore = vi.createExportableSemaphore();
- GrBackendSemaphore backendSemaphore;
- backendSemaphore.initVulkan(semaphore);
+ GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);
GrFlushInfo flushInfo;
DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 3ac4285304..9db3574389 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -26,6 +26,7 @@
namespace android {
namespace {
+
bool isFromMouse(const NotifyMotionArgs& args) {
return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
args.pointerProperties[0].toolType == ToolType::MOUSE;
@@ -44,13 +45,23 @@ bool isHoverAction(int32_t action) {
bool isStylusHoverEvent(const NotifyMotionArgs& args) {
return isStylusEvent(args.source, args.pointerProperties) && isHoverAction(args.action);
}
+
+inline void notifyPointerDisplayChange(std::optional<std::tuple<int32_t, FloatPoint>> change,
+ PointerChoreographerPolicyInterface& policy) {
+ if (!change) {
+ return;
+ }
+ const auto& [displayId, cursorPosition] = *change;
+ policy.notifyPointerDisplayIdChanged(displayId, cursorPosition);
+}
+
} // namespace
// --- PointerChoreographer ---
PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
PointerChoreographerPolicyInterface& policy)
- : mTouchControllerConstructor([this]() REQUIRES(mLock) {
+ : mTouchControllerConstructor([this]() {
return mPolicy.createPointerController(
PointerControllerInterface::ControllerType::TOUCH);
}),
@@ -62,10 +73,16 @@ PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
mStylusPointerIconEnabled(false) {}
void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
- std::scoped_lock _l(mLock);
+ PointerDisplayChange pointerDisplayChange;
+
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+
+ mInputDeviceInfos = args.inputDeviceInfos;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
- mInputDeviceInfos = args.inputDeviceInfos;
- updatePointerControllersLocked();
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
mNextListener.notify(args);
}
@@ -104,7 +121,7 @@ NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotio
<< args.dump();
}
- auto [displayId, pc] = getDisplayIdAndMouseControllerLocked(args.displayId);
+ auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
@@ -124,7 +141,7 @@ NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotio
}
NotifyMotionArgs PointerChoreographer::processTouchpadEventLocked(const NotifyMotionArgs& args) {
- auto [displayId, pc] = getDisplayIdAndMouseControllerLocked(args.displayId);
+ auto [displayId, pc] = ensureMouseControllerLocked(args.displayId);
NotifyMotionArgs newArgs(args);
newArgs.displayId = displayId;
@@ -308,17 +325,13 @@ int32_t PointerChoreographer::getTargetMouseDisplayLocked(int32_t associatedDisp
return associatedDisplayId == ADISPLAY_ID_NONE ? mDefaultMouseDisplayId : associatedDisplayId;
}
-std::pair<int32_t, PointerControllerInterface&>
-PointerChoreographer::getDisplayIdAndMouseControllerLocked(int32_t associatedDisplayId) {
+std::pair<int32_t, PointerControllerInterface&> PointerChoreographer::ensureMouseControllerLocked(
+ int32_t associatedDisplayId) {
const int32_t displayId = getTargetMouseDisplayLocked(associatedDisplayId);
- // Get the mouse pointer controller for the display, or create one if it doesn't exist.
- auto [it, emplaced] =
- mMousePointersByDisplay.try_emplace(displayId,
- getMouseControllerConstructor(displayId));
- if (emplaced) {
- notifyPointerDisplayIdChangedLocked();
- }
+ auto it = mMousePointersByDisplay.find(displayId);
+ LOG_ALWAYS_FATAL_IF(it == mMousePointersByDisplay.end(),
+ "There is no mouse controller created for display %d", displayId);
return {displayId, *it->second};
}
@@ -333,7 +346,7 @@ bool PointerChoreographer::canUnfadeOnDisplay(int32_t displayId) {
return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
}
-void PointerChoreographer::updatePointerControllersLocked() {
+PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
std::set<int32_t /*displayId*/> mouseDisplaysToKeep;
std::set<DeviceId> touchDevicesToKeep;
std::set<DeviceId> stylusDevicesToKeep;
@@ -382,11 +395,12 @@ void PointerChoreographer::updatePointerControllersLocked() {
mInputDeviceInfos.end();
});
- // Notify the policy if there's a change on the pointer display ID.
- notifyPointerDisplayIdChangedLocked();
+ // Check if we need to notify the policy if there's a change on the pointer display ID.
+ return calculatePointerDisplayChangeToNotify();
}
-void PointerChoreographer::notifyPointerDisplayIdChangedLocked() {
+PointerChoreographer::PointerDisplayChange
+PointerChoreographer::calculatePointerDisplayChangeToNotify() {
int32_t displayIdToNotify = ADISPLAY_ID_NONE;
FloatPoint cursorPosition = {0, 0};
if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
@@ -398,38 +412,49 @@ void PointerChoreographer::notifyPointerDisplayIdChangedLocked() {
displayIdToNotify = pointerController->getDisplayId();
cursorPosition = pointerController->getPosition();
}
-
if (mNotifiedPointerDisplayId == displayIdToNotify) {
- return;
+ return {};
}
- mPolicy.notifyPointerDisplayIdChanged(displayIdToNotify, cursorPosition);
mNotifiedPointerDisplayId = displayIdToNotify;
+ return {{displayIdToNotify, cursorPosition}};
}
void PointerChoreographer::setDefaultMouseDisplayId(int32_t displayId) {
- std::scoped_lock _l(mLock);
+ PointerDisplayChange pointerDisplayChange;
- mDefaultMouseDisplayId = displayId;
- updatePointerControllersLocked();
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+
+ mDefaultMouseDisplayId = displayId;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
- std::scoped_lock _l(mLock);
- for (const auto& viewport : viewports) {
- const int32_t displayId = viewport.displayId;
- if (const auto it = mMousePointersByDisplay.find(displayId);
- it != mMousePointersByDisplay.end()) {
- it->second->setDisplayViewport(viewport);
- }
- for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
- const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
- if (info && info->getAssociatedDisplayId() == displayId) {
- stylusPointerController->setDisplayViewport(viewport);
+ PointerDisplayChange pointerDisplayChange;
+
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ for (const auto& viewport : viewports) {
+ const int32_t displayId = viewport.displayId;
+ if (const auto it = mMousePointersByDisplay.find(displayId);
+ it != mMousePointersByDisplay.end()) {
+ it->second->setDisplayViewport(viewport);
+ }
+ for (const auto& [deviceId, stylusPointerController] : mStylusPointersByDevice) {
+ const InputDeviceInfo* info = findInputDeviceLocked(deviceId);
+ if (info && info->getAssociatedDisplayId() == displayId) {
+ stylusPointerController->setDisplayViewport(viewport);
+ }
}
}
- }
- mViewports = viewports;
- notifyPointerDisplayIdChangedLocked();
+ mViewports = viewports;
+ pointerDisplayChange = calculatePointerDisplayChangeToNotify();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
@@ -453,21 +478,33 @@ FloatPoint PointerChoreographer::getMouseCursorPosition(int32_t displayId) {
}
void PointerChoreographer::setShowTouchesEnabled(bool enabled) {
- std::scoped_lock _l(mLock);
- if (mShowTouchesEnabled == enabled) {
- return;
- }
- mShowTouchesEnabled = enabled;
- updatePointerControllersLocked();
+ PointerDisplayChange pointerDisplayChange;
+
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ if (mShowTouchesEnabled == enabled) {
+ return;
+ }
+ mShowTouchesEnabled = enabled;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
void PointerChoreographer::setStylusPointerIconEnabled(bool enabled) {
- std::scoped_lock _l(mLock);
- if (mStylusPointerIconEnabled == enabled) {
- return;
- }
- mStylusPointerIconEnabled = enabled;
- updatePointerControllersLocked();
+ PointerDisplayChange pointerDisplayChange;
+
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ if (mStylusPointerIconEnabled == enabled) {
+ return;
+ }
+ mStylusPointerIconEnabled = enabled;
+ pointerDisplayChange = updatePointerControllersLocked();
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
bool PointerChoreographer::setPointerIcon(
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index 6aab3aade0..db1488b546 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -109,11 +109,13 @@ public:
void dump(std::string& dump) override;
private:
- void updatePointerControllersLocked() REQUIRES(mLock);
- void notifyPointerDisplayIdChangedLocked() REQUIRES(mLock);
+ using PointerDisplayChange =
+ std::optional<std::tuple<int32_t /*displayId*/, FloatPoint /*cursorPosition*/>>;
+ [[nodiscard]] PointerDisplayChange updatePointerControllersLocked() REQUIRES(mLock);
+ [[nodiscard]] PointerDisplayChange calculatePointerDisplayChangeToNotify() REQUIRES(mLock);
const DisplayViewport* findViewportByIdLocked(int32_t displayId) const REQUIRES(mLock);
int32_t getTargetMouseDisplayLocked(int32_t associatedDisplayId) const REQUIRES(mLock);
- std::pair<int32_t, PointerControllerInterface&> getDisplayIdAndMouseControllerLocked(
+ std::pair<int32_t /*displayId*/, PointerControllerInterface&> ensureMouseControllerLocked(
int32_t associatedDisplayId) REQUIRES(mLock);
InputDeviceInfo* findInputDeviceLocked(DeviceId deviceId) REQUIRES(mLock);
bool canUnfadeOnDisplay(int32_t displayId) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 057b996a23..10e0a36f8a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -676,13 +676,13 @@ std::optional<nsecs_t> getDownTime(const EventEntry& eventEntry) {
std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState,
const TouchState& newTouchState,
const MotionEntry& entry) {
- std::vector<TouchedWindow> out;
const int32_t maskedAction = MotionEvent::getActionMasked(entry.action);
if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
// ACTION_SCROLL events should not affect the hovering pointer dispatch
return {};
}
+ std::vector<TouchedWindow> out;
// We should consider all hovering pointers here. But for now, just use the first one
const PointerProperties& pointer = entry.pointerProperties[0];
@@ -2651,19 +2651,14 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
{
std::vector<TouchedWindow> hoveringWindows =
getHoveringWindowsLocked(oldState, tempTouchState, entry);
+ // Hardcode to single hovering pointer for now.
+ std::bitset<MAX_POINTER_ID + 1> pointerIds;
+ pointerIds.set(entry.pointerProperties[0].id);
for (const TouchedWindow& touchedWindow : hoveringWindows) {
- std::optional<InputTarget> target =
- createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
- touchedWindow.targetFlags,
- touchedWindow.getDownTimeInTarget(entry.deviceId));
- if (!target) {
- continue;
- }
- // Hardcode to single hovering pointer for now.
- std::bitset<MAX_POINTER_ID + 1> pointerIds;
- pointerIds.set(entry.pointerProperties[0].id);
- target->addPointers(pointerIds, touchedWindow.windowHandle->getInfo()->transform);
- targets.push_back(*target);
+ addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
+ touchedWindow.targetFlags, pointerIds,
+ touchedWindow.getDownTimeInTarget(entry.deviceId),
+ targets);
}
}
diff --git a/services/inputflinger/include/PointerChoreographerPolicyInterface.h b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
index 8b47b555e5..462aedc539 100644
--- a/services/inputflinger/include/PointerChoreographerPolicyInterface.h
+++ b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
@@ -25,6 +25,9 @@ namespace android {
*
* This is the interface that PointerChoreographer uses to talk to Window Manager and other
* system components.
+ *
+ * NOTE: In general, the PointerChoreographer must not interact with the policy while
+ * holding any locks.
*/
class PointerChoreographerPolicyInterface {
public:
@@ -37,6 +40,9 @@ public:
* for and runnable on the host, the PointerController implementation must be in a separate
* library, libinputservice, that has the additional dependencies. The PointerController
* will be mocked when testing PointerChoreographer.
+ *
+ * Since this is a factory method used to work around dependencies, it will not interact with
+ * other input components and may be called with the PointerChoreographer lock held.
*/
virtual std::shared_ptr<PointerControllerInterface> createPointerController(
PointerControllerInterface::ControllerType type) = 0;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index 3e1d8b5bf3..ad59f1a574 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -834,13 +834,16 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
const bool touchBoostForExplicitExact = [&] {
if (supportsAppFrameRateOverrideByContent()) {
// Enable touch boost if there are other layers besides exact
- return explicitExact + noVoteLayers != layers.size();
+ return explicitExact + noVoteLayers + explicitGteLayers != layers.size();
} else {
// Enable touch boost if there are no exact layers
return explicitExact == 0;
}
}();
+ const bool touchBoostForCategory =
+ explicitCategoryVoteLayers + noVoteLayers + explicitGteLayers != layers.size();
+
const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
using fps_approx_ops::operator<;
@@ -851,6 +854,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
const bool hasInteraction = signals.touch || interactiveLayers > 0;
if (hasInteraction && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
+ touchBoostForCategory &&
scores.front().frameRateMode.fps < touchRefreshRates.front().frameRateMode.fps) {
ALOGV("Touch Boost");
ATRACE_FORMAT_INSTANT("%s (Touch Boost [late])",
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index d5b6852c1a..fe0e3d11ae 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -1793,6 +1793,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_HighH
lr1.frameRateCategory = FrameRateCategory::HighHint;
lr1.name = "ExplicitCategory HighHint";
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr2.frameRateCategory = FrameRateCategory::Default;
lr2.desiredRefreshRate = 30_Hz;
lr2.name = "30Hz ExplicitExactOrMultiple";
actualRankedFrameRates = selector.getRankedFrameRates(layers);
@@ -1819,6 +1820,153 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_HighH
EXPECT_EQ(kModeId30, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
}
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz Heuristic";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
+ // Gets touch boost
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = LayerVoteType::Min;
+ lr2.name = "Min";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
+ // Gets touch boost
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = LayerVoteType::Max;
+ lr2.name = "Max";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
+ // Gets touch boost
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+}
+
+TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_TouchBoost) {
+ auto selector = createSelector(makeModes(kMode24, kMode30, kMode60, kMode120), kModeId60);
+
+ std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}};
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::NoVote;
+ lr2.name = "NoVote";
+ auto actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode60, 60_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+
+ // No touch boost, for example a game that uses setFrameRate(30, default compatibility).
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitDefault";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode60, 60_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitCategory;
+ lr2.frameRateCategory = FrameRateCategory::HighHint;
+ lr2.name = "ExplicitCategory HighHint";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitCategory;
+ lr2.frameRateCategory = FrameRateCategory::Low;
+ lr2.name = "ExplicitCategory Low";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode60, 60_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr2.frameRateCategory = FrameRateCategory::Default;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitExactOrMultiple";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitExact;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitExact";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ if (selector.supportsAppFrameRateOverrideByContent()) {
+ EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz,
+ actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+ } else {
+ EXPECT_FRAME_RATE_MODE(kMode30, 30_Hz,
+ actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+ }
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::Min;
+ lr2.name = "Min";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::Max;
+ lr2.name = "Max";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "30Hz Heuristic";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitGte;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitGte";
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kMode60, 60_Hz, actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
}
TEST_P(RefreshRateSelectorTest,