TunableTvView.java revision fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aa
1d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leepackage com.android.tv.ui;
2900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
3900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.content.Context;
49035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputInfo;
59035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputManager;
69035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputManager.Session;
79035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvView;
8900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.os.Handler;
9900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.os.Message;
10900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.AttributeSet;
11900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.Log;
12900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.view.SurfaceHolder;
13900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
14900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport com.android.internal.util.Preconditions;
15d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.data.Channel;
1621abb13274f379e69c3c86d51e493122cccca345Dongwon Kangimport com.android.tv.data.StreamInfo;
1721abb13274f379e69c3c86d51e493122cccca345Dongwon Kangimport com.android.tv.ui.TunableTvView.OnTuneListener;
18d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.TvInputManagerHelper;
19d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.Utils;
20900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
2121abb13274f379e69c3c86d51e493122cccca345Dongwon Kangpublic class TunableTvView extends TvView implements StreamInfo {
22900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final boolean DEBUG = true;
23900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final String TAG = "TunableTvView";
24900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
25900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final int DELAY_FOR_SURFACE_RELEASE = 300;
26900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final int MSG_TUNE = 0;
27900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
28900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private float mVolume;
29900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private long mChannelId = Channel.INVALID_ID;
30900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private TvInputManagerHelper mInputManagerHelper;
31900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private boolean mStarted;
32900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private TvInputInfo mInputInfo;
33900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private TvInputManager.Session mSession;
34900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private OnTuneListener mOnTuneListener;
3521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    private int mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN;
36e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    private int mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
37e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    private boolean mHasClosedCaption = false;
38900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private final Handler mHandler = new Handler() {
39900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        @Override
40900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        public void handleMessage(Message msg) {
41900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            switch (msg.what) {
42900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                case MSG_TUNE:
43900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    Preconditions.checkState(mChannelId != Channel.INVALID_ID);
44900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    Preconditions.checkNotNull(mSession);
45900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
46900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    mSession.tune(Utils.getChannelUri(mChannelId));
47900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    if (mOnTuneListener != null) {
48900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mOnTuneListener.onTuned(true, mChannelId);
49900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    }
50900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    break;
51900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            }
52900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
53900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    };
54900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
55900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
56900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        @Override
57900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
58900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
59900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        @Override
60900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        public void surfaceCreated(SurfaceHolder holder) { }
61900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
62900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        @Override
63900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        public void surfaceDestroyed(SurfaceHolder holder) {
64900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // TODO: It is a hack to wait to release a surface at TIS. If there is a way to
65900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // know when the surface is released at TIS, we don't need this hack.
66900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            try {
67900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                if (DEBUG) Log.d(TAG, "Sleep to wait destroying a surface");
68900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                Thread.sleep(DELAY_FOR_SURFACE_RELEASE);
69900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                if (DEBUG) Log.d(TAG, "Wake up from sleeping");
70900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            } catch (InterruptedException e) {
71900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                e.printStackTrace();
72900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            }
73900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
74900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    };
75900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
76900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private final TvInputManager.SessionCallback mSessionCallback =
77900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            new TvInputManager.SessionCallback() {
78900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                @Override
79900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                public void onSessionCreated(TvInputManager.Session session) {
80900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    if (session != null) {
81900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mSession = session;
82900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mSession.setVolume(mVolume);
83900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mHandler.sendEmptyMessage(MSG_TUNE);
84900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    } else {
85900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        Log.w(TAG, "Failed to create a session");
86900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        long channelId = mChannelId;
87900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mChannelId = Channel.INVALID_ID;
88900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mInputInfo = null;
89900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mSession = null;
90900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        if (mOnTuneListener != null) {
91900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                            mOnTuneListener.onTuned(false, channelId);
92900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                            mOnTuneListener = null;
93900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        }
94900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    }
95900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                }
96900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
97900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                @Override
98900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                public void onSessionReleased(TvInputManager.Session session) {
99900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    Log.w(TAG, "Session is released by crash");
100900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    long channelId = mChannelId;
101900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    mChannelId = Channel.INVALID_ID;
102900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    mInputInfo = null;
103900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    mSession = null;
104900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    if (mOnTuneListener != null) {
105900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mOnTuneListener.onUnexpectedStop(channelId);
106900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                        mOnTuneListener = null;
107900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    }
108900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                }
10921abb13274f379e69c3c86d51e493122cccca345Dongwon Kang
11021abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                @Override
111fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                public void onVideoStreamChanged(Session session, int width, int height,
112fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        boolean interlaced) {
11321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    mVideoFormat = Utils.getVideoDefinitionLevelFromSize(width, height);
11421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    if (mOnTuneListener != null) {
11521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
11621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    }
11721abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                }
118fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang
119fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                @Override
120fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                public void onAudioStreamChanged(Session session, int channelCount) {
121fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    mAudioChannelCount = channelCount;
122fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    if (mOnTuneListener != null) {
123fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
124fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    }
125fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                }
126fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang
127fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                @Override
128fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                public void onClosedCaptionStreamChanged(Session session,
129fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        boolean hasClosedCaption) {
130fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    mHasClosedCaption = hasClosedCaption;
131fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    if (mOnTuneListener != null) {
132fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
133fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    }
134fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                }
135900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            };
136900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
137900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context) {
138900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        this(context, null, 0);
139900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
140900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
141900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context, AttributeSet attrs) {
142900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        this(context, attrs, 0);
143900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
144900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
145900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context, AttributeSet attrs, int defStyleAttr) {
146900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        super(context, attrs, defStyleAttr);
147900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        getHolder().addCallback(mSurfaceHolderCallback);
148900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
149900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
150900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public void start(TvInputManagerHelper tvInputManagerHelper) {
151900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mInputManagerHelper = tvInputManagerHelper;
152900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (mStarted) {
153900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return;
154900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
155900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mStarted = true;
156900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
157900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
158900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public void stop() {
159900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
160900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return;
161900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
162900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mHandler.removeMessages(MSG_TUNE);
163900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mStarted = false;
164900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mSession = null;
165900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        unbindTvInput();
166900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mChannelId = Channel.INVALID_ID;
167900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mInputInfo = null;
168900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mOnTuneListener = null;
169900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
170900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
171900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public boolean isPlaying() {
172900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return mStarted;
173900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
174900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
175900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public boolean tuneTo(long channelId, OnTuneListener listener) {
176900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
177900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            throw new IllegalStateException("TvView isn't started");
178900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
179900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (DEBUG) Log.d(TAG, "tuneTo " + channelId);
180900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mHandler.removeMessages(MSG_TUNE);
18121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN;
182e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
183e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        mHasClosedCaption = false;
184900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        String inputId = Utils.getInputIdForChannel(getContext(), channelId);
185900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        TvInputInfo inputInfo = mInputManagerHelper.getTvInputInfo(inputId);
186900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (inputInfo == null || !mInputManagerHelper.isAvailable(inputInfo)) {
187900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return false;
188900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
189900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mOnTuneListener = listener;
190900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mChannelId = channelId;
191900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!inputInfo.equals(mInputInfo)) {
192900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            mSession = null;
193900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            unbindTvInput();
194900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
195900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // TODO: It is a hack to wait to release a surface at TIS. If there is a way to
196900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // know when the surface is released at TIS, we don't need this hack.
197900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            try {
198900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                Thread.sleep(DELAY_FOR_SURFACE_RELEASE);
199900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            } catch (InterruptedException e) {
200900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                e.printStackTrace();
201900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            }
202900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
203900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            mInputInfo = inputInfo;
204900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            bindTvInput(mInputInfo.getId(), mSessionCallback);
205900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            // mChannelId will be tuned after onSessionCreated.
206900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        } else {
20756008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho            if (mSession == null) {
20856008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho                // onSessionCreated is not called yet. MSG_TUNE will be sent in onSessionCreated.
20956008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho            } else {
21056008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho                mHandler.sendEmptyMessage(MSG_TUNE);
21156008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho            }
212900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
213900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return true;
214900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
215900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
216900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TvInputInfo getCurrentTvInputInfo() {
217900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return mInputInfo;
218900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
219900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
220900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public long getCurrentChannelId() {
221900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return mChannelId;
222900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
223900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
224900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public void setVolume(float volume) {
225900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
226900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            throw new IllegalStateException("TvView isn't started");
227900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
228900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (DEBUG) Log.d(TAG, "setVolume " + volume);
229900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mVolume = volume;
230900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (mSession != null) {
231900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            mSession.setVolume(volume);
232900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
233900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
234900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
235900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public interface OnTuneListener {
236900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        void onTuned(boolean success, long channelId);
237900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        void onUnexpectedStop(long channelId);
23821abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        void onStreamInfoChanged(StreamInfo info);
23921abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    }
24021abb13274f379e69c3c86d51e493122cccca345Dongwon Kang
24121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    @Override
24221abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    public int getVideoDefinitionLevel() {
24321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        return mVideoFormat;
244900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
245e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang
246e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    @Override
247e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    public int getAudioChannelCount() {
248e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        return mAudioChannelCount;
249e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    }
250e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang
251e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    @Override
252e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    public boolean hasClosedCaption() {
253e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        return mHasClosedCaption;
254e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    }
255900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho}
256