diff --git a/.gitignore b/.gitignore index 75e728babe..20ed5e93c1 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,6 @@ artifacts /install* vulkansdk*.exe *.tar.zst + +# Build-time generated external sources +externals/generated diff --git a/CMakeLists.txt b/CMakeLists.txt index 477e7c636d..bc4b991b4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,8 +214,6 @@ if(MSVC) endif() # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system -cmake_dependent_option(YUZU_USE_BUNDLED_SDL3 "Download bundled SDL3 build" "${MSVC}" "NOT ANDROID" OFF) - option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) set(EXT_DEFAULT OFF) @@ -223,6 +221,8 @@ if (MSVC OR ANDROID) set(EXT_DEFAULT ON) endif() +option(YUZU_USE_BUNDLED_SDL3 "Download bundled SDL3 build" ${EXT_DEFAULT}) + # ffmpeg option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT}) cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from external source" "${SOLARIS}" "NOT WIN32 AND NOT ANDROID" OFF) diff --git a/cpmfile.json b/cpmfile.json index c0d879f838..c5ea35c955 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -186,12 +186,6 @@ "repo": "eden-emulator/oaknut", "version": "v2.0.3" }, - "oboe": { - "bundled": true, - "hash": "ce4011afe7345370d4ead3b891cd69a5ef224b129535783586c0ca75051d303ed446e6c7f10bde8da31fff58d6e307f1732a3ffd03b249f9ef1fd48fd4132715", - "repo": "google/oboe", - "version": "1.10.0" - }, "openssl": { "hash": "29002ce50cb95a4f4f1d0e9d3f684401fbd4eac34203dc2eef3b6334af5d44aa46bf788b63a6f5c139c383eafb7269ae87a58a9a3ad5912903b9773e545ccc0a", "min_version": "3.0.0", diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 6e324ce9f6..0682f643e2 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -136,48 +136,49 @@ if(ENABLE_CUBEB) endif() endif() -if (NOT ANDROID) - if (NOT YUZU_USE_BUNDLED_SDL3) - if (NOT WIN32) - # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers - # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) - # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) - # CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809) - set(SDL_UNUSED_SUBSYSTEMS - File Filesystem - Locale Power Render) - foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) - string(TOUPPER ${_SUB} _OPT) - set(SDL_${_OPT} OFF) - endforeach() +if (NOT YUZU_USE_BUNDLED_SDL3) + if (NOT WIN32) + # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers + # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) + # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) + # CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809) + set(SDL_UNUSED_SUBSYSTEMS + File Filesystem + Locale Power Render) + foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) + string(TOUPPER ${_SUB} _OPT) + set(SDL_${_OPT} OFF) + endforeach() - set(HIDAPI ON) - endif() - - if (APPLE) - set(SDL_FILE ON) - endif() - - AddJsonPackage(sdl3) - else() - message(STATUS "Using bundled SDL3") - AddJsonPackage(sdl3-ci) + set(HIDAPI ON) endif() - # Normalize SDL3 link target across package variants. - # Some SDL3 packages export only SDL3::SDL3-shared or SDL3::SDL3-static. - if (NOT TARGET SDL3::SDL3) - if (TARGET SDL3::SDL3-shared) - add_library(SDL3::SDL3 ALIAS SDL3::SDL3-shared) - elseif (TARGET SDL3::SDL3-static) - add_library(SDL3::SDL3 ALIAS SDL3::SDL3-static) - else() - message(FATAL_ERROR "SDL3 package found, but no usable SDL3 target was exported") - endif() + if (APPLE) + set(SDL_FILE ON) + endif() + + AddJsonPackage(sdl3) +else() + message(STATUS "Using bundled SDL3") + AddJsonPackage(sdl3-ci) + + # copy sdl java sources for consumption by Gradle + if (ANDROID) + file(COPY ${SDL3_SOURCE_DIR}/java DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/generated/sdl) endif() endif() -set(BUILD_SHARED_LIBS OFF) +# Normalize SDL3 link target across package variants. +# Some SDL3 packages export only SDL3::SDL3-shared or SDL3::SDL3-static. +if (NOT TARGET SDL3::SDL3) + if (TARGET SDL3::SDL3-shared) + add_library(SDL3::SDL3 ALIAS SDL3::SDL3-shared) + elseif (TARGET SDL3::SDL3-static) + add_library(SDL3::SDL3 ALIAS SDL3::SDL3-static) + else() + message(FATAL_ERROR "SDL3 package found, but no usable SDL3 target was exported") + endif() +endif() # SPIRV Headers AddJsonPackage(spirv-headers) @@ -385,13 +386,6 @@ if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client) endif() endif() -# oboe -if (ANDROID) - AddJsonPackage(oboe) - - add_library(oboe::oboe ALIAS oboe) -endif() - if (APPLE) # moltenvk if (NOT YUZU_USE_BUNDLED_MOLTENVK) diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index 0cef7e7196..3ae6d73994 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -272,6 +272,13 @@ android { resValue("string", "app_name_suffixed", "$currentName$suffix") resValue("string", "app_name", "Eden$suffix") } + + sourceSets { + named("main") { + java.srcDir("${edenDir}/externals/generated/sdl/java") + kotlin.srcDir("${edenDir}/externals/generated/sdl/java") + } + } } idea { diff --git a/src/android/app/proguard-rules.pro b/src/android/app/proguard-rules.pro index 691e08fd03..91f63bbb84 100644 --- a/src/android/app/proguard-rules.pro +++ b/src/android/app/proguard-rules.pro @@ -9,6 +9,9 @@ -keep class org.ini4j.spi.IniBuilder -keep class org.ini4j.spi.IniFormatter +-keep class org.libsdl.app.** { *; } +-keepclassmembers class org.libsdl.app.** { *; } + # Suppress warnings for R8 -dontwarn org.bouncycastle.jsse.BCSSLParameters -dontwarn org.bouncycastle.jsse.BCSSLSocket diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index 4b46dd76a2..77222884c6 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt @@ -16,6 +16,7 @@ import android.widget.TextView import androidx.annotation.Keep import androidx.core.net.toUri import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.libsdl.app.SDL import java.lang.ref.WeakReference import org.yuzu.yuzu_emu.activities.EmulationActivity import org.yuzu.yuzu_emu.fragments.CoreErrorDialogFragment @@ -52,6 +53,8 @@ object NativeLibrary { init { try { System.loadLibrary("yuzu-android") + SDL.setupJNI() + initJvm() } catch (ex: UnsatisfiedLinkError) { error("[NativeLibrary] $ex") } @@ -367,6 +370,7 @@ object NativeLibrary { NetPlayManager.clearChat() } + external fun initJvm() external fun initMultiplayer() @Keep diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index 7013691765..86c05d7c0d 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -22,7 +22,7 @@ add_library(yuzu-android SHARED set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common video_core) -target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) +target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log GLESv2) if (ARCHITECTURE_arm64) target_link_libraries(yuzu-android PRIVATE adrenotools) endif() diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 9fc550985a..423edc2c1b 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -1730,6 +1730,15 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_loadAmiibo(JNIEnv* env, jobject jobj, return static_cast(info); } +extern "C" JNIEXPORT void JNICALL +Java_org_yuzu_yuzu_1emu_NativeLibrary_initJvm(JNIEnv *env, jclass clazz) { + JavaVM *vm; + if (env->GetJavaVM(&vm) != JNI_OK) + return; + + Common::Android::Initialize(vm, env); +} + JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_initMultiplayer( JNIEnv* env, [[maybe_unused]] jobject obj) { diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml index 98b94d166d..6b40d97f2a 100644 --- a/src/android/app/src/main/res/values-fa/strings.xml +++ b/src/android/app/src/main/res/values-fa/strings.xml @@ -800,7 +800,6 @@ تاریک - oboe cubeb diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index b1c0a98a61..931cf2bfa7 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -465,13 +465,13 @@ @string/auto - @string/oboe + @string/sdl3 @string/cubeb @string/string_null 0 - 4 + 2 1 3 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 3f6d1889ff..55783f6e43 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -1240,7 +1240,7 @@ Dark - oboe + SDL3 cubeb diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index b186edaab4..b244d657a9 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -238,20 +238,11 @@ if (ENABLE_CUBEB) target_compile_definitions(audio_core PRIVATE HAVE_CUBEB=1) endif() -if(ANDROID) - target_sources(audio_core PRIVATE - sink/oboe_sink.cpp - sink/oboe_sink.h) +target_sources(audio_core PRIVATE + sink/sdl3_sink.cpp + sink/sdl3_sink.h) - target_link_libraries(audio_core PRIVATE oboe) - target_compile_definitions(audio_core PUBLIC HAVE_OBOE) -else() - target_sources(audio_core PRIVATE - sink/sdl3_sink.cpp - sink/sdl3_sink.h) - - target_link_libraries(audio_core PRIVATE SDL3::SDL3) - target_compile_definitions(audio_core PRIVATE HAVE_SDL3) -endif() +target_link_libraries(audio_core PRIVATE SDL3::SDL3) +target_compile_definitions(audio_core PRIVATE HAVE_SDL3) create_target_directory_groups(audio_core) diff --git a/src/audio_core/sink/oboe_sink.cpp b/src/audio_core/sink/oboe_sink.cpp deleted file mode 100644 index d1ead7d880..0000000000 --- a/src/audio_core/sink/oboe_sink.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include - -#include - -#include "audio_core/common/common.h" -#include "audio_core/sink/oboe_sink.h" -#include "audio_core/sink/sink_stream.h" -#include "common/logging.h" -#include "common/scope_exit.h" -#include "core/core.h" - -namespace AudioCore::Sink { - -class OboeSinkStream final : public SinkStream, - public oboe::AudioStreamDataCallback, - public oboe::AudioStreamErrorCallback { -public: - explicit OboeSinkStream(Core::System& system_, StreamType type_, const std::string& name_, - u32 system_channels_) - : SinkStream(system_, type_) { - name = name_; - system_channels = system_channels_; - - this->OpenStream(); - } - - ~OboeSinkStream() override { - LOG_INFO(Audio_Sink, "Destroyed Oboe stream"); - } - - void Finalize() override { - this->Stop(); - m_stream.reset(); - } - - void Start(bool resume = false) override { - if (!m_stream || !paused) { - return; - } - - paused = false; - - if (m_stream->start() != oboe::Result::OK) { - LOG_CRITICAL(Audio_Sink, "Error starting Oboe stream"); - } - } - - void Stop() override { - if (!m_stream || paused) { - return; - } - - this->SignalPause(); - - if (m_stream->stop() != oboe::Result::OK) { - LOG_CRITICAL(Audio_Sink, "Error stopping Oboe stream"); - } - } - -public: - static s32 QueryChannelCount(oboe::Direction direction) { - std::shared_ptr temp_stream; - oboe::AudioStreamBuilder builder; - - const auto result = ConfigureBuilder(builder, direction)->openStream(temp_stream); - if (result == oboe::Result::OK) { - return temp_stream->getChannelCount() >= 6 ? 6 : 2; - } - - LOG_ERROR(Audio_Sink, "Failed to open {} stream. Using default channel count 2", - direction == oboe::Direction::Output ? "output" : "input"); - return 2; - } - -protected: - oboe::DataCallbackResult onAudioReady(oboe::AudioStream*, void* audio_data, - s32 num_buffer_frames) override { - const size_t num_channels = this->GetDeviceChannels(); - const size_t frame_size = num_channels; - const size_t num_frames = static_cast(num_buffer_frames); - - if (type == StreamType::In) { - std::span input_buffer{reinterpret_cast(audio_data), - num_frames * frame_size}; - this->ProcessAudioIn(input_buffer, num_frames); - } else { - std::span output_buffer{reinterpret_cast(audio_data), - num_frames * frame_size}; - this->ProcessAudioOutAndRender(output_buffer, num_frames); - } - - return oboe::DataCallbackResult::Continue; - } - - void onErrorAfterClose(oboe::AudioStream*, oboe::Result) override { - LOG_INFO(Audio_Sink, "Audio stream closed, reinitializing"); - - if (this->OpenStream()) { - m_stream->start(); - } - } - -private: - static oboe::AudioStreamBuilder* ConfigureBuilder(oboe::AudioStreamBuilder& builder, - oboe::Direction direction) { - // TODO: investigate callback delay issues when using AAudio - return builder.setPerformanceMode(oboe::PerformanceMode::LowLatency) - ->setAudioApi(oboe::AudioApi::OpenSLES) - ->setDirection(direction) - ->setSampleRate(TargetSampleRate) - ->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::High) - ->setFormat(oboe::AudioFormat::I16) - ->setFormatConversionAllowed(true) - ->setUsage(oboe::Usage::Game) - ->setBufferCapacityInFrames(TargetSampleCount * 2); - } - - bool OpenStream() { - const auto direction = [&]() { - switch (type) { - case StreamType::In: - return oboe::Direction::Input; - case StreamType::Out: - case StreamType::Render: - return oboe::Direction::Output; - default: - ASSERT(false); - return oboe::Direction::Output; - } - }(); - - const auto expected_channels = QueryChannelCount(direction); - const auto expected_mask = [&]() { - switch (expected_channels) { - case 1: - return oboe::ChannelMask::Mono; - case 2: - return oboe::ChannelMask::Stereo; - case 6: - return oboe::ChannelMask::CM5Point1; - default: - ASSERT(false); - return oboe::ChannelMask::Unspecified; - } - }(); - - oboe::AudioStreamBuilder builder; - const auto result = ConfigureBuilder(builder, direction) - ->setChannelCount(expected_channels) - ->setChannelMask(expected_mask) - ->setChannelConversionAllowed(true) - ->setDataCallback(this) - ->setErrorCallback(this) - ->openStream(m_stream); - ASSERT(result == oboe::Result::OK); - return result == oboe::Result::OK && this->SetStreamProperties(); - } - - bool SetStreamProperties() { - ASSERT(m_stream); - - m_stream->setBufferSizeInFrames(TargetSampleCount * 2); - device_channels = m_stream->getChannelCount(); - - const auto sample_rate = m_stream->getSampleRate(); - const auto buffer_capacity = m_stream->getBufferCapacityInFrames(); - const auto stream_backend = - m_stream->getAudioApi() == oboe::AudioApi::AAudio ? "AAudio" : "OpenSLES"; - - LOG_INFO(Audio_Sink, "Opened Oboe {} stream with {} channels sample rate {} capacity {}", - stream_backend, device_channels, sample_rate, buffer_capacity); - - return true; - } - - std::shared_ptr m_stream{}; -}; - -OboeSink::OboeSink() { - // TODO: This is not generally knowable - // The channel count is distinct based on direction and can change - device_channels = OboeSinkStream::QueryChannelCount(oboe::Direction::Output); -} - -OboeSink::~OboeSink() = default; - -SinkStream* OboeSink::AcquireSinkStream(Core::System& system, u32 system_channels, - const std::string& name, StreamType type) { - SinkStreamPtr& stream = sink_streams.emplace_back( - std::make_unique(system, type, name, system_channels)); - - return stream.get(); -} - -void OboeSink::CloseStream(SinkStream* to_remove) { - sink_streams.remove_if([&](auto& stream) { return stream.get() == to_remove; }); -} - -void OboeSink::CloseStreams() { - sink_streams.clear(); -} - -f32 OboeSink::GetDeviceVolume() const { - if (sink_streams.empty()) { - return 1.0f; - } - - return sink_streams.front()->GetDeviceVolume(); -} - -void OboeSink::SetDeviceVolume(f32 volume) { - for (auto& stream : sink_streams) { - stream->SetDeviceVolume(volume); - } -} - -void OboeSink::SetSystemVolume(f32 volume) { - for (auto& stream : sink_streams) { - stream->SetSystemVolume(volume); - } -} - -} // namespace AudioCore::Sink diff --git a/src/audio_core/sink/oboe_sink.h b/src/audio_core/sink/oboe_sink.h deleted file mode 100644 index 8f6f54ab53..0000000000 --- a/src/audio_core/sink/oboe_sink.h +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -#include "audio_core/sink/sink.h" - -namespace Core { -class System; -} - -namespace AudioCore::Sink { -class SinkStream; - -class OboeSink final : public Sink { -public: - explicit OboeSink(); - ~OboeSink() override; - - /** - * Create a new sink stream. - * - * @param system - Core system. - * @param system_channels - Number of channels the audio system expects. - * May differ from the device's channel count. - * @param name - Name of this stream. - * @param type - Type of this stream, render/in/out. - * - * @return A pointer to the created SinkStream - */ - SinkStream* AcquireSinkStream(Core::System& system, u32 system_channels, - const std::string& name, StreamType type) override; - - /** - * Close a given stream. - * - * @param stream - The stream to close. - */ - void CloseStream(SinkStream* stream) override; - - /** - * Close all streams. - */ - void CloseStreams() override; - - /** - * Get the device volume. Set from calls to the IAudioDevice service. - * - * @return Volume of the device. - */ - f32 GetDeviceVolume() const override; - - /** - * Set the device volume. Set from calls to the IAudioDevice service. - * - * @param volume - New volume of the device. - */ - void SetDeviceVolume(f32 volume) override; - - /** - * Set the system volume. Comes from the audio system using this stream. - * - * @param volume - New volume of the system. - */ - void SetSystemVolume(f32 volume) override; - -private: - /// List of streams managed by this sink - std::list sink_streams{}; -}; - -} // namespace AudioCore::Sink diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp index 1b737eb12e..efd8fceb32 100644 --- a/src/audio_core/sink/sink_details.cpp +++ b/src/audio_core/sink/sink_details.cpp @@ -10,9 +10,6 @@ #include #include "audio_core/sink/sink_details.h" -#ifdef HAVE_OBOE -#include "audio_core/sink/oboe_sink.h" -#endif #ifdef HAVE_CUBEB #include "audio_core/sink/cubeb_sink.h" #endif @@ -43,24 +40,8 @@ struct SinkDetails { /// SuitableFn is_suitable; // REVERTED FOR LatencyFn latency ABOVE - DIABLO 3 FIX }; -// NOTE TO PROBABLY FIX LATER FOR ANDROID - the return value "0u" for the first HAVE_OBOE -// section below was just copied from the null section so there's a somewhat valid value -// being returned, since the previous "true" value probably isn't compatible with the -// previous EA-3833 code. (HAVE_OBOE was introduced in a later release.) Eventually need -// to change "0u" for something else directly from the oboe_sink.cpp functions. - // sink_details is ordered in terms of desirability, with the best choice at the top. constexpr SinkDetails sink_details[] = { -#ifdef HAVE_OBOE - SinkDetails{ - Settings::AudioEngine::Oboe, - [](std::string_view device_id) -> std::unique_ptr { - return std::make_unique(); - }, - [](bool capture) { return std::vector{"Default"}; }, - []() { return 0u; }, - }, -#endif #ifdef HAVE_CUBEB SinkDetails{ Settings::AudioEngine::Cubeb, diff --git a/src/common/android/android_common.cpp b/src/common/android/android_common.cpp index a1cf081695..5041579e0e 100644 --- a/src/common/android/android_common.cpp +++ b/src/common/android/android_common.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -// SPDX-FileCopyrightText: 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include "android_common.h" @@ -51,7 +51,7 @@ jstring ToJString(JNIEnv* env, std::u16string_view str) { } double GetJDouble(JNIEnv* env, jobject jdouble) { - return env->GetDoubleField(jdouble, GetDoubleValueField()); + return env->CallDoubleMethod(jdouble, GetDoubleValueMethod()); } jobject ToJDouble(JNIEnv* env, double value) { @@ -59,7 +59,7 @@ jobject ToJDouble(JNIEnv* env, double value) { } s32 GetJInteger(JNIEnv* env, jobject jinteger) { - return env->GetIntField(jinteger, GetIntegerValueField()); + return env->CallIntMethod(jinteger, GetIntegerValueMethod()); } jobject ToJInteger(JNIEnv* env, s32 value) { @@ -67,7 +67,7 @@ jobject ToJInteger(JNIEnv* env, s32 value) { } bool GetJBoolean(JNIEnv* env, jobject jboolean) { - return env->GetBooleanField(jboolean, GetBooleanValueField()); + return env->CallBooleanMethod(jboolean, GetBooleanValueMethod()); } jobject ToJBoolean(JNIEnv* env, bool value) { diff --git a/src/common/android/id_cache.cpp b/src/common/android/id_cache.cpp index 0fb358f6e4..3da532703a 100644 --- a/src/common/android/id_cache.cpp +++ b/src/common/android/id_cache.cpp @@ -63,15 +63,15 @@ static jfieldID s_patch_title_id_field; static jclass s_double_class; static jmethodID s_double_constructor; -static jfieldID s_double_value_field; +static jmethodID s_double_value_method; static jclass s_integer_class; static jmethodID s_integer_constructor; -static jfieldID s_integer_value_field; +static jmethodID s_integer_value_method; static jclass s_boolean_class; static jmethodID s_boolean_constructor; -static jfieldID s_boolean_value_field; +static jmethodID s_boolean_value_method; static jclass s_player_input_class; static jmethodID s_player_input_constructor; @@ -103,7 +103,6 @@ static jmethodID s_clear_chat; static constexpr jint JNI_VERSION = JNI_VERSION_1_6; namespace Common::Android { - JNIEnv *GetEnvForThread() { thread_local static struct OwnedEnv { OwnedEnv() { @@ -299,8 +298,8 @@ namespace Common::Android { return s_double_constructor; } - jfieldID GetDoubleValueField() { - return s_double_value_field; + jmethodID GetDoubleValueMethod() { + return s_double_value_method; } jclass GetIntegerClass() { @@ -311,8 +310,8 @@ namespace Common::Android { return s_integer_constructor; } - jfieldID GetIntegerValueField() { - return s_integer_value_field; + jmethodID GetIntegerValueMethod() { + return s_integer_value_method; } jclass GetBooleanClass() { @@ -323,8 +322,8 @@ namespace Common::Android { return s_boolean_constructor; } - jfieldID GetBooleanValueField() { - return s_boolean_value_field; + jmethodID GetBooleanValueMethod() { + return s_boolean_value_method; } jclass GetPlayerInputClass() { @@ -429,188 +428,6 @@ namespace Common::Android { jint InitFFmpegOnLoad(JavaVM *vm); - jint JNI_OnLoad(JavaVM *vm, void *reserved) { - s_java_vm = vm; - InitFFmpegOnLoad(vm); - - JNIEnv *env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION) != JNI_OK) - return JNI_ERR; - - // Initialize Java classes - const jclass native_library_class = env->FindClass("org/yuzu/yuzu_emu/NativeLibrary"); - s_native_library_class = reinterpret_cast(env->NewGlobalRef(native_library_class)); - s_disk_cache_progress_class = reinterpret_cast(env->NewGlobalRef( - env->FindClass("org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress"))); - s_load_callback_stage_class = reinterpret_cast(env->NewGlobalRef(env->FindClass( - "org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress$LoadCallbackStage"))); - - const jclass game_dir_class = env->FindClass("org/yuzu/yuzu_emu/model/GameDir"); - s_game_dir_class = reinterpret_cast(env->NewGlobalRef(game_dir_class)); - s_game_dir_constructor = env->GetMethodID(game_dir_class, "", - "(Ljava/lang/String;Z)V"); - env->DeleteLocalRef(game_dir_class); - - // Initialize methods - s_exit_emulation_activity = - env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V"); - s_disk_cache_load_progress = - env->GetStaticMethodID(s_disk_cache_progress_class, "loadProgress", "(III)V"); - s_copy_to_storage = env->GetStaticMethodID(s_native_library_class, "copyFileToStorage", - "(Ljava/lang/String;Ljava/lang/String;)Z"); - s_file_exists = env->GetStaticMethodID(s_native_library_class, "exists", - "(Ljava/lang/String;)Z"); - s_file_extension = env->GetStaticMethodID(s_native_library_class, "getFileExtension", - "(Ljava/lang/String;)Ljava/lang/String;"); - s_on_emulation_started = - env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V"); - s_on_emulation_stopped = - env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V"); - s_on_program_changed = - env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V"); - - const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game"); - s_game_class = reinterpret_cast(env->NewGlobalRef(game_class)); - s_game_constructor = env->GetMethodID(game_class, "", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" - "String;Ljava/lang/String;Ljava/lang/String;Z)V"); - s_game_title_field = env->GetFieldID(game_class, "title", "Ljava/lang/String;"); - s_game_path_field = env->GetFieldID(game_class, "path", "Ljava/lang/String;"); - s_game_program_id_field = env->GetFieldID(game_class, "programId", "Ljava/lang/String;"); - s_game_developer_field = env->GetFieldID(game_class, "developer", "Ljava/lang/String;"); - s_game_version_field = env->GetFieldID(game_class, "version", "Ljava/lang/String;"); - s_game_is_homebrew_field = env->GetFieldID(game_class, "isHomebrew", "Z"); - env->DeleteLocalRef(game_class); - - const jclass string_class = env->FindClass("java/lang/String"); - s_string_class = reinterpret_cast(env->NewGlobalRef(string_class)); - env->DeleteLocalRef(string_class); - - const jclass pair_class = env->FindClass("kotlin/Pair"); - s_pair_class = reinterpret_cast(env->NewGlobalRef(pair_class)); - s_pair_constructor = - env->GetMethodID(pair_class, "", "(Ljava/lang/Object;Ljava/lang/Object;)V"); - s_pair_first_field = env->GetFieldID(pair_class, "first", "Ljava/lang/Object;"); - s_pair_second_field = env->GetFieldID(pair_class, "second", "Ljava/lang/Object;"); - env->DeleteLocalRef(pair_class); - - const jclass overlay_control_data_class = - env->FindClass("org/yuzu/yuzu_emu/overlay/model/OverlayControlData"); - s_overlay_control_data_class = - reinterpret_cast(env->NewGlobalRef(overlay_control_data_class)); - s_overlay_control_data_constructor = - env->GetMethodID(overlay_control_data_class, "", - "(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;F)V"); - s_overlay_control_data_id_field = - env->GetFieldID(overlay_control_data_class, "id", "Ljava/lang/String;"); - s_overlay_control_data_enabled_field = - env->GetFieldID(overlay_control_data_class, "enabled", "Z"); - s_overlay_control_data_landscape_position_field = - env->GetFieldID(overlay_control_data_class, "landscapePosition", "Lkotlin/Pair;"); - s_overlay_control_data_portrait_position_field = - env->GetFieldID(overlay_control_data_class, "portraitPosition", "Lkotlin/Pair;"); - s_overlay_control_data_foldable_position_field = - env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); - s_overlay_control_data_individual_scale_field = - env->GetFieldID(overlay_control_data_class, "individualScale", "F"); - env->DeleteLocalRef(overlay_control_data_class); - - const jclass patch_class = env->FindClass("org/yuzu/yuzu_emu/model/Patch"); - s_patch_class = reinterpret_cast(env->NewGlobalRef(patch_class)); - s_patch_constructor = env->GetMethodID( - patch_class, "", - "(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JI)V"); - s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z"); - s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;"); - s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;"); - s_patch_type_field = env->GetFieldID(patch_class, "type", "I"); - s_patch_program_id_field = env->GetFieldID(patch_class, "programId", "Ljava/lang/String;"); - s_patch_title_id_field = env->GetFieldID(patch_class, "titleId", "Ljava/lang/String;"); - env->DeleteLocalRef(patch_class); - - const jclass double_class = env->FindClass("java/lang/Double"); - s_double_class = reinterpret_cast(env->NewGlobalRef(double_class)); - s_double_constructor = env->GetMethodID(double_class, "", "(D)V"); - s_double_value_field = env->GetFieldID(double_class, "value", "D"); - env->DeleteLocalRef(double_class); - - const jclass int_class = env->FindClass("java/lang/Integer"); - s_integer_class = reinterpret_cast(env->NewGlobalRef(int_class)); - s_integer_constructor = env->GetMethodID(int_class, "", "(I)V"); - s_integer_value_field = env->GetFieldID(int_class, "value", "I"); - env->DeleteLocalRef(int_class); - - const jclass boolean_class = env->FindClass("java/lang/Boolean"); - s_boolean_class = reinterpret_cast(env->NewGlobalRef(boolean_class)); - s_boolean_constructor = env->GetMethodID(boolean_class, "", "(Z)V"); - s_boolean_value_field = env->GetFieldID(boolean_class, "value", "Z"); - env->DeleteLocalRef(boolean_class); - - const jclass player_input_class = - env->FindClass("org/yuzu/yuzu_emu/features/input/model/PlayerInput"); - s_player_input_class = reinterpret_cast(env->NewGlobalRef(player_input_class)); - s_player_input_constructor = env->GetMethodID( - player_input_class, "", - "(Z[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZIJJJJLjava/lang/String;Z)V"); - s_player_input_connected_field = env->GetFieldID(player_input_class, "connected", "Z"); - s_player_input_buttons_field = - env->GetFieldID(player_input_class, "buttons", "[Ljava/lang/String;"); - s_player_input_analogs_field = - env->GetFieldID(player_input_class, "analogs", "[Ljava/lang/String;"); - s_player_input_motions_field = - env->GetFieldID(player_input_class, "motions", "[Ljava/lang/String;"); - s_player_input_vibration_enabled_field = - env->GetFieldID(player_input_class, "vibrationEnabled", "Z"); - s_player_input_vibration_strength_field = - env->GetFieldID(player_input_class, "vibrationStrength", "I"); - s_player_input_body_color_left_field = - env->GetFieldID(player_input_class, "bodyColorLeft", "J"); - s_player_input_body_color_right_field = - env->GetFieldID(player_input_class, "bodyColorRight", "J"); - s_player_input_button_color_left_field = - env->GetFieldID(player_input_class, "buttonColorLeft", "J"); - s_player_input_button_color_right_field = - env->GetFieldID(player_input_class, "buttonColorRight", "J"); - s_player_input_profile_name_field = - env->GetFieldID(player_input_class, "profileName", "Ljava/lang/String;"); - s_player_input_use_system_vibrator_field = - env->GetFieldID(player_input_class, "useSystemVibrator", "Z"); - env->DeleteLocalRef(player_input_class); - - const jclass yuzu_input_device_interface = - env->FindClass("org/yuzu/yuzu_emu/features/input/YuzuInputDevice"); - s_yuzu_input_device_interface = - reinterpret_cast(env->NewGlobalRef(yuzu_input_device_interface)); - s_yuzu_input_device_get_name = - env->GetMethodID(yuzu_input_device_interface, "getName", "()Ljava/lang/String;"); - s_yuzu_input_device_get_guid = - env->GetMethodID(yuzu_input_device_interface, "getGUID", "()Ljava/lang/String;"); - s_yuzu_input_device_get_port = env->GetMethodID(yuzu_input_device_interface, "getPort", - "()I"); - s_yuzu_input_device_get_supports_vibration = - env->GetMethodID(yuzu_input_device_interface, "getSupportsVibration", "()Z"); - s_yuzu_input_device_vibrate = env->GetMethodID(yuzu_input_device_interface, "vibrate", - "(F)V"); - s_yuzu_input_device_get_axes = - env->GetMethodID(yuzu_input_device_interface, "getAxes", "()[Ljava/lang/Integer;"); - s_yuzu_input_device_has_keys = - env->GetMethodID(yuzu_input_device_interface, "hasKeys", "([I)[Z"); - env->DeleteLocalRef(yuzu_input_device_interface); - s_add_netplay_message = env->GetStaticMethodID(s_native_library_class, "addNetPlayMessage", - "(ILjava/lang/String;)V"); - s_clear_chat = env->GetStaticMethodID(s_native_library_class, "clearChat", "()V"); - - - // Initialize Android Storage - Common::FS::Android::RegisterCallbacks(env, s_native_library_class); - - // Initialize applets - Common::Android::SoftwareKeyboard::InitJNI(env); - Common::Android::WebBrowser::InitJNI(env); - - return JNI_VERSION; - } - void JNI_OnUnload(JavaVM *vm, void *reserved) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION) != JNI_OK) { @@ -645,4 +462,183 @@ namespace Common::Android { } #endif +void Initialize(JavaVM* vm, JNIEnv *env) { + s_java_vm = vm; + InitFFmpegOnLoad(vm); + + if (env->ExceptionCheck()) { + env->ExceptionClear(); + } + + // Initialize Java classes + const jclass native_library_class = env->FindClass("org/yuzu/yuzu_emu/NativeLibrary"); + s_native_library_class = reinterpret_cast(env->NewGlobalRef(native_library_class)); + s_disk_cache_progress_class = reinterpret_cast(env->NewGlobalRef( + env->FindClass("org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress"))); + s_load_callback_stage_class = reinterpret_cast(env->NewGlobalRef(env->FindClass( + "org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress$LoadCallbackStage"))); + + const jclass game_dir_class = env->FindClass("org/yuzu/yuzu_emu/model/GameDir"); + s_game_dir_class = reinterpret_cast(env->NewGlobalRef(game_dir_class)); + s_game_dir_constructor = env->GetMethodID(game_dir_class, "", + "(Ljava/lang/String;Z)V"); + env->DeleteLocalRef(game_dir_class); + + // Initialize methods + s_exit_emulation_activity = + env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V"); + s_disk_cache_load_progress = + env->GetStaticMethodID(s_disk_cache_progress_class, "loadProgress", "(III)V"); + s_copy_to_storage = env->GetStaticMethodID(s_native_library_class, "copyFileToStorage", + "(Ljava/lang/String;Ljava/lang/String;)Z"); + s_file_exists = env->GetStaticMethodID(s_native_library_class, "exists", + "(Ljava/lang/String;)Z"); + s_file_extension = env->GetStaticMethodID(s_native_library_class, "getFileExtension", + "(Ljava/lang/String;)Ljava/lang/String;"); + s_on_emulation_started = + env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V"); + s_on_emulation_stopped = + env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V"); + s_on_program_changed = + env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V"); + + const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game"); + s_game_class = reinterpret_cast(env->NewGlobalRef(game_class)); + s_game_constructor = env->GetMethodID(game_class, "", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" + "String;Ljava/lang/String;Ljava/lang/String;Z)V"); + s_game_title_field = env->GetFieldID(game_class, "title", "Ljava/lang/String;"); + s_game_path_field = env->GetFieldID(game_class, "path", "Ljava/lang/String;"); + s_game_program_id_field = env->GetFieldID(game_class, "programId", "Ljava/lang/String;"); + s_game_developer_field = env->GetFieldID(game_class, "developer", "Ljava/lang/String;"); + s_game_version_field = env->GetFieldID(game_class, "version", "Ljava/lang/String;"); + s_game_is_homebrew_field = env->GetFieldID(game_class, "isHomebrew", "Z"); + env->DeleteLocalRef(game_class); + + const jclass string_class = env->FindClass("java/lang/String"); + s_string_class = reinterpret_cast(env->NewGlobalRef(string_class)); + env->DeleteLocalRef(string_class); + + const jclass pair_class = env->FindClass("kotlin/Pair"); + s_pair_class = reinterpret_cast(env->NewGlobalRef(pair_class)); + s_pair_constructor = + env->GetMethodID(pair_class, "", "(Ljava/lang/Object;Ljava/lang/Object;)V"); + s_pair_first_field = env->GetFieldID(pair_class, "first", "Ljava/lang/Object;"); + s_pair_second_field = env->GetFieldID(pair_class, "second", "Ljava/lang/Object;"); + env->DeleteLocalRef(pair_class); + + const jclass overlay_control_data_class = + env->FindClass("org/yuzu/yuzu_emu/overlay/model/OverlayControlData"); + s_overlay_control_data_class = + reinterpret_cast(env->NewGlobalRef(overlay_control_data_class)); + s_overlay_control_data_constructor = + env->GetMethodID(overlay_control_data_class, "", + "(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;F)V"); + s_overlay_control_data_id_field = + env->GetFieldID(overlay_control_data_class, "id", "Ljava/lang/String;"); + s_overlay_control_data_enabled_field = + env->GetFieldID(overlay_control_data_class, "enabled", "Z"); + s_overlay_control_data_landscape_position_field = + env->GetFieldID(overlay_control_data_class, "landscapePosition", "Lkotlin/Pair;"); + s_overlay_control_data_portrait_position_field = + env->GetFieldID(overlay_control_data_class, "portraitPosition", "Lkotlin/Pair;"); + s_overlay_control_data_foldable_position_field = + env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); + s_overlay_control_data_individual_scale_field = + env->GetFieldID(overlay_control_data_class, "individualScale", "F"); + env->DeleteLocalRef(overlay_control_data_class); + + const jclass patch_class = env->FindClass("org/yuzu/yuzu_emu/model/Patch"); + s_patch_class = reinterpret_cast(env->NewGlobalRef(patch_class)); + s_patch_constructor = env->GetMethodID( + patch_class, "", + "(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JI)V"); + s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z"); + s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;"); + s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;"); + s_patch_type_field = env->GetFieldID(patch_class, "type", "I"); + s_patch_program_id_field = env->GetFieldID(patch_class, "programId", "Ljava/lang/String;"); + s_patch_title_id_field = env->GetFieldID(patch_class, "titleId", "Ljava/lang/String;"); + env->DeleteLocalRef(patch_class); + + const jclass double_class = env->FindClass("java/lang/Double"); + s_double_class = reinterpret_cast(env->NewGlobalRef(double_class)); + s_double_constructor = env->GetMethodID(double_class, "", "(D)V"); + s_double_value_method = env->GetMethodID(double_class, "doubleValue", "()D"); + env->DeleteLocalRef(double_class); + + const jclass int_class = env->FindClass("java/lang/Integer"); + s_integer_class = reinterpret_cast(env->NewGlobalRef(int_class)); + s_integer_constructor = env->GetMethodID(int_class, "", "(I)V"); + s_integer_value_method = env->GetMethodID(int_class, "intValue", "()I"); + env->DeleteLocalRef(int_class); + + const jclass boolean_class = env->FindClass("java/lang/Boolean"); + s_boolean_class = reinterpret_cast(env->NewGlobalRef(boolean_class)); + s_boolean_constructor = env->GetMethodID(boolean_class, "", "(Z)V"); + s_boolean_value_method = env->GetMethodID(boolean_class, "booleanValue", "()Z"); + env->DeleteLocalRef(boolean_class); + + const jclass player_input_class = + env->FindClass("org/yuzu/yuzu_emu/features/input/model/PlayerInput"); + s_player_input_class = reinterpret_cast(env->NewGlobalRef(player_input_class)); + s_player_input_constructor = env->GetMethodID( + player_input_class, "", + "(Z[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZIJJJJLjava/lang/String;Z)V"); + s_player_input_connected_field = env->GetFieldID(player_input_class, "connected", "Z"); + s_player_input_buttons_field = + env->GetFieldID(player_input_class, "buttons", "[Ljava/lang/String;"); + s_player_input_analogs_field = + env->GetFieldID(player_input_class, "analogs", "[Ljava/lang/String;"); + s_player_input_motions_field = + env->GetFieldID(player_input_class, "motions", "[Ljava/lang/String;"); + s_player_input_vibration_enabled_field = + env->GetFieldID(player_input_class, "vibrationEnabled", "Z"); + s_player_input_vibration_strength_field = + env->GetFieldID(player_input_class, "vibrationStrength", "I"); + s_player_input_body_color_left_field = + env->GetFieldID(player_input_class, "bodyColorLeft", "J"); + s_player_input_body_color_right_field = + env->GetFieldID(player_input_class, "bodyColorRight", "J"); + s_player_input_button_color_left_field = + env->GetFieldID(player_input_class, "buttonColorLeft", "J"); + s_player_input_button_color_right_field = + env->GetFieldID(player_input_class, "buttonColorRight", "J"); + s_player_input_profile_name_field = + env->GetFieldID(player_input_class, "profileName", "Ljava/lang/String;"); + s_player_input_use_system_vibrator_field = + env->GetFieldID(player_input_class, "useSystemVibrator", "Z"); + env->DeleteLocalRef(player_input_class); + + const jclass yuzu_input_device_interface = + env->FindClass("org/yuzu/yuzu_emu/features/input/YuzuInputDevice"); + s_yuzu_input_device_interface = + reinterpret_cast(env->NewGlobalRef(yuzu_input_device_interface)); + s_yuzu_input_device_get_name = + env->GetMethodID(yuzu_input_device_interface, "getName", "()Ljava/lang/String;"); + s_yuzu_input_device_get_guid = + env->GetMethodID(yuzu_input_device_interface, "getGUID", "()Ljava/lang/String;"); + s_yuzu_input_device_get_port = env->GetMethodID(yuzu_input_device_interface, "getPort", + "()I"); + s_yuzu_input_device_get_supports_vibration = + env->GetMethodID(yuzu_input_device_interface, "getSupportsVibration", "()Z"); + s_yuzu_input_device_vibrate = env->GetMethodID(yuzu_input_device_interface, "vibrate", + "(F)V"); + s_yuzu_input_device_get_axes = + env->GetMethodID(yuzu_input_device_interface, "getAxes", "()[Ljava/lang/Integer;"); + s_yuzu_input_device_has_keys = + env->GetMethodID(yuzu_input_device_interface, "hasKeys", "([I)[Z"); + env->DeleteLocalRef(yuzu_input_device_interface); + s_add_netplay_message = env->GetStaticMethodID(s_native_library_class, "addNetPlayMessage", + "(ILjava/lang/String;)V"); + s_clear_chat = env->GetStaticMethodID(s_native_library_class, "clearChat", "()V"); + + // Initialize Android Storage + Common::FS::Android::RegisterCallbacks(env, s_native_library_class); + + // Initialize applets + Common::Android::SoftwareKeyboard::InitJNI(env); + Common::Android::WebBrowser::InitJNI(env); +} + } // namespace Common::Android diff --git a/src/common/android/id_cache.h b/src/common/android/id_cache.h index 6e47acb746..6da385d521 100644 --- a/src/common/android/id_cache.h +++ b/src/common/android/id_cache.h @@ -11,6 +11,7 @@ namespace Common::Android { +void Initialize(JavaVM* vm, JNIEnv *env); JNIEnv* GetEnvForThread(); /** @@ -80,15 +81,15 @@ jfieldID GetPatchTitleIdField(); jclass GetDoubleClass(); jmethodID GetDoubleConstructor(); -jfieldID GetDoubleValueField(); +jmethodID GetDoubleValueMethod(); jclass GetIntegerClass(); jmethodID GetIntegerConstructor(); -jfieldID GetIntegerValueField(); +jmethodID GetIntegerValueMethod(); jclass GetBooleanClass(); jmethodID GetBooleanConstructor(); -jfieldID GetBooleanValueField(); +jmethodID GetBooleanValueMethod(); jclass GetPlayerInputClass(); jmethodID GetPlayerInputConstructor(); diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index a43df6924c..4b406f4c35 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -92,14 +92,14 @@ struct EnumMetadata { // AudioEngine must be specified discretely due to having existing but slightly different // canonicalizations // TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id -enum class AudioEngine : u32 { Auto, Cubeb, Sdl3, Null, Oboe, }; +enum class AudioEngine : u32 { Auto, Cubeb, Sdl3, Null, }; template<> inline std::vector> EnumMetadata::Canonicalizations() { return { {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl3", AudioEngine::Sdl3}, - {"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe}, + {"null", AudioEngine::Null}, }; } /// @brief This is just a sufficiently large number that is more than the number of other enums declared here @@ -113,7 +113,7 @@ inline AudioEngine EnumMetadata::GetFirst() { } template<> inline AudioEngine EnumMetadata::GetLast() { - return AudioEngine::Oboe; + return AudioEngine::Null; } ENUM(AudioMode, Mono, Stereo, Surround); diff --git a/src/input_common/drivers/android.cpp b/src/input_common/drivers/android.cpp index 6ab12dfe0e..966abbef94 100644 --- a/src/input_common/drivers/android.cpp +++ b/src/input_common/drivers/android.cpp @@ -114,7 +114,7 @@ std::set Android::GetDeviceAxes(JNIEnv* env, jobject& j_device) const { std::set axes; for (int i = 0; i < env->GetArrayLength(j_axes); ++i) { jobject axis = env->GetObjectArrayElement(j_axes, i); - axes.insert(env->GetIntField(axis, Common::Android::GetIntegerValueField())); + axes.insert(env->CallIntMethod(axis, Common::Android::GetIntegerValueMethod())); } return axes; }