Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0888a067 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "Fix AudioFocus for back-to-back notifications"

parents 23bbe02b 6313cbe1
Loading
Loading
Loading
Loading
+35 −12
Original line number Original line Diff line number Diff line
@@ -91,6 +91,9 @@ public class NotificationPlayer implements OnCompletionListener {
                    if ((mCmd.uri != null) && (mCmd.uri.getEncodedPath() != null)
                    if ((mCmd.uri != null) && (mCmd.uri.getEncodedPath() != null)
                            && (mCmd.uri.getEncodedPath().length() > 0)) {
                            && (mCmd.uri.getEncodedPath().length() > 0)) {
                        if (!audioManager.isMusicActiveRemotely()) {
                        if (!audioManager.isMusicActiveRemotely()) {
                            synchronized(mQueueAudioFocusLock) {
                                if (mAudioManagerWithAudioFocus == null) {
                                    if (mDebug) Log.d(mTag, "requesting AudioFocus");
                                    if (mCmd.looping) {
                                    if (mCmd.looping) {
                                        audioManager.requestAudioFocus(null, mCmd.stream,
                                        audioManager.requestAudioFocus(null, mCmd.stream,
                                                AudioManager.AUDIOFOCUS_GAIN);
                                                AudioManager.AUDIOFOCUS_GAIN);
@@ -98,8 +101,18 @@ public class NotificationPlayer implements OnCompletionListener {
                                        audioManager.requestAudioFocus(null, mCmd.stream,
                                        audioManager.requestAudioFocus(null, mCmd.stream,
                                                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
                                                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
                                    }
                                    }
                                    mAudioManagerWithAudioFocus = audioManager;
                                } else {
                                    if (mDebug) Log.d(mTag, "AudioFocus was previously requested");
                                }
                            }
                            }
                        }
                        }
                    }
                    // FIXME Having to start a new thread so we can receive completion callbacks
                    //  is wrong, as we kill this thread whenever a new sound is to be played. This
                    //  can lead to AudioFocus being released too early, before the second sound is
                    //  done playing. This class should be modified to use a single thread, on which
                    //  command are issued, and on which it receives the completion callbacks.
                    player.setOnCompletionListener(NotificationPlayer.this);
                    player.setOnCompletionListener(NotificationPlayer.this);
                    player.start();
                    player.start();
                    if (mPlayer != null) {
                    if (mPlayer != null) {
@@ -110,7 +123,6 @@ public class NotificationPlayer implements OnCompletionListener {
                catch (Exception e) {
                catch (Exception e) {
                    Log.w(mTag, "error loading sound for " + mCmd.uri, e);
                    Log.w(mTag, "error loading sound for " + mCmd.uri, e);
                }
                }
                mAudioManager = audioManager;
                this.notify();
                this.notify();
            }
            }
            Looper.loop();
            Looper.loop();
@@ -181,8 +193,12 @@ public class NotificationPlayer implements OnCompletionListener {
                        mPlayer.stop();
                        mPlayer.stop();
                        mPlayer.release();
                        mPlayer.release();
                        mPlayer = null;
                        mPlayer = null;
                        mAudioManager.abandonAudioFocus(null);
                        synchronized(mQueueAudioFocusLock) {
                        mAudioManager = null;
                            if (mAudioManagerWithAudioFocus != null) {
                                mAudioManagerWithAudioFocus.abandonAudioFocus(null);
                                mAudioManagerWithAudioFocus = null;
                            }
                        }
                        if((mLooper != null)
                        if((mLooper != null)
                                && (mLooper.getThread().getState() != Thread.State.TERMINATED)) {
                                && (mLooper.getThread().getState() != Thread.State.TERMINATED)) {
                            mLooper.quit();
                            mLooper.quit();
@@ -209,8 +225,14 @@ public class NotificationPlayer implements OnCompletionListener {
    }
    }


    public void onCompletion(MediaPlayer mp) {
    public void onCompletion(MediaPlayer mp) {
        if (mAudioManager != null) {
        synchronized(mQueueAudioFocusLock) {
            mAudioManager.abandonAudioFocus(null);
            if (mAudioManagerWithAudioFocus != null) {
                if (mDebug) Log.d(mTag, "onCompletion() abandonning AudioFocus");
                mAudioManagerWithAudioFocus.abandonAudioFocus(null);
                mAudioManagerWithAudioFocus = null;
            } else {
                if (mDebug) Log.d(mTag, "onCompletion() no need to abandon AudioFocus");
            }
        }
        }
        // if there are no more sounds to play, end the Looper to listen for media completion
        // if there are no more sounds to play, end the Looper to listen for media completion
        synchronized (mCmdQueue) {
        synchronized (mCmdQueue) {
@@ -231,7 +253,8 @@ public class NotificationPlayer implements OnCompletionListener {
    private final Object mCompletionHandlingLock = new Object();
    private final Object mCompletionHandlingLock = new Object();
    private MediaPlayer mPlayer;
    private MediaPlayer mPlayer;
    private PowerManager.WakeLock mWakeLock;
    private PowerManager.WakeLock mWakeLock;
    private AudioManager mAudioManager;
    private final Object mQueueAudioFocusLock = new Object();
    private AudioManager mAudioManagerWithAudioFocus; // synchronized on mQueueAudioFocusLock


    // The current state according to the caller.  Reality lags behind
    // The current state according to the caller.  Reality lags behind
    // because of the asynchronous nature of this class.
    // because of the asynchronous nature of this class.