| 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..9245980a77e812285296c15a97e96bd4113a55e8
|
| --- /dev/null
|
| +++ b/media/base/android/java/src/org/chromium/media/MediaServerCrashListener.java
|
| @@ -0,0 +1,109 @@
|
| +// 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 android.os.SystemClock;
|
| +
|
| +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";
|
| + 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.
|
| + 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() {
|
| + if (mPlayer == null) return;
|
| +
|
| + mPlayer.release();
|
| + mPlayer = null;
|
| + }
|
| +
|
| + @CalledByNative
|
| + public boolean startListening() {
|
| + 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, false);
|
| + mLastReportedWatchdogCreationFailure = currentTime;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + @Override
|
| + public boolean onError(MediaPlayer mp, int what, int extra) {
|
| + if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
|
| + nativeOnMediaServerCrashDetected(mNativeMediaServerCrashListener, true);
|
| + releaseWatchdog();
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + private native void nativeOnMediaServerCrashDetected(
|
| + long nativeMediaServerCrashListener, boolean watchdogNeedsRelease);
|
| +}
|
|
|