Chromium Code Reviews| Index: media/base/android/java/src/org/chromium/media/MediaServerCrashListener.java |
| diff --git a/media/base/android/java/src/org/chromium/media/MediaServerCrashListener.java b/media/base/android/java/src/org/chromium/media/MediaServerCrashListener.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6db33392e99b90f6ca59da6b001efbf9562faec3 |
| --- /dev/null |
| +++ b/media/base/android/java/src/org/chromium/media/MediaServerCrashListener.java |
| @@ -0,0 +1,111 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.media; |
| + |
| +import android.content.Context; |
| +import android.media.MediaPlayer; |
| + |
| +import org.chromium.base.Log; |
| +import org.chromium.base.annotations.CalledByNative; |
| +import org.chromium.base.annotations.JNINamespace; |
| +import org.chromium.base.annotations.MainDex; |
| +import org.chromium.content.R; |
| + |
| +/** |
| + * Class for listening to Android MediaServer crashes to throttle media decoding |
| + * when needed. |
| + */ |
| +@MainDex |
| +@JNINamespace("media") |
| +public class MediaServerCrashListener implements MediaPlayer.OnErrorListener { |
| + private static final String TAG = "crMediaCrashListener"; |
|
DaleCurtis
2016/11/15 00:49:32
Don't know about the prefix, might be special in r
tguilbert
2016/11/15 19:29:07
Acknowledged.
|
| + private static final long UNKNOWN_TIME = -1; |
| + |
| + // Watchdog player. Used to listen to all media server crashes. |
| + private MediaPlayer mPlayer; |
| + private final Context mContext; |
| + |
| + // Protecting the creation/release of the watchdog player. |
|
DaleCurtis
2016/11/15 00:49:32
As discussed offline, lets not call releaseWatchdo
tguilbert
2016/11/15 19:29:07
Done.
|
| + private final Object mLock = new Object(); |
| + |
| + // Approximate time necessary for the MediaServer to restart after a crash. |
| + private static final int APPROX_MEDIA_SERVER_RESTART_TIME_IN_MS = 5000; |
| + |
| + // The last time we reported a failure to create the watchdog as a server crash. |
| + private long mLastReportedWatchdogCreationFailure = UNKNOWN_TIME; |
| + |
| + private long mNativeMediaServerCrashListener; |
| + |
| + @CalledByNative |
| + private static MediaServerCrashListener create( |
| + Context context, long nativeMediaServerCrashListener) { |
| + return new MediaServerCrashListener(context, nativeMediaServerCrashListener); |
| + } |
| + |
| + private MediaServerCrashListener(Context context, long nativeMediaServerCrashListener) { |
| + mContext = context; |
| + mNativeMediaServerCrashListener = nativeMediaServerCrashListener; |
| + } |
| + |
| + @CalledByNative |
| + public void releaseWatchdog() { |
| + synchronized (mLock) { |
| + if (mPlayer != null) { |
| + mPlayer.release(); |
| + mPlayer = null; |
| + } |
| + } |
| + } |
| + |
| + @CalledByNative |
| + public boolean startListening() { |
| + synchronized (mLock) { |
| + if (mPlayer != null) return true; |
| + |
| + try { |
| + mPlayer = MediaPlayer.create(mContext, R.raw.empty); |
| + } catch (IllegalStateException e) { |
| + Log.e(TAG, "Exception while creating the watchdog player.", e); |
| + } catch (RuntimeException e) { |
| + Log.e(TAG, "Exception while creating the watchdog player.", e); |
| + } |
| + |
| + if (mPlayer != null) { |
| + mPlayer.setOnErrorListener(MediaServerCrashListener.this); |
| + |
| + // Reset the reported creation failure time on successful |
| + // watchdog creation. |
| + mLastReportedWatchdogCreationFailure = UNKNOWN_TIME; |
| + return true; |
| + } |
| + |
| + long currentTime = SystemClock.elapsedRealtime(); |
| + |
| + // It takes ~5s for the MediaServer to restart. Do not report a |
| + // failure to create a watchdog MediaPlayer as a crash more than |
| + // once per 5s, to prevent a burst of calls to startListening() from |
| + // artificially inflating the number of crashes. |
| + if (mLastReportedWatchdogCreationFailure == UNKNOWN_TIME |
| + || (currentTime - mLastReportedWatchdogCreationFailure) |
| + > APPROX_MEDIA_SERVER_RESTART_TIME_IN_MS) { |
| + Log.e(TAG, "Unable to create watchdog player, treating it as server crash."); |
| + nativeOnMediaServerCrashDetected(mNativeMediaServerCrashListener); |
| + mLastReportedWatchdogCreationFailure = currentTime; |
| + } |
| + return false; |
| + } |
| + } |
| + |
| + @Override |
| + public boolean onError(MediaPlayer mp, int what, int extra) { |
| + if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) { |
| + nativeOnMediaServerCrashDetected(mNativeMediaServerCrashListener); |
| + releaseWatchdog(); |
| + } |
| + return true; |
| + } |
| + |
| + private native void nativeOnMediaServerCrashDetected(long nativeMediaServerCrashListener); |
| +} |