Merge "Remove InputManager#getInstance" into udc-dev

This commit is contained in:
Asmita Poddar
2023-04-13 22:17:38 +00:00
committed by Android (Google) Code Review
17 changed files with 178 additions and 170 deletions

View File

@@ -506,10 +506,10 @@ public final class SystemServiceRegistry {
// InputManager stores its own static instance for historical purposes. // InputManager stores its own static instance for historical purposes.
registerService(Context.INPUT_SERVICE, InputManager.class, registerService(Context.INPUT_SERVICE, InputManager.class,
new ServiceFetcher<InputManager>() { new CachedServiceFetcher<InputManager>() {
@Override @Override
public InputManager getService(ContextImpl ctx) { public InputManager createService(ContextImpl ctx) {
return InputManager.getInstance(ctx.getOuterContext()); return new InputManager(ctx.getOuterContext());
}}); }});
registerService(Context.DISPLAY_SERVICE, DisplayManager.class, registerService(Context.DISPLAY_SERVICE, DisplayManager.class,

View File

@@ -53,11 +53,8 @@ import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -73,19 +70,9 @@ public final class InputManager {
// To enable these logs, run: 'adb shell setprop log.tag.InputManager DEBUG' (requires restart) // To enable these logs, run: 'adb shell setprop log.tag.InputManager DEBUG' (requires restart)
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static InputManager sInstance;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final IInputManager mIm; private final IInputManager mIm;
/**
* We hold a weak reference to the context to avoid leaking it indefinitely,
* since we currently store the input manager instance as a static variable that
* will outlive any context.
*/
@Nullable
private WeakReference<Context> mWeakContext;
/** /**
* Whether a PointerIcon is shown for stylus pointers. * Whether a PointerIcon is shown for stylus pointers.
* Obtain using {@link #isStylusPointerIconEnabled()}. * Obtain using {@link #isStylusPointerIconEnabled()}.
@@ -255,99 +242,43 @@ public final class InputManager {
*/ */
public static final int SWITCH_STATE_ON = 1; public static final int SWITCH_STATE_ON = 1;
private static String sVelocityTrackerStrategy; private final InputManagerGlobal mGlobal;
private final Context mContext;
private InputManagerGlobal mGlobal; /** @hide */
public InputManager(Context context) {
private InputManager() {
mGlobal = InputManagerGlobal.getInstance(); mGlobal = InputManagerGlobal.getInstance();
mIm = mGlobal.getInputManagerService(); mIm = mGlobal.getInputManagerService();
try { mContext = context;
sVelocityTrackerStrategy = mIm.getVelocityTrackerStrategy();
} catch (RemoteException ex) {
Log.w(TAG, "Could not get VelocityTracker strategy: " + ex);
}
} }
/** /**
* Gets an instance of the input manager. * Gets an instance of the input manager.
* *
* @return The input manager instance. * Warning: The usage of this method is not supported!
*
* @hide
*/
@VisibleForTesting
public static InputManager resetInstance(IInputManager inputManagerService) {
synchronized (InputManager.class) {
InputManagerGlobal.resetInstance(inputManagerService);
sInstance = new InputManager();
return sInstance;
}
}
/**
* Clear the instance of the input manager.
*
* @hide
*/
@VisibleForTesting
public static void clearInstance() {
synchronized (InputManager.class) {
InputManagerGlobal.clearInstance();
sInstance = null;
}
}
/**
* Gets an instance of the input manager.
* *
* @return The input manager instance. * @return The input manager instance.
* @deprecated Use {@link Context#getSystemService(Class)} or {@link #getInstance(Context)} * Use {@link Context#getSystemService(Class)}
* to obtain the InputManager instance. * to obtain the InputManager instance.
*
* TODO (b/277717573): Soft remove this API in version V.
* TODO (b/277039664): Migrate app usage off this API.
*
* @hide * @hide
*/ */
@Deprecated @Deprecated
@UnsupportedAppUsage @UnsupportedAppUsage
public static InputManager getInstance() { public static InputManager getInstance() {
return getInstance(ActivityThread.currentApplication()); return Objects.requireNonNull(ActivityThread.currentApplication())
.getSystemService(InputManager.class);
} }
/** /**
* Gets an instance of the input manager. * Get the current VelocityTracker strategy.
*
* @return The input manager instance.
* @hide
*/
public static InputManager getInstance(Context context) {
synchronized (InputManager.class) {
if (sInstance == null) {
sInstance = new InputManager();
}
if (sInstance.mWeakContext == null || sInstance.mWeakContext.get() == null) {
sInstance.mWeakContext = new WeakReference(context);
}
return sInstance;
}
}
@NonNull
private Context getContext() {
WeakReference<Context> weakContext = Objects.requireNonNull(mWeakContext,
"A context is required for InputManager. Get the InputManager instance using "
+ "Context#getSystemService before calling this method.");
// If we get at this point, an app calling this function could potentially expect a
// Context that has disappeared due to garbage collection. Holding a weak reference
// is a temporary solution that should be resolved before the release of a
// production version. This is being tracked in b/267758905
return Objects.requireNonNull(weakContext.get(), "missing Context");
}
/**
* Get the current VelocityTracker strategy. Only works when the system has fully booted up.
* @hide * @hide
*/ */
public String getVelocityTrackerStrategy() { public String getVelocityTrackerStrategy() {
return sVelocityTrackerStrategy; return mGlobal.getVelocityTrackerStrategy();
} }
/** /**
@@ -584,11 +515,7 @@ public final class InputManager {
@NonNull @NonNull
public KeyboardLayout[] getKeyboardLayoutsForInputDevice( public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
@NonNull InputDeviceIdentifier identifier) { @NonNull InputDeviceIdentifier identifier) {
try { return mGlobal.getKeyboardLayoutsForInputDevice(identifier);
return mIm.getKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} }
/** /**
@@ -647,19 +574,8 @@ public final class InputManager {
@RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT) @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
public void setCurrentKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier, public void setCurrentKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
@NonNull String keyboardLayoutDescriptor) { @NonNull String keyboardLayoutDescriptor) {
if (identifier == null) { mGlobal.setCurrentKeyboardLayoutForInputDevice(identifier,
throw new IllegalArgumentException("identifier must not be null");
}
if (keyboardLayoutDescriptor == null) {
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
}
try {
mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
keyboardLayoutDescriptor); keyboardLayoutDescriptor);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} }
/** /**
@@ -956,8 +872,7 @@ public final class InputManager {
*/ */
@FloatRange(from = 0, to = 1) @FloatRange(from = 0, to = 1)
public float getMaximumObscuringOpacityForTouch() { public float getMaximumObscuringOpacityForTouch() {
Context context = ActivityThread.currentApplication(); return InputSettings.getMaximumObscuringOpacityForTouch(mContext);
return InputSettings.getMaximumObscuringOpacityForTouch(context);
} }
/** /**
@@ -1123,7 +1038,7 @@ public final class InputManager {
*/ */
public boolean isStylusPointerIconEnabled() { public boolean isStylusPointerIconEnabled() {
if (mIsStylusPointerIconEnabled == null) { if (mIsStylusPointerIconEnabled == null) {
mIsStylusPointerIconEnabled = getContext().getResources() mIsStylusPointerIconEnabled = mContext.getResources()
.getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon) .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
|| InputProperties.force_enable_stylus_pointer_icon().orElse(false); || InputProperties.force_enable_stylus_pointer_icon().orElse(false);
} }

View File

@@ -102,17 +102,26 @@ public final class InputManagerGlobal {
private static InputManagerGlobal sInstance; private static InputManagerGlobal sInstance;
private final String mVelocityTrackerStrategy;
private final IInputManager mIm; private final IInputManager mIm;
public InputManagerGlobal(IInputManager im) { public InputManagerGlobal(IInputManager im) {
mIm = im; mIm = im;
String strategy = null;
try {
strategy = mIm.getVelocityTrackerStrategy();
} catch (RemoteException ex) {
Log.w(TAG, "Could not get VelocityTracker strategy: " + ex);
}
mVelocityTrackerStrategy = strategy;
} }
/** /**
* Gets an instance of the input manager global singleton. * Gets an instance of the input manager global singleton.
* *
* @return The display manager instance, may be null early in system startup * @return The input manager instance, may be null early in system startup
* before the display manager has been fully initialized. * before the input manager has been fully initialized.
*/ */
public static InputManagerGlobal getInstance() { public static InputManagerGlobal getInstance() {
synchronized (InputManagerGlobal.class) { synchronized (InputManagerGlobal.class) {
@@ -151,6 +160,14 @@ public final class InputManagerGlobal {
} }
} }
/**
* Get the current VelocityTracker strategy.
* Only works when the system has fully booted up.
*/
public String getVelocityTrackerStrategy() {
return mVelocityTrackerStrategy;
}
/** /**
* @see InputManager#getInputDevice(int) * @see InputManager#getInputDevice(int)
*/ */
@@ -309,9 +326,7 @@ public final class InputManagerGlobal {
* @see InputManager#registerInputDeviceListener * @see InputManager#registerInputDeviceListener
*/ */
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) { public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
if (listener == null) { Objects.requireNonNull(listener, "listener must not be null");
throw new IllegalArgumentException("listener must not be null");
}
synchronized (mInputDeviceListeners) { synchronized (mInputDeviceListeners) {
populateInputDevicesLocked(); populateInputDevicesLocked();
@@ -407,9 +422,7 @@ public final class InputManagerGlobal {
* @see InputManager#getInputDeviceByDescriptor * @see InputManager#getInputDeviceByDescriptor
*/ */
InputDevice getInputDeviceByDescriptor(String descriptor) { InputDevice getInputDeviceByDescriptor(String descriptor) {
if (descriptor == null) { Objects.requireNonNull(descriptor, "descriptor must not be null.");
throw new IllegalArgumentException("descriptor must not be null.");
}
synchronized (mInputDeviceListeners) { synchronized (mInputDeviceListeners) {
populateInputDevicesLocked(); populateInputDevicesLocked();
@@ -526,9 +539,8 @@ public final class InputManagerGlobal {
*/ */
void registerOnTabletModeChangedListener( void registerOnTabletModeChangedListener(
OnTabletModeChangedListener listener, Handler handler) { OnTabletModeChangedListener listener, Handler handler) {
if (listener == null) { Objects.requireNonNull(listener, "listener must not be null");
throw new IllegalArgumentException("listener must not be null");
}
synchronized (mOnTabletModeChangedListeners) { synchronized (mOnTabletModeChangedListeners) {
if (mOnTabletModeChangedListeners == null) { if (mOnTabletModeChangedListeners == null) {
initializeTabletModeListenerLocked(); initializeTabletModeListenerLocked();
@@ -546,9 +558,8 @@ public final class InputManagerGlobal {
* @see InputManager#unregisterOnTabletModeChangedListener(OnTabletModeChangedListener) * @see InputManager#unregisterOnTabletModeChangedListener(OnTabletModeChangedListener)
*/ */
void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) { void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
if (listener == null) { Objects.requireNonNull(listener, "listener must not be null");
throw new IllegalArgumentException("listener must not be null");
}
synchronized (mOnTabletModeChangedListeners) { synchronized (mOnTabletModeChangedListeners) {
int idx = findOnTabletModeChangedListenerLocked(listener); int idx = findOnTabletModeChangedListenerLocked(listener);
if (idx >= 0) { if (idx >= 0) {
@@ -603,7 +614,7 @@ public final class InputManagerGlobal {
/** /**
* @see InputManager#addInputDeviceBatteryListener(int, Executor, InputDeviceBatteryListener) * @see InputManager#addInputDeviceBatteryListener(int, Executor, InputDeviceBatteryListener)
*/ */
void addInputDeviceBatteryListener(int deviceId, @NonNull Executor executor, public void addInputDeviceBatteryListener(int deviceId, @NonNull Executor executor,
@NonNull InputDeviceBatteryListener listener) { @NonNull InputDeviceBatteryListener listener) {
Objects.requireNonNull(executor, "executor should not be null"); Objects.requireNonNull(executor, "executor should not be null");
Objects.requireNonNull(listener, "listener should not be null"); Objects.requireNonNull(listener, "listener should not be null");
@@ -714,7 +725,7 @@ public final class InputManagerGlobal {
} }
/** /**
* @see InputManager#getInputDeviceBatteryState(int, boolean) * @see #getInputDeviceBatteryState(int, boolean)
*/ */
@NonNull @NonNull
public BatteryState getInputDeviceBatteryState(int deviceId, boolean hasBattery) { public BatteryState getInputDeviceBatteryState(int deviceId, boolean hasBattery) {
@@ -876,6 +887,38 @@ public final class InputManagerGlobal {
} }
} }
/**
* @see InputManager#getKeyboardLayoutsForInputDevice(InputDeviceIdentifier)
*/
@NonNull
public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
@NonNull InputDeviceIdentifier identifier) {
try {
return mIm.getKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/**
* @see InputManager#setCurrentKeyboardLayoutForInputDevice
* (InputDeviceIdentifier, String)
*/
@RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
public void setCurrentKeyboardLayoutForInputDevice(
@NonNull InputDeviceIdentifier identifier,
@NonNull String keyboardLayoutDescriptor) {
Objects.requireNonNull(identifier, "identifier must not be null");
Objects.requireNonNull(keyboardLayoutDescriptor,
"keyboardLayoutDescriptor must not be null");
try {
mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
keyboardLayoutDescriptor);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/** /**
* @see InputDevice#getSensorManager() * @see InputDevice#getSensorManager()
*/ */
@@ -1162,9 +1205,8 @@ public final class InputManagerGlobal {
*/ */
public boolean injectInputEvent(InputEvent event, int mode, int targetUid) { public boolean injectInputEvent(InputEvent event, int mode, int targetUid) {
if (event == null) { Objects.requireNonNull(event , "event must not be null");
throw new IllegalArgumentException("event must not be null");
}
if (mode != InputEventInjectionSync.NONE if (mode != InputEventInjectionSync.NONE
&& mode != InputEventInjectionSync.WAIT_FOR_FINISHED && mode != InputEventInjectionSync.WAIT_FOR_FINISHED
&& mode != InputEventInjectionSync.WAIT_FOR_RESULT) { && mode != InputEventInjectionSync.WAIT_FOR_RESULT) {

View File

@@ -18,7 +18,7 @@ package android.view;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager; import android.hardware.input.InputManagerGlobal;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Pools.SynchronizedPool; import android.util.Pools.SynchronizedPool;
@@ -286,7 +286,8 @@ public final class VelocityTracker {
private VelocityTracker(@VelocityTrackerStrategy int strategy) { private VelocityTracker(@VelocityTrackerStrategy int strategy) {
// If user has not selected a specific strategy // If user has not selected a specific strategy
if (strategy == VELOCITY_TRACKER_STRATEGY_DEFAULT) { if (strategy == VELOCITY_TRACKER_STRATEGY_DEFAULT) {
final String strategyProperty = InputManager.getInstance().getVelocityTrackerStrategy(); final String strategyProperty = InputManagerGlobal.getInstance()
.getVelocityTrackerStrategy();
// Check if user specified strategy by overriding system property. // Check if user specified strategy by overriding system property.
if (strategyProperty == null || strategyProperty.isEmpty()) { if (strategyProperty == null || strategyProperty.isEmpty()) {
mStrategy = strategy; mStrategy = strategy;

View File

@@ -15,11 +15,14 @@
*/ */
package android.hardware.input package android.hardware.input
import android.content.Context
import android.content.ContextWrapper
import android.hardware.BatteryState import android.hardware.BatteryState
import android.os.Handler import android.os.Handler
import android.os.HandlerExecutor import android.os.HandlerExecutor
import android.os.test.TestLooper import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit import android.platform.test.annotations.Presubmit
import androidx.test.core.app.ApplicationProvider
import com.android.server.testutils.any import com.android.server.testutils.any
import java.util.concurrent.Executor import java.util.concurrent.Executor
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -32,8 +35,10 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyInt
import org.mockito.Mockito.doAnswer import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoJUnitRunner import org.mockito.junit.MockitoJUnitRunner
@@ -53,6 +58,7 @@ class InputDeviceBatteryListenerTest {
private var registeredListener: IInputDeviceBatteryListener? = null private var registeredListener: IInputDeviceBatteryListener? = null
private val monitoredDevices = mutableListOf<Int>() private val monitoredDevices = mutableListOf<Int>()
private lateinit var executor: Executor private lateinit var executor: Executor
private lateinit var context: Context
private lateinit var inputManager: InputManager private lateinit var inputManager: InputManager
@Mock @Mock
@@ -60,11 +66,15 @@ class InputDeviceBatteryListenerTest {
@Before @Before
fun setUp() { fun setUp() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
testLooper = TestLooper() testLooper = TestLooper()
executor = HandlerExecutor(Handler(testLooper.looper)) executor = HandlerExecutor(Handler(testLooper.looper))
registeredListener = null registeredListener = null
monitoredDevices.clear() monitoredDevices.clear()
inputManager = InputManager.resetInstance(iInputManagerMock) InputManagerGlobal.resetInstance(iInputManagerMock)
inputManager = InputManager(context)
`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager)
// Handle battery listener registration. // Handle battery listener registration.
doAnswer { doAnswer {
@@ -102,7 +112,7 @@ class InputDeviceBatteryListenerTest {
@After @After
fun tearDown() { fun tearDown() {
InputManager.clearInstance() InputManagerGlobal.clearInstance()
} }
private fun notifyBatteryStateChanged( private fun notifyBatteryStateChanged(

View File

@@ -28,9 +28,12 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.lights.Light; import android.hardware.lights.Light;
import android.hardware.lights.LightState; import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager; import android.hardware.lights.LightsManager;
@@ -40,6 +43,8 @@ import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.view.InputDevice; import android.view.InputDevice;
import androidx.test.InstrumentationRegistry;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
@@ -76,12 +81,15 @@ public class InputDeviceLightsManagerTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
final Context context = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID}); when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn( when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
createInputDevice(DEVICE_ID)); createInputDevice(DEVICE_ID));
mInputManager = InputManager.resetInstance(mIInputManagerMock); InputManagerGlobal.resetInstance(mIInputManagerMock);
mInputManager = new InputManager(context);
when(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(mInputManager);
ArrayMap<Integer, LightState> lightStatesById = new ArrayMap<>(); ArrayMap<Integer, LightState> lightStatesById = new ArrayMap<>();
doAnswer(invocation -> { doAnswer(invocation -> {
@@ -106,7 +114,7 @@ public class InputDeviceLightsManagerTest {
@After @After
public void tearDown() { public void tearDown() {
InputManager.clearInstance(); InputManagerGlobal.clearInstance();
} }
private InputDevice createInputDevice(int id) { private InputDevice createInputDevice(int id) {

View File

@@ -81,9 +81,9 @@ public class InputDeviceSensorManagerTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
final Context context = spy(new ContextWrapper(InstrumentationRegistry.getContext())); final Context context = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
InputManager inputManager = InputManager.resetInstance(mIInputManagerMock); InputManagerGlobal.resetInstance(mIInputManagerMock);
mInputManager = new InputManager(context);
when(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager); when(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(mInputManager);
when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID}); when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
@@ -98,13 +98,11 @@ public class InputDeviceSensorManagerTest {
.thenReturn(true); .thenReturn(true);
when(mIInputManagerMock.registerSensorListener(any())).thenReturn(true); when(mIInputManagerMock.registerSensorListener(any())).thenReturn(true);
mInputManager = context.getSystemService(InputManager.class);
} }
@After @After
public void tearDown() { public void tearDown() {
InputManager.clearInstance(); InputManagerGlobal.clearInstance();
} }
private class InputTestSensorEventListener implements SensorEventListener { private class InputTestSensorEventListener implements SensorEventListener {

View File

@@ -15,11 +15,14 @@
*/ */
package android.hardware.input package android.hardware.input
import android.content.Context
import android.content.ContextWrapper
import android.content.res.Resources import android.content.res.Resources
import android.platform.test.annotations.Presubmit import android.platform.test.annotations.Presubmit
import android.view.Display import android.view.Display
import android.view.DisplayInfo import android.view.DisplayInfo
import android.view.InputDevice import android.view.InputDevice
import androidx.test.core.app.ApplicationProvider
import org.junit.After import org.junit.After
import org.junit.Assert.assertNotNull import org.junit.Assert.assertNotNull
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
@@ -28,6 +31,7 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.eq import org.mockito.Mockito.eq
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
@@ -52,17 +56,20 @@ class InputManagerTest {
@get:Rule @get:Rule
val rule = MockitoJUnit.rule()!! val rule = MockitoJUnit.rule()!!
private lateinit var inputManager: InputManager
private lateinit var devicesChangedListener: IInputDevicesChangedListener private lateinit var devicesChangedListener: IInputDevicesChangedListener
private val deviceGenerationMap = mutableMapOf<Int /*deviceId*/, Int /*generation*/>() private val deviceGenerationMap = mutableMapOf<Int /*deviceId*/, Int /*generation*/>()
private lateinit var context: Context
private lateinit var inputManager: InputManager
@Mock @Mock
private lateinit var iInputManager: IInputManager private lateinit var iInputManager: IInputManager
@Before @Before
fun setUp() { fun setUp() {
inputManager = InputManager.resetInstance(iInputManager) context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
InputManagerGlobal.resetInstance(iInputManager)
inputManager = InputManager(context)
`when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
`when`(iInputManager.inputDeviceIds).then { `when`(iInputManager.inputDeviceIds).then {
deviceGenerationMap.keys.toIntArray() deviceGenerationMap.keys.toIntArray()
} }
@@ -70,7 +77,7 @@ class InputManagerTest {
@After @After
fun tearDown() { fun tearDown() {
InputManager.clearInstance() InputManagerGlobal.clearInstance()
} }
private fun notifyDeviceChanged( private fun notifyDeviceChanged(

View File

@@ -16,10 +16,13 @@
package android.hardware.input package android.hardware.input
import android.content.Context
import android.content.ContextWrapper
import android.os.Handler import android.os.Handler
import android.os.HandlerExecutor import android.os.HandlerExecutor
import android.os.test.TestLooper import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit import android.platform.test.annotations.Presubmit
import androidx.test.core.app.ApplicationProvider
import com.android.server.testutils.any import com.android.server.testutils.any
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@@ -27,7 +30,9 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.doAnswer import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoJUnitRunner import org.mockito.junit.MockitoJUnitRunner
import java.util.concurrent.Executor import java.util.concurrent.Executor
@@ -51,6 +56,7 @@ class KeyboardBacklightListenerTest {
private lateinit var testLooper: TestLooper private lateinit var testLooper: TestLooper
private var registeredListener: IKeyboardBacklightListener? = null private var registeredListener: IKeyboardBacklightListener? = null
private lateinit var executor: Executor private lateinit var executor: Executor
private lateinit var context: Context
private lateinit var inputManager: InputManager private lateinit var inputManager: InputManager
@Mock @Mock
@@ -58,10 +64,14 @@ class KeyboardBacklightListenerTest {
@Before @Before
fun setUp() { fun setUp() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
InputManagerGlobal.resetInstance(iInputManagerMock)
testLooper = TestLooper() testLooper = TestLooper()
executor = HandlerExecutor(Handler(testLooper.looper)) executor = HandlerExecutor(Handler(testLooper.looper))
registeredListener = null registeredListener = null
inputManager = InputManager.resetInstance(iInputManagerMock) inputManager = InputManager(context)
`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager)
// Handle keyboard backlight listener registration. // Handle keyboard backlight listener registration.
doAnswer { doAnswer {
@@ -89,7 +99,7 @@ class KeyboardBacklightListenerTest {
@After @After
fun tearDown() { fun tearDown() {
InputManager.clearInstance() InputManagerGlobal.clearInstance()
} }
private fun notifyKeyboardBacklightChanged( private fun notifyKeyboardBacklightChanged(

View File

@@ -36,7 +36,7 @@ import android.content.Context;
import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal;
import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.IInputManager; import android.hardware.input.IInputManager;
import android.hardware.input.InputManager; import android.hardware.input.InputManagerGlobal;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
import android.os.Process; import android.os.Process;
@@ -178,7 +178,7 @@ public class InputMethodManagerServiceTestBase {
// Injecting and mocked InputMethodBindingController and InputMethod. // Injecting and mocked InputMethodBindingController and InputMethod.
mMockInputMethodInvoker = IInputMethodInvoker.create(mMockInputMethod); mMockInputMethodInvoker = IInputMethodInvoker.create(mMockInputMethod);
InputManager.resetInstance(mMockIInputManager); InputManagerGlobal.resetInstance(mMockIInputManager);
synchronized (ImfLock.class) { synchronized (ImfLock.class) {
when(mMockInputMethodBindingController.getCurMethod()) when(mMockInputMethodBindingController.getCurMethod())
.thenReturn(mMockInputMethodInvoker); .thenReturn(mMockInputMethodInvoker);

View File

@@ -25,7 +25,7 @@ import static org.mockito.Mockito.when;
import android.hardware.input.IInputDevicesChangedListener; import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager; import android.hardware.input.IInputManager;
import android.hardware.input.InputManager; import android.hardware.input.InputManagerGlobal;
import android.os.RemoteException; import android.os.RemoteException;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.view.InputDevice; import android.view.InputDevice;
@@ -38,7 +38,8 @@ import java.util.Objects;
import java.util.stream.IntStream; import java.util.stream.IntStream;
/** /**
* A test utility class used to share the logic for setting up {@link InputManager}'s callback for * A test utility class used to share the logic for setting up
* {@link android.hardware.input.InputManager}'s callback for
* when a virtual input device being added. * when a virtual input device being added.
*/ */
class InputManagerMockHelper { class InputManagerMockHelper {
@@ -76,7 +77,7 @@ class InputManagerMockHelper {
// Set a new instance of InputManager for testing that uses the IInputManager mock as the // Set a new instance of InputManager for testing that uses the IInputManager mock as the
// interface to the server. // interface to the server.
InputManager.resetInstance(mIInputManagerMock); InputManagerGlobal.resetInstance(mIInputManagerMock);
} }
private long handleNativeOpenInputDevice(InvocationOnMock inv) { private long handleNativeOpenInputDevice(InvocationOnMock inv) {

View File

@@ -19,8 +19,6 @@ package com.android.server.input
import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.ContextWrapper
import android.hardware.BatteryState.STATUS_CHARGING import android.hardware.BatteryState.STATUS_CHARGING
import android.hardware.BatteryState.STATUS_DISCHARGING import android.hardware.BatteryState.STATUS_DISCHARGING
import android.hardware.BatteryState.STATUS_FULL import android.hardware.BatteryState.STATUS_FULL
@@ -31,12 +29,14 @@ import android.hardware.input.IInputDeviceBatteryState
import android.hardware.input.IInputDevicesChangedListener import android.hardware.input.IInputDevicesChangedListener
import android.hardware.input.IInputManager import android.hardware.input.IInputManager
import android.hardware.input.InputManager import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.os.Binder import android.os.Binder
import android.os.IBinder import android.os.IBinder
import android.os.test.TestLooper import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit import android.platform.test.annotations.Presubmit
import android.testing.TestableContext
import android.view.InputDevice import android.view.InputDevice
import androidx.test.InstrumentationRegistry import androidx.test.core.app.ApplicationProvider
import com.android.server.input.BatteryController.BluetoothBatteryManager import com.android.server.input.BatteryController.BluetoothBatteryManager
import com.android.server.input.BatteryController.BluetoothBatteryManager.BluetoothBatteryListener import com.android.server.input.BatteryController.BluetoothBatteryManager.BluetoothBatteryListener
import com.android.server.input.BatteryController.POLLING_PERIOD_MILLIS import com.android.server.input.BatteryController.POLLING_PERIOD_MILLIS
@@ -66,7 +66,6 @@ import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.eq import org.mockito.Mockito.eq
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
import org.mockito.Mockito.never import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times import org.mockito.Mockito.times
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.verifyNoMoreInteractions
@@ -197,17 +196,18 @@ class BatteryControllerTests {
private lateinit var bluetoothBatteryManager: BluetoothBatteryManager private lateinit var bluetoothBatteryManager: BluetoothBatteryManager
private lateinit var batteryController: BatteryController private lateinit var batteryController: BatteryController
private lateinit var context: Context private lateinit var context: TestableContext
private lateinit var testLooper: TestLooper private lateinit var testLooper: TestLooper
private lateinit var devicesChangedListener: IInputDevicesChangedListener private lateinit var devicesChangedListener: IInputDevicesChangedListener
private val deviceGenerationMap = mutableMapOf<Int /*deviceId*/, Int /*generation*/>() private val deviceGenerationMap = mutableMapOf<Int /*deviceId*/, Int /*generation*/>()
@Before @Before
fun setup() { fun setup() {
context = spy(ContextWrapper(InstrumentationRegistry.getContext())) context = TestableContext(ApplicationProvider.getApplicationContext())
testLooper = TestLooper() testLooper = TestLooper()
val inputManager = InputManager.resetInstance(iInputManager) InputManagerGlobal.resetInstance(iInputManager)
`when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager) val inputManager = InputManager(context)
context.addMockSystemService(InputManager::class.java, inputManager)
`when`(iInputManager.inputDeviceIds).then { `when`(iInputManager.inputDeviceIds).then {
deviceGenerationMap.keys.toIntArray() deviceGenerationMap.keys.toIntArray()
} }
@@ -256,7 +256,7 @@ class BatteryControllerTests {
@After @After
fun tearDown() { fun tearDown() {
InputManager.clearInstance() InputManagerGlobal.clearInstance()
} }
@Test @Test

View File

@@ -20,6 +20,7 @@ import android.content.Context
import android.content.ContextWrapper import android.content.ContextWrapper
import android.hardware.input.IInputManager import android.hardware.input.IInputManager
import android.hardware.input.InputManager import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.os.test.TestLooper import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit import android.platform.test.annotations.Presubmit
import android.provider.Settings import android.provider.Settings
@@ -102,7 +103,8 @@ class KeyRemapperTests {
dataStore, dataStore,
testLooper.looper testLooper.looper
) )
val inputManager = InputManager.resetInstance(iInputManager) InputManagerGlobal.resetInstance(iInputManager)
val inputManager = InputManager(context)
Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE))) Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager) .thenReturn(inputManager)
Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID)) Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
@@ -110,7 +112,7 @@ class KeyRemapperTests {
@After @After
fun tearDown() { fun tearDown() {
InputManager.clearInstance() InputManagerGlobal.clearInstance()
} }
@Test @Test

View File

@@ -23,6 +23,7 @@ import android.hardware.input.IInputManager
import android.hardware.input.IKeyboardBacklightListener import android.hardware.input.IKeyboardBacklightListener
import android.hardware.input.IKeyboardBacklightState import android.hardware.input.IKeyboardBacklightState
import android.hardware.input.InputManager import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.hardware.lights.Light import android.hardware.lights.Light
import android.os.UEventObserver import android.os.UEventObserver
import android.os.test.TestLooper import android.os.test.TestLooper
@@ -116,7 +117,8 @@ class KeyboardBacklightControllerTests {
testLooper = TestLooper() testLooper = TestLooper()
keyboardBacklightController = keyboardBacklightController =
KeyboardBacklightController(context, native, dataStore, testLooper.looper) KeyboardBacklightController(context, native, dataStore, testLooper.looper)
val inputManager = InputManager.resetInstance(iInputManager) InputManagerGlobal.resetInstance(iInputManager)
val inputManager = InputManager(context)
`when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager) `when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID)) `when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
`when`(native.setLightColor(anyInt(), anyInt(), anyInt())).then { `when`(native.setLightColor(anyInt(), anyInt(), anyInt())).then {
@@ -131,7 +133,7 @@ class KeyboardBacklightControllerTests {
@After @After
fun tearDown() { fun tearDown() {
InputManager.clearInstance() InputManagerGlobal.clearInstance()
} }
@Test @Test

View File

@@ -25,6 +25,7 @@ import android.content.pm.ResolveInfo
import android.content.pm.ServiceInfo import android.content.pm.ServiceInfo
import android.hardware.input.IInputManager import android.hardware.input.IInputManager
import android.hardware.input.InputManager import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.hardware.input.KeyboardLayout import android.hardware.input.KeyboardLayout
import android.icu.util.ULocale import android.icu.util.ULocale
import android.os.Bundle import android.os.Bundle
@@ -144,7 +145,8 @@ class KeyboardLayoutManagerTests {
} }
private fun setupInputDevices() { private fun setupInputDevices() {
val inputManager = InputManager.resetInstance(iInputManager) InputManagerGlobal.resetInstance(iInputManager)
val inputManager = InputManager(context)
Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE))) Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager) .thenReturn(inputManager)

View File

@@ -77,16 +77,19 @@ public class InputDeviceDelegateTest {
private TestLooper mTestLooper; private TestLooper mTestLooper;
private ContextWrapper mContextSpy; private ContextWrapper mContextSpy;
private InputManager mInputManager;
private InputDeviceDelegate mInputDeviceDelegate; private InputDeviceDelegate mInputDeviceDelegate;
private IInputDevicesChangedListener mIInputDevicesChangedListener; private IInputDevicesChangedListener mIInputDevicesChangedListener;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
mTestLooper = new TestLooper(); mTestLooper = new TestLooper();
InputManager inputManager = InputManager.resetInstance(mIInputManagerMock); InputManagerGlobal.resetInstance(mIInputManagerMock);
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager); mInputManager = new InputManager(mContextSpy);
when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE)))
.thenReturn(mInputManager);
doAnswer(invocation -> mIInputDevicesChangedListener = invocation.getArgument(0)) doAnswer(invocation -> mIInputDevicesChangedListener = invocation.getArgument(0))
.when(mIInputManagerMock).registerInputDevicesChangedListener(any()); .when(mIInputManagerMock).registerInputDevicesChangedListener(any());
@@ -97,7 +100,7 @@ public class InputDeviceDelegateTest {
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
InputManager.clearInstance(); InputManagerGlobal.clearInstance();
} }
@Test @Test

View File

@@ -47,6 +47,7 @@ import android.content.ContextWrapper;
import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal;
import android.hardware.input.IInputManager; import android.hardware.input.IInputManager;
import android.hardware.input.InputManager; import android.hardware.input.InputManager;
import android.hardware.input.InputManagerGlobal;
import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibrator;
import android.hardware.vibrator.IVibratorManager; import android.hardware.vibrator.IVibratorManager;
import android.media.AudioAttributes; import android.media.AudioAttributes;
@@ -184,11 +185,13 @@ public class VibratorManagerServiceTest {
private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener
mRegisteredAppsOnVirtualDeviceListener; mRegisteredAppsOnVirtualDeviceListener;
private InputManager mInputManager;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
mTestLooper = new TestLooper(); mTestLooper = new TestLooper();
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
InputManager inputManager = InputManager.resetInstance(mIInputManagerMock); InputManagerGlobal.resetInstance(mIInputManagerMock);
mVibrationConfig = new VibrationConfig(mContextSpy.getResources()); mVibrationConfig = new VibrationConfig(mContextSpy.getResources());
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy); ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
@@ -196,7 +199,10 @@ public class VibratorManagerServiceTest {
mVibrator = new FakeVibrator(mContextSpy); mVibrator = new FakeVibrator(mContextSpy);
when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibrator); when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibrator);
when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager);
mInputManager = new InputManager(mContextSpy);
when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE)))
.thenReturn(mInputManager);
when(mContextSpy.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManagerMock); when(mContextSpy.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManagerMock);
when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]); when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]);
when(mPackageManagerInternalMock.getSystemUiServiceComponent()) when(mPackageManagerInternalMock.getSystemUiServiceComponent())
@@ -259,6 +265,7 @@ public class VibratorManagerServiceTest {
LocalServices.removeServiceForTest(PowerManagerInternal.class); LocalServices.removeServiceForTest(PowerManagerInternal.class);
// Ignore potential exceptions about the looper having never dispatched any messages. // Ignore potential exceptions about the looper having never dispatched any messages.
mTestLooper.stopAutoDispatchAndIgnoreExceptions(); mTestLooper.stopAutoDispatchAndIgnoreExceptions();
InputManagerGlobal.clearInstance();
} }
private VibratorManagerService createSystemReadyService() { private VibratorManagerService createSystemReadyService() {