Merge pull request #6247 from ByteHamster/rewrite-audio-focus
Rework audio focus handling
This commit is contained in:
commit
0776f232d3
@ -4,9 +4,10 @@ import android.app.UiModeManager;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
@ -44,7 +45,6 @@ import de.danoeh.antennapod.playback.base.RewindAfterPauseUtils;
|
|||||||
import de.danoeh.antennapod.core.util.playback.AudioPlayer;
|
import de.danoeh.antennapod.core.util.playback.AudioPlayer;
|
||||||
import de.danoeh.antennapod.core.util.playback.IPlayer;
|
import de.danoeh.antennapod.core.util.playback.IPlayer;
|
||||||
import de.danoeh.antennapod.model.playback.Playable;
|
import de.danoeh.antennapod.model.playback.Playable;
|
||||||
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
|
||||||
import de.danoeh.antennapod.core.util.playback.VideoPlayer;
|
import de.danoeh.antennapod.core.util.playback.VideoPlayer;
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
|
||||||
@ -66,6 +66,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
|
|||||||
private volatile boolean pausedBecauseOfTransientAudiofocusLoss;
|
private volatile boolean pausedBecauseOfTransientAudiofocusLoss;
|
||||||
private volatile Pair<Integer, Integer> videoSize;
|
private volatile Pair<Integer, Integer> videoSize;
|
||||||
private final AudioFocusRequestCompat audioFocusRequest;
|
private final AudioFocusRequestCompat audioFocusRequest;
|
||||||
|
private final Handler audioFocusCanceller;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads
|
* Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads
|
||||||
@ -154,6 +155,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
|
|||||||
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||||
this.playerLock = new PlayerLock();
|
this.playerLock = new PlayerLock();
|
||||||
this.startWhenPrepared = new AtomicBoolean(false);
|
this.startWhenPrepared = new AtomicBoolean(false);
|
||||||
|
audioFocusCanceller = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
executor = new PlayerExecutor();
|
executor = new PlayerExecutor();
|
||||||
executor.threadPool = new ThreadPoolExecutor(1, 1, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<>(),
|
executor.threadPool = new ThreadPoolExecutor(1, 1, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<>(),
|
||||||
@ -853,53 +855,46 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
|
|||||||
if (!PlaybackService.isRunning) {
|
if (!PlaybackService.isRunning) {
|
||||||
abandonAudioFocus();
|
abandonAudioFocus();
|
||||||
Log.d(TAG, "onAudioFocusChange: PlaybackService is no longer running");
|
Log.d(TAG, "onAudioFocusChange: PlaybackService is no longer running");
|
||||||
if (focusChange == AudioManager.AUDIOFOCUS_GAIN && pausedBecauseOfTransientAudiofocusLoss) {
|
|
||||||
pausedBecauseOfTransientAudiofocusLoss = false;
|
|
||||||
new PlaybackServiceStarter(context, getPlayable())
|
|
||||||
.callEvenIfRunning(false)
|
|
||||||
.start();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
executor.submit(() -> {
|
executor.submit(() -> {
|
||||||
playerLock.lock();
|
playerLock.lock();
|
||||||
|
if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
|
||||||
// If there is an incoming call, playback should be paused permanently
|
|
||||||
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
|
||||||
final int callState = (tm != null) ? tm.getCallState() : 0;
|
|
||||||
Log.i(TAG, "Call state:" + callState);
|
|
||||||
|
|
||||||
if (focusChange == AudioManager.AUDIOFOCUS_LOSS ||
|
|
||||||
(!UserPreferences.shouldResumeAfterCall() && callState != TelephonyManager.CALL_STATE_IDLE)) {
|
|
||||||
Log.d(TAG, "Lost audio focus");
|
Log.d(TAG, "Lost audio focus");
|
||||||
pause(true, false);
|
pause(true, false);
|
||||||
callback.shouldStop();
|
callback.shouldStop();
|
||||||
|
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
|
||||||
|
&& !UserPreferences.shouldPauseForFocusLoss()) {
|
||||||
|
if (playerStatus == PlayerStatus.PLAYING) {
|
||||||
|
Log.d(TAG, "Lost audio focus temporarily. Ducking...");
|
||||||
|
setVolumeSync(0.25f, 0.25f);
|
||||||
|
pausedBecauseOfTransientAudiofocusLoss = false;
|
||||||
|
}
|
||||||
|
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
|
||||||
|
|| focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
|
||||||
|
if (playerStatus == PlayerStatus.PLAYING) {
|
||||||
|
Log.d(TAG, "Lost audio focus temporarily. Pausing...");
|
||||||
|
mediaPlayer.pause(); // Pause without telling the PlaybackService
|
||||||
|
pausedBecauseOfTransientAudiofocusLoss = true;
|
||||||
|
|
||||||
|
audioFocusCanceller.removeCallbacksAndMessages(null);
|
||||||
|
audioFocusCanceller.postDelayed(() -> {
|
||||||
|
if (pausedBecauseOfTransientAudiofocusLoss) {
|
||||||
|
// Still did not get back the audio focus. Now actually pause.
|
||||||
|
pause(true, false);
|
||||||
|
}
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
|
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
|
||||||
Log.d(TAG, "Gained audio focus");
|
Log.d(TAG, "Gained audio focus");
|
||||||
|
audioFocusCanceller.removeCallbacksAndMessages(null);
|
||||||
if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now
|
if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now
|
||||||
resume();
|
mediaPlayer.start();
|
||||||
} else { // we ducked => raise audio level back
|
} else { // we ducked => raise audio level back
|
||||||
setVolumeSync(1.0f, 1.0f);
|
setVolumeSync(1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
|
pausedBecauseOfTransientAudiofocusLoss = false;
|
||||||
if (playerStatus == PlayerStatus.PLAYING) {
|
|
||||||
if (!UserPreferences.shouldPauseForFocusLoss()) {
|
|
||||||
Log.d(TAG, "Lost audio focus temporarily. Ducking...");
|
|
||||||
setVolumeSync(0.25f, 0.25f);
|
|
||||||
pausedBecauseOfTransientAudiofocusLoss = false;
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing...");
|
|
||||||
pause(false, false);
|
|
||||||
pausedBecauseOfTransientAudiofocusLoss = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
|
|
||||||
if (playerStatus == PlayerStatus.PLAYING) {
|
|
||||||
Log.d(TAG, "Lost audio focus temporarily. Pausing...");
|
|
||||||
pause(false, false);
|
|
||||||
pausedBecauseOfTransientAudiofocusLoss = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
playerLock.unlock();
|
playerLock.unlock();
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user