13bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/*
23bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Copyright (C) 2017 The Android Open Source Project
33bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *
43bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Licensed under the Apache License, Version 2.0 (the "License");
53bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * you may not use this file except in compliance with the License.
63bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * You may obtain a copy of the License at
73bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *
83bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *      http://www.apache.org/licenses/LICENSE-2.0
93bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *
103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Unless required by applicable law or agreed to in writing, software
113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * distributed under the License is distributed on an "AS IS" BASIS,
123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * See the License for the specific language governing permissions and
143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * limitations under the License.
153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */
163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.media;
183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
193bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.content.Context;
203bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.media.AudioManager;
213bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.media.MediaPlayer;
223bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.net.Uri;
233bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.os.Handler;
243bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.SurfaceHolder;
253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
268619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.R;
278619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas
283bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport java.io.IOException;
293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/**
313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * This implementation extends the {@link PlayerAdapter} with a {@link MediaPlayer}.
323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */
333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupublic class MediaPlayerAdapter extends PlayerAdapter {
343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    Context mContext;
363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final MediaPlayer mPlayer = new MediaPlayer();
373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    SurfaceHolderGlueHost mSurfaceHolderGlueHost;
383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final Runnable mRunnable = new Runnable() {
393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void run() {
413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            getCallback().onCurrentPositionChanged(MediaPlayerAdapter.this);
423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mHandler.postDelayed(this, getUpdatePeriod());
433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    };;
453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final Handler mHandler = new Handler();
463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    boolean mInitialized = false; // true when the MediaPlayer is prepared/initialized
473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    Uri mMediaSourceUri = null;
483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    boolean mHasDisplay;
493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    long mBufferedProgress;
503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    MediaPlayer.OnPreparedListener mOnPreparedListener = new MediaPlayer.OnPreparedListener() {
523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void onPrepared(MediaPlayer mp) {
543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mInitialized = true;
553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            notifyBufferingStartEnd();
563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            if (mSurfaceHolderGlueHost == null || mHasDisplay) {
573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                getCallback().onPreparedStateChanged(MediaPlayerAdapter.this);
583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    };
613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final MediaPlayer.OnCompletionListener mOnCompletionListener =
633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            new MediaPlayer.OnCompletionListener() {
643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void onCompletion(MediaPlayer mediaPlayer) {
663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            getCallback().onPlayStateChanged(MediaPlayerAdapter.this);
673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            getCallback().onPlayCompleted(MediaPlayerAdapter.this);
683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    };
703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener =
723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            new MediaPlayer.OnBufferingUpdateListener() {
733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void onBufferingUpdate(MediaPlayer mp, int percent) {
753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mBufferedProgress = getDuration() * percent / 100;
763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            getCallback().onBufferedPositionChanged(MediaPlayerAdapter.this);
773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    };
793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            new MediaPlayer.OnVideoSizeChangedListener() {
823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            getCallback().onVideoSizeChanged(MediaPlayerAdapter.this, width, height);
853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    };
873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final MediaPlayer.OnErrorListener mOnErrorListener =
893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            new MediaPlayer.OnErrorListener() {
903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                @Override
913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                public boolean onError(MediaPlayer mp, int what, int extra) {
923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    getCallback().onError(MediaPlayerAdapter.this, what,
933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                            mContext.getString(R.string.lb_media_player_error, what, extra));
943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    return MediaPlayerAdapter.this.onError(what, extra);
953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                }
963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            };
973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final MediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener =
993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            new MediaPlayer.OnSeekCompleteListener() {
1003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                @Override
1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                public void onSeekComplete(MediaPlayer mp) {
1023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    MediaPlayerAdapter.this.onSeekComplete();
1033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                }
1043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            };
1053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final MediaPlayer.OnInfoListener mOnInfoListener = new MediaPlayer.OnInfoListener() {
1073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
1083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public boolean onInfo(MediaPlayer mp, int what, int extra) {
1093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            boolean handled = false;
1103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            switch (what) {
1113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                case MediaPlayer.MEDIA_INFO_BUFFERING_START:
1123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mBufferingStart = true;
1133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    notifyBufferingStartEnd();
1143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    handled = true;
1153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    break;
1163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                case MediaPlayer.MEDIA_INFO_BUFFERING_END:
1173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mBufferingStart = false;
1183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    notifyBufferingStartEnd();
1193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    handled = true;
1203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    break;
1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
1223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            boolean thisHandled = MediaPlayerAdapter.this.onInfo(what, extra);
1233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            return handled || thisHandled;
1243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    };
1263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    boolean mBufferingStart;
1283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void notifyBufferingStartEnd() {
1303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        getCallback().onBufferingStateChanged(MediaPlayerAdapter.this,
1313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mBufferingStart || !mInitialized);
1323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
1353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Constructor.
1363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
1373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public MediaPlayerAdapter(Context context) {
1383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mContext = context;
1393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
1423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void onAttachedToHost(PlaybackGlueHost host) {
1433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (host instanceof SurfaceHolderGlueHost) {
1443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mSurfaceHolderGlueHost = ((SurfaceHolderGlueHost) host);
1453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mSurfaceHolderGlueHost.setSurfaceHolderCallback(new VideoPlayerSurfaceHolderCallback());
1463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
1503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Will reset the {@link MediaPlayer} and the glue such that a new file can be played. You are
1513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * not required to call this method before playing the first file. However you have to call it
1523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * before playing a second one.
1533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
1543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void reset() {
1553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        changeToUnitialized();
1563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.reset();
1573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void changeToUnitialized() {
1603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (mInitialized) {
1613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mInitialized = false;
1623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            notifyBufferingStartEnd();
1633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            if (mHasDisplay) {
1643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                getCallback().onPreparedStateChanged(MediaPlayerAdapter.this);
1653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
1663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
1703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Release internal MediaPlayer. Should not use the object after call release().
1713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
1723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void release() {
1733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        changeToUnitialized();
1743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mHasDisplay = false;
1753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.release();
1763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
1793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void onDetachedFromHost() {
1803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (mSurfaceHolderGlueHost != null) {
1813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mSurfaceHolderGlueHost.setSurfaceHolderCallback(null);
1823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mSurfaceHolderGlueHost = null;
1833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        reset();
1853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        release();
1863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
1893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Called to indicate an error.
1903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     *
1913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @param what    the type of error that has occurred:
1923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <ul>
1933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_ERROR_UNKNOWN}
1943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_ERROR_SERVER_DIED}
1953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * </ul>
1963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @param extra an extra code, specific to the error. Typically
1973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * implementation dependent.
1983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <ul>
1993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_ERROR_IO}
2003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_ERROR_MALFORMED}
2013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_ERROR_UNSUPPORTED}
2023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_ERROR_TIMED_OUT}
2033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li><code>MEDIA_ERROR_SYSTEM (-2147483648)</code> - low-level system error.
2043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * </ul>
2053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @return True if the method handled the error, false if it didn't.
2063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Returning false, will cause the {@link PlayerAdapter.Callback#onPlayCompleted(PlayerAdapter)}
2073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * being called.
2083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
2093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    protected boolean onError(int what, int extra) {
2103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return false;
2113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
2143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Called to indicate the completion of a seek operation.
2153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
2163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    protected void onSeekComplete() {
2173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
2203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Called to indicate an info or a warning.
2213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     *
2223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @param what    the type of info or warning.
2233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <ul>
2243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_UNKNOWN}
2253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_VIDEO_TRACK_LAGGING}
2263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_VIDEO_RENDERING_START}
2273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_BUFFERING_START}
2283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_BUFFERING_END}
2293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li><code>MEDIA_INFO_NETWORK_BANDWIDTH (703)</code> -
2303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     *     bandwidth information is available (as <code>extra</code> kbps)
2313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_BAD_INTERLEAVING}
2323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_NOT_SEEKABLE}
2333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_METADATA_UPDATE}
2343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_UNSUPPORTED_SUBTITLE}
2353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * <li>{@link MediaPlayer#MEDIA_INFO_SUBTITLE_TIMED_OUT}
2363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * </ul>
2373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @param extra an extra code, specific to the info. Typically
2383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * implementation dependent.
2393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @return True if the method handled the info, false if it didn't.
2403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Returning false, will cause the info to be discarded.
2413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
2423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    protected boolean onInfo(int what, int extra) {
2433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return false;
2443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
2473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @see MediaPlayer#setDisplay(SurfaceHolder)
2483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
2493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void setDisplay(SurfaceHolder surfaceHolder) {
2503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        boolean hadDisplay = mHasDisplay;
2513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mHasDisplay = surfaceHolder != null;
2523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (hadDisplay == mHasDisplay) {
2533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            return;
2543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
2553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setDisplay(surfaceHolder);
2563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (mHasDisplay) {
2573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            if (mInitialized) {
2583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                getCallback().onPreparedStateChanged(MediaPlayerAdapter.this);
2593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
2603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        } else {
2613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            if (mInitialized) {
2623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                getCallback().onPreparedStateChanged(MediaPlayerAdapter.this);
2633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
2643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
2653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
2693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void setProgressUpdatingEnabled(final boolean enabled) {
2703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mHandler.removeCallbacks(mRunnable);
2713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (!enabled) {
2723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            return;
2733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
2743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mHandler.postDelayed(mRunnable, getUpdatePeriod());
2753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    int getUpdatePeriod() {
2783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return 16;
2793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
2823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public boolean isPlaying() {
2833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return mInitialized && mPlayer.isPlaying();
2843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
2873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public long getDuration() {
2883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return mInitialized ? mPlayer.getDuration() : -1;
2893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
2923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public long getCurrentPosition() {
2933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return mInitialized ? mPlayer.getCurrentPosition() : -1;
2943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
2973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void play() {
2983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (!mInitialized || mPlayer.isPlaying()) {
2993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            return;
3003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.start();
3023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        getCallback().onPlayStateChanged(MediaPlayerAdapter.this);
3033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        getCallback().onCurrentPositionChanged(MediaPlayerAdapter.this);
3043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
3073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void pause() {
3083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (isPlaying()) {
3093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mPlayer.pause();
3103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            getCallback().onPlayStateChanged(MediaPlayerAdapter.this);
3113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
3153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekTo(long newPosition) {
3163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (!mInitialized) {
3173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            return;
3183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.seekTo((int) newPosition);
3203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
3233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public long getBufferedPosition() {
3243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return mBufferedProgress;
3253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
3283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Sets the media source of the player witha given URI.
3293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     *
3303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @return Returns <code>true</code> if uri represents a new media; <code>false</code>
3313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * otherwise.
3323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @see MediaPlayer#setDataSource(String)
3333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
3343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public boolean setDataSource(Uri uri) {
3353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (mMediaSourceUri != null ? mMediaSourceUri.equals(uri) : uri == null) {
3363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            return false;
3373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaSourceUri = uri;
3393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        prepareMediaForPlaying();
3403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return true;
3413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    private void prepareMediaForPlaying() {
3443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        reset();
3453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        try {
3463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            if (mMediaSourceUri != null) {
3473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mPlayer.setDataSource(mContext, mMediaSourceUri);
3483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            } else {
3493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                return;
3503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
3513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        } catch (IOException e) {
3523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            e.printStackTrace();
3533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            throw new RuntimeException(e);
3543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
3563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setOnPreparedListener(mOnPreparedListener);
3573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
3583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setOnErrorListener(mOnErrorListener);
3593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setOnSeekCompleteListener(mOnSeekCompleteListener);
3603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setOnCompletionListener(mOnCompletionListener);
3613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setOnInfoListener(mOnInfoListener);
3623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
3633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        notifyBufferingStartEnd();
3643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mPlayer.prepareAsync();
3653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        getCallback().onPlayStateChanged(MediaPlayerAdapter.this);
3663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
3693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * @return True if MediaPlayer OnPreparedListener is invoked and got a SurfaceHolder if
3703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * {@link PlaybackGlueHost} provides SurfaceHolder.
3713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
3723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
3733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public boolean isPrepared() {
3743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return mInitialized && (mSurfaceHolderGlueHost == null || mHasDisplay);
3753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    /**
3783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * Implements {@link SurfaceHolder.Callback} that can then be set on the
3793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * {@link PlaybackGlueHost}.
3803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     */
3813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    class VideoPlayerSurfaceHolderCallback implements SurfaceHolder.Callback {
3823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
3833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void surfaceCreated(SurfaceHolder surfaceHolder) {
3843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            setDisplay(surfaceHolder);
3853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
3883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
3893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        @Override
3923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
3933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            setDisplay(null);
3943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
3953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu}
397