Merge "MediaPlayer2: move SubtitleData listener into EventCallback"
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 70ef81f..b747291 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -883,15 +883,6 @@
     // This is a synchronous call.
     public abstract void clearPendingCommands();
 
-    /**
-     * Stops playback after playback has been started or paused.
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     * @hide
-     */
-    public void stop() { }
-
     //--------------------------------------------------------------------------
     // Explicit Routing
     //--------------------
@@ -1714,7 +1705,7 @@
          * @param dsd the DataSourceDesc of this data source
          * @param timestamp the new media clock.
          */
-        public void onMediaTimeChanged(
+        public void onMediaTimeDiscontinuity(
                 MediaPlayer2 mp, DataSourceDesc dsd, MediaTimestamp timestamp) { }
 
         /**
@@ -1725,44 +1716,34 @@
          *        {@link #notifyWhenCommandLabelReached(Object)}.
          */
         public void onCommandLabelReached(MediaPlayer2 mp, @NonNull Object label) { }
+
+        /**
+         * Called when when a player subtitle track has new subtitle data available.
+         * @param mp the player that reports the new subtitle data
+         * @param dsd the DataSourceDesc of this data source
+         * @param data the subtitle data
+         */
+        public void onSubtitleData(
+                MediaPlayer2 mp, DataSourceDesc dsd, @NonNull SubtitleData data) { }
     }
 
     /**
      * Sets the callback to be invoked when the media source is ready for playback.
      *
-     * @param eventCallback the callback that will be run
      * @param executor the executor through which the callback should be invoked
+     * @param eventCallback the callback that will be run
      */
     // This is a synchronous call.
-    public abstract void setEventCallback(@NonNull @CallbackExecutor Executor executor,
+    public abstract void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull EventCallback eventCallback);
 
     /**
-     * Clears the {@link EventCallback}.
+     * Unregisters the {@link EventCallback}.
+     *
+     * @param eventCallback the callback to be unregistered
      */
     // This is a synchronous call.
-    public abstract void clearEventCallback();
-
-    /**
-     * Interface definition of a callback to be invoked when a
-     * track has data available.
-     *
-     * @hide
-     */
-    public interface OnSubtitleDataListener
-    {
-        public void onSubtitleData(MediaPlayer2 mp, SubtitleData data);
-    }
-
-    /**
-     * Register a callback to be invoked when a track has data available.
-     *
-     * @param listener the callback that will be run
-     *
-     * @hide
-     */
-    // This is a synchronous call.
-    public void setOnSubtitleDataListener(OnSubtitleDataListener listener) { }
+    public abstract void unregisterEventCallback(EventCallback eventCallback);
 
 
     /* Do not change these values without updating their counterparts
@@ -2056,11 +2037,6 @@
      */
     public static final int CALL_COMPLETED_SET_PLAYBACK_PARAMS = 24;
 
-    /** The player just completed a call {@link #setPlaybackSpeed}.
-     * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
-     */
-    public static final int CALL_COMPLETED_SET_PLAYBACK_SPEED = 25;
-
     /** The player just completed a call {@link #setPlayerVolume}.
      * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
      */
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 2b61b2e..283b8ec 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -998,20 +998,6 @@
 
     private native int _getAudioStreamType() throws IllegalStateException;
 
-    /**
-     * Stops playback after playback has been started or paused.
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     * #hide
-     */
-    @Override
-    public void stop() {
-        stayAwake(false);
-        _stop();
-    }
-
-    private native void _stop() throws IllegalStateException;
 
     //--------------------------------------------------------------------------
     // Explicit Routing
@@ -2059,9 +2045,9 @@
     private int mSelectedSubtitleTrackIndex = -1;
     private Vector<InputStream> mOpenSubtitleSources;
 
