1616
1717package androidx .test .espresso .base ;
1818
19+ import android .hardware .input .InputManager ;
1920import android .os .Build ;
2021import android .os .SystemClock ;
2122import android .util .Log ;
2425import android .view .KeyEvent ;
2526import android .view .MotionEvent ;
2627import androidx .test .espresso .InjectEventSecurityException ;
28+ import androidx .test .platform .app .InstrumentationRegistry ;
2729import java .lang .reflect .Field ;
2830import java .lang .reflect .InvocationTargetException ;
2931import 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