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

Commit a761b905 authored by Vladimir Komsiyski's avatar Vladimir Komsiyski
Browse files

Clean up VDM's InputController

Rename it back, remove dead code and add a listener to clean up the
internal devices state when an input device is closed outside of VDM

Fix: 419493538
Test: presubmit
Flag: EXEMPT refactor
Change-Id: I990acc763e375803dc1f9e01d31bed27a9585774
parent 48558838
Loading
Loading
Loading
Loading
+49 −68
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package com.android.server.companion.virtual;

import android.annotation.NonNull;
import android.content.AttributionSource;
import android.graphics.PointF;
import android.content.Context;
import android.hardware.input.IVirtualInputDevice;
import android.hardware.input.InputManager;
import android.hardware.input.VirtualDpadConfig;
@@ -28,11 +28,9 @@ import android.hardware.input.VirtualNavigationTouchpadConfig;
import android.hardware.input.VirtualRotaryEncoderConfig;
import android.hardware.input.VirtualStylusConfig;
import android.hardware.input.VirtualTouchscreenConfig;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.WindowManager;

import com.android.internal.annotations.GuardedBy;
@@ -46,9 +44,7 @@ import java.util.Iterator;
import java.util.Map;

/** Controls virtual input devices, including device lifecycle and event dispatch. */
class VirtualInputController {

    private static final String TAG = "InputController";
class InputController {

