diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index 42d4f687f4..be614f0a6a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -15,6 +15,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.pm.PackageManager import android.content.res.Configuration import android.graphics.Rect import android.graphics.drawable.Icon @@ -87,6 +88,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager private val emulationViewModel: EmulationViewModel by viewModels() private var foregroundService: Intent? = null + private val pictureInPictureFailureActions: MutableSet = mutableSetOf() override fun attachBaseContext(base: Context) { super.attachBaseContext(YuzuApplication.applyLanguage(base)) @@ -217,12 +219,18 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager } override fun onUserLeaveHint() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { - if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) { - val pictureInPictureParamsBuilder = PictureInPictureParams.Builder() - .getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder() - enterPictureInPictureMode(pictureInPictureParamsBuilder.build()) - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S || + !isPictureInPictureSupported() || + !BooleanSetting.PICTURE_IN_PICTURE.getBoolean() || + isInPictureInPictureMode + ) { + return + } + + val pictureInPictureParamsBuilder = PictureInPictureParams.Builder() + .getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder() + runPictureInPictureAction("enter picture-in-picture mode") { + enterPictureInPictureMode(pictureInPictureParamsBuilder.build()) } } @@ -496,7 +504,30 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager return this.apply { setActions(pictureInPictureActions) } } + private fun isPictureInPictureSupported(): Boolean { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) + } + + private fun runPictureInPictureAction(actionName: String, action: () -> Unit) { + try { + action() + } catch (e: IllegalStateException) { + if (pictureInPictureFailureActions.add(actionName)) { + Log.warning("[PiP] Failed to $actionName: ${e.message}") + } + } catch (e: UnsupportedOperationException) { + if (pictureInPictureFailureActions.add(actionName)) { + Log.warning("[PiP] Failed to $actionName: ${e.message}") + } + } + } + fun buildPictureInPictureParams() { + if (!isPictureInPictureSupported()) { + return + } + val pictureInPictureParamsBuilder = PictureInPictureParams.Builder() .getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { @@ -506,7 +537,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive ) } - setPictureInPictureParams(pictureInPictureParamsBuilder.build()) + runPictureInPictureAction("set picture-in-picture params") { + setPictureInPictureParams(pictureInPictureParamsBuilder.build()) + } } fun displayMultiplayerDialog() {