Loading services/core/java/com/android/server/input/InputManagerService.java +7 −3 Original line number Diff line number Diff line Loading @@ -597,9 +597,6 @@ public class InputManagerService extends IInputManager.Stub mKeyRemapper.systemRunning(); mPointerIconCache.systemRunning(); mKeyboardGlyphManager.systemRunning(); if (mTouchpadDebugViewController != null) { mTouchpadDebugViewController.systemRunning(); } } private void reloadDeviceAliases() { Loading Loading @@ -3340,6 +3337,13 @@ public class InputManagerService extends IInputManager.Stub } } void updateTouchpadVisualizerEnabled(boolean enabled) { mNative.setShouldNotifyTouchpadHardwareState(enabled); if (mTouchpadDebugViewController != null) { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(enabled); } } void updatePointerLocationEnabled(boolean enabled) { mWindowManagerCallbacks.notifyPointerLocationChanged(enabled); } Loading services/core/java/com/android/server/input/InputSettingsObserver.java +1 −1 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ class InputSettingsObserver extends ContentObserver { } private void updateTouchpadHardwareStateNotificationsEnabled() { mNative.setShouldNotifyTouchpadHardwareState(InputSettings.useTouchpadVisualizer(mContext)); mService.updateTouchpadVisualizerEnabled(InputSettings.useTouchpadVisualizer(mContext)); } private void updateTouchpadRightClickZoneEnabled() { Loading services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java +45 −35 Original line number Diff line number Diff line Loading @@ -18,12 +18,10 @@ package com.android.server.input.debug; import android.annotation.Nullable; import android.content.Context; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; import android.util.Slog; import android.view.Display; import android.view.InputDevice; import android.view.WindowManager; Loading @@ -32,7 +30,7 @@ import com.android.server.input.TouchpadHardwareProperties; import java.util.Objects; public class TouchpadDebugViewController { public class TouchpadDebugViewController implements InputManager.InputDeviceListener { private static final String TAG = "TouchpadDebugView"; Loading @@ -43,28 +41,16 @@ public class TouchpadDebugViewController { private TouchpadDebugView mTouchpadDebugView; private final InputManagerService mInputManagerService; private boolean mTouchpadVisualizerEnabled = false; public TouchpadDebugViewController(Context context, Looper looper, InputManagerService inputManagerService) { final DisplayManager displayManager = Objects.requireNonNull( context.getSystemService(DisplayManager.class)); final Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); mContext = context.createDisplayContext(defaultDisplay); //TODO(b/363979581): Handle multi-display scenarios mContext = context; mHandler = new Handler(looper); mInputManagerService = inputManagerService; } public void systemRunning() { final InputManager inputManager = Objects.requireNonNull( mContext.getSystemService(InputManager.class)); inputManager.registerInputDeviceListener(mInputDeviceListener, mHandler); for (int deviceId : inputManager.getInputDeviceIds()) { mInputDeviceListener.onInputDeviceAdded(deviceId); } } private final InputManager.InputDeviceListener mInputDeviceListener = new InputManager.InputDeviceListener() { @Override public void onInputDeviceAdded(int deviceId) { final InputManager inputManager = Objects.requireNonNull( Loading @@ -72,7 +58,8 @@ public class TouchpadDebugViewController { InputDevice inputDevice = inputManager.getInputDevice(deviceId); if (Objects.requireNonNull(inputDevice).supportsSource( InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)) { InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE) && mTouchpadVisualizerEnabled) { showDebugView(deviceId); } } Loading @@ -85,7 +72,30 @@ public class TouchpadDebugViewController { @Override public void onInputDeviceChanged(int deviceId) { } }; /** * Notify the controller that the touchpad visualizer setting value has changed. * This must be called from the same looper thread as {@code mHandler}. */ public void updateTouchpadVisualizerEnabled(boolean touchpadVisualizerEnabled) { if (mTouchpadVisualizerEnabled == touchpadVisualizerEnabled) { return; } mTouchpadVisualizerEnabled = touchpadVisualizerEnabled; final InputManager inputManager = Objects.requireNonNull( mContext.getSystemService(InputManager.class)); if (touchpadVisualizerEnabled) { inputManager.registerInputDeviceListener(this, mHandler); for (int deviceId : inputManager.getInputDeviceIds()) { onInputDeviceAdded(deviceId); } } else { if (mTouchpadDebugView != null) { hideDebugView(mTouchpadDebugView.getTouchpadId()); } inputManager.unregisterInputDeviceListener(this); } } private void showDebugView(int touchpadId) { if (mTouchpadDebugView != null) { Loading tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java 0 → 100644 +215 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.input.debug; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.graphics.Rect; import android.hardware.input.InputManager; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.InputDevice; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowMetrics; import androidx.test.platform.app.InstrumentationRegistry; import com.android.server.input.InputManagerService; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; /** * Build/Install/Run: * atest TouchpadDebugViewControllerTests */ @RunWith(AndroidTestingRunner.class) @RunWithLooper public class TouchpadDebugViewControllerTests { private static final int DEVICE_ID = 1000; private static final String TAG = "TouchpadDebugViewController"; @Rule public final MockitoRule mockito = MockitoJUnit.rule(); private Context mContext; private TouchpadDebugViewController mTouchpadDebugViewController; @Mock private InputManager mInputManagerMock; @Mock private InputManagerService mInputManagerServiceMock; @Mock private WindowManager mWindowManagerMock; private TestableLooper mTestableLooper; @Before public void setup() throws Exception { mContext = InstrumentationRegistry.getInstrumentation().getContext(); TestableContext mTestableContext = new TestableContext(mContext); mTestableContext.addMockSystemService(WindowManager.class, mWindowManagerMock); Rect bounds = new Rect(0, 0, 2560, 1600); WindowMetrics metrics = new WindowMetrics(bounds, new WindowInsets(bounds), 1.0f); when(mWindowManagerMock.getCurrentWindowMetrics()).thenReturn(metrics); unMockTouchpad(); mTestableLooper = TestableLooper.get(this); mTestableContext.addMockSystemService(InputManager.class, mInputManagerMock); mTouchpadDebugViewController = new TouchpadDebugViewController(mTestableContext, mTestableLooper.getLooper(), mInputManagerServiceMock); } private InputDevice createTouchpadInputDevice(int id) { return new InputDevice.Builder() .setId(id) .setSources(InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE) .setName("Test Device " + id) .build(); } private void mockTouchpad() { when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID}); when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn( createTouchpadInputDevice(DEVICE_ID)); } private void unMockTouchpad() { when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{}); when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(null); } @Test public void touchpadConnectedWhileSettingDisabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void settingEnabledWhileNoTouchpadConnected() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingEnabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingEnabledThenDisabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, times(1)).removeView(any()); } @Test public void touchpadConnectedWhileSettingDisabledThenEnabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingDisabledThenTouchpadDisconnected() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); unMockTouchpad(); mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingEnabledThenTouchpadDisconnectedThenSettingDisabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); unMockTouchpad(); mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, times(1)).removeView(any()); mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, times(1)).removeView(any()); } } Loading
services/core/java/com/android/server/input/InputManagerService.java +7 −3 Original line number Diff line number Diff line Loading @@ -597,9 +597,6 @@ public class InputManagerService extends IInputManager.Stub mKeyRemapper.systemRunning(); mPointerIconCache.systemRunning(); mKeyboardGlyphManager.systemRunning(); if (mTouchpadDebugViewController != null) { mTouchpadDebugViewController.systemRunning(); } } private void reloadDeviceAliases() { Loading Loading @@ -3340,6 +3337,13 @@ public class InputManagerService extends IInputManager.Stub } } void updateTouchpadVisualizerEnabled(boolean enabled) { mNative.setShouldNotifyTouchpadHardwareState(enabled); if (mTouchpadDebugViewController != null) { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(enabled); } } void updatePointerLocationEnabled(boolean enabled) { mWindowManagerCallbacks.notifyPointerLocationChanged(enabled); } Loading
services/core/java/com/android/server/input/InputSettingsObserver.java +1 −1 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ class InputSettingsObserver extends ContentObserver { } private void updateTouchpadHardwareStateNotificationsEnabled() { mNative.setShouldNotifyTouchpadHardwareState(InputSettings.useTouchpadVisualizer(mContext)); mService.updateTouchpadVisualizerEnabled(InputSettings.useTouchpadVisualizer(mContext)); } private void updateTouchpadRightClickZoneEnabled() { Loading
services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java +45 −35 Original line number Diff line number Diff line Loading @@ -18,12 +18,10 @@ package com.android.server.input.debug; import android.annotation.Nullable; import android.content.Context; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; import android.util.Slog; import android.view.Display; import android.view.InputDevice; import android.view.WindowManager; Loading @@ -32,7 +30,7 @@ import com.android.server.input.TouchpadHardwareProperties; import java.util.Objects; public class TouchpadDebugViewController { public class TouchpadDebugViewController implements InputManager.InputDeviceListener { private static final String TAG = "TouchpadDebugView"; Loading @@ -43,28 +41,16 @@ public class TouchpadDebugViewController { private TouchpadDebugView mTouchpadDebugView; private final InputManagerService mInputManagerService; private boolean mTouchpadVisualizerEnabled = false; public TouchpadDebugViewController(Context context, Looper looper, InputManagerService inputManagerService) { final DisplayManager displayManager = Objects.requireNonNull( context.getSystemService(DisplayManager.class)); final Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); mContext = context.createDisplayContext(defaultDisplay); //TODO(b/363979581): Handle multi-display scenarios mContext = context; mHandler = new Handler(looper); mInputManagerService = inputManagerService; } public void systemRunning() { final InputManager inputManager = Objects.requireNonNull( mContext.getSystemService(InputManager.class)); inputManager.registerInputDeviceListener(mInputDeviceListener, mHandler); for (int deviceId : inputManager.getInputDeviceIds()) { mInputDeviceListener.onInputDeviceAdded(deviceId); } } private final InputManager.InputDeviceListener mInputDeviceListener = new InputManager.InputDeviceListener() { @Override public void onInputDeviceAdded(int deviceId) { final InputManager inputManager = Objects.requireNonNull( Loading @@ -72,7 +58,8 @@ public class TouchpadDebugViewController { InputDevice inputDevice = inputManager.getInputDevice(deviceId); if (Objects.requireNonNull(inputDevice).supportsSource( InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)) { InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE) && mTouchpadVisualizerEnabled) { showDebugView(deviceId); } } Loading @@ -85,7 +72,30 @@ public class TouchpadDebugViewController { @Override public void onInputDeviceChanged(int deviceId) { } }; /** * Notify the controller that the touchpad visualizer setting value has changed. * This must be called from the same looper thread as {@code mHandler}. */ public void updateTouchpadVisualizerEnabled(boolean touchpadVisualizerEnabled) { if (mTouchpadVisualizerEnabled == touchpadVisualizerEnabled) { return; } mTouchpadVisualizerEnabled = touchpadVisualizerEnabled; final InputManager inputManager = Objects.requireNonNull( mContext.getSystemService(InputManager.class)); if (touchpadVisualizerEnabled) { inputManager.registerInputDeviceListener(this, mHandler); for (int deviceId : inputManager.getInputDeviceIds()) { onInputDeviceAdded(deviceId); } } else { if (mTouchpadDebugView != null) { hideDebugView(mTouchpadDebugView.getTouchpadId()); } inputManager.unregisterInputDeviceListener(this); } } private void showDebugView(int touchpadId) { if (mTouchpadDebugView != null) { Loading
tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java 0 → 100644 +215 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.input.debug; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.graphics.Rect; import android.hardware.input.InputManager; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.InputDevice; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowMetrics; import androidx.test.platform.app.InstrumentationRegistry; import com.android.server.input.InputManagerService; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; /** * Build/Install/Run: * atest TouchpadDebugViewControllerTests */ @RunWith(AndroidTestingRunner.class) @RunWithLooper public class TouchpadDebugViewControllerTests { private static final int DEVICE_ID = 1000; private static final String TAG = "TouchpadDebugViewController"; @Rule public final MockitoRule mockito = MockitoJUnit.rule(); private Context mContext; private TouchpadDebugViewController mTouchpadDebugViewController; @Mock private InputManager mInputManagerMock; @Mock private InputManagerService mInputManagerServiceMock; @Mock private WindowManager mWindowManagerMock; private TestableLooper mTestableLooper; @Before public void setup() throws Exception { mContext = InstrumentationRegistry.getInstrumentation().getContext(); TestableContext mTestableContext = new TestableContext(mContext); mTestableContext.addMockSystemService(WindowManager.class, mWindowManagerMock); Rect bounds = new Rect(0, 0, 2560, 1600); WindowMetrics metrics = new WindowMetrics(bounds, new WindowInsets(bounds), 1.0f); when(mWindowManagerMock.getCurrentWindowMetrics()).thenReturn(metrics); unMockTouchpad(); mTestableLooper = TestableLooper.get(this); mTestableContext.addMockSystemService(InputManager.class, mInputManagerMock); mTouchpadDebugViewController = new TouchpadDebugViewController(mTestableContext, mTestableLooper.getLooper(), mInputManagerServiceMock); } private InputDevice createTouchpadInputDevice(int id) { return new InputDevice.Builder() .setId(id) .setSources(InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE) .setName("Test Device " + id) .build(); } private void mockTouchpad() { when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID}); when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn( createTouchpadInputDevice(DEVICE_ID)); } private void unMockTouchpad() { when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{}); when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(null); } @Test public void touchpadConnectedWhileSettingDisabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void settingEnabledWhileNoTouchpadConnected() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingEnabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingEnabledThenDisabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, times(1)).removeView(any()); } @Test public void touchpadConnectedWhileSettingDisabledThenEnabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingDisabledThenTouchpadDisconnected() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); unMockTouchpad(); mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID); verify(mWindowManagerMock, never()).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); } @Test public void touchpadConnectedWhileSettingEnabledThenTouchpadDisconnectedThenSettingDisabled() throws Exception { mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true); mockTouchpad(); mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, never()).removeView(any()); unMockTouchpad(); mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, times(1)).removeView(any()); mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false); verify(mWindowManagerMock, times(1)).addView(any(), any()); verify(mWindowManagerMock, times(1)).removeView(any()); } }