Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ba7aa93 authored by Christine Franks's avatar Christine Franks Committed by Android (Google) Code Review
Browse files

Merge "Add API to hide cursor for virtual mice"

parents 17f18817 27a354bf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2761,6 +2761,7 @@ package android.companion.virtual {
    method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
    method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.LaunchCallback);
    method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
    method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
  }
  public final class VirtualDeviceParams implements android.os.Parcelable {
+3 −0
Original line number Diff line number Diff line
@@ -77,4 +77,7 @@ interface IVirtualDevice {
    void launchPendingIntent(
            int displayId, in PendingIntent pendingIntent, in ResultReceiver resultReceiver);
    PointF getCursorPosition(IBinder token);

    /** Sets whether to show or hide the cursor while this virtual device is active. */
    void setShowPointerIcon(boolean showPointerIcon);
}
+16 −0
Original line number Diff line number Diff line
@@ -337,6 +337,22 @@ public final class VirtualDeviceManager {
            }
        }

        /**
         * Sets the visibility of the pointer icon for this VirtualDevice's associated displays.
         *
         * @param showPointerIcon True if the pointer should be shown; false otherwise. The default
         *                        visibility is true.
         */
        @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
        @NonNull
        public void setShowPointerIcon(boolean showPointerIcon) {
            try {
                mVirtualDevice.setShowPointerIcon(showPointerIcon);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        /**
         * Returns the display flags that should be added to a particular virtual display.
         * Additional device-level flags from {@link
+10 −1
Original line number Diff line number Diff line
@@ -87,6 +87,12 @@ public abstract class InputManagerInternal {
     */
    public abstract void setVirtualMousePointerDisplayId(int pointerDisplayId);

    /**
     * Gets the display id that the MouseCursorController is being forced to target. Returns
     * {@link android.view.Display#INVALID_DISPLAY} if there is no override
     */
    public abstract int getVirtualMousePointerDisplayId();

    /** Gets the current position of the mouse cursor. */
    public abstract PointF getCursorPosition();

@@ -94,7 +100,7 @@ public abstract class InputManagerInternal {
     * Sets the pointer acceleration.
     * See {@code frameworks/native/include/input/VelocityControl.h#VelocityControlParameters}.
     */
    public abstract void setPointerAcceleration(float acceleration);
    public abstract void setPointerAcceleration(float acceleration, int displayId);

    /**
     * Sets the eligibility of windows on a given display for pointer capture. If a display is
@@ -103,6 +109,9 @@ public abstract class InputManagerInternal {
     */
    public abstract void setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible);

    /** Sets the visibility of the cursor. */
    public abstract void setPointerIconVisible(boolean visible, int displayId);

    /** Registers the {@link LidSwitchCallback} to begin receiving notifications. */
    public abstract void registerLidSwitchCallback(@NonNull LidSwitchCallback callbacks);

+51 −41
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.hardware.input.VirtualMouseRelativeEvent;
import android.hardware.input.VirtualMouseScrollEvent;
import android.hardware.input.VirtualTouchEvent;
import android.os.IBinder;
import android.os.IInputConstants;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;
@@ -43,6 +42,7 @@ import com.android.server.LocalServices;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

@@ -76,13 +76,6 @@ class InputController {
    private final DisplayManagerInternal mDisplayManagerInternal;
    private final InputManagerInternal mInputManagerInternal;

    /**
     * Because the pointer is a singleton, it can only be targeted at one display at a time. Because
     * multiple mice could be concurrently registered, mice that are associated with a different
     * display than the current target display should not be allowed to affect the current target.
     */
    @VisibleForTesting int mActivePointerDisplayId;

    InputController(@NonNull Object lock) {
        this(lock, new NativeWrapper());
    }
@@ -91,18 +84,21 @@ class InputController {
    InputController(@NonNull Object lock, @NonNull NativeWrapper nativeWrapper) {
        mLock = lock;
        mNativeWrapper = nativeWrapper;
        mActivePointerDisplayId = Display.INVALID_DISPLAY;
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
    }

    void close() {
        synchronized (mLock) {
            for (InputDeviceDescriptor inputDeviceDescriptor : mInputDeviceDescriptors.values()) {
                mNativeWrapper.closeUinput(inputDeviceDescriptor.getFileDescriptor());
            final Iterator<Map.Entry<IBinder, InputDeviceDescriptor>> iterator =
                    mInputDeviceDescriptors.entrySet().iterator();
            if (iterator.hasNext()) {
                final Map.Entry<IBinder, InputDeviceDescriptor> entry = iterator.next();
                final IBinder token = entry.getKey();
                final InputDeviceDescriptor inputDeviceDescriptor = entry.getValue();
                iterator.remove();
                closeInputDeviceDescriptorLocked(token, inputDeviceDescriptor);
            }
            mInputDeviceDescriptors.clear();
            resetMouseValuesLocked();
        }
    }

@@ -150,8 +146,6 @@ class InputController {
                    new InputDeviceDescriptor(fd, binderDeathRecipient,
                            InputDeviceDescriptor.TYPE_MOUSE, displayId, phys));
            mInputManagerInternal.setVirtualMousePointerDisplayId(displayId);
            mInputManagerInternal.setPointerAcceleration(1);
            mActivePointerDisplayId = displayId;
        }
        try {
            deviceToken.linkToDeath(binderDeathRecipient, /* flags= */ 0);
@@ -197,23 +191,44 @@ class InputController {
                throw new IllegalArgumentException(
                        "Could not unregister input device for given token");
            }
            closeInputDeviceDescriptorLocked(token, inputDeviceDescriptor);
        }
    }

    @GuardedBy("mLock")
    private void closeInputDeviceDescriptorLocked(IBinder token,
            InputDeviceDescriptor inputDeviceDescriptor) {
        token.unlinkToDeath(inputDeviceDescriptor.getDeathRecipient(), /* flags= */ 0);
        mNativeWrapper.closeUinput(inputDeviceDescriptor.getFileDescriptor());
        InputManager.getInstance().removeUniqueIdAssociation(inputDeviceDescriptor.getPhys());

        // Reset values to the default if all virtual mice are unregistered, or set display
            // id if there's another mouse (choose the most recent).
        // id if there's another mouse (choose the most recent). The inputDeviceDescriptor must be
        // removed from the mInputDeviceDescriptors instance variable prior to this point.
        if (inputDeviceDescriptor.isMouse()) {
                updateMouseValuesLocked();
            if (mInputManagerInternal.getVirtualMousePointerDisplayId()
                    == inputDeviceDescriptor.getDisplayId()) {
                updateActivePointerDisplayIdLocked();
            }
        }
    }

    void setShowPointerIcon(boolean visible, int displayId) {
        mInputManagerInternal.setPointerIconVisible(visible, displayId);
    }

    void setPointerAcceleration(float pointerAcceleration, int displayId) {
        mInputManagerInternal.setPointerAcceleration(pointerAcceleration, displayId);
    }

    void setDisplayEligibilityForPointerCapture(boolean isEligible, int displayId) {
        mInputManagerInternal.setDisplayEligibilityForPointerCapture(displayId, isEligible);
    }

    @GuardedBy("mLock")
    private void updateMouseValuesLocked() {
    private void updateActivePointerDisplayIdLocked() {
        InputDeviceDescriptor mostRecentlyCreatedMouse = null;
        for (InputDeviceDescriptor otherInputDeviceDescriptor :
                mInputDeviceDescriptors.values()) {
        for (InputDeviceDescriptor otherInputDeviceDescriptor : mInputDeviceDescriptors.values()) {
            if (otherInputDeviceDescriptor.isMouse()) {
                if (mostRecentlyCreatedMouse == null
                        || (otherInputDeviceDescriptor.getCreationOrderNumber()
@@ -225,18 +240,10 @@ class InputController {
        if (mostRecentlyCreatedMouse != null) {
            mInputManagerInternal.setVirtualMousePointerDisplayId(
                    mostRecentlyCreatedMouse.getDisplayId());
            mActivePointerDisplayId = mostRecentlyCreatedMouse.getDisplayId();
        } else {
            // All mice have been unregistered; reset all values.
            resetMouseValuesLocked();
        }
    }

    private void resetMouseValuesLocked() {
            // All mice have been unregistered
            mInputManagerInternal.setVirtualMousePointerDisplayId(Display.INVALID_DISPLAY);
        mInputManagerInternal.setPointerAcceleration(
                IInputConstants.DEFAULT_POINTER_ACCELERATION);
        mActivePointerDisplayId = Display.INVALID_DISPLAY;
        }
    }

    private static String createPhys(@PhysType String type) {
@@ -269,7 +276,8 @@ class InputController {
                throw new IllegalArgumentException(
                        "Could not send button event to input device for given token");
            }
            if (inputDeviceDescriptor.getDisplayId() != mActivePointerDisplayId) {
            if (inputDeviceDescriptor.getDisplayId()
                    != mInputManagerInternal.getVirtualMousePointerDisplayId()) {
                throw new IllegalStateException(
                        "Display id associated with this mouse is not currently targetable");
            }
@@ -300,7 +308,8 @@ class InputController {
                throw new IllegalArgumentException(
                        "Could not send relative event to input device for given token");
            }
            if (inputDeviceDescriptor.getDisplayId() != mActivePointerDisplayId) {
            if (inputDeviceDescriptor.getDisplayId()
                    != mInputManagerInternal.getVirtualMousePointerDisplayId()) {
                throw new IllegalStateException(
                        "Display id associated with this mouse is not currently targetable");
            }
@@ -317,7 +326,8 @@ class InputController {
                throw new IllegalArgumentException(
                        "Could not send scroll event to input device for given token");
            }
            if (inputDeviceDescriptor.getDisplayId() != mActivePointerDisplayId) {
            if (inputDeviceDescriptor.getDisplayId()
                    != mInputManagerInternal.getVirtualMousePointerDisplayId()) {
                throw new IllegalStateException(
                        "Display id associated with this mouse is not currently targetable");
            }
@@ -334,7 +344,8 @@ class InputController {
                throw new IllegalArgumentException(
                        "Could not get cursor position for input device for given token");
            }
            if (inputDeviceDescriptor.getDisplayId() != mActivePointerDisplayId) {
            if (inputDeviceDescriptor.getDisplayId()
                    != mInputManagerInternal.getVirtualMousePointerDisplayId()) {
                throw new IllegalStateException(
                        "Display id associated with this mouse is not currently targetable");
            }
@@ -354,7 +365,6 @@ class InputController {
                fout.println("          type: " + inputDeviceDescriptor.getType());
                fout.println("          phys: " + inputDeviceDescriptor.getPhys());
            }
            fout.println("      Active mouse display id: " + mActivePointerDisplayId);
        }
    }

Loading