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