-    private OnSubtitleDataListener mSubtitleDataListener = new OnSubtitleDataListener() {
+    private EventCallback mSubtitleDataCallback = new EventCallback() {
         @Override
-        public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+        public void onSubtitleData(MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
             int index = data.getTrackIndex();
             synchronized (mIndexTrackPairs) {
                 for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) {
@@ -2085,7 +2071,7 @@
             }
             mSelectedSubtitleTrackIndex = -1;
         }
-        setOnSubtitleDataListener(null);
+        unregisterEventCallback(mSubtitleDataCallback);
         if (track == null) {
             return;
         }
@@ -2105,7 +2091,8 @@
                 selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true);
             } catch (IllegalStateException e) {
             }
-            setOnSubtitleDataListener(mSubtitleDataListener);
+            final Executor executor = (runnable) -> mEventHandler.post(runnable);
+            registerEventCallback(executor, mSubtitleDataCallback);
         }
         // no need to select out-of-band tracks
     }
@@ -2628,7 +2615,6 @@
             mTimeProvider.close();
             mTimeProvider = null;
         }
-        mOnSubtitleDataListener = null;
 
         // Modular DRM clean up
         mOnDrmConfigHelper = null;
@@ -2969,7 +2955,8 @@
 
                 synchronized (mEventCbLock) {
                     for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, mCurrentDSD, text));
+                        cb.first.execute(() -> cb.second.onTimedText(
+                                mMediaPlayer, mCurrentDSD, text));
                     }
                 }
                 return;
@@ -2977,15 +2964,16 @@
 
             case MEDIA_SUBTITLE_DATA:
             {
-                OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
-                if (onSubtitleDataListener == null) {
-                    return;
-                }
                 if (msg.obj instanceof Parcel) {
                     Parcel parcel = (Parcel) msg.obj;
                     SubtitleData data = new SubtitleData(parcel);
                     parcel.recycle();
-                    onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+                    synchronized (mEventCbLock) {
+                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                            cb.first.execute(() -> cb.second.onSubtitleData(
+                                    mMediaPlayer, mCurrentDSD, data));
+                        }
+                    }
                 }
                 return;
             }
@@ -3118,7 +3106,7 @@
      * @param executor the executor through which the callback should be invoked
      */
     @Override
-    public void setEventCallback(@NonNull @CallbackExecutor Executor executor,
+    public void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull EventCallback eventCallback) {
         if (eventCallback == null) {
             throw new IllegalArgumentException("Illegal null EventCallback");
@@ -3136,27 +3124,16 @@
      * Clears the {@link EventCallback}.
      */
     @Override
-    public void clearEventCallback() {
+    public void unregisterEventCallback(EventCallback eventCallback) {
         synchronized (mEventCbLock) {
-            mEventCallbackRecords.clear();
+            for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                if (cb.second == eventCallback) {
+                    mEventCallbackRecords.remove(cb);
+                }
+            }
         }
     }
 
-    /**
-     * Register a callback to be invoked when a track has data available.
-     *
-     * @param listener the callback that will be run
-     *
-     * @hide
-     */
-    @Override
-    public void setOnSubtitleDataListener(OnSubtitleDataListener listener) {
-        mOnSubtitleDataListener = listener;
-    }
-
-    private OnSubtitleDataListener mOnSubtitleDataListener;
-
-
     // Modular DRM begin
 
     /**
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index d166cc3..abf0534 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -568,18 +568,6 @@
 }
 
 static void
-android_media_MediaPlayer2_stop(JNIEnv *env, jobject thiz)
-{
-    ALOGV("stop");
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return;
-    }
-    process_media_player_call( env, thiz, mp->stop(), NULL, NULL );
-}
-
-static void
 android_media_MediaPlayer2_pause(JNIEnv *env, jobject thiz)
 {
     ALOGV("pause");
@@ -1501,7 +1489,6 @@
     {"_setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
     {"_prepare",            "()V",                              (void *)android_media_MediaPlayer2_prepare},
     {"_start",              "()V",                              (void *)android_media_MediaPlayer2_start},
-    {"_stop",               "()V",                              (void *)android_media_MediaPlayer2_stop},
     {"native_getState",     "()I",                              (void *)android_media_MediaPlayer2_getState},
     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer2_getVideoWidth},
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer2_getVideoHeight},