diff options
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface/Android')
| -rw-r--r-- | Source/Core/InputCommon/ControllerInterface/Android/Android.cpp | 122 |
1 files changed, 82 insertions, 40 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index cf7e602a77..058a9e3171 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -67,8 +67,7 @@ jclass s_sensor_event_listener_class; jmethodID s_sensor_event_listener_constructor; jmethodID s_sensor_event_listener_constructor_input_device; jmethodID s_sensor_event_listener_set_device_qualifier; -jmethodID s_sensor_event_listener_enable_sensor_events; -jmethodID s_sensor_event_listener_disable_sensor_events; +jmethodID s_sensor_event_listener_request_unsuspend_sensor; jmethodID s_sensor_event_listener_get_axis_names; jmethodID s_sensor_event_listener_get_negative_axes; @@ -494,9 +493,45 @@ private: class AndroidSensorAxis final : public AndroidAxis { public: - AndroidSensorAxis(std::string name, bool negative) : AndroidAxis(std::move(name), negative) {} + // This class does not create its own global reference to the passed-in sensor_event_listener. + // That is, it's up to the device that contains this axis to keep sensor_event_listener valid. + // It does however create its own global reference to the passed-in name. + AndroidSensorAxis(JNIEnv* env, jobject sensor_event_listener, jstring j_name, bool negative) + : AndroidAxis(GetJString(env, j_name), negative), + m_sensor_event_listener(sensor_event_listener), + m_j_name(reinterpret_cast<jstring>(env->NewGlobalRef(j_name))) + { + } + + ~AndroidSensorAxis() { IDCache::GetEnvForThread()->DeleteGlobalRef(m_j_name); } bool IsDetectable() const override { return false; } + + ControlState GetState() const override + { + if (m_is_suspended.load(std::memory_order_relaxed)) + { + IDCache::GetEnvForThread()->CallVoidMethod( + m_sensor_event_listener, s_sensor_event_listener_request_unsuspend_sensor, m_j_name); + + // m_is_suspended is intentionally not updated here. To prevent the C++ suspended status from + // ending up desynced with the Java suspended status, we only update m_is_suspended when Java + // calls notifySensorSuspendedState (which calls NotifyIsSuspended). This way, Java is the + // authoritative source for the suspended status, and C++ mirrors it (possibly with a delay). + } + + return AndroidAxis::GetState(); + } + + void NotifyIsSuspended(bool is_suspended) + { + m_is_suspended.store(is_suspended, std::memory_order_relaxed); + } + +private: + const jobject m_sensor_event_listener; + const jstring m_j_name; + std::atomic<bool> m_is_suspended = true; }; class AndroidDevice final : public Core::Device @@ -611,40 +646,45 @@ private: jobject AddSensors(JNIEnv* env, jobject input_device) { - jobject sensor_event_listener; + jobject local_sensor_event_listener; if (input_device) { - sensor_event_listener = + local_sensor_event_listener = env->NewObject(s_sensor_event_listener_class, s_sensor_event_listener_constructor_input_device, input_device); } else { - sensor_event_listener = + local_sensor_event_listener = env->NewObject(s_sensor_event_listener_class, s_sensor_event_listener_constructor); } + jobject sensor_event_listener = env->NewGlobalRef(local_sensor_event_listener); + + env->DeleteLocalRef(local_sensor_event_listener); + jobjectArray j_axis_names = reinterpret_cast<jobjectArray>( env->CallObjectMethod(sensor_event_listener, s_sensor_event_listener_get_axis_names)); - std::vector<std::string> axis_names = JStringArrayToVector(env, j_axis_names); - env->DeleteLocalRef(j_axis_names); jbooleanArray j_negative_axes = reinterpret_cast<jbooleanArray>( env->CallObjectMethod(sensor_event_listener, s_sensor_event_listener_get_negative_axes)); jboolean* negative_axes = env->GetBooleanArrayElements(j_negative_axes, nullptr); - ASSERT(axis_names.size() == env->GetArrayLength(j_negative_axes)); - for (size_t i = 0; i < axis_names.size(); ++i) - AddInput(new AndroidSensorAxis(axis_names[i], negative_axes[i])); + const jsize axis_count = env->GetArrayLength(j_axis_names); + ASSERT(axis_count == env->GetArrayLength(j_negative_axes)); + for (jsize i = 0; i < axis_count; ++i) + { + const jstring axis_name = + reinterpret_cast<jstring>(env->GetObjectArrayElement(j_axis_names, i)); + AddInput(new AndroidSensorAxis(env, sensor_event_listener, axis_name, negative_axes[i])); + env->DeleteLocalRef(axis_name); + } + env->DeleteLocalRef(j_axis_names); env->ReleaseBooleanArrayElements(j_negative_axes, negative_axes, 0); env->DeleteLocalRef(j_negative_axes); - jobject global_sensor_event_listener = env->NewGlobalRef(sensor_event_listener); - - env->DeleteLocalRef(sensor_event_listener); - - return global_sensor_event_listener; + return sensor_event_listener; } const jobject m_sensor_event_listener; @@ -735,11 +775,8 @@ void Init() env->GetMethodID(s_sensor_event_listener_class, "<init>", "(Landroid/view/InputDevice;)V"); s_sensor_event_listener_set_device_qualifier = env->GetMethodID( s_sensor_event_listener_class, "setDeviceQualifier", "(Ljava/lang/String;)V"); - s_sensor_event_listener_enable_sensor_events = - env->GetMethodID(s_sensor_event_listener_class, "enableSensorEvents", - "(Lorg/dolphinemu/dolphinemu/features/input/model/SensorEventRequester;)V"); - s_sensor_event_listener_disable_sensor_events = - env->GetMethodID(s_sensor_event_listener_class, "disableSensorEvents", "()V"); + s_sensor_event_listener_request_unsuspend_sensor = env->GetMethodID( + s_sensor_event_listener_class, "requestUnsuspendSensor", "(Ljava/lang/String;)V"); s_sensor_event_listener_get_axis_names = env->GetMethodID(s_sensor_event_listener_class, "getAxisNames", "()[Ljava/lang/String;"); s_sensor_event_listener_get_negative_axes = @@ -934,7 +971,7 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } -JNIEXPORT void JNICALL +JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatchSensorEvent( JNIEnv* env, jclass, jstring j_device_qualifier, jstring j_axis_name, jfloat value) { @@ -943,10 +980,12 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch const std::shared_ptr<ciface::Core::Device> device = g_controller_interface.FindDevice(device_qualifier); if (!device) - return; + return JNI_FALSE; const std::string axis_name = GetJString(env, j_axis_name); + Clock::time_point last_polled{}; + for (ciface::Core::Device::Input* input : device->Inputs()) { const std::string input_name = input->GetName(); @@ -954,31 +993,34 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch { auto casted_input = static_cast<ciface::Android::AndroidInput*>(input); casted_input->SetState(value); + last_polled = std::max(last_polled, casted_input->GetLastPolled()); } } -} -JNIEXPORT void JNICALL -Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_enableSensorEvents( - JNIEnv* env, jclass, jobject j_sensor_event_requester) -{ - for (std::shared_ptr<ciface::Core::Device>& device : g_controller_interface.GetAllDevices()) - { - env->CallVoidMethod( - static_cast<ciface::Android::AndroidDevice*>(device.get())->GetSensorEventListener(), - s_sensor_event_listener_enable_sensor_events, j_sensor_event_requester); - } + return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } JNIEXPORT void JNICALL -Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_disableSensorEvents( - JNIEnv* env, jclass) +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_notifySensorSuspendedState( + JNIEnv* env, jclass, jstring j_device_qualifier, jobjectArray j_axis_names, jboolean suspended) { - for (std::shared_ptr<ciface::Core::Device>& device : g_controller_interface.GetAllDevices()) + ciface::Core::DeviceQualifier device_qualifier; + device_qualifier.FromString(GetJString(env, j_device_qualifier)); + const std::shared_ptr<ciface::Core::Device> device = + g_controller_interface.FindDevice(device_qualifier); + if (!device) + return; + + const std::vector<std::string> axis_names = JStringArrayToVector(env, j_axis_names); + + for (ciface::Core::Device::Input* input : device->Inputs()) { - env->CallVoidMethod( - static_cast<ciface::Android::AndroidDevice*>(device.get())->GetSensorEventListener(), - s_sensor_event_listener_disable_sensor_events); + const std::string input_name = input->GetName(); + if (std::find(axis_names.begin(), axis_names.end(), input_name) != axis_names.end()) + { + auto casted_input = static_cast<ciface::Android::AndroidSensorAxis*>(input); + casted_input->NotifyIsSuspended(static_cast<bool>(suspended)); + } } } |
