diff options
| author | 2018-11-05 21:37:54 -0800 | |
|---|---|---|
| committer | 2018-11-13 16:39:35 -0800 | |
| commit | 56f7c90c943bc338d1fe9b2665a265bcc693d437 (patch) | |
| tree | d4d8a2d797fc0af652db612f92f1c9d18f8b2913 | |
| parent | 45ac8e40024ed729ef85c51356b8047d27750433 (diff) | |
MediaPlayer2Impl: pack source info into subclass
Bug: 109928575
Test: android.media.cts.MediaPlayer2Test
Change-Id: Ia478b828f4fa11502f7693a530a367ff769d2881
| -rw-r--r-- | media/java/android/media/MediaPlayer2Impl.java | 225 |
1 files changed, 123 insertions, 102 deletions
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 2b5dea157c90..38975d081074 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -57,15 +57,20 @@ import java.net.URL; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.UUID; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; /** * @hide @@ -95,17 +100,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private final Object mSrcLock = new Object(); //--- guarded by |mSrcLock| start - private long mSrcIdGenerator = 0; - private DataSourceDesc mCurrentDSD; - private long mCurrentSrcId = mSrcIdGenerator++; - private List<DataSourceDesc> mNextDSDs; - private long mNextSrcId = mSrcIdGenerator++; - private int mNextSourceState = NEXT_SOURCE_STATE_INIT; - private boolean mNextSourcePlayPending = false; + private SourceInfo mCurrentSourceInfo; + private final Queue<SourceInfo> mNextSourceInfos = new ConcurrentLinkedQueue<>(); //--- guarded by |mSrcLock| end + private final AtomicLong mSrcIdGenerator = new AtomicLong(0); - private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0); - private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0); private volatile float mVolume = 1.0f; private VideoSize mVideoSize = new VideoSize(0, 0); @@ -221,7 +220,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public long getBufferedPosition() { // Use cached buffered percent for now. - return getDuration() * mBufferedPercentageCurrent.get() / 100; + int bufferedPercentage; + synchronized (mSrcLock) { + if (mCurrentSourceInfo == null) { + bufferedPercentage = 0; + } else { + bufferedPercentage = mCurrentSourceInfo.mBufferedPercentage.get(); + } + } + return getDuration() * bufferedPercentage / 100; } @Override @@ -263,9 +270,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } synchronized (mSrcLock) { - mCurrentDSD = dsd; - mCurrentSrcId = mSrcIdGenerator++; - handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId); + mCurrentSourceInfo = new SourceInfo(dsd); + handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId); } } }); @@ -278,10 +284,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { void process() { checkArgument(dsd != null, "the DataSourceDesc cannot be null"); synchronized (mSrcLock) { - mNextDSDs = new ArrayList<DataSourceDesc>(1); - mNextDSDs.add(dsd); - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mNextSourceInfos.clear(); + mNextSourceInfos.add(new SourceInfo(dsd)); } prepareNextDataSource(); } @@ -304,9 +308,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } synchronized (mSrcLock) { - mNextDSDs = new ArrayList(dsds); - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mNextSourceInfos.clear(); + for (DataSourceDesc dsd : dsds) { + mNextSourceInfos.add(new SourceInfo(dsd)); + } } prepareNextDataSource(); } @@ -318,22 +323,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) { @Override void process() { - synchronized (mSrcLock) { - if (mNextDSDs != null) { - mNextDSDs.clear(); - mNextDSDs = null; - } - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; - } + mNextSourceInfos.clear(); } }); } @Override - public @NonNull DataSourceDesc getCurrentDataSource() { + public DataSourceDesc getCurrentDataSource() { synchronized (mSrcLock) { - return mCurrentDSD; + return mCurrentSourceInfo == null ? null : mCurrentSourceInfo.mDSD; } } @@ -702,34 +700,29 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } boolean hasNextDSD; - synchronized (mSrcLock) { - hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty()); - } - int state = getState(); - if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) { - // Current source has not been prepared yet. - return hasNextDSD; - } - synchronized (mSrcLock) { - if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) { + hasNextDSD = !mNextSourceInfos.isEmpty(); + if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) { + // Current source has not been prepared yet. + return hasNextDSD; + } + + SourceInfo nextSource = mNextSourceInfos.peek(); + if (!hasNextDSD || nextSource.mStateAsNextSource != NEXT_SOURCE_STATE_INIT) { // There is no next source or it's in preparing or prepared state. return hasNextDSD; } try { - mNextSourceState = NEXT_SOURCE_STATE_PREPARING; - handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId); + nextSource.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARING; + handleDataSource(false /* isCurrent */, nextSource.mDSD, nextSource.mId); } catch (Exception e) { Message msg = mTaskHandler.obtainMessage( MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null); - mTaskHandler.handleMessage(msg, mNextSrcId); + mTaskHandler.handleMessage(msg, nextSource.mId); - mNextDSDs.remove(0); - // make a new SrcId to obsolete notification for previous one. - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mNextSourceInfos.poll(); return prepareNextDataSource(); } } @@ -744,19 +737,14 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { boolean hasNextDSD = false; synchronized (mSrcLock) { - if (mNextDSDs != null && !mNextDSDs.isEmpty()) { + if (!mNextSourceInfos.isEmpty()) { hasNextDSD = true; - if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) { + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); + if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_PREPARED) { // Switch to next source only when it has been prepared. - mCurrentDSD = mNextDSDs.get(0); - mCurrentSrcId = mNextSrcId; - mBufferedPercentageCurrent.set(mBufferedPercentageNext.get()); - mNextDSDs.remove(0); - mNextSrcId = mSrcIdGenerator++; // make it different from |mCurrentSrcId| - mBufferedPercentageNext.set(0); - mNextSourceState = NEXT_SOURCE_STATE_INIT; - - long srcId = mCurrentSrcId; + mCurrentSourceInfo = mNextSourceInfos.poll(); + + long srcId = mCurrentSourceInfo.mId; try { nativePlayNextDataSource(srcId); } catch (Exception e) { @@ -771,9 +759,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // Now a new current src is playing. // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source. - mNextSourcePlayPending = false; } - } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { + } else if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_INIT) { hasNextDSD = prepareNextDataSource(); } } @@ -1180,12 +1167,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { mDrmEventCallbackRecords.clear(); } synchronized (mSrcLock) { - if (mNextDSDs != null) { - mNextDSDs.clear(); - mNextDSDs = null; - } - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mCurrentSourceInfo = null; + mNextSourceInfos.clear(); } stayAwake(false); @@ -1637,20 +1620,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { final int what = msg.arg1; final int extra = msg.arg2; - final DataSourceDesc dsd; - boolean isCurrentSrcId = false; - boolean isNextSrcId = false; - synchronized (mSrcLock) { - if (srcId == mCurrentSrcId) { - dsd = mCurrentDSD; - isCurrentSrcId = true; - } else if (mNextDSDs != null && !mNextDSDs.isEmpty() && srcId == mNextSrcId) { - dsd = mNextDSDs.get(0); - isNextSrcId = true; - } else { - return; - } + final SourceInfo sourceInfo = getSourceInfoById(srcId); + if (sourceInfo == null) { + return; } + final DataSourceDesc dsd = sourceInfo.mDSD; switch(msg.what) { case MEDIA_PREPARED: @@ -1666,14 +1640,16 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } synchronized (mSrcLock) { + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId - + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId); + + ", curSrc=" + mCurrentSourceInfo + + ", nextSrc=" + nextSourceInfo); - if (isCurrentSrcId) { + if (isCurrentSource(srcId)) { prepareNextDataSource(); - } else if (isNextSrcId) { - mNextSourceState = NEXT_SOURCE_STATE_PREPARED; - if (mNextSourcePlayPending) { + } else if (isNextSource(srcId)) { + nextSourceInfo.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARED; + if (nextSourceInfo.mPlayPendingAsNextSource) { playNextDataSource(); } } @@ -1726,7 +1702,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { case MEDIA_PLAYBACK_COMPLETE: { - if (isCurrentSrcId) { + if (isCurrentSource(srcId)) { sendEvent(new EventNotifier() { @Override public void notify(EventCallback callback) { @@ -1737,11 +1713,13 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { stayAwake(false); synchronized (mSrcLock) { - mNextSourcePlayPending = true; - + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); + if (nextSourceInfo != null) { + nextSourceInfo.mPlayPendingAsNextSource = true; + } Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId - + ", currentSrcId=" + mCurrentSrcId - + ", nextSrcId=" + mNextSrcId); + + ", curSrc=" + mCurrentSourceInfo + + ", nextSrc=" + nextSourceInfo); } playNextDataSource(); @@ -1772,13 +1750,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } }); - synchronized (mSrcLock) { - if (isCurrentSrcId) { - mBufferedPercentageCurrent.set(percent); - } else if (isNextSrcId) { - mBufferedPercentageNext.set(percent); - } + SourceInfo src = getSourceInfoById(srcId); + if (src != null) { + src.mBufferedPercentage.set(percent); } + return; } @@ -1850,7 +1826,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { }); if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) { - if (isCurrentSrcId) { + if (isCurrentSource(srcId)) { prepareNextDataSource(); } } @@ -1965,6 +1941,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } } + } /* @@ -2241,7 +2218,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( - MediaPlayer2Impl.this, mCurrentDSD, prepareDrmStatus); + MediaPlayer2Impl.this, getCurrentDataSource(), prepareDrmStatus); } }); @@ -2307,7 +2284,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // call the callback outside the lock if (mOnDrmConfigHelper != null) { - mOnDrmConfigHelper.onDrmConfig(this, mCurrentDSD); + mOnDrmConfigHelper.onDrmConfig(this, getCurrentDataSource()); } synchronized (mDrmLock) { @@ -2956,7 +2933,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( - mediaPlayer, mCurrentDSD, status); + mediaPlayer, getCurrentDataSource(), status); } }); @@ -3223,9 +3200,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } catch (Exception e) { status = CALL_STATUS_ERROR_UNKNOWN; } - synchronized (mSrcLock) { - mDSD = mCurrentDSD; - } + mDSD = getCurrentDataSource(); // TODO: Make native implementations asynchronous and let them send notifications. if (!mNeedToWaitForEventToComplete || status != CALL_STATUS_NO_ERROR) { @@ -3262,4 +3237,50 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { super(detailMessage); } }; + + private final class SourceInfo { + final DataSourceDesc mDSD; + final long mId = mSrcIdGenerator.getAndIncrement(); + AtomicInteger mBufferedPercentage = new AtomicInteger(0); + + // m*AsNextSource (below) only applies to pending data sources in the playlist; + // the meanings of mCurrentSourceInfo.{mStateAsNextSource,mPlayPendingAsNextSource} + // are undefined. + int mStateAsNextSource = NEXT_SOURCE_STATE_INIT; + boolean mPlayPendingAsNextSource = false; + + SourceInfo(DataSourceDesc dsd) { + this.mDSD = dsd; + } + + @Override + public String toString() { + return String.format("%s(%d)", SourceInfo.class.getName(), mId); + } + + } + + private SourceInfo getSourceInfoById(long srcId) { + synchronized (mSrcLock) { + if (isCurrentSource(srcId)) { + return mCurrentSourceInfo; + } + if (isNextSource(srcId)) { + return mNextSourceInfos.peek(); + } + } + return null; + } + + private boolean isCurrentSource(long srcId) { + synchronized (mSrcLock) { + return mCurrentSourceInfo != null && mCurrentSourceInfo.mId == srcId; + } + } + + private boolean isNextSource(long srcId) { + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); + return nextSourceInfo != null && nextSourceInfo.mId == srcId; + } + } |