mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-15 07:20:31 +02:00
Android: Tie emulation and audio to visibility, not focus
onPause used to join the render thread and stop the audio, so anything taking focus while the game stayed on screen (a permission dialog, a share sheet, the other app of a split screen before Android 10) tore down the whole graphics context and silenced the game. Emulation, audio, sensors and input listeners now follow onStart/onStop. The render loop itself already follows the surface; onStop joins it too, for devices that keep a stopped activity's surface. The camera stays on onPause/onResume, as it goes to the focused app. A finishing activity lets go of the render thread in onPause, since a quick relaunch creates the next activity before this one's onStop, and that onStop then leaves the audio and location updates alone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
87353cfd01
commit
2123e7fdac
1 file changed
+57
-33
@@ -989,16 +989,64 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList
|
||||
Log.i(TAG, "onDestroy end");
|
||||
}
|
||||
|
||||
// Emulation, audio and input follow visibility (onStart/onStop) rather than focus (onPause/onResume): a
|
||||
// permission dialog on top, or the other app of a split screen having focus, leaves the game on screen,
|
||||
// and it should keep running and playing. The render loop is really owned by the surface (notifySurface),
|
||||
// which normally goes away with the visibility anyway.
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
Log.i(TAG, "onStart");
|
||||
if (m_hasNoNativeBinary) {
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "onStart begin");
|
||||
|
||||
if (mLocationHelper != null) {
|
||||
mLocationHelper.resume();
|
||||
}
|
||||
|
||||
updateAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
||||
NativeApp.resume();
|
||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
|
||||
|
||||
InputManager inputManager = (InputManager)getSystemService(Context.INPUT_SERVICE);
|
||||
inputManager.registerInputDeviceListener(inputDeviceListener, null);
|
||||
|
||||
// In case the surface outlived the stop. Otherwise this waits for surfaceCreated.
|
||||
startRenderLoopThread();
|
||||
Log.i(TAG, "onStart end");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Log.i(TAG, "onStop");
|
||||
if (m_hasNoNativeBinary) {
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "onStop begin");
|
||||
|
||||
InputManager inputManager = (InputManager)getSystemService(Context.INPUT_SERVICE);
|
||||
inputManager.unregisterInputDeviceListener(inputDeviceListener);
|
||||
|
||||
// Normally surfaceDestroyed has done this already, but not every device destroys the surface of a
|
||||
// stopped activity, and an invisible game shouldn't keep running.
|
||||
Log.i(TAG, "Joining render thread...");
|
||||
joinRenderLoopThread();
|
||||
Log.i(TAG, "Joined render thread");
|
||||
|
||||
mSensorManager.unregisterListener(this);
|
||||
loseAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
||||
|
||||
// After a finish() and a quick relaunch, this comes after the new activity's onStart, and the audio and
|
||||
// the location updates are its now.
|
||||
if (instance == latestInstance) {
|
||||
Log.i(TAG, "Calling NativeApp.pause...");
|
||||
NativeApp.pause();
|
||||
if (mLocationHelper != null) {
|
||||
mLocationHelper.pause();
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "onStop end");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1008,27 +1056,17 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "onPause begin");
|
||||
|
||||
InputManager inputManager = (InputManager)getSystemService(Context.INPUT_SERVICE);
|
||||
inputManager.unregisterInputDeviceListener(inputDeviceListener);
|
||||
|
||||
Log.i(TAG, "Joining render thread...");
|
||||
joinRenderLoopThread();
|
||||
Log.i(TAG, "Joined render thread");
|
||||
|
||||
Log.i(TAG, "mSensorManager.unregisterListener...");
|
||||
mSensorManager.unregisterListener(this);
|
||||
|
||||
loseAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
||||
Log.i(TAG, "Calling NativeApp.pause...");
|
||||
NativeApp.pause();
|
||||
if (isFinishing()) {
|
||||
// Gone for good. A quick relaunch creates the next activity before this one's onStop, and the
|
||||
// render thread has to be free for it by then.
|
||||
Log.i(TAG, "Finishing, joining render thread...");
|
||||
joinRenderLoopThread();
|
||||
}
|
||||
// The camera goes to whichever app has focus.
|
||||
if (mCameraHelper != null) {
|
||||
Log.i(TAG, "Calling mCameraHelper.pause");
|
||||
mCameraHelper.pause();
|
||||
}
|
||||
if (mLocationHelper != null) {
|
||||
mLocationHelper.pause();
|
||||
}
|
||||
Log.i(TAG, "onPause end");
|
||||
}
|
||||
|
||||
@@ -1049,20 +1087,6 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList
|
||||
if (mCameraHelper != null) {
|
||||
mCameraHelper.resume();
|
||||
}
|
||||
if (mLocationHelper != null) {
|
||||
mLocationHelper.resume();
|
||||
}
|
||||
|
||||
updateAudioFocus(this.audioManager, this.audioFocusChangeListener);
|
||||
NativeApp.resume();
|
||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
|
||||
|
||||
InputManager inputManager =
|
||||
(InputManager)getSystemService(Context.INPUT_SERVICE);
|
||||
inputManager.registerInputDeviceListener(inputDeviceListener, null);
|
||||
|
||||
// Restart the render loop.
|
||||
startRenderLoopThread();
|
||||
Log.i(TAG, "onResume end");
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user