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

Commit dc98489c authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

NotificationPlayer: release MediaPlayer on error and exception

Add a lock to synchronize changes to mPlayer in the playback
  thread and callback thread.
Refactor the exception handling CreationAndCompletionThread to
  always release the player that was set up to play the sound.
In the error and completion callbacks release the media player.

Bug: 110021815
Test: play notifications with wrong URI, verify players are released.

Change-Id: Ibbd06a64c8211dff24b4cfc5960d017721eca123
parent ef6a5bf7
Loading
Loading
Loading
Loading
+35 −18
Original line number Diff line number Diff line
@@ -86,11 +86,12 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener
            // synchronized on mCompletionHandlingLock due to the Object.wait() in startSound(cmd)
            mLooper = Looper.myLooper();
            if (DEBUG) Log.d(mTag, "in run: new looper " + mLooper);
            MediaPlayer player = null;
            synchronized(this) {
                AudioManager audioManager =
                    (AudioManager) mCmd.context.getSystemService(Context.AUDIO_SERVICE);
                try {
                    MediaPlayer player = new MediaPlayer();
                    player = new MediaPlayer();
                    if (mCmd.attributes == null) {
                        mCmd.attributes = new AudioAttributes.Builder()
                                .setUsage(AudioAttributes.USAGE_NOTIFICATION)
@@ -137,25 +138,25 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener
                        Log.e(mTag, "Exception while sleeping to sync notification playback"
                                + " with ducking", e);
                    }
                    try {
                    player.start();
                    if (DEBUG) { Log.d(mTag, "player.start"); }
                } catch (Exception e) {
                    if (player != null) {
                        player.release();
                        player = null;
                    }
                    Log.w(mTag, "error loading sound for " + mCmd.uri, e);
                    // playing the notification didn't work, revert the focus request
                    abandonAudioFocusAfterError();
                }
                    if (mPlayer != null) {
                        if (DEBUG) { Log.d(mTag, "mPlayer.release"); }
                        mPlayer.release();
                    }
                final MediaPlayer mp;
                synchronized (mPlayerLock) {
                    mp = mPlayer;
                    mPlayer = player;
                }
                catch (Exception e) {
                    Log.w(mTag, "error loading sound for " + mCmd.uri, e);
                    // playing the notification didn't work, revert the focus request
                    abandonAudioFocusAfterError();
                if (mp != null) {
                    if (DEBUG) { Log.d(mTag, "mPlayer.release"); }
                    mp.release();
                }
                this.notify();
            }
@@ -230,14 +231,20 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener
                    break;
                case STOP:
                    if (DEBUG) Log.d(mTag, "STOP");
                    if (mPlayer != null) {
                    final MediaPlayer mp;
                    synchronized (mPlayerLock) {
                        mp = mPlayer;
                        mPlayer = null;
                    }
                    if (mp != null) {
                        long delay = SystemClock.uptimeMillis() - cmd.requestTime;
                        if (delay > 1000) {
                            Log.w(mTag, "Notification stop delayed by " + delay + "msecs");
                        }
                        mPlayer.stop();
                        mPlayer.release();
                        mPlayer = null;
                        try {
                            mp.stop();
                        } catch (Exception e) { }
                        mp.release();
                        synchronized(mQueueAudioFocusLock) {
                            if (mAudioManagerWithAudioFocus != null) {
                                if (DEBUG) { Log.d(mTag, "in STOP: abandonning AudioFocus"); }
@@ -297,6 +304,14 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener
                }
            }
        }
        synchronized (mPlayerLock) {
            if (mp == mPlayer) {
                mPlayer = null;
            }
        }
        if (mp != null) {
            mp.release();
        }
    }

    public boolean onError(MediaPlayer mp, int what, int extra) {
@@ -311,6 +326,8 @@ public class NotificationPlayer implements OnCompletionListener, OnErrorListener
    @GuardedBy("mCmdQueue")
    private CmdThread mThread;

    private final Object mPlayerLock = new Object();
    @GuardedBy("mPlayerLock")
    private MediaPlayer mPlayer;