android: threading fix. stop vibrator thread. allow screen saver

If the android activity is destroyed and the game unloaded, the gui's
game state wasn't updated, leading to a crash if resuming. Same for the
android game state if pausing, destroying then resuming.
tentative fix for MINIDUMP-27, MINIDUMP-25, MINIDUMP-23
Wait until emu is stopped in single-threaded.
Stop vibrator thread when view is detached
Allow the screen saver when a game isn't running.
This commit is contained in:
Flyinghead 2023-01-11 11:44:28 +01:00
parent 5fa98da17e
commit 673fb26d6e
6 changed files with 65 additions and 23 deletions

View File

@ -88,8 +88,11 @@ static void emuEventCallback(Event event, void *)
game_started = true;
break;
case Event::Start:
GamepadDevice::load_system_mappings();
break;
case Event::Terminate:
GamepadDevice::load_system_mappings();
game_started = false;
break;
default:
break;
@ -490,7 +493,6 @@ void gui_stop_game(const std::string& message)
// Exit to main menu
emu.unloadGame();
gui_state = GuiState::Main;
game_started = false;
reset_vmus();
if (!message.empty())
gui_error("Flycast has stopped.\n\n" + message);

View File

@ -15,7 +15,6 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />

View File

@ -79,7 +79,6 @@ public abstract class BaseGLActivity extends Activity implements ActivityCompat.
getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
if (!getFilesDir().exists()) {
getFilesDir().mkdir();
}
@ -406,5 +405,17 @@ public abstract class BaseGLActivity extends Activity implements ActivityCompat.
}
}
// Called from native code
public void onGameStateChange(boolean started) {
runOnUiThread(new Runnable() {
public void run() {
if (started)
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
else
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
});
}
private static native void register(BaseGLActivity activity);
}

View File

@ -35,7 +35,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
public NativeGLView(final Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
setKeepScreenOn(true);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
@ -53,13 +52,24 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
}
});
}
vjoyDelegate = new VirtualJoystickDelegate(this);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
this.setLayerType(LAYER_TYPE_HARDWARE, null);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
vjoyDelegate = new VirtualJoystickDelegate(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
vjoyDelegate.stop();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{

View File

@ -46,6 +46,14 @@ public class VirtualJoystickDelegate {
scaleGestureDetector = new ScaleGestureDetector(context, new OscOnScaleGestureListener());
}
public void stop() {
vibratorThread.stopVibrator();
try {
vibratorThread.join();
} catch (InterruptedException e) {
}
}
public void readCustomVjoyValues() {
vjoy_d_custom = VJoy.readCustomVjoyValues(context);
}
@ -58,7 +66,6 @@ public class VirtualJoystickDelegate {
view.requestLayout();
}
private void reset_analog()
{

View File

@ -102,15 +102,29 @@ jobject g_emulator;
jmethodID saveAndroidSettingsMid;
static ANativeWindow *g_window = 0;
// Activity
static jobject g_activity;
static jmethodID VJoyStartEditingMID;
static jmethodID VJoyStopEditingMID;
static jmethodID VJoyResetEditingMID;
static jmethodID showTextInputMid;
static jmethodID hideTextInputMid;
static jmethodID isScreenKeyboardShownMid;
static jmethodID onGameStateChangeMid;
static void emuEventCallback(Event event, void *)
{
switch (event)
{
case Event::Pause:
game_started = false;
if (g_activity != nullptr)
jvm_attacher.getEnv()->CallVoidMethod(g_activity, onGameStateChangeMid, false);
break;
case Event::Resume:
game_started = true;
if (g_activity != nullptr)
jvm_attacher.getEnv()->CallVoidMethod(g_activity, onGameStateChangeMid, true);
break;
default:
break;
@ -302,15 +316,6 @@ jmethodID audioInitMid;
jmethodID audioTermMid;
static jobject g_audioBackend;
// Activity
static jobject g_activity;
static jmethodID VJoyStartEditingMID;
static jmethodID VJoyStopEditingMID;
static jmethodID VJoyResetEditingMID;
static jmethodID showTextInputMid;
static jmethodID hideTextInputMid;
static jmethodID isScreenKeyboardShownMid;
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(JNIEnv *env,jobject obj,jobject sip)
{
sipemu = env->NewGlobalRef(sip);
@ -319,11 +324,22 @@ extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(J
stopRecordingMid = env->GetMethodID(env->GetObjectClass(sipemu),"stopRecording","()V");
}
static void stopEmu()
{
if (!emu.running())
game_started = false;
else
emu.stop();
// in single-threaded mode, stopping is delayed
while (game_started)
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_pause(JNIEnv *env,jobject obj)
{
if (game_started)
if (emu.running())
{
emu.stop();
stopEmu();
game_started = true; // restart when resumed
if (config::AutoSaveState)
dc_savestate(config::SavestateSlot);
@ -339,14 +355,10 @@ extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_resume(JNI
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_stop(JNIEnv *env,jobject obj)
{
if (emu.running()) {
emu.stop();
if (config::AutoSaveState)
dc_savestate(config::SavestateSlot);
}
stopEmu();
emu.unloadGame();
gui_state = GuiState::Main;
settings.content.path.clear();
game_started = false;
}
static void *render_thread_func(void *)
@ -652,6 +664,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_BaseGLActivity_regis
showTextInputMid = env->GetMethodID(env->GetObjectClass(activity), "showTextInput", "(IIII)V");
hideTextInputMid = env->GetMethodID(env->GetObjectClass(activity), "hideTextInput", "()V");
isScreenKeyboardShownMid = env->GetMethodID(env->GetObjectClass(activity), "isScreenKeyboardShown", "()Z");
onGameStateChangeMid = env->GetMethodID(env->GetObjectClass(activity), "onGameStateChange", "(Z)V");
}
}