From 24c882622fbcfc7dafee14824ba1f070b000b3aa Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Sat, 10 Jun 2023 05:08:25 -0400 Subject: [PATCH] Android: Convert ControllerInterface to Kotlin --- .../input/model/ControllerInterface.java | 178 ------------------ .../input/model/ControllerInterface.kt | 150 +++++++++++++++ 2 files changed, 150 insertions(+), 178 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.java deleted file mode 100644 index 732ed97a7c..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.java +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.dolphinemu.dolphinemu.features.input.model; - -import android.content.Context; -import android.hardware.input.InputManager; -import android.os.Build; -import android.os.Handler; -import android.os.VibrationEffect; -import android.os.Vibrator; -import android.os.VibratorManager; -import android.view.InputDevice; -import android.view.KeyEvent; -import android.view.MotionEvent; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.dolphinemu.dolphinemu.DolphinApplication; -import org.dolphinemu.dolphinemu.utils.LooperThread; - -/** - * This class interfaces with the native ControllerInterface, - * which is where the emulator core gets inputs from. - */ -public final class ControllerInterface -{ - private static final class InputDeviceListener implements InputManager.InputDeviceListener - { - @Override - public void onInputDeviceAdded(int deviceId) - { - // Simple implementation for now. We could do something fancier if we wanted to. - refreshDevices(); - } - - @Override - public void onInputDeviceRemoved(int deviceId) - { - // Simple implementation for now. We could do something fancier if we wanted to. - refreshDevices(); - } - - @Override - public void onInputDeviceChanged(int deviceId) - { - // Simple implementation for now. We could do something fancier if we wanted to. - refreshDevices(); - } - } - - private static InputDeviceListener mInputDeviceListener; - private static LooperThread mLooperThread; - - /** - * Activities which want to pass on inputs to native code - * should call this in their own dispatchKeyEvent method. - * - * @return true if the emulator core seems to be interested in this event. - * false if the event should be passed on to the default dispatchKeyEvent. - */ - public static native boolean dispatchKeyEvent(KeyEvent event); - - /** - * Activities which want to pass on inputs to native code - * should call this in their own dispatchGenericMotionEvent method. - * - * @return true if the emulator core seems to be interested in this event. - * false if the event should be passed on to the default dispatchGenericMotionEvent. - */ - public static native boolean dispatchGenericMotionEvent(MotionEvent event); - - /** - * {@link DolphinSensorEventListener} calls this for each axis of a received SensorEvent. - * - * @return true if the emulator core seems to be interested in this event. - * false if the sensor can be suspended to save battery. - */ - public static native boolean dispatchSensorEvent(String deviceQualifier, String axisName, - float value); - - /** - * Called when a sensor is suspended or unsuspended. - * - * @param deviceQualifier A string used by native code for uniquely identifying devices. - * @param axisNames The name of all axes for the sensor. - * @param suspended Whether the sensor is now suspended. - */ - public static native void notifySensorSuspendedState(String deviceQualifier, String[] axisNames, - boolean suspended); - - /** - * Rescans for input devices. - */ - public static native void refreshDevices(); - - public static native String[] getAllDeviceStrings(); - - @Nullable - public static native CoreDevice getDevice(String deviceString); - - @Keep - private static void registerInputDeviceListener() - { - if (mLooperThread == null) - { - mLooperThread = new LooperThread("Hotplug thread"); - mLooperThread.start(); - } - - if (mInputDeviceListener == null) - { - InputManager im = (InputManager) - DolphinApplication.getAppContext().getSystemService(Context.INPUT_SERVICE); - - mInputDeviceListener = new InputDeviceListener(); - im.registerInputDeviceListener(mInputDeviceListener, new Handler(mLooperThread.getLooper())); - } - } - - @Keep - private static void unregisterInputDeviceListener() - { - if (mInputDeviceListener != null) - { - InputManager im = (InputManager) - DolphinApplication.getAppContext().getSystemService(Context.INPUT_SERVICE); - - im.unregisterInputDeviceListener(mInputDeviceListener); - mInputDeviceListener = null; - } - } - - @Keep @NonNull - private static DolphinVibratorManager getVibratorManager(InputDevice device) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) - { - return new DolphinVibratorManagerPassthrough(device.getVibratorManager()); - } - else - { - return new DolphinVibratorManagerCompat(device.getVibrator()); - } - } - - @Keep @NonNull - private static DolphinVibratorManager getSystemVibratorManager() - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) - { - VibratorManager vibratorManager = (VibratorManager) - DolphinApplication.getAppContext().getSystemService(Context.VIBRATOR_MANAGER_SERVICE); - - if (vibratorManager != null) - return new DolphinVibratorManagerPassthrough(vibratorManager); - } - - Vibrator vibrator = (Vibrator) - DolphinApplication.getAppContext().getSystemService(Context.VIBRATOR_SERVICE); - - return new DolphinVibratorManagerCompat(vibrator); - } - - @Keep - private static void vibrate(@NonNull Vibrator vibrator) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - { - vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)); - } - else - { - vibrator.vibrate(100); - } - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt new file mode 100644 index 0000000000..3bca59f7b7 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.features.input.model + +import android.content.Context +import android.hardware.input.InputManager +import android.os.Build +import android.os.Handler +import android.os.VibrationEffect +import android.os.Vibrator +import android.os.VibratorManager +import android.view.InputDevice +import android.view.KeyEvent +import android.view.MotionEvent +import androidx.annotation.Keep +import org.dolphinemu.dolphinemu.DolphinApplication +import org.dolphinemu.dolphinemu.utils.LooperThread + +/** + * This class interfaces with the native ControllerInterface, + * which is where the emulator core gets inputs from. + */ +object ControllerInterface { + private var inputDeviceListener: InputDeviceListener? = null + private lateinit var looperThread: LooperThread + + /** + * Activities which want to pass on inputs to native code + * should call this in their own dispatchKeyEvent method. + * + * @return true if the emulator core seems to be interested in this event. + * false if the event should be passed on to the default dispatchKeyEvent. + */ + external fun dispatchKeyEvent(event: KeyEvent): Boolean + + /** + * Activities which want to pass on inputs to native code + * should call this in their own dispatchGenericMotionEvent method. + * + * @return true if the emulator core seems to be interested in this event. + * false if the event should be passed on to the default dispatchGenericMotionEvent. + */ + external fun dispatchGenericMotionEvent(event: MotionEvent): Boolean + + /** + * [DolphinSensorEventListener] calls this for each axis of a received SensorEvent. + * + * @return true if the emulator core seems to be interested in this event. + * false if the sensor can be suspended to save battery. + */ + external fun dispatchSensorEvent( + deviceQualifier: String, + axisName: String, + value: Float + ): Boolean + + /** + * Called when a sensor is suspended or unsuspended. + * + * @param deviceQualifier A string used by native code for uniquely identifying devices. + * @param axisNames The name of all axes for the sensor. + * @param suspended Whether the sensor is now suspended. + */ + external fun notifySensorSuspendedState( + deviceQualifier: String, + axisNames: Array, + suspended: Boolean + ) + + /** + * Rescans for input devices. + */ + external fun refreshDevices() + + external fun getAllDeviceStrings(): Array + + external fun getDevice(deviceString: String): CoreDevice? + + @Keep + @JvmStatic + private fun registerInputDeviceListener() { + looperThread = LooperThread("Hotplug thread") + looperThread.start() + + if (inputDeviceListener == null) { + val im = DolphinApplication.getAppContext() + .getSystemService(Context.INPUT_SERVICE) as InputManager? + + inputDeviceListener = InputDeviceListener() + im!!.registerInputDeviceListener(inputDeviceListener, Handler(looperThread.looper)) + } + } + + @Keep + @JvmStatic + private fun unregisterInputDeviceListener() { + if (inputDeviceListener != null) { + val im = DolphinApplication.getAppContext() + .getSystemService(Context.INPUT_SERVICE) as InputManager? + + im!!.unregisterInputDeviceListener(inputDeviceListener) + inputDeviceListener = null + } + } + + @Keep + @JvmStatic + private fun getVibratorManager(device: InputDevice): DolphinVibratorManager { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + DolphinVibratorManagerPassthrough(device.vibratorManager) + } else { + DolphinVibratorManagerCompat(device.vibrator) + } + } + + @Keep + @JvmStatic + private fun getSystemVibratorManager(): DolphinVibratorManager { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val vibratorManager = DolphinApplication.getAppContext() + .getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager? + if (vibratorManager != null) + return DolphinVibratorManagerPassthrough(vibratorManager) + } + val vibrator = DolphinApplication.getAppContext() + .getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + return DolphinVibratorManagerCompat(vibrator) + } + + @Keep + @JvmStatic + private fun vibrate(vibrator: Vibrator) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)) + } else { + vibrator.vibrate(100) + } + } + + private class InputDeviceListener : InputManager.InputDeviceListener { + // Simple implementation for now. We could do something fancier if we wanted to. + override fun onInputDeviceAdded(deviceId: Int) = refreshDevices() + + // Simple implementation for now. We could do something fancier if we wanted to. + override fun onInputDeviceRemoved(deviceId: Int) = refreshDevices() + + // Simple implementation for now. We could do something fancier if we wanted to. + override fun onInputDeviceChanged(deviceId: Int) = refreshDevices() + } +}