diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index fedf58d7c6d07..e748c692743d4 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -262,19 +262,34 @@ void PointerController::reloadPointerResources() { } void PointerController::setDisplayViewport(const DisplayViewport& viewport) { - std::scoped_lock lock(getLock()); + struct PointerDisplayChangeArgs { + int32_t displayId; + float x, y; + }; + std::optional pointerDisplayChanged; - bool getAdditionalMouseResources = false; - if (mLocked.presentation == PointerController::Presentation::POINTER || - mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) { - getAdditionalMouseResources = true; - } - mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources); - if (viewport.displayId != mLocked.pointerDisplayId) { - float xPos, yPos; - mCursorController.getPosition(&xPos, &yPos); - mContext.getPolicy()->onPointerDisplayIdChanged(viewport.displayId, xPos, yPos); - mLocked.pointerDisplayId = viewport.displayId; + { // acquire lock + std::scoped_lock lock(getLock()); + + bool getAdditionalMouseResources = false; + if (mLocked.presentation == PointerController::Presentation::POINTER || + mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) { + getAdditionalMouseResources = true; + } + mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources); + if (viewport.displayId != mLocked.pointerDisplayId) { + float xPos, yPos; + mCursorController.getPosition(&xPos, &yPos); + mLocked.pointerDisplayId = viewport.displayId; + pointerDisplayChanged = {viewport.displayId, xPos, yPos}; + } + } // release lock + + if (pointerDisplayChanged) { + // Notify the policy without holding the pointer controller lock. + mContext.getPolicy()->onPointerDisplayIdChanged(pointerDisplayChanged->displayId, + pointerDisplayChanged->x, + pointerDisplayChanged->y); } } diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java index 4d03e44bfd19e..7e990c6c2f4a3 100644 --- a/services/core/java/com/android/server/input/InputManagerInternal.java +++ b/services/core/java/com/android/server/input/InputManagerInternal.java @@ -96,7 +96,11 @@ public abstract class InputManagerInternal { */ public abstract int getVirtualMousePointerDisplayId(); - /** Gets the current position of the mouse cursor. */ + /** + * Gets the current position of the mouse cursor. + * + * Returns NaN-s as the coordinates if the cursor is not available. + */ public abstract PointF getCursorPosition(); /** diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index b2b22a0a083ad..efc4f11168bbe 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -2863,9 +2863,6 @@ public class InputManagerService extends IInputManager.Stub int getPointerDisplayId(); - /** Gets the x and y coordinates of the cursor's current position. */ - PointF getCursorPosition(); - /** * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event * occurred on a window that did not have focus. @@ -3189,7 +3186,11 @@ public class InputManagerService extends IInputManager.Stub @Override public PointF getCursorPosition() { - return mWindowManagerCallbacks.getCursorPosition(); + final float[] p = mNative.getMouseCursorPosition(); + if (p == null || p.length != 2) { + throw new IllegalStateException("Failed to get mouse cursor position"); + } + return new PointF(p[0], p[1]); } @Override diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java index 22226e88f15f2..5395302d1c320 100644 --- a/services/core/java/com/android/server/input/NativeInputManagerService.java +++ b/services/core/java/com/android/server/input/NativeInputManagerService.java @@ -224,6 +224,16 @@ interface NativeInputManagerService { /** Set whether stylus button reporting through motion events should be enabled. */ void setStylusButtonMotionEventsEnabled(boolean enabled); + /** + * Get the current position of the mouse cursor. + * + * If the mouse cursor is not currently shown, the coordinate values will be NaN-s. + * + * NOTE: This will grab the PointerController's lock, so we must be careful about calling this + * from the InputReader or Display threads, which may result in a deadlock. + */ + float[] getMouseCursorPosition(); + /** The native implementation of InputManagerService methods. */ class NativeImpl implements NativeInputManagerService { /** Pointer to native input manager service object, used by native code. */ @@ -465,5 +475,8 @@ interface NativeInputManagerService { @Override public native void setStylusButtonMotionEventsEnabled(boolean enabled); + + @Override + public native float[] getMouseCursorPosition(); } } diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java index 1e9d451b1a69d..0a47fe09dbd99 100644 --- a/services/core/java/com/android/server/wm/InputManagerCallback.java +++ b/services/core/java/com/android/server/wm/InputManagerCallback.java @@ -25,7 +25,6 @@ import static com.android.server.wm.WindowManagerService.H.ON_POINTER_DOWN_OUTSI import android.annotation.NonNull; import android.annotation.Nullable; -import android.graphics.PointF; import android.os.Debug; import android.os.IBinder; import android.util.Slog; @@ -220,11 +219,6 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal } } - @Override - public PointF getCursorPosition() { - return mService.getLatestMousePosition(); - } - @Override public void onPointerDownOutsideFocus(IBinder touchedToken) { mService.mH.obtainMessage(ON_POINTER_DOWN_OUTSIDE_FOCUS, touchedToken).sendToTarget(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 45cdacd503a8a..42d23e755b216 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -186,7 +186,6 @@ import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.Point; -import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region; import android.hardware.configstore.V1_0.OptionalBool; @@ -7361,14 +7360,6 @@ public class WindowManagerService extends IWindowManager.Stub .setPointerIconType(PointerIcon.TYPE_DEFAULT); } } - - PointF getLatestMousePosition() { - synchronized (mMousePositionTracker) { - return new PointF(mMousePositionTracker.mLatestMouseX, - mMousePositionTracker.mLatestMouseY); - } - } - void setMousePointerDisplayId(int displayId) { mMousePositionTracker.setPointerDisplayId(displayId); } diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index b4e2fb6ca3e3f..dc43949984f01 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -308,6 +308,7 @@ public: void setMotionClassifierEnabled(bool enabled); std::optional getBluetoothAddress(int32_t deviceId); void setStylusButtonMotionEventsEnabled(bool enabled); + std::array getMouseCursorPosition(); /* --- InputReaderPolicyInterface implementation --- */ @@ -1655,6 +1656,16 @@ bool NativeInputManager::isPerDisplayTouchModeEnabled() { return static_cast(enabled); } +std::array NativeInputManager::getMouseCursorPosition() { + AutoMutex _l(mLock); + const auto pc = mLocked.pointerController.lock(); + if (!pc) return {{std::nanf(""), std::nanf("")}}; + + std::array p{}; + pc->getPosition(&p[0], &p[1]); + return p; +} + // ---------------------------------------------------------------------------- static NativeInputManager* getNativeInputManager(JNIEnv* env, jobject clazz) { @@ -2547,6 +2558,14 @@ static void nativeSetStylusButtonMotionEventsEnabled(JNIEnv* env, jobject native im->setStylusButtonMotionEventsEnabled(enabled); } +static jfloatArray nativeGetMouseCursorPosition(JNIEnv* env, jobject nativeImplObj) { + NativeInputManager* im = getNativeInputManager(env, nativeImplObj); + const std::array p = im->getMouseCursorPosition(); + jfloatArray outArr = env->NewFloatArray(2); + env->SetFloatArrayRegion(outArr, 0, p.size(), p.data()); + return outArr; +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gInputManagerMethods[] = { @@ -2640,6 +2659,7 @@ static const JNINativeMethod gInputManagerMethods[] = { {"getBluetoothAddress", "(I)Ljava/lang/String;", (void*)nativeGetBluetoothAddress}, {"setStylusButtonMotionEventsEnabled", "(Z)V", (void*)nativeSetStylusButtonMotionEventsEnabled}, + {"getMouseCursorPosition", "()[F", (void*)nativeGetMouseCursorPosition}, }; #define FIND_CLASS(var, className) \