From 47cab8322a01edee503f10e9d5cbec2a5b5cffc3 Mon Sep 17 00:00:00 2001 From: Dongwon Kang Date: Fri, 2 Mar 2018 10:08:53 -0800 Subject: [PATCH 1/2] Remove unused imports in MediaPlayer2. Test: build. Change-Id: I2f2a05ef4fc41d14f91e6805217852adf5bbb28e --- media/java/android/media/MediaPlayer2.java | 18 +++--------------- media/java/android/media/MediaPlayer2Impl.java | 10 +++------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java index 0d472abe9f9cc..0cc744186a75d 100644 --- a/media/java/android/media/MediaPlayer2.java +++ b/media/java/android/media/MediaPlayer2.java @@ -22,17 +22,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.SurfaceTexture; -import android.media.MediaDrm; -import android.media.MediaFormat; -import android.media.MediaPlayer2Impl; -import android.media.MediaPlayerBase; -import android.media.MediaTimeProvider; -import android.media.PlaybackParams; -import android.media.SubtitleController; -import android.media.SubtitleController.Anchor; -import android.media.SubtitleData; -import android.media.SubtitleTrack.RenderingWidget; -import android.media.SyncParams; import android.net.Uri; import android.os.Handler; import android.os.Parcel; @@ -43,14 +32,13 @@ import android.view.SurfaceHolder; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; -import java.lang.AutoCloseable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.concurrent.Executor; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.Executor; /** @@ -2019,12 +2007,12 @@ public abstract class MediaPlayer2 extends MediaPlayerBase public static final int MEDIA_CALL_DESELECT_TRACK = 2; /** The player just completed a call {@code loopCurrent}. - * @see android.media.MediaPlayer2.MediaPlayer2EventCallback.CallComplete + * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete */ public static final int MEDIA_CALL_LOOP_CURRENT = 3; /** The player just completed a call {@code pause}. - * @see android.media.MediaPlayer2.MediaPlayer2EventCallback.CallComplete + * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete */ public static final int MEDIA_CALL_PAUSE = 4; diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 50e3543171620..2d92d64e6a963 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -35,16 +35,16 @@ import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; -import android.os.Process; import android.os.PowerManager; +import android.os.Process; import android.os.SystemProperties; import android.provider.Settings; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import android.util.ArrayMap; import android.util.Log; import android.util.Pair; -import android.util.ArrayMap; import android.view.Surface; import android.view.SurfaceHolder; import android.widget.VideoView; @@ -63,10 +63,7 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.lang.Runnable; import java.lang.ref.WeakReference; -import java.net.CookieHandler; -import java.net.CookieManager; import java.net.HttpCookie; import java.net.HttpURLConnection; import java.net.URL; @@ -74,8 +71,6 @@ import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; -import java.util.Collections; -import java.util.concurrent.Executor; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -83,6 +78,7 @@ import java.util.Scanner; import java.util.Set; import java.util.UUID; import java.util.Vector; +import java.util.concurrent.Executor; /** From adf77a01e8142a5abb496997beddead7b48f43b7 Mon Sep 17 00:00:00 2001 From: Dongwon Kang Date: Fri, 2 Mar 2018 18:10:49 -0800 Subject: [PATCH 2/2] Make MP2.prepare|play handled with task queue Test: plays video Bug: 63934228 Change-Id: Iecf8b2079e87241365ab6b7b7b0a5a669c948427 --- .../java/android/media/MediaPlayer2Impl.java | 101 +++++++++++++++++- media/jni/android_media_MediaPlayer2.cpp | 2 +- 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 2d92d64e6a963..7c114df660374 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -72,6 +72,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Scanner; @@ -131,6 +132,14 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private ProvisioningThread mDrmProvisioningThread; //--- guarded by |mDrmLock| end + private HandlerThread mHandlerThread; + private final Handler mTaskHandler; + private final Object mTaskLock = new Object(); + @GuardedBy("mTaskLock") + private final List mPendingTasks = new LinkedList<>(); + @GuardedBy("mTaskLock") + private Task mCurrentTask; + /** * Default constructor. *

When done with the MediaPlayer2Impl, you should call {@link #close()}, @@ -147,6 +156,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { mEventHandler = null; } + mHandlerThread = new HandlerThread("MediaPlayer2TaskThread"); + mHandlerThread.start(); + looper = mHandlerThread.getLooper(); + mTaskHandler = new Handler(looper); + mTimeProvider = new TimeProvider(this); mOpenSubtitleSources = new Vector(); mGuard.open("close"); @@ -197,8 +211,18 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { */ @Override public void play() { - stayAwake(true); - _start(); + synchronized (mTaskLock) { + mPendingTasks.add(new Task(MEDIA_CALL_PLAY, false) { + @Override + int process() { + stayAwake(true); + _start(); + // TODO: define public constants for return value (status). + return 0; + } + }); + processPendingTask_l(); + } } private native void _start() throws IllegalStateException; @@ -214,7 +238,21 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { * @throws IllegalStateException if it is called in an invalid state */ @Override - public native void prepare(); + public void prepare() { + synchronized (mTaskLock) { + mPendingTasks.add(new Task(MEDIA_CALL_PREPARE, true) { + @Override + int process() { + _prepare(); + // TODO: define public constants for return value (status). + return 0; + } + }); + processPendingTask_l(); + } + } + + public native void _prepare(); /** * Pauses playback. Call play() to resume. @@ -691,6 +729,18 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { public void clearPendingCommands() { } + @GuardedBy("mTaskLock") + private void processPendingTask_l() { + if (mCurrentTask != null) { + return; + } + if (!mPendingTasks.isEmpty()) { + Task task = mPendingTasks.remove(0); + mCurrentTask = task; + mTaskHandler.post(task); + } + } + private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId) throws IOException { Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null"); @@ -2521,6 +2571,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { synchronized (mEventCbLock) { mEventCallbackRecords.clear(); } + if (mHandlerThread != null) { + mHandlerThread.quitSafely(); + mHandlerThread = null; + } if (mTimeProvider != null) { mTimeProvider.close(); mTimeProvider = null; @@ -2634,6 +2688,13 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } } + synchronized (mTaskLock) { + if (mCurrentTask.mMediaCallType == MEDIA_CALL_PREPARE + && mCurrentTask.mNeedToWaitForEventToComplete) { + mCurrentTask = null; + processPendingTask_l(); + } + } return; } @@ -4502,4 +4563,38 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } } + + private abstract class Task implements Runnable { + private final int mMediaCallType; + private final boolean mNeedToWaitForEventToComplete; + + public Task (int mediaCallType, boolean needToWaitForEventToComplete) { + mMediaCallType = mediaCallType; + mNeedToWaitForEventToComplete = needToWaitForEventToComplete; + } + + abstract int process(); + + @Override + public void run() { + int status = process(); + + if (!mNeedToWaitForEventToComplete) { + final DataSourceDesc dsd; + synchronized (mSrcLock) { + dsd = mCurrentDSD; + } + synchronized (mEventCbLock) { + for (Pair cb : mEventCallbackRecords) { + cb.first.execute(() -> cb.second.onCallComplete( + MediaPlayer2Impl.this, dsd, mMediaCallType, status)); + } + } + synchronized (mTaskLock) { + mCurrentTask = null; + processPendingTask_l(); + } + } + } + }; } diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp index af78777a900b7..918b82b065703 100644 --- a/media/jni/android_media_MediaPlayer2.cpp +++ b/media/jni/android_media_MediaPlayer2.cpp @@ -1490,7 +1490,7 @@ static const JNINativeMethod gMethods[] = { {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer2_setVideoSurface}, {"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer2_getBufferingParams}, {"setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams}, - {"prepare", "()V", (void *)android_media_MediaPlayer2_prepare}, + {"_prepare", "()V", (void *)android_media_MediaPlayer2_prepare}, {"_start", "()V", (void *)android_media_MediaPlayer2_start}, {"_stop", "()V", (void *)android_media_MediaPlayer2_stop}, {"native_getMediaPlayer2State", "()I", (void *)android_media_MediaPlayer2_getMediaPlayer2State},