Fix KtSettings JNI usage

* Use a global ref for NativeSettings JNI instance
* Always use the JNI env from the JNI call to ensure it's safe to use in the current thread
This commit is contained in:
lynxnb 2023-02-06 19:41:57 +01:00 committed by Billy Laws
parent 5b0a397165
commit fc9b34846c
4 changed files with 16 additions and 12 deletions

View file

@ -27,7 +27,7 @@ std::weak_ptr<skyline::kernel::OS> OsWeak;
std::weak_ptr<skyline::gpu::GPU> GpuWeak;
std::weak_ptr<skyline::audio::Audio> AudioWeak;
std::weak_ptr<skyline::input::Input> InputWeak;
std::weak_ptr<skyline::Settings> SettingsWeak;
std::weak_ptr<skyline::AndroidSettings> SettingsWeak;
// https://cs.android.com/android/platform/superproject/+/master:bionic/libc/tzcode/bionic.cpp;l=43;drc=master;bpv=1;bpt=1
static std::string GetTimeZoneName() {
@ -85,7 +85,8 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(
auto jvmManager{std::make_shared<skyline::JvmManager>(env, instance)};
std::shared_ptr<skyline::Settings> settings{std::make_shared<skyline::AndroidSettings>(env, settingsInstance)};
auto androidSettings{std::make_shared<skyline::AndroidSettings>(env, settingsInstance)};
std::shared_ptr<skyline::Settings> settings{androidSettings};
skyline::JniString publicAppFilesPath(env, publicAppFilesPathJstring);
skyline::Logger::EmulationContext.Initialize(publicAppFilesPath + "logs/emulation.sklog");
@ -115,7 +116,7 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(
GpuWeak = os->state.gpu;
AudioWeak = os->state.audio;
InputWeak = os->state.input;
SettingsWeak = settings;
SettingsWeak = androidSettings;
jvmManager->InitializeControllers();
skyline::Logger::DebugNoPrefix("Launching ROM {}", skyline::JniString(env, romUriJstring));
@ -247,6 +248,7 @@ extern "C" JNIEXPORT void JNICALL Java_emu_skyline_utils_NativeSettings_updateNa
auto settings{SettingsWeak.lock()};
if (!settings)
return; // We don't mind if we miss settings updates while settings haven't been initialized
settings->BeginTransaction(env);
settings->Update();
}

View file

@ -20,14 +20,12 @@ namespace skyline {
* @note Will construct the underlying KtSettings object in-place
*/
AndroidSettings(JNIEnv *env, jobject settingsInstance) : ktSettings(env, settingsInstance) {
ktSettings.BeginTransaction(env);
Update();
}
/**
* @note Will take ownership of the passed KtSettings object
*/
AndroidSettings(KtSettings &&ktSettings) : ktSettings(std::move(ktSettings)) {
Update();
void BeginTransaction(JNIEnv *env) {
ktSettings.BeginTransaction(env);
}
void Update() override {
@ -50,6 +48,6 @@ namespace skyline {
disableSubgroupShuffle = ktSettings.GetBool("disableSubgroupShuffle");
isAudioOutputDisabled = ktSettings.GetBool("isAudioOutputDisabled");
validationLayer = ktSettings.GetBool("validationLayer");
};
}
};
}

View file

@ -33,7 +33,7 @@ namespace skyline::gpu {
auto desc{presentationTrack.Serialize()};
desc.set_name("Presentation");
perfetto::TrackEvent::SetTrackDescriptor(presentationTrack, desc);
state.settings->disableFrameThrottling.AddCallback(std::bind(&PresentationEngine::OnDisableFrameThrottlingChanged, this, std::placeholders::_1));
state.settings->disableFrameThrottling.AddCallback([this](auto && value) { OnDisableFrameThrottlingChanged(value); });
}
PresentationEngine::~PresentationEngine() {

View file

@ -25,12 +25,12 @@ namespace skyline {
*/
class KtSettings {
private:
JNIEnv *env; //!< A pointer to the current jni environment
JNIEnv *env{}; //!< The JNI environment
jclass settingsClass; //!< The settings class
jobject settingsInstance; //!< The settings instance
public:
KtSettings(JNIEnv *env, jobject settingsInstance) : env(env), settingsInstance(settingsInstance), settingsClass(env->GetObjectClass(settingsInstance)) {}
KtSettings(JNIEnv *env, jobject settingsInstance) : settingsInstance(env->NewGlobalRef(settingsInstance)), settingsClass(reinterpret_cast<jclass>(env->NewGlobalRef(env->GetObjectClass(settingsInstance)))) {}
KtSettings(const KtSettings &) = delete;
@ -38,6 +38,10 @@ namespace skyline {
KtSettings(KtSettings &&) = default;
void BeginTransaction(JNIEnv *pEnv) {
this->env = pEnv;
}
/**
* @param key A null terminated string containing the key of the setting to get
*/