Skip to content

Commit 4b4e329

Browse files
brettchabotcopybara-androidxtest
authored andcommitted
Use getSystemService to get InputManager.
Espresso's InputManagerEventInjectionStrategy currently uses reflection to call InputManager.getInstance. This is no longer necessary since on APIs >=23 the public API getSystemService can be used. PiperOrigin-RevId: 769778949
1 parent fc8edba commit 4b4e329

2 files changed

Lines changed: 22 additions & 26 deletions

File tree

espresso/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The following artifacts were released:
1818

1919
* Fix #2349, where multi-process + different rotation on 2 activities would
2020
instantly timeout when waiting for the UI to rotate.
21+
* Use getSystemService instead of reflective InputManager.getInstance
2122

2223
**New Features**
2324

espresso/core/java/androidx/test/espresso/base/InputManagerEventInjectionStrategy.java

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package androidx.test.espresso.base;
1818

19+
import android.hardware.input.InputManager;
1920
import android.os.Build;
2021
import android.os.SystemClock;
2122
import android.util.Log;
@@ -24,6 +25,7 @@
2425
import android.view.KeyEvent;
2526
import android.view.MotionEvent;
2627
import androidx.test.espresso.InjectEventSecurityException;
28+
import androidx.test.platform.app.InstrumentationRegistry;
2729
import java.lang.reflect.Field;
2830
import java.lang.reflect.InvocationTargetException;
2931
import java.lang.reflect.Method;
@@ -41,7 +43,7 @@ final class InputManagerEventInjectionStrategy implements EventInjectionStrategy
4143
private boolean initComplete;
4244
private Method injectInputEventMethod;
4345
private Method setSourceMotionMethod;
44-
private Object instanceInputManagerObject;
46+
private InputManager inputManager;
4547
private int asyncEventMode;
4648
private int syncEventMode;
4749

@@ -55,49 +57,44 @@ InputManagerEventInjectionStrategy initialize() {
5557
try {
5658
Log.d(TAG, "Creating injection strategy with input manager.");
5759

58-
// Get the InputManager class object and initialize if necessary.
59-
Class<?> inputManagerClassObject = Class.forName("android.hardware.input.InputManager");
60-
Method getInstanceMethod = inputManagerClassObject.getDeclaredMethod("getInstance");
61-
getInstanceMethod.setAccessible(true);
60+
if (Build.VERSION.SDK_INT < 23) {
61+
Method getInstanceMethod = InputManager.class.getDeclaredMethod("getInstance");
62+
getInstanceMethod.setAccessible(true);
6263

63-
instanceInputManagerObject = getInstanceMethod.invoke(inputManagerClassObject);
64+
inputManager = (InputManager) getInstanceMethod.invoke(InputManager.class);
65+
} else {
66+
inputManager =
67+
InstrumentationRegistry.getInstrumentation()
68+
.getTargetContext()
69+
.getSystemService(InputManager.class);
70+
}
6471

6572
injectInputEventMethod =
66-
instanceInputManagerObject
67-
.getClass()
68-
.getDeclaredMethod("injectInputEvent", InputEvent.class, Integer.TYPE);
73+
InputManager.class.getDeclaredMethod("injectInputEvent", InputEvent.class, Integer.TYPE);
6974
injectInputEventMethod.setAccessible(true);
7075

7176
// Setting event mode to INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH to ensure
7277
// that we've dispatched the event and any side effects its had on the view hierarchy
7378
// have occurred.
7479
Field motionEventModeField =
75-
inputManagerClassObject.getField("INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH");
80+
InputManager.class.getField("INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH");
7681
motionEventModeField.setAccessible(true);
77-
syncEventMode = motionEventModeField.getInt(inputManagerClassObject);
82+
syncEventMode = motionEventModeField.getInt(InputManager.class);
7883

7984
if (Build.VERSION.SDK_INT >= 28) {
8085
// Starting from android P it is not allowed to access this field with reflection, hardcoded
8186
// this value as workaround.
8287
asyncEventMode = 0;
8388
} else {
8489
Field asyncMotionEventModeField =
85-
inputManagerClassObject.getField("INJECT_INPUT_EVENT_MODE_ASYNC");
90+
InputManager.class.getField("INJECT_INPUT_EVENT_MODE_ASYNC");
8691
asyncMotionEventModeField.setAccessible(true);
87-
asyncEventMode = asyncMotionEventModeField.getInt(inputManagerClassObject);
92+
asyncEventMode = asyncMotionEventModeField.getInt(InputManager.class);
8893
}
8994

9095
setSourceMotionMethod = MotionEvent.class.getDeclaredMethod("setSource", Integer.TYPE);
9196
initComplete = true;
92-
} catch (ClassNotFoundException e) {
93-
throw new RuntimeException(e);
94-
} catch (IllegalAccessException e) {
95-
throw new RuntimeException(e);
96-
} catch (InvocationTargetException e) {
97-
throw new RuntimeException(e);
98-
} catch (NoSuchMethodException e) {
99-
throw new RuntimeException(e);
100-
} catch (NoSuchFieldException e) {
97+
} catch (ReflectiveOperationException e) {
10198
throw new RuntimeException(e);
10299
}
103100
return this;
@@ -106,8 +103,7 @@ InputManagerEventInjectionStrategy initialize() {
106103
@Override
107104
public boolean injectKeyEvent(KeyEvent keyEvent) throws InjectEventSecurityException {
108105
try {
109-
return (Boolean)
110-
injectInputEventMethod.invoke(instanceInputManagerObject, keyEvent, syncEventMode);
106+
return (Boolean) injectInputEventMethod.invoke(inputManager, keyEvent, syncEventMode);
111107
} catch (IllegalAccessException e) {
112108
throw new RuntimeException(e);
113109
} catch (InvocationTargetException e) {
@@ -139,8 +135,7 @@ private boolean innerInjectMotionEvent(MotionEvent motionEvent, boolean shouldRe
139135
setSourceMotionMethod.invoke(motionEvent, InputDevice.SOURCE_TOUCHSCREEN);
140136
}
141137
int eventMode = sync ? syncEventMode : asyncEventMode;
142-
return (Boolean)
143-
injectInputEventMethod.invoke(instanceInputManagerObject, motionEvent, eventMode);
138+
return (Boolean) injectInputEventMethod.invoke(inputManager, motionEvent, eventMode);
144139
} catch (IllegalAccessException e) {
145140
throw new RuntimeException(e);
146141
} catch (IllegalArgumentException e) {

0 commit comments

Comments
 (0)