    private final Object mLock = new Object();

@@ -60,17 +56,20 @@ class VirtualInputController {
    private final InputManager mInputManager;
    private final WindowManager mWindowManager;
    private final AttributionSource mAttributionSource;
    private final InputDeviceListener mInputDeviceListener = new InputDeviceListener();

    @VisibleForTesting
    VirtualInputController(@NonNull InputManager inputManager, @NonNull WindowManager windowManager,
            AttributionSource attributionSource) {
    InputController(@NonNull Context context, AttributionSource attributionSource) {
        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
        mInputManager = inputManager;
        mWindowManager = windowManager;
        mInputManager = context.getSystemService(InputManager.class);
        mWindowManager = context.getSystemService(WindowManager.class);
        mAttributionSource = attributionSource;
        mInputManager.registerInputDeviceListener(
                mInputDeviceListener, context.getMainThreadHandler());
    }

    void close() {
        mInputManager.unregisterInputDeviceListener(mInputDeviceListener);
        synchronized (mLock) {
            final Iterator<Map.Entry<IBinder, IVirtualInputDevice>> iterator =
                    mInputDevices.entrySet().iterator();
@@ -146,36 +145,6 @@ class VirtualInputController {
        return device;
    }

    void unregisterInputDevice(@NonNull IBinder token) {
        synchronized (mLock) {
            final IVirtualInputDevice inputDeviceDescriptor = mInputDevices.remove(token);
            if (inputDeviceDescriptor == null) {
                Slog.w(TAG, "Could not unregister input device for given token.");
            } else {
                Binder.withCleanCallingIdentity(() ->
                        mInputManagerInternal.closeVirtualInputDevice(token));
            }
        }
    }

    /**
     * @return the device id for a given token (identifiying a device)
     */
    int getInputDeviceId(IBinder token) {
        synchronized (mLock) {
            final IVirtualInputDevice inputDeviceDescriptor = mInputDevices.get(token);
            if (inputDeviceDescriptor == null) {
                throw new IllegalArgumentException("Could not get device id for given token");
            }
            try {
                return inputDeviceDescriptor.getInputDeviceId();
            } catch (RemoteException e) {
                e.rethrowFromSystemServer();
            }
        }
        return -1;
    }

    void setShowPointerIcon(boolean visible, int displayId) {
        mInputManagerInternal.setPointerIconVisible(visible, displayId);
    }
@@ -192,25 +161,6 @@ class VirtualInputController {
        mWindowManager.setDisplayImePolicy(displayId, policy);
    }

    public PointF getCursorPosition(@NonNull IBinder token) {
        synchronized (mLock) {
            final IVirtualInputDevice inputDeviceDescriptor = mInputDevices.get(token);
            if (inputDeviceDescriptor == null) {
                throw new IllegalArgumentException(
                        "Could not get cursor position for input device for given token");
            }
            return Binder.withCleanCallingIdentity(() -> {
                try {
                    return mInputManager.getCursorPosition(
                            inputDeviceDescriptor.getAssociatedDisplayId());
                } catch (RemoteException e) {
                    e.rethrowFromSystemServer();
                    return null;
                }
            });
        }
    }

    public void dump(@NonNull PrintWriter fout) {
        final String prefix = "    ";
        fout.println(prefix + "InputController: ");
@@ -232,19 +182,50 @@ class VirtualInputController {
        }
    }

    @VisibleForTesting
    void removeDeviceForTesting(IBinder token) {
        synchronized (mLock) {
            mInputDevices.remove(token);
        }
    }

    boolean isInputDevicePresent(int inputDeviceId) {
        synchronized (mLock) {
            return getTokenForInputDeviceIdLocked(inputDeviceId) != null;
        }
    }

    @GuardedBy("mLock")
    private IBinder getTokenForInputDeviceIdLocked(int inputDeviceId) {
        try {
            for (int i = 0; i < mInputDevices.size(); ++i) {
                IVirtualInputDevice device = mInputDevices.valueAt(i);
                if (device.getInputDeviceId() == inputDeviceId) {
                        return true;
                    return mInputDevices.keyAt(i);
                }
            }
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        return null;
    }

    private class InputDeviceListener implements InputManager.InputDeviceListener {

        @Override
        public void onInputDeviceAdded(int deviceId) {}

        @Override
        public void onInputDeviceChanged(int deviceId) {}

        @Override
        public void onInputDeviceRemoved(int deviceId) {
            synchronized (mLock) {
                IBinder token = getTokenForInputDeviceIdLocked(deviceId);
                if (token != null) {
                    mInputDevices.remove(token);
                }
            }
        }
        return false;
    }
}
+3 −6
Original line number Diff line number Diff line
@@ -77,7 +77,6 @@ import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.IVirtualInputDevice;
import android.hardware.input.InputManager;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyboardConfig;
import android.hardware.input.VirtualMouseConfig;
@@ -195,7 +194,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    private final int mDeviceId;
    @Nullable
    private final String mPersistentDeviceId;
    private final VirtualInputController mInputController;
    private final InputController mInputController;
    private final SensorController mSensorController;
    private final CameraAccessController mCameraAccessController;
    @Nullable private final ViewConfigurationController mViewConfigurationController;
@@ -425,7 +424,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            IBinder token,
            AttributionSource attributionSource,
            int deviceId,
            VirtualInputController inputController,
            InputController inputController,
            CameraAccessController cameraAccessController,
            PendingTrampolineCallback pendingTrampolineCallback,
            IVirtualDeviceActivityListener activityListener,
@@ -479,9 +478,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        mBaseVirtualDisplayFlags = flags;

        if (inputController == null) {
            mInputController = new VirtualInputController(
                    context.getSystemService(InputManager.class),
                    context.getSystemService(WindowManager.class), mAttributionSource);
            mInputController = new InputController(mContext, mAttributionSource);
        } else {
            mInputController = inputController;
        }
+4 −10
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ import android.hardware.display.IDisplayManager;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.IVirtualInputDevice;
import android.hardware.input.InputManager;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyboardConfig;
import android.hardware.input.VirtualMouseConfig;
@@ -222,7 +221,7 @@ public class VirtualDeviceManagerServiceTest {

    private Context mContext;
    private VirtualDeviceImpl mDeviceImpl;
    private VirtualInputController mInputController;
    private InputController mInputController;
    private SensorController mSensorController;
    private CameraAccessController mCameraAccessController;
    private AssociationInfo mAssociationInfo;
@@ -322,9 +321,6 @@ public class VirtualDeviceManagerServiceTest {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        LocalServices.removeServiceForTest(DisplayManagerInternal.class);
        LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);

        when(mInputManagerInternalMock.createVirtualTouchscreen(any(), any()))
                .thenReturn(mIVirtualInputDevice);
        when(mInputManagerInternalMock.createVirtualKeyboard(any(), any()))
@@ -350,15 +346,13 @@ public class VirtualDeviceManagerServiceTest {
        doNothing().when(mContext).sendBroadcastAsUser(any(), any());
        when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
                mDevicePolicyManagerMock);
        when(mContext.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mWindowManager);

        PowerManager powerManager = new PowerManager(mContext, mIPowerManagerMock,
                mIThermalServiceMock,
                new Handler(TestableLooper.get(this).getLooper()));
        when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
        mInputController = new VirtualInputController(
                InstrumentationRegistry.getInstrumentation().getTargetContext().getSystemService(
                        InputManager.class), mWindowManager,
                AttributionSource.myAttributionSource());
        mInputController = new InputController(mContext, AttributionSource.myAttributionSource());
        mCameraAccessController =
                new CameraAccessController(mContext, mLocalService, mCameraAccessBlockedCallback);

@@ -642,7 +636,7 @@ public class VirtualDeviceManagerServiceTest {
        mInputController.addDeviceForTesting(BINDER, mIVirtualInputDevice);
        assertThat(mLocalService.isInputDeviceOwnedByVirtualDevice(INPUT_DEVICE_ID)).isTrue();

        mInputController.unregisterInputDevice(BINDER);
        mInputController.removeDeviceForTesting(BINDER);
        assertThat(mLocalService.isInputDeviceOwnedByVirtualDevice(INPUT_DEVICE_ID)).isFalse();
    }