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

Commit 95bd2329 authored by Glenn Kasten's avatar Glenn Kasten
Browse files

Simplify AudioTrack event handling and fix a race

Fixed race where mEventHandlerDelegate was accessed multiple times with
an assumption that all values read were the same.

If setPlaybackPositionUpdateListener was called with a null listener,
it did not update the delegate.

Inner classes can access final local variables of the enclosing method.
Use this to remove fields mPositionListener, mPositionListenerLock, mListener.

Change-Id: Ibf5cae61a1a9d21b745b90d4b74f9be14b66e37b
parent 3251d363
Loading
Loading
Loading
Loading
+17 −30
Original line number Diff line number Diff line
@@ -156,16 +156,6 @@ public class AudioTrack
     * Lock to make sure mPlayState updates are reflecting the actual state of the object.
     */
    private final Object mPlayStateLock = new Object();
    /**
     * The listener the AudioTrack notifies when the playback position reaches a marker
     * or for periodic updates during the progression of the playback head.
     *  @see #setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener)
     */
    private OnPlaybackPositionUpdateListener mPositionListener = null;
    /**
     * Lock to protect event listener updates against event notifications.
     */
    private final Object mPositionListenerLock = new Object();
    /**
     * Size of the native audio buffer.
     */
@@ -173,7 +163,7 @@ public class AudioTrack
    /**
     * Handler for marker events coming from the native code.
     */
    private NativeEventHandlerDelegate mEventHandlerDelegate = null;
    private NativeEventHandlerDelegate mEventHandlerDelegate;
    /**
     * Looper associated with the thread that creates the AudioTrack instance.
     */
@@ -733,13 +723,11 @@ public class AudioTrack
     */
    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener,
                                                    Handler handler) {
        synchronized (mPositionListenerLock) {
            mPositionListener = listener;
        }
        if (listener != null) {
            mEventHandlerDelegate = new NativeEventHandlerDelegate(this, handler);
            mEventHandlerDelegate = new NativeEventHandlerDelegate(this, listener, handler);
        } else {
            mEventHandlerDelegate = null;
        }

    }


@@ -1131,11 +1119,11 @@ public class AudioTrack
     * (potentially) handled in a different thread
     */
    private class NativeEventHandlerDelegate {
        private final AudioTrack mAudioTrack;
        private final Handler mHandler;

        NativeEventHandlerDelegate(AudioTrack track, Handler handler) {
            mAudioTrack = track;
        NativeEventHandlerDelegate(final AudioTrack track,
                                   final OnPlaybackPositionUpdateListener listener,
                                   Handler handler) {
            // find the looper for our new event handler
            Looper looper;
            if (handler != null) {
@@ -1151,22 +1139,18 @@ public class AudioTrack
                mHandler = new Handler(looper) {
                    @Override
                    public void handleMessage(Message msg) {
                        if (mAudioTrack == null) {
                        if (track == null) {
                            return;
                        }
                        OnPlaybackPositionUpdateListener listener = null;
                        synchronized (mPositionListenerLock) {
                            listener = mAudioTrack.mPositionListener;
                        }
                        switch(msg.what) {
                        case NATIVE_EVENT_MARKER:
                            if (listener != null) {
                                listener.onMarkerReached(mAudioTrack);
                                listener.onMarkerReached(track);
                            }
                            break;
                        case NATIVE_EVENT_NEW_POS:
                            if (listener != null) {
                                listener.onPeriodicNotification(mAudioTrack);
                                listener.onPeriodicNotification(track);
                            }
                            break;
                        default:
@@ -1199,10 +1183,13 @@ public class AudioTrack
            return;
        }

        if (track.mEventHandlerDelegate != null) {
            Message m =
                track.mEventHandlerDelegate.getHandler().obtainMessage(what, arg1, arg2, obj);
            track.mEventHandlerDelegate.getHandler().sendMessage(m);
        NativeEventHandlerDelegate delegate = track.mEventHandlerDelegate;
        if (delegate != null) {
            Handler handler = delegate.getHandler();
            if (handler != null) {
                Message m = handler.obtainMessage(what, arg1, arg2, obj);
                handler.sendMessage(m);
            }
        }

    }