diff options
| author | 2018-01-26 12:40:47 -0800 | |
|---|---|---|
| committer | 2018-01-29 11:20:03 -0800 | |
| commit | 63f793f0f3e815c3a4895be7b02941d27d54159c (patch) | |
| tree | 4fcbcf90567ae44afb888ed3a270e681f77d7120 | |
| parent | 1a5a7061eb05731e2dd6f948153447632f095637 (diff) | |
MediaPlayer2: allow multiple EventCallback's
Test: MediaPlayer2 plays
Bug: 63934228
Change-Id: Ie1be29c10d73126d9ebdad8358110ba507a034d5
| -rw-r--r-- | media/java/android/media/MediaPlayer2.java | 13 | ||||
| -rw-r--r-- | media/java/android/media/MediaPlayer2Impl.java | 283 |
2 files changed, 150 insertions, 146 deletions
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java index d36df845cc2e..d84eedf94820 100644 --- a/media/java/android/media/MediaPlayer2.java +++ b/media/java/android/media/MediaPlayer2.java @@ -96,22 +96,13 @@ import java.util.UUID; * {@link #close()} is called, it is in the <em>End</em> state. Between these * two states is the life cycle of the MediaPlayer2 object. * <ul> - * <li>There is a subtle but important difference between a newly constructed - * MediaPlayer2 object and the MediaPlayer2 object after {@link #reset()} - * is called. It is a programming error to invoke methods such + * <li> It is a programming error to invoke methods such * as {@link #getCurrentPosition()}, * {@link #getDuration()}, {@link #getVideoHeight()}, * {@link #getVideoWidth()}, {@link #setAudioAttributes(AudioAttributes)}, * {@link #setVolume(float, float)}, {@link #pause()}, {@link #play()}, * {@link #seekTo(long, int)} or - * {@link #prepareAsync()} in the <em>Idle</em> state for both cases. If any of these - * methods is called right after a MediaPlayer2 object is constructed, - * the user supplied callback method OnErrorListener.onError() won't be - * called by the internal player engine and the object state remains - * unchanged; but if these methods are called right after {@link #reset()}, - * the user supplied callback method OnErrorListener.onError() will be - * invoked by the internal player engine and the object will be - * transfered to the <em>Error</em> state. </li> + * {@link #prepareAsync()} in the <em>Idle</em> state. * <li>It is also recommended that once * a MediaPlayer2 object is no longer being used, call {@link #close()} immediately * so that resources used by the internal player engine associated with the diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 86a285cccaf9..222c66ea4551 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -1960,6 +1960,13 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { mTimeProvider = null; } + synchronized (mEventCbLock) { + mEventCallbackRecords.clear(); + } + synchronized (mDrmEventCbLock) { + mDrmEventCallbackRecords.clear(); + } + stayAwake(false); _reset(); // make sure none of the listeners get called anymore @@ -3049,8 +3056,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { stayAwake(false); updateSurfaceScreenOn(); synchronized (mEventCbLock) { - mEventCb = null; - mEventExec = null; + mEventCallbackRecords.clear(); } if (mTimeProvider != null) { mTimeProvider.close(); @@ -3061,8 +3067,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // Modular DRM clean up mOnDrmConfigHelper = null; synchronized (mDrmEventCbLock) { - mDrmEventCb = null; - mDrmEventExec = null; + mDrmEventCallbackRecords.clear(); } resetDrmState(); @@ -3118,18 +3123,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { Log.w(TAG, "mediaplayer2 went away with unhandled events"); return; } - final Executor eventExec; - final EventCallback eventCb; - synchronized (mEventCbLock) { - eventExec = mEventExec; - eventCb = mEventCb; - } - final Executor drmEventExec; - final DrmEventCallback drmEventCb; - synchronized (mDrmEventCbLock) { - drmEventExec = mDrmEventExec; - drmEventCb = mDrmEventCb; - } + final int what = msg.arg1; + final int extra = msg.arg2; switch(msg.what) { case MEDIA_PREPARED: try { @@ -3143,33 +3138,36 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { sendMessage(msg2); } - if (eventCb != null && eventExec != null) { - eventExec.execute(() -> eventCb.onInfo( - mMediaPlayer, 0, MEDIA_INFO_PREPARED, 0)); + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onInfo( + mMediaPlayer, 0, MEDIA_INFO_PREPARED, 0)); + } } return; case MEDIA_DRM_INFO: - Log.v(TAG, "MEDIA_DRM_INFO " + mDrmEventCb); - if (msg.obj == null) { Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL"); } else if (msg.obj instanceof Parcel) { - if (drmEventExec != null && drmEventCb != null) { - // The parcel was parsed already in postEventFromNative - final DrmInfoImpl drmInfo; - - synchronized (mDrmLock) { - if (mDrmInfoImpl != null) { - drmInfo = mDrmInfoImpl.makeCopy(); - } else { - drmInfo = null; - } + // The parcel was parsed already in postEventFromNative + final DrmInfoImpl drmInfo; + + synchronized (mDrmLock) { + if (mDrmInfoImpl != null) { + drmInfo = mDrmInfoImpl.makeCopy(); + } else { + drmInfo = null; } + } - // notifying the client outside the lock - if (drmInfo != null) { - drmEventExec.execute(() -> drmEventCb.onDrmInfo(mMediaPlayer, drmInfo)); + // notifying the client outside the lock + if (drmInfo != null) { + synchronized (mEventCbLock) { + for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { + cb.first.execute(() -> cb.second.onDrmInfo( + mMediaPlayer, drmInfo)); + } } } } else { @@ -3178,9 +3176,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { return; case MEDIA_PLAYBACK_COMPLETE: - if (eventCb != null && eventExec != null) { - eventExec.execute(() -> eventCb.onInfo( - mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onInfo( + mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); + } } stayAwake(false); return; @@ -3205,16 +3205,21 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { break; case MEDIA_BUFFERING_UPDATE: - if (eventCb != null && eventExec != null) { - final int percent = msg.arg1; - eventExec.execute(() -> eventCb.onBufferingUpdate(mMediaPlayer, 0, percent)); + final int percent = msg.arg1; + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onBufferingUpdate( + mMediaPlayer, 0, percent)); + } } return; case MEDIA_SEEK_COMPLETE: - if (eventCb != null && eventExec != null) { - eventExec.execute(() -> eventCb.onInfo( - mMediaPlayer, 0, MEDIA_INFO_COMPLETE_CALL_SEEK, 0)); + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onInfo( + mMediaPlayer, 0, MEDIA_INFO_COMPLETE_CALL_SEEK, 0)); + } } // fall through @@ -3228,61 +3233,68 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { return; case MEDIA_SET_VIDEO_SIZE: - if (eventCb != null && eventExec != null) { - final int width = msg.arg1; - final int height = msg.arg2; - eventExec.execute(() -> eventCb.onVideoSizeChanged( - mMediaPlayer, 0, width, height)); + final int width = msg.arg1; + final int height = msg.arg2; + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onVideoSizeChanged( + mMediaPlayer, 0, width, height)); + } } return; case MEDIA_ERROR: Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")"); - if (eventCb != null && eventExec != null) { - final int what = msg.arg1; - final int extra = msg.arg2; - eventExec.execute(() -> eventCb.onError(mMediaPlayer, 0, what, extra)); - eventExec.execute(() -> eventCb.onInfo( - mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onError( + mMediaPlayer, 0, what, extra)); + cb.first.execute(() -> cb.second.onInfo( + mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); + } } stayAwake(false); return; case MEDIA_INFO: switch (msg.arg1) { - case MEDIA_INFO_VIDEO_TRACK_LAGGING: - Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")"); - break; - case MEDIA_INFO_METADATA_UPDATE: - try { - scanInternalSubtitleTracks(); - } catch (RuntimeException e) { - Message msg2 = obtainMessage( - MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); - sendMessage(msg2); - } - // fall through + case MEDIA_INFO_VIDEO_TRACK_LAGGING: + Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")"); + break; - case MEDIA_INFO_EXTERNAL_METADATA_UPDATE: - msg.arg1 = MEDIA_INFO_METADATA_UPDATE; - // update default track selection - if (mSubtitleController != null) { - mSubtitleController.selectDefaultTrack(); - } - break; - case MEDIA_INFO_BUFFERING_START: - case MEDIA_INFO_BUFFERING_END: - TimeProvider timeProvider = mTimeProvider; - if (timeProvider != null) { - timeProvider.onBuffering(msg.arg1 == MEDIA_INFO_BUFFERING_START); - } - break; + case MEDIA_INFO_METADATA_UPDATE: + try { + scanInternalSubtitleTracks(); + } catch (RuntimeException e) { + Message msg2 = obtainMessage( + MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, + null); + sendMessage(msg2); + } + // fall through + + case MEDIA_INFO_EXTERNAL_METADATA_UPDATE: + msg.arg1 = MEDIA_INFO_METADATA_UPDATE; + // update default track selection + if (mSubtitleController != null) { + mSubtitleController.selectDefaultTrack(); + } + break; + + case MEDIA_INFO_BUFFERING_START: + case MEDIA_INFO_BUFFERING_END: + TimeProvider timeProvider = mTimeProvider; + if (timeProvider != null) { + timeProvider.onBuffering(msg.arg1 == MEDIA_INFO_BUFFERING_START); + } + break; } - if (eventCb != null && eventExec != null) { - final int what = msg.arg1; - final int extra = msg.arg2; - eventExec.execute(() -> eventCb.onInfo(mMediaPlayer, 0, what, extra)); + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onInfo( + mMediaPlayer, 0, what, extra)); + } } // No real default action so far. return; @@ -3295,17 +3307,18 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { return; case MEDIA_TIMED_TEXT: - if (eventCb == null || eventExec == null) { - return; - } - if (msg.obj == null) { - eventExec.execute(() -> eventCb.onTimedText(mMediaPlayer, 0, null)); + final TimedText text; + if (msg.obj instanceof Parcel) { + Parcel parcel = (Parcel)msg.obj; + text = new TimedText(parcel); + parcel.recycle(); } else { - if (msg.obj instanceof Parcel) { - Parcel parcel = (Parcel)msg.obj; - TimedText text = new TimedText(parcel); - parcel.recycle(); - eventExec.execute(() -> eventCb.onTimedText(mMediaPlayer, 0, text)); + text = null; + } + + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, 0, text)); } } return; @@ -3324,15 +3337,20 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { return; case MEDIA_META_DATA: - if (eventCb == null || eventExec == null) { - return; - } + final TimedMetaData data; if (msg.obj instanceof Parcel) { Parcel parcel = (Parcel) msg.obj; - TimedMetaData data = TimedMetaData.createTimedMetaDataFromParcel(parcel); + data = TimedMetaData.createTimedMetaDataFromParcel(parcel); parcel.recycle(); - eventExec.execute(() -> eventCb.onTimedMetaDataAvailable( - mMediaPlayer, 0, data)); + } else { + data = null; + } + + synchronized (mEventCbLock) { + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onTimedMetaDataAvailable( + mMediaPlayer, 0, data)); + } } return; @@ -3420,9 +3438,9 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } - private Executor mEventExec; - private EventCallback mEventCb; private final Object mEventCbLock = new Object(); + private ArrayList<Pair<Executor, EventCallback> > mEventCallbackRecords + = new ArrayList<Pair<Executor, EventCallback> >(); /** * Register a callback to be invoked when the media source is ready @@ -3441,9 +3459,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { throw new IllegalArgumentException("Illegal null Executor for the EventCallback"); } synchronized (mEventCbLock) { - // TODO: support multiple callbacks. - mEventExec = executor; - mEventCb = eventCallback; + mEventCallbackRecords.add(new Pair(executor, eventCallback)); } } @@ -3455,9 +3471,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void unregisterEventCallback(EventCallback callback) { synchronized (mEventCbLock) { - if (callback == mEventCb) { - mEventExec = null; - mEventCb = null; + for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { + if (cb.second == callback) { + mEventCallbackRecords.remove(cb); + } } } } @@ -3497,9 +3514,9 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private OnDrmConfigHelper mOnDrmConfigHelper; - private Executor mDrmEventExec; - private DrmEventCallback mDrmEventCb; private final Object mDrmEventCbLock = new Object(); + private ArrayList<Pair<Executor, DrmEventCallback> > mDrmEventCallbackRecords + = new ArrayList<Pair<Executor, DrmEventCallback> >(); /** * Register a callback to be invoked when the media source is ready @@ -3518,9 +3535,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { throw new IllegalArgumentException("Illegal null Executor for the EventCallback"); } synchronized (mDrmEventCbLock) { - // TODO: support multiple callbacks. - mDrmEventExec = executor; - mDrmEventCb = eventCallback; + mDrmEventCallbackRecords.add(new Pair(executor, eventCallback)); } } @@ -3532,9 +3547,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void unregisterDrmEventCallback(DrmEventCallback callback) { synchronized (mDrmEventCbLock) { - if (callback == mDrmEventCb) { - mDrmEventExec = null; - mDrmEventCb = null; + for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { + if (cb.second == callback) { + mDrmEventCallbackRecords.remove(cb); + break; + } } } } @@ -3733,15 +3750,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // if finished successfully without provisioning, call the callback outside the lock if (allDoneWithoutProvisioning) { - final Executor drmEventExec; - final DrmEventCallback drmEventCb; synchronized (mDrmEventCbLock) { - drmEventExec = mDrmEventExec; - drmEventCb = mDrmEventCb; - } - if (drmEventExec != null && drmEventCb != null) { - drmEventExec.execute(() -> drmEventCb.onDrmPrepared( - this, PREPARE_DRM_STATUS_SUCCESS)); + for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { + cb.first.execute(() -> cb.second.onDrmPrepared( + this, PREPARE_DRM_STATUS_SUCCESS)); + } } } @@ -4324,14 +4337,12 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { boolean succeeded = false; - final Executor drmEventExec; - final DrmEventCallback drmEventCb; + boolean hasCallback = false; synchronized (mDrmEventCbLock) { - drmEventExec = mDrmEventExec; - drmEventCb = mDrmEventCb; + hasCallback = !mDrmEventCallbackRecords.isEmpty(); } // non-blocking mode needs the lock - if (drmEventExec != null && drmEventCb != null) { + if (hasCallback) { synchronized (drmLock) { // continuing with prepareDrm @@ -4349,7 +4360,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } // synchronized // calling the callback outside the lock - drmEventExec.execute(() -> drmEventCb.onDrmPrepared(mediaPlayer, status)); + synchronized (mDrmEventCbLock) { + for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { + cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, status)); + } + } } else { // blocking mode already has the lock // continuing with prepareDrm @@ -4397,13 +4412,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { int result; // non-blocking: this is not the final result - final Executor drmEventExec; - final DrmEventCallback drmEventCb; + boolean hasCallback = false; synchronized (mDrmEventCbLock) { - drmEventExec = mDrmEventExec; - drmEventCb = mDrmEventCb; + hasCallback = !mDrmEventCallbackRecords.isEmpty(); } - if (drmEventCb != null && drmEventExec != null) { + if (hasCallback) { result = PREPARE_DRM_STATUS_SUCCESS; } else { // if blocking mode, wait till provisioning is done |