Remove InputManager#getInstance

Replace all instances of InputManager with instances of InputManagerGlobal.
Add the context field in InputManager.
All methods previously accessed through instances of InputManager
have been refactored to be accessed through InputManagerGlobal, which is
a singleton class.
The SystemServiceRegistry no longer returns an instance of InputManager.

Bug: b/267758905
Test: Pre-submit
Change-Id: I2f3db1f5f4e27be9eb11d0d307aaee16a33f014d
This commit is contained in:
Asmita Poddar
2023-03-24 08:48:51 +00:00
parent 056b718336
commit fb12466e81
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.
registerService(Context.INPUT_SERVICE, InputManager.class,
new ServiceFetcher<InputManager>() {
new CachedServiceFetcher<InputManager>() {
@Override
public InputManager getService(ContextImpl ctx) {
return InputManager.getInstance(ctx.getOuterContext());
public InputManager createService(ContextImpl ctx) {
return new InputManager(ctx.getOuterContext());
}});
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.InputMethodSubtype;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
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)
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static InputManager sInstance;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
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.
* Obtain using {@link #isStylusPointerIconEnabled()}.
@@ -255,99 +242,43 @@ public final class InputManager {
*/
public static final int SWITCH_STATE_ON = 1;
private static String sVelocityTrackerStrategy;
private final InputManagerGlobal mGlobal;
private final Context mContext;
private InputManagerGlobal mGlobal;
private InputManager() {
/** @hide */
public InputManager(Context context) {
mGlobal = InputManagerGlobal.getInstance();
mIm = mGlobal.getInputManagerService();
try {
sVelocityTrackerStrategy = mIm.getVelocityTrackerStrategy();
} catch (RemoteException ex) {
Log.w(TAG, "Could not get VelocityTracker strategy: " + ex);
}
mContext = context;
}
/**
* 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.
* @return The input manager instance.
* Use {@link Context#getSystemService(Class)}
* to obtain the InputManager instance.
*
* @hide
*/
@VisibleForTesting
public static void clearInstance() {
synchronized (InputManager.class) {
InputManagerGlobal.clearInstance();
sInstance = null;
}
}
/**
* Gets an instance of the input manager.
* TODO (b/277717573): Soft remove this API in version V.
* TODO (b/277039664): Migrate app usage off this API.
*
* @return The input manager instance.
* @deprecated Use {@link Context#getSystemService(Class)} or {@link #getInstance(Context)}
* to obtain the InputManager instance.
* @hide
*/
@Deprecated
@UnsupportedAppUsage
public static InputManager getInstance() {
return getInstance(ActivityThread.currentApplication());
return Objects.requireNonNull(ActivityThread.currentApplication())
.getSystemService(InputManager.class);
}
/**
* Gets an instance of the input manager.
*
* @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.
* Get the current VelocityTracker strategy.
* @hide
*/
public String getVelocityTrackerStrategy() {
return sVelocityTrackerStrategy;
return mGlobal.getVelocityTrackerStrategy();
}
/**
@@ -584,11 +515,7 @@ public final class InputManager {
@NonNull
public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
@NonNull InputDeviceIdentifier identifier) {
try {
return mIm.getKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
return mGlobal.getKeyboardLayoutsForInputDevice(identifier);
}
/**
@@ -647,19 +574,8 @@ public final class InputManager {
@RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
public void setCurrentKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
@NonNull String keyboardLayoutDescriptor) {
if (identifier == null) {
throw new IllegalArgumentException("identifier must not be null");
}
if (keyboardLayoutDescriptor == null) {
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
}
try {
mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
keyboardLayoutDescriptor);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
mGlobal.setCurrentKeyboardLayoutForInputDevice(identifier,
keyboardLayoutDescriptor);
}
/**
@@ -956,8 +872,7 @@ public final class InputManager {
*/
@FloatRange(from = 0, to = 1)
public float getMaximumObscuringOpacityForTouch() {
Context context = ActivityThread.currentApplication();
return InputSettings.getMaximumObscuringOpacityForTouch(context);
return InputSettings.getMaximumObscuringOpacityForTouch(mContext);
}
/**
@@ -1123,7 +1038,7 @@ public final class InputManager {
*/
public boolean isStylusPointerIconEnabled() {
if (mIsStylusPointerIconEnabled == null) {
mIsStylusPointerIconEnabled = getContext().getResources()
mIsStylusPointerIconEnabled = mContext.getResources()
.getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
|| InputProperties.force_enable_stylus_pointer_icon().orElse(false);
}

View File

@@ -102,17 +102,26 @@ public final class InputManagerGlobal {
private static InputManagerGlobal sInstance;
private final String mVelocityTrackerStrategy;
private final IInputManager mIm;
public InputManagerGlobal(IInputManager 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.
*
* @return The display manager instance, may be null early in system startup
* before the display manager has been fully initialized.
* @return The input manager instance, may be null early in system startup
* before the input manager has been fully initialized.
*/
public static InputManagerGlobal getInstance() {
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)
*/
@@ -309,9 +326,7 @@ public final class InputManagerGlobal {
* @see InputManager#registerInputDeviceListener
*/
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
Objects.requireNonNull(listener, "listener must not be null");
synchronized (mInputDeviceListeners) {
populateInputDevicesLocked();
@@ -407,9 +422,7 @@ public final class InputManagerGlobal {
* @see InputManager#getInputDeviceByDescriptor
*/
InputDevice getInputDeviceByDescriptor(String descriptor) {
if (descriptor == null) {
throw new IllegalArgumentException("descriptor must not be null.");
}
Objects.requireNonNull(descriptor, "descriptor must not be null.");
synchronized (mInputDeviceListeners) {
populateInputDevicesLocked();
@@ -526,9 +539,8 @@ public final class InputManagerGlobal {
*/
void registerOnTabletModeChangedListener(
OnTabletModeChangedListener listener, Handler handler) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
Objects.requireNonNull(listener, "listener must not be null");
synchronized (mOnTabletModeChangedListeners) {
if (mOnTabletModeChangedListeners == null) {
initializeTabletModeListenerLocked();
@@ -546,9 +558,8 @@ public final class InputManagerGlobal {
* @see InputManager#unregisterOnTabletModeChangedListener(OnTabletModeChangedListener)
*/
void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
Objects.requireNonNull(listener, "listener must not be null");
synchronized (mOnTabletModeChangedListeners) {
int idx = findOnTabletModeChangedListenerLocked(listener);
if (idx >= 0) {
@@ -603,7 +614,7 @@ public final class InputManagerGlobal {
/**
* @see InputManager#addInputDeviceBatteryListener(int, Executor, InputDeviceBatteryListener)
*/
void addInputDeviceBatteryListener(int deviceId, @NonNull Executor executor,
public void addInputDeviceBatteryListener(int deviceId, @NonNull Executor executor,
@NonNull InputDeviceBatteryListener listener) {
Objects.requireNonNull(executor, "executor 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
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()
*/
@@ -1162,9 +1205,8 @@ public final class InputManagerGlobal {
*/
public boolean injectInputEvent(InputEvent event, int mode, int targetUid) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
Objects.requireNonNull(event , "event must not be null");
if (mode != InputEventInjectionSync.NONE
&& mode != InputEventInjectionSync.WAIT_FOR_FINISHED
&& mode != InputEventInjectionSync.WAIT_FOR_RESULT) {

View File

@@ -18,7 +18,7 @@ package android.view;
import android.annotation.IntDef;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerGlobal;
import android.util.ArrayMap;
import android.util.Pools.SynchronizedPool;
@@ -286,7 +286,8 @@ public final class VelocityTracker {
private VelocityTracker(@VelocityTrackerStrategy int strategy) {
// If user has not selected a specific strategy
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.
if (strategyProperty == null || strategyProperty.isEmpty()) {
mStrategy = strategy;

View File

@@ -15,11 +15,14 @@
*/
package android.hardware.input
import android.content.Context
import android.content.ContextWrapper
import android.hardware.BatteryState
import android.os.Handler
import android.os.HandlerExecutor
import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit
import androidx.test.core.app.ApplicationProvider
import com.android.server.testutils.any
import java.util.concurrent.Executor
import kotlin.test.assertEquals
@@ -32,8 +35,10 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoJUnitRunner
@@ -53,6 +58,7 @@ class InputDeviceBatteryListenerTest {
private var registeredListener: IInputDeviceBatteryListener? = null
private val monitoredDevices = mutableListOf<Int>()
private lateinit var executor: Executor
private lateinit var context: Context
private lateinit var inputManager: InputManager
@Mock
@@ -60,11 +66,15 @@ class InputDeviceBatteryListenerTest {
@Before
fun setUp() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
testLooper = TestLooper()
executor = HandlerExecutor(Handler(testLooper.looper))
registeredListener = null
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.
doAnswer {
@@ -102,7 +112,7 @@ class InputDeviceBatteryListenerTest {
@After
fun tearDown() {
InputManager.clearInstance()
InputManagerGlobal.clearInstance()
}
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.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.lights.Light;
import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager;
@@ -40,6 +43,8 @@ import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.view.InputDevice;
import androidx.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -76,12 +81,15 @@ public class InputDeviceLightsManagerTest {
@Before
public void setUp() throws Exception {
final Context context = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
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<>();
doAnswer(invocation -> {
@@ -106,7 +114,7 @@ public class InputDeviceLightsManagerTest {
@After
public void tearDown() {
InputManager.clearInstance();
InputManagerGlobal.clearInstance();
}
private InputDevice createInputDevice(int id) {

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,7 @@ import static org.mockito.Mockito.when;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerGlobal;
import android.os.RemoteException;
import android.testing.TestableLooper;
import android.view.InputDevice;
@@ -38,7 +38,8 @@ import java.util.Objects;
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.
*/
class InputManagerMockHelper {
@@ -76,7 +77,7 @@ class InputManagerMockHelper {
// Set a new instance of InputManager for testing that uses the IInputManager mock as the
// interface to the server.
InputManager.resetInstance(mIInputManagerMock);
InputManagerGlobal.resetInstance(mIInputManagerMock);
}
private long handleNativeOpenInputDevice(InvocationOnMock inv) {

View File

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

View File

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

View File

@@ -23,6 +23,7 @@ import android.hardware.input.IInputManager
import android.hardware.input.IKeyboardBacklightListener
import android.hardware.input.IKeyboardBacklightState
import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.hardware.lights.Light
import android.os.UEventObserver
import android.os.test.TestLooper
@@ -116,7 +117,8 @@ class KeyboardBacklightControllerTests {
testLooper = TestLooper()
keyboardBacklightController =
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`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
`when`(native.setLightColor(anyInt(), anyInt(), anyInt())).then {
@@ -131,7 +133,7 @@ class KeyboardBacklightControllerTests {
@After
fun tearDown() {
InputManager.clearInstance()
InputManagerGlobal.clearInstance()
}
@Test

View File

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

View File

@@ -77,16 +77,19 @@ public class InputDeviceDelegateTest {
private TestLooper mTestLooper;
private ContextWrapper mContextSpy;
private InputManager mInputManager;
private InputDeviceDelegate mInputDeviceDelegate;
private IInputDevicesChangedListener mIInputDevicesChangedListener;
@Before
public void setUp() throws Exception {
mTestLooper = new TestLooper();
InputManager inputManager = InputManager.resetInstance(mIInputManagerMock);
InputManagerGlobal.resetInstance(mIInputManagerMock);
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))
.when(mIInputManagerMock).registerInputDevicesChangedListener(any());
@@ -97,7 +100,7 @@ public class InputDeviceDelegateTest {
@After
public void tearDown() throws Exception {
InputManager.clearInstance();
InputManagerGlobal.clearInstance();
}
@Test

View File

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