From 6aee256d92dc2b3150a1568314c430291436c554 Mon Sep 17 00:00:00 2001 From: Toshikazu Saito Date: Thu, 8 Sep 2016 21:54:25 +0900 Subject: [PATCH] Fix a dead lock for SubtitleTrack Dead lock happens in notifyTrackData() and scheduleUpdate() of TimeProvider. notifyTrackData() gets lock and calls SRTTrack.onData(). SRTTrack gets lock in addCue() but does not get lock in onData(). So SRTTrack.setTimeProvider() can call before next addCue() is called. When scheduleUpdate() is called from SRTTrack.setTimeProvider() in that case, dead lock happens because following reason. - TimeProvider is already gotten lock in notifyTrackData() - scheduleUpdate() tries to get lock of TimeProvider but notifyTrackData() is not finished because SRTTrack.onData() waits for calling next addCue() - SRTTrack waits for finishing setTimeProvider() to get lock - setTimeProvider() is not finished because lock cannot be gotten in scheduleUpdate() This fix changes the looper for SubtitleController to the looper used in TimeProvider$EventHandler not to interrupt a message by SubtitleController while running notifyTrackData(). Bug: 122051638 Test: check if subtitle works correctly with MediaPlayer Change-Id: Ib77144c5adb811676899a8d7e7681045663de0d2 --- media/java/android/media/MediaPlayer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index e4d356b48f6d2..08ce9fc87918a 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -2645,6 +2645,7 @@ public class MediaPlayer extends PlayerBase */ private synchronized void setSubtitleAnchor() { if ((mSubtitleController == null) && (ActivityThread.currentApplication() != null)) { + getMediaTimeProvider(); final HandlerThread thread = new HandlerThread("SetSubtitleAnchorThread"); thread.start(); Handler handler = new Handler(thread.getLooper()); @@ -2660,7 +2661,7 @@ public class MediaPlayer extends PlayerBase @Override public Looper getSubtitleLooper() { - return Looper.getMainLooper(); + return mTimeProvider.mEventHandler.getLooper(); } }); thread.getLooper().quitSafely();