TunableTvView.java revision 816a4be1a0f34f6a48877c8afd3dbbca19eac435
1816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/*
2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project
3816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
4816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
5816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * you may not use this file except in compliance with the License.
6816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * You may obtain a copy of the License at
7816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
8816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
9816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
10816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unless required by applicable law or agreed to in writing, software
11816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
12816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * See the License for the specific language governing permissions and
14816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * limitations under the License.
15816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */
16816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
17d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leepackage com.android.tv.ui;
18900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
19816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.animation.Animator;
20816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.animation.AnimatorInflater;
21816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.animation.AnimatorListenerAdapter;
22816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.animation.TimeInterpolator;
23816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.annotation.SuppressLint;
24900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.content.Context;
25829ca34b57d208a84430b2ccecd8975598d086daYoungsang Choimport android.content.pm.PackageManager;
26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.PlaybackParams;
27816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvContentRating;
289035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputInfo;
294e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kimimport android.media.tv.TvInputManager;
305459428da9aca1b91e3a976a80e1db783caac674Dongwon Kangimport android.media.tv.TvTrackInfo;
319035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvView;
32d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenimport android.media.tv.TvView.OnUnhandledInputEventListener;
33816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvView.TvInputCallback;
34cdde1b3be4391c4b0d3b57cce3c63eee8c81819aDongwon Kangimport android.net.Uri;
352c62d08f28cddda68005660c5cf62c5874b7f587Sungsoo Limimport android.os.Bundle;
36816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.support.annotation.IntDef;
37816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.TextUtils;
38900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.AttributeSet;
39900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.Log;
40829ca34b57d208a84430b2ccecd8975598d086daYoungsang Choimport android.view.KeyEvent;
41829ca34b57d208a84430b2ccecd8975598d086daYoungsang Choimport android.view.MotionEvent;
42816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.SurfaceView;
43816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.View;
44d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenimport android.view.ViewGroup;
45d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenimport android.widget.FrameLayout;
46816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.widget.TextView;
47900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
484e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kimimport com.android.tv.R;
49816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.TvApplication;
50816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.DurationTimer;
51816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.Tracker;
52816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.common.TvCommonConstants;
53d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.data.Channel;
5421abb13274f379e69c3c86d51e493122cccca345Dongwon Kangimport com.android.tv.data.StreamInfo;
55816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.parental.ContentRatingsManager;
56d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.TvInputManagerHelper;
57d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.Utils;
58900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
59816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.lang.annotation.Retention;
60816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.lang.annotation.RetentionPolicy;
615459428da9aca1b91e3a976a80e1db783caac674Dongwon Kangimport java.util.List;
625459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang
63d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenpublic class TunableTvView extends FrameLayout implements StreamInfo {
64816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final boolean DEBUG = false;
65900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private static final String TAG = "TunableTvView";
66900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
67829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    public static final String PERMISSION_RECEIVE_INPUT_EVENT =
68816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            "com.android.tv.permission.RECEIVE_INPUT_EVENT";
69816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
70816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int VIDEO_UNAVAILABLE_REASON_NOT_TUNED = -1;
71816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
72816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int BLOCK_SCREEN_TYPE_NO_UI = 0;
73816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW = 1;
74816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int BLOCK_SCREEN_TYPE_NORMAL = 2;
75816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
76816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Retention(RetentionPolicy.SOURCE)
77816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @IntDef({ TIME_SHIFT_STATE_NONE, TIME_SHIFT_STATE_PLAY, TIME_SHIFT_STATE_PAUSE,
78816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        TIME_SHIFT_STATE_REWIND, TIME_SHIFT_STATE_FAST_FORWARD })
79816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public @interface TimeShiftState {}
80816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int TIME_SHIFT_STATE_NONE = 0;
81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int TIME_SHIFT_STATE_PLAY = 1;
82816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int TIME_SHIFT_STATE_PAUSE = 2;
83816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int TIME_SHIFT_STATE_REWIND = 3;
84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static final int TIME_SHIFT_STATE_FAST_FORWARD = 4;
85816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
86816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final int FADED_IN = 0;
87816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final int FADED_OUT = 1;
88816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final int FADING_IN = 2;
89816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final int FADING_OUT = 3;
90816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
91816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final long INVALID_TIME = -1;
92816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
93816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // It is too small to see the description text without PIP_BLOCK_SCREEN_SCALE_FACTOR.
94816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final float PIP_BLOCK_SCREEN_SCALE_FACTOR = 1.2f;
95900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
96816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private AppLayerTvView mTvView;
97816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private Channel mCurrentChannel;
98900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private TvInputManagerHelper mInputManagerHelper;
99816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private ContentRatingsManager mContentRatingsManager;
100900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private boolean mStarted;
101900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private TvInputInfo mInputInfo;
102900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    private OnTuneListener mOnTuneListener;
103e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    private int mVideoWidth;
104e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    private int mVideoHeight;
10521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    private int mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN;
106816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private float mVideoFrameRate;
107e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    private int mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
108e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    private boolean mHasClosedCaption = false;
109816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private boolean mVideoAvailable;
110816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private boolean mScreenBlocked;
111816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private OnScreenBlockingChangedListener mOnScreenBlockedListener;
112816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private TvContentRating mBlockedContentRating;
113816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int mVideoUnavailableReason = VIDEO_UNAVAILABLE_REASON_NOT_TUNED;
114829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    private boolean mCanReceiveInputEvent;
115d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    private boolean mIsMuted;
116d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    private float mVolume;
117816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private boolean mParentControlEnabled;
118816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int mFixedSurfaceWidth;
119816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int mFixedSurfaceHeight;
120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private boolean mIsPip;
121816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int mScreenHeight;
122816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int mShrunkenTvViewHeight;
123816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
124816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @TimeShiftState private int mTimeShiftState = TIME_SHIFT_STATE_NONE;
125816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private TimeShiftListener mTimeShiftListener;
126816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private boolean mTimeShiftAvailable;
127816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private long mTimeShiftCurrentPositionMs = INVALID_TIME;
128816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final Tracker mTracker;
130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final DurationTimer mChannelViewTimer = new DurationTimer();
131816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
132816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // A block screen view which has lock icon with black background.
133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // This indicates that user's action is needed to play video.
134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mBlockScreenView;
135816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mBlockScreenDescriptionView;
137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mBlockScreenIconView;
138816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mBlockScreenShrunkenIconView;
139816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final TextView mBlockScreenTextView;
140816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // Animators used for fade in/out of block screen icon.
142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final Animator mBlockScreenDescriptionFadeIn;
143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final Animator mBlockScreenDescriptionFadeOut;
144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // A View to hide screen when there's problem in video playback.
146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mHideScreenView;
147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // A View to block screen until onContentAllowed is received if parental control is on.
149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mBlockScreenForTuneView;
150900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // A spinner view to show buffering status.
152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mBufferingSpinnerView;
153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // A View for fade-in/out animation
155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final View mDimScreenView;
156816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int mFadeState = FADED_IN;
157816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private Runnable mActionAfterFade;
158816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
159816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private int mBlockScreenType;
160816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
161816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private final TvInputCallback mCallback =
162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            new TvInputCallback() {
163900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                @Override
164816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                public void onConnectionFailed(String inputId) {
165816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    Log.w(TAG, "Failed to bind an input");
166816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    Channel channel = mCurrentChannel;
167816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mCurrentChannel = null;
168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mInputInfo = null;
169816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mCanReceiveInputEvent = false;
170816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (mOnTuneListener != null) {
171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        // If tune is called inside onTuneFailed, mOnTuneListener will be set to
172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        // a new instance. In order to avoid to clear the new mOnTuneListener,
173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        // we copy mOnTuneListener to l and clear mOnTuneListener before
174816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        // calling onTuneFailed.
175816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        OnTuneListener listener = mOnTuneListener;
176816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mOnTuneListener = null;
177816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        listener.onTuneFailed(channel);
178816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
179816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
180816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
181816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                @Override
182816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                public void onDisconnected(String inputId) {
183816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    Log.w(TAG, "Session is released by crash");
184816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    Channel channel = mCurrentChannel;
185816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mCurrentChannel = null;
186816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mInputInfo = null;
187816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mCanReceiveInputEvent = false;
188816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (mOnTuneListener != null) {
189816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        OnTuneListener listener = mOnTuneListener;
190816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mOnTuneListener = null;
191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        listener.onUnexpectedStop(channel);
192900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                    }
193900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                }
194900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
195900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho                @Override
1965459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang                public void onChannelRetuned(String inputId, Uri channelUri) {
1978f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo                    if (DEBUG) {
1985459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang                        Log.d(TAG, "onChannelRetuned(inputId=" + inputId + ", channelUri="
1995459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang                                + channelUri + ")");
2008f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo                    }
20121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    if (mOnTuneListener != null) {
202816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mOnTuneListener.onChannelRetuned(channelUri);
20321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                    }
20421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang                }
205fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang
206fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                @Override
207ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) {
208ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                    mHasClosedCaption = false;
209ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                    for (TvTrackInfo track : tracks) {
210ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        if (track.getType() == TvTrackInfo.TYPE_SUBTITLE) {
211ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            mHasClosedCaption = true;
212ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            break;
213ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        }
214ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                    }
215512017945a2cd192797d7ca404cba08d792877ddDongwon Kang                    if (mOnTuneListener != null) {
216512017945a2cd192797d7ca404cba08d792877ddDongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
217512017945a2cd192797d7ca404cba08d792877ddDongwon Kang                    }
218512017945a2cd192797d7ca404cba08d792877ddDongwon Kang                }
219512017945a2cd192797d7ca404cba08d792877ddDongwon Kang
220512017945a2cd192797d7ca404cba08d792877ddDongwon Kang                @Override
221ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                public void onTrackSelected(String inputId, int type, String trackId) {
222ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                    if (trackId == null) {
223ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        // A track is unselected.
224512017945a2cd192797d7ca404cba08d792877ddDongwon Kang                        if (type == TvTrackInfo.TYPE_VIDEO) {
225ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            mVideoWidth = 0;
226ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            mVideoHeight = 0;
227ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN;
228816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                            mVideoFrameRate = 0f;
229512017945a2cd192797d7ca404cba08d792877ddDongwon Kang                        } else if (type == TvTrackInfo.TYPE_AUDIO) {
230ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
231ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        }
232ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                    } else {
233ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        List<TvTrackInfo> tracks = getTracks(type);
234ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        boolean trackFound = false;
235ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        if (tracks != null) {
236ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            for (TvTrackInfo track : getTracks(type)) {
237ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                if (track.getId().equals(trackId)) {
238ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                    if (type == TvTrackInfo.TYPE_VIDEO) {
239ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                        mVideoWidth = track.getVideoWidth();
240ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                        mVideoHeight = track.getVideoHeight();
241ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                        mVideoFormat = Utils.getVideoDefinitionLevelFromSize(
242ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                                mVideoWidth, mVideoHeight);
243816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                                        mVideoFrameRate = track.getVideoFrameRate();
244ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                    } else if (type == TvTrackInfo.TYPE_AUDIO) {
245ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                        mAudioChannelCount = track.getAudioChannelCount();
246ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                    }
247ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                    trackFound = true;
248ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                    break;
249ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                                }
250ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            }
251ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        }
252ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                        if (!trackFound) {
253ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang                            Log.w(TAG, "Invalid track ID: " + trackId);
2545459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang                        }
255fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    }
256fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    if (mOnTuneListener != null) {
257fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
258fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                    }
259fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang                }
2604e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim
2614e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                @Override
2624e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                public void onVideoAvailable(String inputId) {
263816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    unhideScreenByVideoAvailability();
2644e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                    if (mOnTuneListener != null) {
2654e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
2664e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                    }
2674e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                }
2684e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim
2694e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                @Override
2704e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                public void onVideoUnavailable(String inputId, int reason) {
271816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    hideScreenByVideoAvailability(reason);
2724e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                    if (mOnTuneListener != null) {
2734e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                        mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
2744e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                    }
2754e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim                }
276816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
277816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                @Override
278816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                public void onContentAllowed(String inputId) {
279816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenForTuneView.setVisibility(View.GONE);
280816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    unblockScreenByContentRating();
281816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (mOnTuneListener != null) {
282816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mOnTuneListener.onContentAllowed();
283816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
284816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
285816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
286816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                @Override
287816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                public void onContentBlocked(String inputId, TvContentRating rating) {
288816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    blockScreenByContentRating(rating);
289816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (mOnTuneListener != null) {
290816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mOnTuneListener.onContentBlocked();
291816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
292816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
293816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
294816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                @Override
295816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                public void onTimeShiftStatusChanged(String inputId, int status) {
296816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    setTimeShiftAvailable(status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE);
297816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
298900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            };
299900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
300900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context) {
301d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        this(context, null);
302900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
303900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
304900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context, AttributeSet attrs) {
305900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        this(context, attrs, 0);
306900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
307900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
308900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public TunableTvView(Context context, AttributeSet attrs, int defStyleAttr) {
309d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        this(context, attrs, defStyleAttr, 0);
310d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
311d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
312d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    public TunableTvView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
313d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        super(context, attrs, defStyleAttr, defStyleRes);
314d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        inflate(getContext(), R.layout.tunable_tv_view, this);
315d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
316816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTracker = ((TvApplication) context.getApplicationContext()).getTracker();
317816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenType = BLOCK_SCREEN_TYPE_NORMAL;
318816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenView = findViewById(R.id.block_screen);
319816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenDescriptionView = findViewById(R.id.block_screen_description);
320816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
321816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenIconView = mBlockScreenView.findViewById(R.id.block_screen_icon);
322816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenShrunkenIconView = mBlockScreenView.findViewById(
323816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                R.id.block_screen_shrunken_icon);
324816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenTextView = (TextView) mBlockScreenView.findViewById(R.id.block_screen_text);
325816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
326816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenDescriptionFadeIn = AnimatorInflater.loadAnimator(context,
327816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                R.animator.tvview_block_screen_fade_in);
328816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenDescriptionFadeIn.setTarget(mBlockScreenDescriptionView);
329816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenDescriptionFadeIn.addListener(new AnimatorListenerAdapter() {
330816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            @Override
331816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            public void onAnimationStart(Animator animation) {
332816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                switch (mBlockScreenType) {
333816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    case BLOCK_SCREEN_TYPE_NORMAL:
334816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenIconView.setVisibility(VISIBLE);
335816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenShrunkenIconView.setVisibility(GONE);
336816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        break;
337816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
338816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenIconView.setVisibility(GONE);
339816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenShrunkenIconView.setVisibility(VISIBLE);
340816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        break;
341816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
342816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mBlockScreenDescriptionView.setVisibility(VISIBLE);
343816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
344816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        });
345816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenDescriptionFadeOut = AnimatorInflater.loadAnimator(context,
346816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                R.animator.tvview_block_screen_fade_out);
347816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenDescriptionFadeOut.setTarget(mBlockScreenDescriptionView);
348816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenDescriptionFadeOut.addListener(new AnimatorListenerAdapter() {
349816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            @Override
350816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            public void onAnimationEnd(Animator animation) {
351816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mBlockScreenDescriptionView.setVisibility(GONE);
352816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mBlockScreenDescriptionView.setAlpha(1f);
353816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                updateBlockScreenTextView();
354816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
355816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        });
356816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
357816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mHideScreenView = findViewById(R.id.hide_screen);
358816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBufferingSpinnerView = findViewById(R.id.buffering_spinner);
359816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenForTuneView = findViewById(R.id.block_screen_for_tune);
360816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView = findViewById(R.id.dim);
361816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.animate().setListener(new AnimatorListenerAdapter() {
362816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            @Override
363816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            public void onAnimationEnd(Animator animation) {
364816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (mActionAfterFade != null) {
365816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mActionAfterFade.run();
366816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
367816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
368816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
369816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            @Override
370816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            public void onAnimationCancel(Animator animation) {
371816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (mActionAfterFade != null) {
372816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mActionAfterFade.run();
373816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
374816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
375816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        });
376816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
377816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
378816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void initialize(AppLayerTvView tvView, boolean isPip, int screenHeight,
379816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            int shrunkenTvViewHeight) {
380816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView = tvView;
381816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mIsPip = isPip;
382816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mScreenHeight = screenHeight;
383816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mShrunkenTvViewHeight = shrunkenTvViewHeight;
384816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.setZOrderOnTop(isPip);
385816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        copyLayoutParamsToTvView();
386900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
387900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
388900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public void start(TvInputManagerHelper tvInputManagerHelper) {
389900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mInputManagerHelper = tvInputManagerHelper;
390816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentRatingsManager = tvInputManagerHelper.getContentRatingsManager();
391900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (mStarted) {
392900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return;
393900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
394900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mStarted = true;
395900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
396900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
397900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public void stop() {
398900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
399900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return;
400900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
401900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mStarted = false;
402816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mCurrentChannel != null) {
403816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTracker.sendChannelViewStop(mCurrentChannel, mChannelViewTimer.reset());
404816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
405816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        reset();
406816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
407816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
408816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void reset() {
409d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mTvView.reset();
410816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mCurrentChannel = null;
411900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mInputInfo = null;
412829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho        mCanReceiveInputEvent = false;
413900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mOnTuneListener = null;
414816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        setTimeShiftAvailable(false);
415816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        hideScreenByVideoAvailability(VIDEO_UNAVAILABLE_REASON_NOT_TUNED);
416816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
417816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
418816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setMain() {
419816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.setMain();
420900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
421900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
422900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public boolean isPlaying() {
423900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return mStarted;
424900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
425900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
426816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
427816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Called when parental control is changed.
428816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
429816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void onParentalControlChanged(boolean enabled) {
430816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mParentControlEnabled = enabled;
431816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!mParentControlEnabled) {
432816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenForTuneView.setVisibility(View.GONE);
433816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
434816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
435816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
436816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
437816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Tunes to a channel with the {@code channelId}.
438816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
439816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @param params extra data to send it to TIS and store the data in TIMS.
440816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @return false, if the TV input is not a proper state to tune to a channel. For example,
441816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *         if the state is disconnected or channelId doesn't exist, it returns false.
442816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
443816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public boolean tuneTo(Channel channel, Bundle params, OnTuneListener listener) {
444900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
445900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            throw new IllegalStateException("TvView isn't started");
446900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
447816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (DEBUG) Log.d(TAG, "tuneTo " + channel);
448816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        TvInputInfo inputInfo = mInputManagerHelper.getTvInputInfo(channel.getInputId());
449816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (inputInfo == null) {
450900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            return false;
451900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
452816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mCurrentChannel != null) {
453816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTracker.sendChannelViewStop(mCurrentChannel, mChannelViewTimer.reset());
454816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
455900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        mOnTuneListener = listener;
456816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mCurrentChannel = channel;
457816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTracker.sendChannelViewStart(mCurrentChannel);
458816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelViewTimer.start();
459816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        boolean needSurfaceSizeUpdate = false;
460900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!inputInfo.equals(mInputInfo)) {
461900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            mInputInfo = inputInfo;
462d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten            mCanReceiveInputEvent = getContext().getPackageManager().checkPermission(
463816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    PERMISSION_RECEIVE_INPUT_EVENT, mInputInfo.getServiceInfo().packageName)
464829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho                            == PackageManager.PERMISSION_GRANTED;
465816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (DEBUG) {
466816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Log.d(TAG, "Input \'" + mInputInfo.getId() + "\' can receive input event: "
467816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        + mCanReceiveInputEvent);
468816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
469816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            needSurfaceSizeUpdate = true;
470816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
471816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mVideoWidth = 0;
472816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mVideoHeight = 0;
473816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN;
474816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mVideoFrameRate = 0f;
475816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
476816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mHasClosedCaption = false;
477816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.setCallback(mCallback);
478816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTimeShiftCurrentPositionMs = INVALID_TIME;
479816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (TvCommonConstants.HAS_TIME_SHIFT_API) {
480816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // To reduce the IPCs, unregister the callback here and register it when necessary.
481816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTvView.setTimeShiftPositionCallback(null);
482816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
483816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        setTimeShiftAvailable(false);
484816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.tune(mInputInfo.getId(), mCurrentChannel.getUri(), params);
485816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (needSurfaceSizeUpdate && mFixedSurfaceWidth > 0 && mFixedSurfaceHeight > 0) {
486816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // When the input is changed, TvView recreates its SurfaceView internally.
487816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView.
488816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            getSurfaceView().getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight);
489816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
490816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        hideScreenByVideoAvailability(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
491816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        unblockScreenByContentRating();
492816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (channel.isPassthrough()) {
493816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenForTuneView.setVisibility(View.GONE);
494816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        } else if (mParentControlEnabled) {
495816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenForTuneView.setVisibility(View.VISIBLE);
4969bb548ba08d7e222f276287fead545c6a11704d8Jae Seo        }
4979bb548ba08d7e222f276287fead545c6a11704d8Jae Seo        if (mOnTuneListener != null) {
498816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mOnTuneListener.onStreamInfoChanged(this);
499900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
500900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        return true;
501900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
502900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
50387c1cbb508c96538d1e69ba1fdf3d9f4d52710d6Jaewan Kim    @Override
504816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public Channel getCurrentChannel() {
505816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mCurrentChannel;
506900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
507900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
508816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
509816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Sets the current channel. Call this method only when setting the current channel without
510816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * actually tuning to it.
511816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
512816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @param currentChannel The new current channel to set to.
513816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
514816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setCurrentChannel(Channel currentChannel) {
515816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mCurrentChannel = currentChannel;
516b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang    }
517b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang
518561696c364ee330f4316544f1f85498393883526Jae Seo    public void setStreamVolume(float volume) {
519900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        if (!mStarted) {
520900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho            throw new IllegalStateException("TvView isn't started");
521900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho        }
522d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        if (DEBUG) Log.d(TAG, "setStreamVolume " + volume);
523d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mVolume = volume;
524d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        if (!mIsMuted) {
525d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten            mTvView.setStreamVolume(volume);
526d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        }
527900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
528900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho
529816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
530816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Sets fixed size for the internal {@link android.view.Surface} of
531816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * {@link android.media.tv.TvView}. If either {@code width} or {@code height} is non positive,
532816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * the {@link android.view.Surface}'s size will be matched to the layout.
533816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
534816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Note: Once {@link android.view.SurfaceHolder#setFixedSize} is called,
535816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * {@link android.view.SurfaceView} and its underlying window can be misaligned, when the size
536816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * of {@link android.view.SurfaceView} is changed without changing either left position or top
537816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * position. For detail, please refer the codes of {@link android.view.SurfaceView#updateWindow}
538816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * .
539816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
540816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setFixedSurfaceSize(int width, int height) {
541816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mFixedSurfaceWidth = width;
542816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mFixedSurfaceHeight = height;
543816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mFixedSurfaceWidth > 0 && mFixedSurfaceHeight > 0) {
544816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // When the input is changed, TvView recreates its SurfaceView internally.
545816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView.
546816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            SurfaceView surfaceView = (SurfaceView) mTvView.getChildAt(0);
547816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            surfaceView.getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight);
548816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        } else {
549816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            SurfaceView surfaceView = (SurfaceView) mTvView.getChildAt(0);
550816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            surfaceView.getHolder().setSizeFromLayout();
551816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
552816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
553816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
554829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    @Override
555829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    public boolean dispatchKeyEvent(KeyEvent event) {
556d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        return mCanReceiveInputEvent && mTvView.dispatchKeyEvent(event);
557829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    }
558829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho
559829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    @Override
560829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    public boolean dispatchTouchEvent(MotionEvent event) {
561d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        return mCanReceiveInputEvent && mTvView.dispatchTouchEvent(event);
562829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    }
563829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho
564829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    @Override
565829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    public boolean dispatchTrackballEvent(MotionEvent event) {
566d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        return mCanReceiveInputEvent && mTvView.dispatchTrackballEvent(event);
567829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    }
568829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho
569829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    @Override
570829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    public boolean dispatchGenericMotionEvent(MotionEvent event) {
571d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        return mCanReceiveInputEvent && mTvView.dispatchGenericMotionEvent(event);
572829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho    }
573829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho
574900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    public interface OnTuneListener {
575816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        void onTuneFailed(Channel channel);
576816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        void onUnexpectedStop(Channel channel);
57721abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        void onStreamInfoChanged(StreamInfo info);
578816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        void onChannelRetuned(Uri channel);
579816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        void onContentBlocked();
580816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        void onContentAllowed();
581816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
582816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
583816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void requestUnblockContent(TvContentRating rating) {
584816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.requestUnblockContent(rating);
58521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    }
58621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang
58721abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    @Override
588e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    public int getVideoWidth() {
589e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim        return mVideoWidth;
590e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    }
591e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim
592e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    @Override
593e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    public int getVideoHeight() {
594e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim        return mVideoHeight;
595e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    }
596e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim
597e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim    @Override
59821abb13274f379e69c3c86d51e493122cccca345Dongwon Kang    public int getVideoDefinitionLevel() {
59921abb13274f379e69c3c86d51e493122cccca345Dongwon Kang        return mVideoFormat;
600900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho    }
601e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang
602e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    @Override
603816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public float getVideoFrameRate() {
604816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mVideoFrameRate;
605816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
606816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
607816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
608e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    public int getAudioChannelCount() {
609e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        return mAudioChannelCount;
610e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    }
611e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang
612e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    @Override
613e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    public boolean hasClosedCaption() {
614e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang        return mHasClosedCaption;
615e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang    }
6164e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim
6174e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim    @Override
6184e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim    public boolean isVideoAvailable() {
619816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mVideoAvailable;
6204e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim    }
6214e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim
6224e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim    @Override
6234e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim    public int getVideoUnavailableReason() {
6244e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim        return mVideoUnavailableReason;
6254e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim    }
626d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
627816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
628816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Returns the {@link android.view.SurfaceView} of the {@link android.media.tv.TvView}.
629816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
630816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public SurfaceView getSurfaceView() {
631816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return (SurfaceView) mTvView.getChildAt(0);
632816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
633816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
634d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    public void setOnUnhandledInputEventListener(OnUnhandledInputEventListener listener) {
635d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mTvView.setOnUnhandledInputEventListener(listener);
636d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
637d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
638816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setClosedCaptionEnabled(boolean enabled) {
639816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.setCaptionEnabled(enabled);
640816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
641816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
642ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang    public List<TvTrackInfo> getTracks(int type) {
643ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang        return mTvView.getTracks(type);
644d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
645d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
646816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public String getSelectedTrack(int type) {
647816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mTvView.getSelectedTrack(type);
648816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
649816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
650ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang    public void selectTrack(int type, String trackId) {
651ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang        mTvView.selectTrack(type, trackId);
652d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
653d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
654816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
655816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Returns if the screen is blocked by {@link #blockScreen()}.
656816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
657816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public boolean isScreenBlocked() {
658816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mScreenBlocked;
659816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
660816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
661816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setOnScreenBlockedListener(OnScreenBlockingChangedListener listener) {
662816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mOnScreenBlockedListener = listener;
663816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
664816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
665816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
666816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Returns currently blocked content rating. {@code null} if it's not blocked.
667816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
668816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public TvContentRating getBlockedContentRating() {
669816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mBlockedContentRating;
670816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
671816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
672816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
673816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Locks current TV screen and mutes.
674816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * There would be black screen with lock icon in order to show that
675816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * screen block is intended and not an error.
676816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * TODO: Accept parameter to show lock icon or not.
677816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
678816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void blockScreen() {
679816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mScreenBlocked = true;
680816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        checkBlockScreenAndMuteNeeded();
681816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mOnScreenBlockedListener != null) {
682816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mOnScreenBlockedListener.onScreenBlockingChanged(true);
683816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
684816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
685816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
686816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void blockScreenByContentRating(TvContentRating rating) {
687816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockedContentRating = rating;
688816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        checkBlockScreenAndMuteNeeded();
689816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
690816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
691816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
692816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @SuppressLint("RtlHardcoded")
693816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
694816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        super.onLayout(changed, left, top, right, bottom);
695816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mIsPip) {
696816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            int height = bottom - top;
697816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            float scale;
698816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (mBlockScreenType == BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW) {
699816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                scale = height * PIP_BLOCK_SCREEN_SCALE_FACTOR / mShrunkenTvViewHeight;
700816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            } else {
701816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                scale = height * PIP_BLOCK_SCREEN_SCALE_FACTOR / mScreenHeight;
702816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
703816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // TODO: need to get UX confirmation.
704816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenDescriptionView.setScaleX(scale);
705816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenDescriptionView.setScaleY(scale);
706816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
707816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
708816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
709816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
710816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setLayoutParams(ViewGroup.LayoutParams params) {
711816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        super.setLayoutParams(params);
712816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mTvView != null) {
713816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            copyLayoutParamsToTvView();
714816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
715816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
716816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
717816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void copyLayoutParamsToTvView() {
718816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
719816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        FrameLayout.LayoutParams tvViewLp = (FrameLayout.LayoutParams) mTvView.getLayoutParams();
720816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (tvViewLp.bottomMargin != lp.bottomMargin
721816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                || tvViewLp.topMargin != lp.topMargin
722816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                || tvViewLp.leftMargin != lp.leftMargin
723816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                || tvViewLp.rightMargin != lp.rightMargin
724816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                || tvViewLp.gravity != lp.gravity
725816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                || tvViewLp.height != lp.height
726816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                || tvViewLp.width != lp.width) {
727816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (lp.topMargin == tvViewLp.topMargin && lp.leftMargin == tvViewLp.leftMargin) {
728816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // HACK: If top and left position aren't changed and SurfaceHolder.setFixedSize is
729816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // used, SurfaceView doesn't catch the width and height change. It causes a bug that
730816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // PIP size change isn't shown when PIP is located TOP|LEFT. So we adjust 1 px for
731816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // small size PIP as a workaround.
732816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                tvViewLp.leftMargin = lp.leftMargin + 1;
733816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            } else {
734816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                tvViewLp.leftMargin = lp.leftMargin;
735816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
736816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            tvViewLp.topMargin = lp.topMargin;
737816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            tvViewLp.bottomMargin = lp.bottomMargin;
738816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            tvViewLp.rightMargin = lp.rightMargin;
739816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            tvViewLp.gravity = lp.gravity;
740816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            tvViewLp.height = lp.height;
741816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            tvViewLp.width = lp.width;
742816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTvView.setLayoutParams(tvViewLp);
743816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
744816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
745816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
746816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
747816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    protected void onVisibilityChanged(View changedView, int visibility) {
748816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        super.onVisibilityChanged(changedView, visibility);
749816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mTvView != null) {
750816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTvView.setVisibility(visibility);
751816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
752816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
753816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
754816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
755816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Set the type of block screen. If {@code type} is set to {@code BLOCK_SCREEN_TYPE_NO_UI}, the
756816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * block screen will not show any description such as a lock icon and a text for the blocked
757816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * reason, if {@code type} is set to {@code BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW}, the block screen
758816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * will show the description for shrunken tv view (Small icon and short text), and if
759816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * {@code type} is set to {@code BLOCK_SCREEN_TYPE_NORMAL}, the block screen will show the
760816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * description for normal tv view (Big icon and long text).
761816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
762816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @param type The type of block screen to set.
763816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
764816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setBlockScreenType(int type) {
765816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // TODO: need to support the transition from NORMAL to SHRUNKEN and vice verse.
766816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mBlockScreenType != type) {
767816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenType = type;
768816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            updateBlockScreenUI(true);
769816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
770816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
771816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
772816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void updateBlockScreenUI(boolean animation) {
773816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mBlockScreenDescriptionFadeIn.isRunning()) {
774816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenDescriptionFadeIn.end();
775816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
776816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mBlockScreenDescriptionFadeOut.isRunning()) {
777816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenDescriptionFadeOut.end();
778816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
779816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
780816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!mScreenBlocked && mBlockedContentRating == null) {
781816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mBlockScreenView.setVisibility(GONE);
782816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
783816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
784816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
785816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenView.setVisibility(VISIBLE);
786816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!animation) {
787816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            updateBlockScreenTextView();
788816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            switch (mBlockScreenType) {
789816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NO_UI:
790816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenIconView.setVisibility(GONE);
791816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenShrunkenIconView.setVisibility(GONE);
792816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenDescriptionView.setVisibility(GONE);
793816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
794816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
795816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenIconView.setVisibility(GONE);
796816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenShrunkenIconView.setVisibility(VISIBLE);
797816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenDescriptionView.setVisibility(VISIBLE);
798816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
799816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NORMAL:
800816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenIconView.setVisibility(VISIBLE);
801816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenShrunkenIconView.setVisibility(GONE);
802816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenDescriptionView.setVisibility(VISIBLE);
803816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
804816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
805816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        } else {
806816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            switch (mBlockScreenType) {
807816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NO_UI:
808816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                  if (mBlockScreenDescriptionView.getVisibility() == VISIBLE) {
809816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                      mBlockScreenDescriptionFadeOut.start();
810816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                  }
811816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                  break;
812816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
813816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NORMAL:
814816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    updateBlockScreenTextView();
815816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (mBlockScreenDescriptionView.getVisibility() == GONE) {
816816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenDescriptionFadeIn.start();
817816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
818816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
819816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
820816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
821816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
822816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
823816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void updateBlockScreenTextView() {
824816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // TODO: need to add animation for padding change when the block screen type is changed
825816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // NORMAL to SHRUNKEN and vice verse.
826816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockScreenTextView.setPadding(0,
827816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                getResources().getDimensionPixelOffset(
828816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenType == BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW
829816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                                ? R.dimen.shrunken_tvview_block_text_padding_top
830816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                                : R.dimen.tvview_block_text_padding_top),
831816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                0, 0);
832816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
833816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mScreenBlocked) {
834816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            switch (mBlockScreenType) {
835816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NO_UI:
836816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
837816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenTextView.setText("");
838816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
839816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NORMAL:
840816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenTextView.setText(R.string.tvview_channel_locked);
841816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
842816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
843816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        } else if (mBlockedContentRating != null) {
844816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            String name = mContentRatingsManager.getDisplayNameForRating(mBlockedContentRating);
845816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            switch (mBlockScreenType) {
846816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NO_UI:
847816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mBlockScreenTextView.setText("");
848816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
849816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
850816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (TextUtils.isEmpty(name)) {
851816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenTextView.setText(R.string.shrunken_tvview_content_locked);
852816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    } else {
853816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenTextView.setText(getContext().getString(
854816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                                R.string.shrunken_tvview_content_locked_format, name));
855816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
856816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
857816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case BLOCK_SCREEN_TYPE_NORMAL:
858816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (TextUtils.isEmpty(name)) {
859816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenTextView.setText(R.string.tvview_content_locked);
860816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    } else {
861816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mBlockScreenTextView.setText(getContext().getString(
862816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                                R.string.tvview_content_locked_format, name));
863816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
864816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
865816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
866816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
867816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
868816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
869816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void checkBlockScreenAndMuteNeeded() {
870816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        updateBlockScreenUI(false);
871816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mScreenBlocked || mBlockedContentRating != null) {
872816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mute();
873816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (mIsPip) {
874816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // If we don't make mTvView invisible, some frames are leaked when a user changes
875816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // PIP layout in options.
876816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // Note: When video is unavailable, we keep the mTvView's visibility, because
877816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // TIS implementation may not send video available with no surface.
878816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mTvView.setVisibility(View.INVISIBLE);
879816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
880816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        } else {
881816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            unmuteIfPossible();
882816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (mIsPip) {
883816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mTvView.setVisibility(View.VISIBLE);
884816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
885816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
886816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
887816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
888816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void unblockScreen() {
889816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mScreenBlocked = false;
890816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        checkBlockScreenAndMuteNeeded();
891816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mOnScreenBlockedListener != null) {
892816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mOnScreenBlockedListener.onScreenBlockingChanged(false);
893816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
894816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
895816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
896816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void unblockScreenByContentRating() {
897816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBlockedContentRating = null;
898816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        checkBlockScreenAndMuteNeeded();
899816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
900816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
901816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void hideScreenByVideoAvailability(int reason) {
902d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        switch (reason) {
903816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            case TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING:
904816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mBufferingSpinnerView.setVisibility(VISIBLE);
905d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten                break;
906816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            case TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN:
907c91a6ff8aca631d682764bc7a771cc79fbd41c75Jae Seo            case TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING:
908d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten            case TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL:
909816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            case VIDEO_UNAVAILABLE_REASON_NOT_TUNED:
910816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            default:
911816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mHideScreenView.setVisibility(VISIBLE);
912816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mBufferingSpinnerView.setVisibility(GONE);
913d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten                break;
914d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        }
915816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mVideoAvailable = false;
916816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mVideoUnavailableReason = reason;
917d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mute();
918d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
919d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
920816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void unhideScreenByVideoAvailability() {
921816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mVideoAvailable = true;
922816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mHideScreenView.setVisibility(GONE);
923816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mBufferingSpinnerView.setVisibility(GONE);
924816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        unmuteIfPossible();
925816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
926816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
927816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void unmuteIfPossible() {
928816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mVideoAvailable && !mScreenBlocked && mBlockedContentRating == null) {
929816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            unmute();
930816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
931d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
932d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
933d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    private void mute() {
934d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mIsMuted = true;
935d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mTvView.setStreamVolume(0);
936d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
937d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
938d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    private void unmute() {
939d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mIsMuted = false;
940d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten        mTvView.setStreamVolume(mVolume);
941d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
942d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten
943816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /** Returns true if this view is faded out. */
944816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public boolean isFadedOut() {
945816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mFadeState == FADED_OUT;
946816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
947816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
948816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /** Fade out this TunableTvView. Fade out by increasing the dimming. */
949816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void fadeOut(int durationMillis, TimeInterpolator interpolator,
950816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            final Runnable actionAfterFade) {
951816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.setAlpha(0f);
952816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.setVisibility(View.VISIBLE);
953816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.animate()
954816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .alpha(1f)
955816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .setDuration(durationMillis)
956816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .setInterpolator(interpolator)
957816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .withStartAction(new Runnable() {
958816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    @Override
959816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    public void run() {
960816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mFadeState = FADING_OUT;
961816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mActionAfterFade = actionAfterFade;
962816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
963816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                })
964816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .withEndAction(new Runnable() {
965816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    @Override
966816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    public void run() {
967816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mFadeState = FADED_OUT;
968816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
969816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                });
970816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
971816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
972816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /** Fade in this TunableTvView. Fade in by decreasing the dimming. */
973816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void fadeIn(int durationMillis, TimeInterpolator interpolator,
974816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            final Runnable actionAfterFade) {
975816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.setAlpha(1f);
976816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.setVisibility(View.VISIBLE);
977816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.animate()
978816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .alpha(0f)
979816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .setDuration(durationMillis)
980816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .setInterpolator(interpolator)
981816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .withStartAction(new Runnable() {
982816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    @Override
983816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    public void run() {
984816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mFadeState = FADING_IN;
985816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mActionAfterFade = actionAfterFade;
986816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
987816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                })
988816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                .withEndAction(new Runnable() {
989816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    @Override
990816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    public void run() {
991816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mFadeState = FADED_IN;
992816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mDimScreenView.setVisibility(View.GONE);
993816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
994816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                });
995816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
996816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
997816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /** Remove the fade effect. */
998816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void removeFadeEffect() {
999816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.animate().cancel();
1000816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mDimScreenView.setVisibility(View.GONE);
1001816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mFadeState = FADED_IN;
1002816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1003816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1004816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1005816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Sets the TimeShiftListener
1006816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
1007816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @param listener The instance of {@link TimeShiftListener}.
1008816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1009816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void setTimeShiftListener(TimeShiftListener listener) {
1010816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTimeShiftListener = listener;
1011816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1012816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1013816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void setTimeShiftAvailable(boolean isTimeShiftAvailable) {
1014816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!TvCommonConstants.HAS_TIME_SHIFT_API || mTimeShiftAvailable == isTimeShiftAvailable) {
1015816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1016816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1017816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTimeShiftAvailable = isTimeShiftAvailable;
1018816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (isTimeShiftAvailable) {
1019816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTvView.setTimeShiftPositionCallback(new TvView.TimeShiftPositionCallback() {
1020816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                @Override
1021816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                public void onTimeShiftStartPositionChanged(String inputId, long timeMs) {
1022816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (mTimeShiftListener != null && mCurrentChannel != null
1023816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                            && mCurrentChannel.getInputId().equals(inputId)) {
1024816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        mTimeShiftListener.onRecordStartTimeChanged(timeMs);
1025816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
1026816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
1027816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1028816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                @Override
1029816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) {
1030816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mTimeShiftCurrentPositionMs = timeMs;
1031816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
1032816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            });
1033816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        } else {
1034816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTvView.setTimeShiftPositionCallback(null);
1035816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1036816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mTimeShiftListener != null) {
1037816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mTimeShiftListener.onAvailabilityChanged();
1038816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1039816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1040816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1041816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1042816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Returns if the time shift is available for the current channel.
1043816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1044816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public boolean isTimeShiftAvailable() {
1045816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mTimeShiftAvailable;
1046816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1047816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1048816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1049816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Returns the current time-shift state. It returns one of {@link #TIME_SHIFT_STATE_NONE},
1050816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * {@link #TIME_SHIFT_STATE_PLAY}, {@link #TIME_SHIFT_STATE_PAUSE},
1051816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * {@link #TIME_SHIFT_STATE_REWIND}, {@link #TIME_SHIFT_STATE_FAST_FORWARD}
1052816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * or {@link #TIME_SHIFT_STATE_PAUSE}.
1053816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1054816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @TimeShiftState public int getTimeShiftState() {
1055816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mTimeShiftState;
1056816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1057816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1058816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1059816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Plays the media, if the current input supports time-shifting.
1060816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1061816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void timeshiftPlay() {
1062816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!TvCommonConstants.HAS_TIME_SHIFT_API) {
1063816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Log.w(TAG, "Time shifting is not supported in this platform.");
1064816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1065816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1066816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!isTimeShiftAvailable()) {
1067816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalStateException("Time-shift is not supported for the current channel");
1068816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1069816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mTimeShiftState == TIME_SHIFT_STATE_PLAY) {
1070816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1071816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1072816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.timeShiftResume();
1073816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1074816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1075816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1076816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Pauses the media, if the current input supports time-shifting.
1077816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1078816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void timeshiftPause() {
1079816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!TvCommonConstants.HAS_TIME_SHIFT_API) {
1080816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Log.w(TAG, "Time shifting is not supported in this platform.");
1081816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1082816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1083816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!isTimeShiftAvailable()) {
1084816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalStateException("Time-shift is not supported for the current channel");
1085816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1086816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (mTimeShiftState == TIME_SHIFT_STATE_PAUSE) {
1087816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1088816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1089816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.timeShiftPause();
1090816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1091816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1092816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1093816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Rewinds the media with the given speed, if the current input supports time-shifting.
1094816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
1095816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @param speed The speed to rewind the media. e.g. 2 for 2x, 3 for 3x and 4 for 4x.
1096816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1097816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void timeshiftRewind(int speed) {
1098816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!TvCommonConstants.HAS_TIME_SHIFT_API) {
1099816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Log.w(TAG, "Time shifting is not supported in this platform.");
1100816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1101816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1102816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!isTimeShiftAvailable()) {
1103816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalStateException("Time-shift is not supported for the current channel");
1104816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1105816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (speed <= 0) {
1106816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalArgumentException("The speed should be a positive integer.");
1107816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1108816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTimeShiftState = TIME_SHIFT_STATE_REWIND;
1109816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        PlaybackParams params = new PlaybackParams();
1110816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        params.setSpeed(speed * -1);
1111816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.timeShiftSetPlaybackParams(params);
1112816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1113816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1114816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1115816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Fast-forwards the media with the given speed, if the current input supports time-shifting.
1116816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
1117816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @param speed The speed to forward the media. e.g. 2 for 2x, 3 for 3x and 4 for 4x.
1118816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1119816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void timeshiftFastForward(int speed) {
1120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!TvCommonConstants.HAS_TIME_SHIFT_API) {
1121816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Log.w(TAG, "Time shifting is not supported in this platform.");
1122816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1123816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1124816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!isTimeShiftAvailable()) {
1125816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalStateException("Time-shift is not supported for the current channel");
1126816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1127816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (speed <= 0) {
1128816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalArgumentException("The speed should be a positive integer.");
1129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTimeShiftState = TIME_SHIFT_STATE_FAST_FORWARD;
1131816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        PlaybackParams params = new PlaybackParams();
1132816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        params.setSpeed(speed);
1133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.timeShiftSetPlaybackParams(params);
1134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1135816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Seek to the given time position.
1138816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *
1139816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * @param timeMs The time in milliseconds to seek to.
1140816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void timeshiftSeekTo(long timeMs) {
1142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!TvCommonConstants.HAS_TIME_SHIFT_API) {
1143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Log.w(TAG, "Time shifting is not supported in this platform.");
1144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return;
1145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!isTimeShiftAvailable()) {
1147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalStateException("Time-shift is not supported for the current channel");
1148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mTvView.timeShiftSeekTo(timeMs);
1150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Returns the current playback position in milliseconds.
1154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public long timeshiftGetCurrentPositionMs() {
1156816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!TvCommonConstants.HAS_TIME_SHIFT_API) {
1157816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Log.w(TAG, "Time shifting is not supported in this platform.");
1158816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return INVALID_TIME;
1159816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1160816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (!isTimeShiftAvailable()) {
1161816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw new IllegalStateException("Time-shift is not supported for the current channel");
1162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1163816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        if (DEBUG) {
1164816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            Log.d(TAG, "timeshiftGetCurrentPositionMs: current position ="
1165816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    + Utils.toTimeString(mTimeShiftCurrentPositionMs));
1166816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
1167816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        return mTimeShiftCurrentPositionMs;
1168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1169816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1170816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Used to receive the time-shift events.
1172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static abstract class TimeShiftListener {
1174816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
1175816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Called when the availability of the time-shift for the current channel has been changed.
1176816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * It should be guaranteed that this is called only when the availability is really changed.
1177816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
1178816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public abstract void onAvailabilityChanged();
1179816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1180816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
1181816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Called when the record start time has been changed..
1182816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
1183816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public abstract void onRecordStartTimeChanged(long recordStartTimeMs);
1184816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
1185816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1186816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
1187816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * A listener which receives the notification when the screen is blocked/unblocked.
1188816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1189816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public static abstract class OnScreenBlockingChangedListener {
1190816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
1191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Called when the screen is blocked/unblocked.
1192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
1193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public abstract void onScreenBlockingChanged(boolean blocked);
1194d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten    }
1195900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho}
1196