TunableTvView.java revision 8f1ff2894363afbb6909a3a1edc1f3cbe8657c11
1d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leepackage com.android.tv.ui;
2900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
3900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.content.Context;
49035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputInfo;
59035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvView;
6900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.AttributeSet;
7900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.Log;
8900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.view.SurfaceHolder;
9b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kangimport android.view.SurfaceView;
10900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
11d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.data.Channel;
1221abb13274f379e69c3c86d51e493122cccca345Dongwon Kangimport com.android.tv.data.StreamInfo;
13d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.TvInputManagerHelper;
14d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.Utils;
15900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
1621abb13274f379e69c3c86d51e493122cccca345Dongwon Kangpublic class TunableTvView extends TvView implements StreamInfo {
17900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final boolean DEBUG = true;
18900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final String TAG = "TunableTvView";
19900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
20900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final int DELAY_FOR_SURFACE_RELEASE = 300;
21900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
22900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private float mVolume;
23900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private long mChannelId = Channel.INVALID_ID;
24900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private TvInputManagerHelper mInputManagerHelper;
25900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private boolean mStarted;
26900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private TvInputInfo mInputInfo;
27900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private OnTuneListener mOnTuneListener;
28e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    private int mVideoWidth;
29e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    private int mVideoHeight;
3021abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    private int mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN;
31e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    private int mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
32e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    private boolean mHasClosedCaption = false;
33b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang    private SurfaceView mSurface;
34900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
35900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
36900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        @Override
37900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
38900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
39900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        @Override
40900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        public void surfaceCreated(SurfaceHolder holder) { }
41900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
42900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        @Override
43900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        public void surfaceDestroyed(SurfaceHolder holder) {
44900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // TODO: It is a hack to wait to release a surface at TIS. If there is a way to
45900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // know when the surface is released at TIS, we don't need this hack.
46900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            try {
47900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                if (DEBUG) Log.d(TAG, "Sleep to wait destroying a surface");
48900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                Thread.sleep(DELAY_FOR_SURFACE_RELEASE);
49900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                if (DEBUG) Log.d(TAG, "Wake up from sleeping");
50900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            } catch (InterruptedException e) {
51900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                e.printStackTrace();
52900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            }
53900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
54900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    };
55900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
569bb548ba08d7e222f276287fead545c6a11704d8Jae Seo    private final TvInputListener mListener =
579bb548ba08d7e222f276287fead545c6a11704d8Jae Seo            new TvInputListener() {
58900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                @Override
599bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                public void onError(String inputId, int errorCode) {
609bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                    if (errorCode == TvView.ERROR_BUSY) {
619bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                        Log.w(TAG, "Failed to bind an input");
62900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        long channelId = mChannelId;
63900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mChannelId = Channel.INVALID_ID;
64900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mInputInfo = null;
65900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        if (mOnTuneListener != null) {
66900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                            mOnTuneListener.onTuned(false, channelId);
67900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                            mOnTuneListener = null;
68900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        }
699bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                    } else if (errorCode == TvView.ERROR_TV_INPUT_DISCONNECTED) {
709bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                        Log.w(TAG, "Session is released by crash");
719bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                        long channelId = mChannelId;
729bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                        mChannelId = Channel.INVALID_ID;
739bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                        mInputInfo = null;
749bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                        if (mOnTuneListener != null) {
759bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                            mOnTuneListener.onUnexpectedStop(channelId);
769bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                            mOnTuneListener = null;
779bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                        }
78900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    }
79900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                }
80900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
81900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                @Override
829bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                public void onVideoStreamChanged(String inputId, int width, int height,
83fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        boolean interlaced) {
848f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo                    if (DEBUG) {
858f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo                        Log.d(TAG, "onVideoStreamChanged(inputId=" + inputId + ", width=" + width
868f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo                                + ", height=" + height + ")");
878f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo                    }
88e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim                    mVideoWidth = width;
89e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim                    mVideoHeight = height;
9021abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    mVideoFormat = Utils.getVideoDefinitionLevelFromSize(width, height);
918f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo                    Utils.updateCurrentVideoResolution(getContext(), mChannelId, mVideoFormat);
9221abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    if (mOnTuneListener != null) {
9321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
9421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    }
9521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                }
96fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang
97fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                @Override
989bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                public void onAudioStreamChanged(String inputId, int channelCount) {
99fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    mAudioChannelCount = channelCount;
100fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    if (mOnTuneListener != null) {
101fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
102fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    }
103fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                }
104fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang
105fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                @Override
1069bb548ba08d7e222f276287fead545c6a11704d8Jae Seo                public void onClosedCaptionStreamChanged(String inputId, boolean hasClosedCaption) {
107fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    mHasClosedCaption = hasClosedCaption;
108fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    if (mOnTuneListener != null) {
109fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
110fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    }
111fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                }
112900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            };
113900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
114900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context) {
115900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        this(context, null, 0);
116900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
117900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
118900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context, AttributeSet attrs) {
119900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        this(context, attrs, 0);
120900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
121900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
122900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context, AttributeSet attrs, int defStyleAttr) {
123900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        super(context, attrs, defStyleAttr);
124b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang        for (int i = 0; i < getChildCount(); ++i) {
125b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang            if (getChildAt(i) instanceof SurfaceView) {
126b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang                mSurface = (SurfaceView) getChildAt(i);
127b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang                mSurface.getHolder().addCallback(mSurfaceHolderCallback);
128b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang                return;
129b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang            }
130b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang        }
131b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang        throw new RuntimeException("TvView does not have SurfaceView.");
132900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
133900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
134900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public void start(TvInputManagerHelper tvInputManagerHelper) {
135900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mInputManagerHelper = tvInputManagerHelper;
136900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (mStarted) {
137900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return;
138900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
139900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mStarted = true;
140900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
141900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
142900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public void stop() {
143900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
144900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return;
145900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
146900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mStarted = false;
1479bb548ba08d7e222f276287fead545c6a11704d8Jae Seo        reset();
148900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mChannelId = Channel.INVALID_ID;
149900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mInputInfo = null;
150900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mOnTuneListener = null;
151900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
152900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
153900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public boolean isPlaying() {
154900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return mStarted;
155900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
156900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
157900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public boolean tuneTo(long channelId, OnTuneListener listener) {
158900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
159900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            throw new IllegalStateException("TvView isn't started");
160900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
161900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (DEBUG) Log.d(TAG, "tuneTo " + channelId);
162e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim        mVideoWidth = 0;
163e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim        mVideoHeight = 0;
16421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN;
165e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
166e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        mHasClosedCaption = false;
167900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        String inputId = Utils.getInputIdForChannel(getContext(), channelId);
168900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        TvInputInfo inputInfo = mInputManagerHelper.getTvInputInfo(inputId);
169900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (inputInfo == null || !mInputManagerHelper.isAvailable(inputInfo)) {
170900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return false;
171900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
172900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mOnTuneListener = listener;
173900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mChannelId = channelId;
174900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!inputInfo.equals(mInputInfo)) {
1759bb548ba08d7e222f276287fead545c6a11704d8Jae Seo            reset();
176900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // TODO: It is a hack to wait to release a surface at TIS. If there is a way to
177900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // know when the surface is released at TIS, we don't need this hack.
178900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            try {
179900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                Thread.sleep(DELAY_FOR_SURFACE_RELEASE);
180900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            } catch (InterruptedException e) {
181900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                e.printStackTrace();
182900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            }
183900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            mInputInfo = inputInfo;
1849bb548ba08d7e222f276287fead545c6a11704d8Jae Seo        }
1859bb548ba08d7e222f276287fead545c6a11704d8Jae Seo        setTvInputListener(mListener);
1869bb548ba08d7e222f276287fead545c6a11704d8Jae Seo        tune(mInputInfo.getId(), Utils.getChannelUri(mChannelId));
1879bb548ba08d7e222f276287fead545c6a11704d8Jae Seo        if (mOnTuneListener != null) {
1889bb548ba08d7e222f276287fead545c6a11704d8Jae Seo            // TODO: Add a callback for tune complete and call onTuned when it was successful.
1899bb548ba08d7e222f276287fead545c6a11704d8Jae Seo            mOnTuneListener.onTuned(true, mChannelId);
190900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
191900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return true;
192900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
193900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
19487c1cbb508c96538d1e69ba1fdf3d9f4d52710d6Jaewan Kim    @Override
195900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TvInputInfo getCurrentTvInputInfo() {
196900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return mInputInfo;
197900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
198900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
199900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public long getCurrentChannelId() {
200900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return mChannelId;
201900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
202900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
203b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang    public void setPip(boolean isPip) {
204b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang        mSurface.setZOrderMediaOverlay(isPip);
205b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang    }
206b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang
207561696c364ee330f4316544f1f85498393883526Jae Seo    @Override
208561696c364ee330f4316544f1f85498393883526Jae Seo    public void setStreamVolume(float volume) {
209900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
210900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            throw new IllegalStateException("TvView isn't started");
211900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
212561696c364ee330f4316544f1f85498393883526Jae Seo        if (DEBUG)
213561696c364ee330f4316544f1f85498393883526Jae Seo            Log.d(TAG, "setStreamVolume " + volume);
214900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mVolume = volume;
215561696c364ee330f4316544f1f85498393883526Jae Seo        super.setStreamVolume(volume);
216900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
217900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
218900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public interface OnTuneListener {
219900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        void onTuned(boolean success, long channelId);
220900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        void onUnexpectedStop(long channelId);
22121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        void onStreamInfoChanged(StreamInfo info);
22221abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    }
22321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang
22421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    @Override
225e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    public int getVideoWidth() {
226e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim        return mVideoWidth;
227e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    }
228e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim
229e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    @Override
230e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    public int getVideoHeight() {
231e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim        return mVideoHeight;
232e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    }
233e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim
234e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    @Override
23521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    public int getVideoDefinitionLevel() {
23621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        return mVideoFormat;
237900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
238e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang
239e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    @Override
240e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    public int getAudioChannelCount() {
241e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        return mAudioChannelCount;
242e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    }
243e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang
244e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    @Override
245e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    public boolean hasClosedCaption() {
246e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        return mHasClosedCaption;
247e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    }
248900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho}
249