public static void hook(ClassLoader loader) { final Class<?> CLASS_POINTER_EVENT_DISPATCHER = XposedHelpers.findClass(POINTER_EVENT_DISPATCHER_PATH, loader); XposedHelpers.findAndHookMethod(CLASS_POINTER_EVENT_DISPATCHER, "onInputEvent", InputEvent.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); try { if (param.args[0] instanceof MotionEvent) { MotionEvent event = (MotionEvent) param.args[0]; //XpLog.i("input x "+event.getX()); //XpLog.i("input y "+event.getY()); if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { PhoneWindowManagerHook.gesturesListener.onPointerEvent(event); } } } catch (Exception e) { XpLog.e(e); } } }); }
@Override public boolean handleInputEvent(@NonNull InputEvent event) { if (event instanceof KeyEvent) { KeyEvent keyEvent = (KeyEvent) event; if (keyEvent.getKeyCode() != KeyEvent.KEYCODE_DPAD_CENTER) return false; if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { if (mFastForwardAction != null && mSelectedActionId == mFastForwardAction.getId()) { if (keyEvent.getRepeatCount() == 0) { mCurrentMode = MODE_FAST_FORWARD; invokeFastForwardAction(); } } else if (mRewindAction != null && mSelectedActionId == mRewindAction.getId()) { if (keyEvent.getRepeatCount() == 0) { mCurrentMode = MODE_REWIND; invokeRewindAction(); } } } else if (keyEvent.getAction() == KeyEvent.ACTION_UP) { mCurrentMode = MODE_NOTHING; } } return false; }
public MotionEventSender() { try { Method imInstanceMethod = InputManager.class.getDeclaredMethod("getInstance"); imInstanceMethod.setAccessible(true); inputManager = (InputManager) imInstanceMethod.invoke(null); injectInputEventMethod = InputManager.class.getDeclaredMethod("injectInputEvent", android.view.InputEvent.class, int.class); int[] deviceIds = InputDevice.getDeviceIds(); for (int inputDeviceId : deviceIds) { InputDevice inputDevice = InputDevice.getDevice(inputDeviceId); int deviceSources = inputDevice.getSources(); if ((deviceSources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) { DEVICE_ID = inputDeviceId; break; } } } catch (Exception e) { e.printStackTrace(); exitFailure(); } }
@Override public boolean setEvent(InputEvent event) { VolumeKeyEvent volumeKeyEvent = (VolumeKeyEvent) event; if (volumeKeyEvent.getVolumeKeyEventType() == VolumeKeyEvent.VOLUME_KEY_EVENT_NATIVE && volumeKeyEvent.isVolumeKeyEvent()) { if (volumeKeyEvent.getAction() == KeyEvent.ACTION_DOWN) { if (volumeKeyEvent.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) { volumeDownPressed = true; } else if (volumeKeyEvent.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) { volumeUpPressed = true; } } else if (volumeKeyEvent.getAction() == KeyEvent.ACTION_UP) { if (volumeKeyEvent.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) { volumeDownPressed = false; } else if (volumeKeyEvent.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) { volumeUpPressed = false; } } this.isActionModePerformed(); return true; } return false; }
@Override public void saveEvent() { // Para evitar el problema de acceder en modo ASYNC_HOLD al evento original tras haberse encolado y terminado el proceso del evento por el navegador // En Android lo normal es reutilizar el objeto evento para siguientes eventos por ello tenemos que hacer una copia if (evtNative == null) return; // http://stackoverflow.com/questions/1626667/how-to-use-parcel-in-android Parcel parcelOut = Parcel.obtain(); parcelOut.writeValue(evtNative); byte[] data = parcelOut.marshall(); parcelOut.recycle(); Parcel parcelIn = Parcel.obtain(); parcelIn.unmarshall(data, 0, data.length); parcelIn.setDataPosition(0); this.evtNative = (InputEvent) parcelIn.readValue(evtNative.getClass().getClassLoader()); parcelIn.recycle(); }
private boolean onInterceptInputEvent(InputEvent event) { if (DEBUG) Log.v(TAG, "onInterceptInputEvent status " + mFadingStatus + " event " + event); boolean consumeEvent = (mFadingStatus == IDLE && mBgAlpha == 0); if (event instanceof KeyEvent) { if (consumeEvent) { consumeEvent = isConsumableKey((KeyEvent) event); } int keyCode = ((KeyEvent) event).getKeyCode(); // Back key typically means we're leaving the fragment if (keyCode != KeyEvent.KEYCODE_BACK) { tickle(); } } else { tickle(); } return consumeEvent; }
public EventInput() throws Exception { //Get the instance of InputManager class using reflection String methodName = "getInstance"; Object[] objArr = new Object[0]; im = (InputManager) InputManager.class.getDeclaredMethod(methodName, new Class[0]) .invoke(null, objArr); //Make MotionEvent.obtain() method accessible methodName = "obtain"; MotionEvent.class.getDeclaredMethod(methodName, new Class[0]).setAccessible(true); //Get the reference to injectInputEvent method methodName = "injectInputEvent"; injectInputEventMethod = InputManager.class.getMethod( methodName, new Class[]{InputEvent.class, Integer.TYPE}); }
private InputDeviceContext getContextForEvent(InputEvent event) { // Unknown devices use the default context if (event.getDeviceId() == 0) { return defaultContext; } else if (event.getDevice() == null) { // During device removal, sometimes we can get events after the // input device has been destroyed. In this case we'll see a // != 0 device ID but no device attached. return null; } // Return the existing context if it exists InputDeviceContext context = inputDeviceContexts.get(event.getDeviceId()); if (context != null) { return context; } // Otherwise create a new context context = createInputDeviceContextForDevice(event.getDevice()); inputDeviceContexts.put(event.getDeviceId(), context); return context; }
private void injectMethodFacade(InputEvent event) { try { injectInputEventMethod.invoke(inputManager, event, 2 /* InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH */); } catch (Exception e) { e.printStackTrace(); exitFailure(); } }
@Override public boolean setEvent(InputEvent event) { VolumeKeyEvent volumeKeyEvent = (VolumeKeyEvent) event; if (volumeKeyEvent.getVolumeKeyEventType() == VolumeKeyEvent.VOLUME_KEY_EVENT_ROCKER && volumeKeyEvent.isVolumeKeyEvent()) { buffer[current_ptr] = volumeKeyEvent.getPrevCurrentValue()[0]; current_ptr++; buffer[current_ptr] = volumeKeyEvent.getPrevCurrentValue()[1]; current_ptr++; if (current_ptr == MAX_BUFFER_SIZE) { current_ptr = 0; } return this.isActionModePerformed(); } return false; }
public ActivityViewWrapper(Context ctx) { try { Class<?> clazz = Class.forName("android.app.ActivityView"); mDefaultCtor = clazz.getConstructor(Context.class); mActivityView = (View)mDefaultCtor.newInstance(ctx); mStartActivityMethod = clazz.getMethod("startActivity", Intent.class); mInjectInputEvent = clazz.getDeclaredMethod("injectInputEvent", InputEvent.class); mInjectInputEvent.setAccessible(true); } catch (Exception e) { Log.e(TAG, "ActivityViewWrapper failed " + e); } }
public boolean injectInputEvent(InputEvent e) { try { return (Boolean) mInjectInputEvent.invoke(mActivityView, e); } catch (Exception ex) { Log.e(TAG, "ActivitityViewWrapper failed injectInputEvent", ex); } return false; }
public static boolean isDpadDevice(InputEvent event) { // Check that input comes from a device with directional pads. if ((event.getSource() & InputDevice.SOURCE_DPAD) != InputDevice.SOURCE_DPAD) { return true; } else { return false; } }
private InputDeviceState getInputDeviceState(InputEvent event) { final int deviceId = event.getDeviceId(); InputDeviceState state = mInputDeviceStates.get(deviceId); if (state == null) { final InputDevice device = event.getDevice(); if (device == null) { return null; } state = new InputDeviceState(device); mInputDeviceStates.put(deviceId, state); Log.i(TAG, device.toString()); } return state; }
/** * Until we get a joystick event, it is not certain what InputDevice corresponds to the joystick * Though there are methods for introspection, I was in a hurry and this does the job. */ private void initializeJoystickHandlerIfPossibleAndNecessary(InputEvent event) /*************************************************************************/ { if ((!joystickHandler_.isInitialized()) && (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) joystickHandler_.initializeDevice(event.getDevice()); }
/** * Check if the input event make us think that user is on TV. * If it is the case and if the Ui mode is not setup, then we propose to try the TV UI. * @param event */ private void checkUiChoice(InputEvent event) { // Make sure we go through this method only once if (sUiChoiceCheckDone) { return; } sUiChoiceCheckDone = true; // No need to check more if this APK does not integrate the leanback UI (this is decided at build time) if (!EntryActivity.isLeanbackUiAvailable()) { return; } boolean probablyTv = false; switch (event.getSource()) { // All these case mean the user is probably on TV case InputDevice.SOURCE_KEYBOARD: case InputDevice.SOURCE_TOUCHPAD: case InputDevice.SOURCE_DPAD: case InputDevice.SOURCE_GAMEPAD: case InputDevice.SOURCE_JOYSTICK: case InputDevice.SOURCE_HDMI: Log.d(TAG, "event source = "+event.getSource()+" -> probably TV"); probablyTv = true; break; case InputDevice.SOURCE_STYLUS: case InputDevice.SOURCE_TOUCHSCREEN: case InputDevice.SOURCE_TRACKBALL: case InputDevice.SOURCE_MOUSE: default: Log.d(TAG, "event source = "+event.getSource()+" -> probably not TV"); probablyTv = false; break; } if (!probablyTv) { return; } final String uiMode = PreferenceManager.getDefaultSharedPreferences(this) .getString(UiChoiceDialog.UI_CHOICE_LEANBACK_KEY, "unset"); // If the choice has not been done yet, ask user if (uiMode.equals("unset") && !getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { // no UI choice to do on actual AndroidTV devices new UiChoiceDialog().show(getFragmentManager(), "UiChoiceDialog"); } }
private boolean injectEventSync(InputEvent event) { return mUiAutomatorBridge.injectInputEvent(event, true); }
private boolean injectEventSync(InputEvent event) { return UiAutomatorBridge.getInstance().getInteractionController().injectEventSync(event); }
public boolean injectInputEvent(InputEvent event, boolean sync) throws UiAutomator2Exception { return (Boolean) invoke(method(CLASS_UI_AUTOMATOR_BRIDGE, METHOD_INJECT_INPUT_EVENT, InputEvent.class, boolean.class), uiAutomatorBridge, event, sync); }
public boolean injectEventSync(InputEvent event) throws UiAutomator2Exception { return (Boolean) invoke(method(CLASS_INTERACTION_CONTROLLER, METHOD_INJECT_EVENT_SYNC, InputEvent.class), interactionController, event); }
@Override protected boolean setEvent(InputEvent event) { return false; }
public final void setInputEvent(InputEvent event) { if (this.isEnabled) { this.setEvent(event); } }
@Override public void onUnhandledInputEvent(WebView view, InputEvent event) { logMethodCalled(); super.onUnhandledInputEvent(view, event); }
@Override public void onUnhandledInputEvent(WebView view, InputEvent event) { Logs.i(TAG, "onUnhandledInputEvent"); super.onUnhandledInputEvent(view, event); }
private GamepadDevice getGamepadForEvent(InputEvent event) { return getDeviceById(event.getDeviceId()); }
public DroidInputEventImpl(DroidEventListener listener, InputEvent evtNative) { super(listener); this.evtNative = evtNative; }
public InputEvent getInputEvent() { return evtNative; }
public boolean injectInputEvent(InputEvent e) { return mActivityViewWrapper.injectInputEvent(e); }
public int getDirectionPressed(InputEvent event) { if (!isDpadDevice(event)) { return -1; } // If the input event is a MotionEvent, check its hat axis values. if (event instanceof MotionEvent) { // Use the hat axis value to find the D-pad direction MotionEvent motionEvent = (MotionEvent) event; float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X); float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y); // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad // LEFT and RIGHT direction accordingly. if (Float.compare(xaxis, -1.0f) == 0) { directionPressed = Dpad.LEFT; } else if (Float.compare(xaxis, 1.0f) == 0) { directionPressed = Dpad.RIGHT; } // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad // UP and DOWN direction accordingly. else if (Float.compare(yaxis, -1.0f) == 0) { directionPressed = Dpad.UP; } else if (Float.compare(yaxis, 1.0f) == 0) { directionPressed = Dpad.DOWN; } } // If the input event is a KeyEvent, check its key code. else if (event instanceof KeyEvent) { // Use the key code to find the D-pad direction. KeyEvent keyEvent = (KeyEvent) event; if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) { directionPressed = Dpad.LEFT; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) { directionPressed = Dpad.RIGHT; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) { directionPressed = Dpad.UP; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) { directionPressed = Dpad.DOWN; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) { directionPressed = Dpad.CENTER; } } return directionPressed; }
public InjectionManager(Context c) { if(Integer.valueOf(android.os.Build.VERSION.SDK_INT) < android.os.Build.VERSION_CODES.JELLY_BEAN) { mWmbinder = ServiceManager.getService( INTERNAL_SERVICE_PRE_JELLY ); mWinMan = IWindowManager.Stub.asInterface( mWmbinder ); printDeclaredMethods(mWinMan.getClass()); //TODO: Implement full injection support for pre Jelly Bean solutions } else { mInputManager = c.getSystemService(Context.INPUT_SERVICE); try { //printDeclaredMethods(mInputManager.getClass()); //Unveil hidden methods mInjectEventMethod = mInputManager.getClass().getDeclaredMethod("injectInputEvent", new Class[] { InputEvent.class, Integer.TYPE }); mInjectEventMethod.setAccessible(true); Field eventAsync = mInputManager.getClass().getDeclaredField("INJECT_INPUT_EVENT_MODE_ASYNC"); Field eventResult = mInputManager.getClass().getDeclaredField("INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT"); Field eventFinish = mInputManager.getClass().getDeclaredField("INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH"); eventAsync.setAccessible(true); eventResult.setAccessible(true); eventFinish.setAccessible(true); INJECT_INPUT_EVENT_MODE_ASYNC = eventAsync.getInt(mInputManager.getClass()); INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = eventResult.getInt(mInputManager.getClass()); INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = eventFinish.getInt(mInputManager.getClass()); } catch (NoSuchMethodException nsme) { Log.e(TAG, "Critical methods not available"); } catch (NoSuchFieldException nsfe) { Log.e(TAG, "Critical fields not available"); } catch (IllegalAccessException iae) { Log.e(TAG, "Critical fields not accessable"); } } }
private static void init() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class}); wm = IWindowManager.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"})); im = (InputManager) InputManager.class.getDeclaredMethod("getInstance", new Class[0]).invoke(null, new Object[0]); MotionEvent.class.getDeclaredMethod("obtain", new Class[0]).setAccessible(true); injectInputEventMethod = InputManager.class.getMethod("injectInputEvent", new Class[]{InputEvent.class, Integer.TYPE}); }
@Override public void onUnhandledInputEvent(WebView view, InputEvent event) { }
public void onUnhandledInputEvent(WebView view, InputEvent event);
protected abstract boolean setEvent(InputEvent event);
public InputEvent getInputEvent();