in android/media/MediaPlayer2Impl.java [2780:3125]
public void handleMessage(Message msg, long srcId) {
if (mMediaPlayer.mNativeContext == 0) {
Log.w(TAG, "mediaplayer2 went away with unhandled events");
return;
}
final int what = msg.arg1;
final int extra = msg.arg2;
switch(msg.what) {
case MEDIA_PREPARED:
{
try {
scanInternalSubtitleTracks();
} catch (RuntimeException e) {
// send error message instead of crashing;
// send error message instead of inlining a call to onError
// to avoid code duplication.
Message msg2 = obtainMessage(
MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
sendMessage(msg2);
}
final DataSourceDesc dsd;
synchronized (mSrcLock) {
Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
+ ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
if (srcId == mCurrentSrcId) {
dsd = mCurrentDSD;
prepareNextDataSource_l();
} else if (mNextDSDs != null && !mNextDSDs.isEmpty()
&& srcId == mNextSrcId) {
dsd = mNextDSDs.get(0);
mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
if (mNextSourcePlayPending) {
playNextDataSource_l();
}
} else {
dsd = null;
}
}
if (dsd != null) {
synchronized (mEventCbLock) {
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onInfo(
mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0));
}
}
}
synchronized (mTaskLock) {
if (mCurrentTask != null
&& mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
&& mCurrentTask.mDSD == dsd
&& mCurrentTask.mNeedToWaitForEventToComplete) {
mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
mCurrentTask = null;
processPendingTask_l();
}
}
return;
}
case MEDIA_DRM_INFO:
{
if (msg.obj == null) {
Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
} else if (msg.obj instanceof Parcel) {
// 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) {
synchronized (mEventCbLock) {
for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
cb.first.execute(() -> cb.second.onDrmInfo(
mMediaPlayer, mCurrentDSD, drmInfo));
}
}
}
} else {
Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
}
return;
}
case MEDIA_PLAYBACK_COMPLETE:
{
final DataSourceDesc dsd = mCurrentDSD;
synchronized (mSrcLock) {
if (srcId == mCurrentSrcId) {
Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
+ ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
playNextDataSource_l();
}
}
synchronized (mEventCbLock) {
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onInfo(
mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
}
}
stayAwake(false);
return;
}
case MEDIA_STOPPED:
{
TimeProvider timeProvider = mTimeProvider;
if (timeProvider != null) {
timeProvider.onStopped();
}
break;
}
case MEDIA_STARTED:
case MEDIA_PAUSED:
{
TimeProvider timeProvider = mTimeProvider;
if (timeProvider != null) {
timeProvider.onPaused(msg.what == MEDIA_PAUSED);
}
break;
}
case MEDIA_BUFFERING_UPDATE:
{
final int percent = msg.arg1;
synchronized (mEventCbLock) {
if (srcId == mCurrentSrcId) {
mBufferedPercentageCurrent.set(percent);
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onInfo(
mMediaPlayer, mCurrentDSD, MEDIA_INFO_BUFFERING_UPDATE,
percent));
}
} else if (srcId == mNextSrcId && !mNextDSDs.isEmpty()) {
mBufferedPercentageNext.set(percent);
DataSourceDesc nextDSD = mNextDSDs.get(0);
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onInfo(
mMediaPlayer, nextDSD, MEDIA_INFO_BUFFERING_UPDATE,
percent));
}
}
}
return;
}
case MEDIA_SEEK_COMPLETE:
{
synchronized (mTaskLock) {
if (mCurrentTask != null
&& mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
&& mCurrentTask.mNeedToWaitForEventToComplete) {
mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
mCurrentTask = null;
processPendingTask_l();
}
}
}
// fall through
case MEDIA_SKIPPED:
{
TimeProvider timeProvider = mTimeProvider;
if (timeProvider != null) {
timeProvider.onSeekComplete(mMediaPlayer);
}
return;
}
case MEDIA_SET_VIDEO_SIZE:
{
final int width = msg.arg1;
final int height = msg.arg2;
synchronized (mEventCbLock) {
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onVideoSizeChanged(
mMediaPlayer, mCurrentDSD, width, height));
}
}
return;
}
case MEDIA_ERROR:
{
Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
synchronized (mEventCbLock) {
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onError(
mMediaPlayer, mCurrentDSD, what, extra));
cb.first.execute(() -> cb.second.onInfo(
mMediaPlayer, mCurrentDSD, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
}
}
stayAwake(false);
return;
}
case MEDIA_INFO:
{
switch (msg.arg1) {
case MEDIA_INFO_STARTED_AS_NEXT:
if (srcId == mCurrentSrcId) {
prepareNextDataSource_l();
}
break;
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_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;
}
synchronized (mEventCbLock) {
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onInfo(
mMediaPlayer, mCurrentDSD, what, extra));
}
}
// No real default action so far.
return;
}
case MEDIA_NOTIFY_TIME:
{
TimeProvider timeProvider = mTimeProvider;
if (timeProvider != null) {
timeProvider.onNotifyTime();
}
return;
}
case MEDIA_TIMED_TEXT:
{
final TimedText text;
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel)msg.obj;
text = new TimedText(parcel);
parcel.recycle();
} else {
text = null;
}
synchronized (mEventCbLock) {
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, mCurrentDSD, text));
}
}
return;
}
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);
}
return;
}
case MEDIA_META_DATA:
{
final TimedMetaData data;
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
parcel.recycle();
} else {
data = null;
}
synchronized (mEventCbLock) {
for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onTimedMetaDataAvailable(
mMediaPlayer, mCurrentDSD, data));
}
}
return;
}
case MEDIA_NOP: // interface test message - ignore
{
break;
}
case MEDIA_AUDIO_ROUTING_CHANGED:
{
AudioManager.resetAudioPortGeneration();
synchronized (mRoutingChangeListeners) {
for (NativeRoutingEventHandlerDelegate delegate
: mRoutingChangeListeners.values()) {
delegate.notifyClient();
}
}
return;
}
default:
{
Log.e(TAG, "Unknown message type " + msg.what);
return;
}
}
}