diff options
| -rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 6 | ||||
| -rw-r--r-- | cmds/installd/otapreopt_script.sh | 6 | ||||
| -rw-r--r-- | data/etc/Android.bp | 6 | ||||
| -rw-r--r-- | include/input/Input.h | 20 | ||||
| -rw-r--r-- | libs/binder/Parcel.cpp | 4 | ||||
| -rw-r--r-- | libs/binder/tests/parcel_fuzzer/binder.cpp | 8 | ||||
| -rw-r--r-- | libs/input/Input.cpp | 12 | ||||
| -rw-r--r-- | libs/input/tests/InputEvent_test.cpp | 18 | ||||
| -rw-r--r-- | libs/input/tests/InputPublisherAndConsumer_test.cpp | 6 | ||||
| -rw-r--r-- | libs/math/include/math/mat4.h | 8 | ||||
| -rw-r--r-- | libs/renderengine/skia/SkiaVkRenderEngine.cpp | 7 | ||||
| -rw-r--r-- | services/inputflinger/PointerChoreographer.cpp | 139 | ||||
| -rw-r--r-- | services/inputflinger/PointerChoreographer.h | 8 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 21 | ||||
| -rw-r--r-- | services/inputflinger/include/PointerChoreographerPolicyInterface.h | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/Scheduler/RefreshRateSelector.cpp | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp | 148 |
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, |