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.AnimatorListenerAdapter; 21816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.animation.TimeInterpolator; 22816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.annotation.SuppressLint; 23ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.annotation.TargetApi; 2448dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.content.ContentUris; 25900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.content.Context; 26829ca34b57d208a84430b2ccecd8975598d086daYoungsang Choimport android.content.pm.PackageManager; 27816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.PlaybackParams; 28816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvContentRating; 299035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputInfo; 304e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kimimport android.media.tv.TvInputManager; 315459428da9aca1b91e3a976a80e1db783caac674Dongwon Kangimport android.media.tv.TvTrackInfo; 3248dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.media.tv.TvView; 33d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenimport android.media.tv.TvView.OnUnhandledInputEventListener; 34816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvView.TvInputCallback; 3548dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.net.ConnectivityManager; 36cdde1b3be4391c4b0d3b57cce3c63eee8c81819aDongwon Kangimport android.net.Uri; 3748dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.os.AsyncTask; 38ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.os.Build; 392c62d08f28cddda68005660c5cf62c5874b7f587Sungsoo Limimport android.os.Bundle; 40816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.support.annotation.IntDef; 417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.support.annotation.Nullable; 4248dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.support.annotation.UiThread; 4348dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.support.v4.os.BuildCompat; 44816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.TextUtils; 45900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.AttributeSet; 46900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.Log; 47829ca34b57d208a84430b2ccecd8975598d086daYoungsang Choimport android.view.KeyEvent; 48829ca34b57d208a84430b2ccecd8975598d086daYoungsang Choimport android.view.MotionEvent; 49816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.SurfaceView; 50816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.View; 51d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenimport android.view.ViewGroup; 52d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenimport android.widget.FrameLayout; 537d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.widget.ImageView; 54900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 551abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.ApplicationSingletons; 56ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.R; 57816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.TvApplication; 58816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.DurationTimer; 59816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.Tracker; 6048dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport com.android.tv.common.feature.CommonFeatures; 6148dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport com.android.tv.common.recording.RecordedProgram; 62d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.data.Channel; 6348dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport com.android.tv.data.ChannelDataManager; 6421abb13274f379e69c3c86d51e493122cccca345Dongwon Kangimport com.android.tv.data.StreamInfo; 657d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.WatchedHistoryManager; 6648dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport com.android.tv.dvr.DvrDataManager; 67816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.parental.ContentRatingsManager; 6807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport com.android.tv.recommendation.NotificationService; 6948dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport com.android.tv.util.NetworkUtils; 707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.util.PermissionUtils; 71d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.TvInputManagerHelper; 72d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.Utils; 73900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 74816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.lang.annotation.Retention; 75816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.lang.annotation.RetentionPolicy; 7648dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport java.lang.reflect.InvocationTargetException; 7748dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport java.lang.reflect.Method; 785459428da9aca1b91e3a976a80e1db783caac674Dongwon Kangimport java.util.List; 795459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang 80d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkerstenpublic class TunableTvView extends FrameLayout implements StreamInfo { 81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final boolean DEBUG = false; 82900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private static final String TAG = "TunableTvView"; 83900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final int VIDEO_UNAVAILABLE_REASON_NOT_TUNED = -1; 85816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 8648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho @Retention(RetentionPolicy.SOURCE) 8748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho @IntDef({BLOCK_SCREEN_TYPE_NO_UI, BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW, BLOCK_SCREEN_TYPE_NORMAL}) 8848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public @interface BlockScreenType {} 89816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final int BLOCK_SCREEN_TYPE_NO_UI = 0; 90816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final int BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW = 1; 91816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final int BLOCK_SCREEN_TYPE_NORMAL = 2; 92816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 9348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private static final String PERMISSION_RECEIVE_INPUT_EVENT = 9448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho "com.android.tv.permission.RECEIVE_INPUT_EVENT"; 9548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 96816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Retention(RetentionPolicy.SOURCE) 97816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @IntDef({ TIME_SHIFT_STATE_NONE, TIME_SHIFT_STATE_PLAY, TIME_SHIFT_STATE_PAUSE, 9848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho TIME_SHIFT_STATE_REWIND, TIME_SHIFT_STATE_FAST_FORWARD }) 9948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private @interface TimeShiftState {} 10048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private static final int TIME_SHIFT_STATE_NONE = 0; 10148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private static final int TIME_SHIFT_STATE_PLAY = 1; 10248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private static final int TIME_SHIFT_STATE_PAUSE = 2; 10348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private static final int TIME_SHIFT_STATE_REWIND = 3; 10448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private static final int TIME_SHIFT_STATE_FAST_FORWARD = 4; 105816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 106816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int FADED_IN = 0; 107816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int FADED_OUT = 1; 108816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int FADING_IN = 2; 109816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int FADING_OUT = 3; 110816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 111816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final long INVALID_TIME = -1; 112816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 113816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // It is too small to see the description text without PIP_BLOCK_SCREEN_SCALE_FACTOR. 114816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final float PIP_BLOCK_SCREEN_SCALE_FACTOR = 1.2f; 115900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 116816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private AppLayerTvView mTvView; 117816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private Channel mCurrentChannel; 11848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private RecordedProgram mRecordedProgram; 119900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private TvInputManagerHelper mInputManagerHelper; 120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private ContentRatingsManager mContentRatingsManager; 1217d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Nullable 1227d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private WatchedHistoryManager mWatchedHistoryManager; 123900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private boolean mStarted; 124900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private TvInputInfo mInputInfo; 125900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private OnTuneListener mOnTuneListener; 126e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim private int mVideoWidth; 127e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim private int mVideoHeight; 12821abb13274f379e69c3c86d51e493122cccca345Dongwon Kang private int mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; 129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private float mVideoFrameRate; 13048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private float mVideoDisplayAspectRatio; 131e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang private int mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN; 132e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang private boolean mHasClosedCaption = false; 133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private boolean mVideoAvailable; 134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private boolean mScreenBlocked; 135816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private OnScreenBlockingChangedListener mOnScreenBlockedListener; 136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private TvContentRating mBlockedContentRating; 137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private int mVideoUnavailableReason = VIDEO_UNAVAILABLE_REASON_NOT_TUNED; 138829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho private boolean mCanReceiveInputEvent; 139d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten private boolean mIsMuted; 140d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten private float mVolume; 141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private boolean mParentControlEnabled; 142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private int mFixedSurfaceWidth; 143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private int mFixedSurfaceHeight; 144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private boolean mIsPip; 145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private int mScreenHeight; 146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private int mShrunkenTvViewHeight; 14748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private final boolean mCanModifyParentalControls; 148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @TimeShiftState private int mTimeShiftState = TIME_SHIFT_STATE_NONE; 150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private TimeShiftListener mTimeShiftListener; 151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private boolean mTimeShiftAvailable; 152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private long mTimeShiftCurrentPositionMs = INVALID_TIME; 153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final Tracker mTracker; 155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final DurationTimer mChannelViewTimer = new DurationTimer(); 15648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private InternetCheckTask mInternetCheckTask; 157816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 158816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // A block screen view which has lock icon with black background. 159816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // This indicates that user's action is needed to play video. 16048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private final BlockScreenView mBlockScreenView; 161816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // A View to hide screen when there's problem in video playback. 16348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private final BlockScreenView mHideScreenView; 164816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 165816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // A View to block screen until onContentAllowed is received if parental control is on. 166816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final View mBlockScreenForTuneView; 167900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // A spinner view to show buffering status. 169816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final View mBufferingSpinnerView; 170816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // A View for fade-in/out animation 172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final View mDimScreenView; 173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private int mFadeState = FADED_IN; 174816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private Runnable mActionAfterFade; 175816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 17648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho @BlockScreenType private int mBlockScreenType; 17748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 17848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private final DvrDataManager mDvrDataManager; 17948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private final ChannelDataManager mChannelDataManager; 18048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private final ConnectivityManager mConnectivityManager; 181816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 182816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final TvInputCallback mCallback = 183816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko new TvInputCallback() { 184900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho @Override 185816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onConnectionFailed(String inputId) { 186816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Failed to bind an input"); 1877d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTracker.sendInputConnectionFailure(inputId); 188816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Channel channel = mCurrentChannel; 189816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mCurrentChannel = null; 190816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mInputInfo = null; 191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mCanReceiveInputEvent = false; 192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mOnTuneListener != null) { 193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // If tune is called inside onTuneFailed, mOnTuneListener will be set to 194816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // a new instance. In order to avoid to clear the new mOnTuneListener, 195816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // we copy mOnTuneListener to l and clear mOnTuneListener before 196816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // calling onTuneFailed. 197816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko OnTuneListener listener = mOnTuneListener; 198816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnTuneListener = null; 199816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko listener.onTuneFailed(channel); 200816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 201816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 202816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 203816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 204816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onDisconnected(String inputId) { 205816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Session is released by crash"); 2067d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTracker.sendInputDisconnected(inputId); 207816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Channel channel = mCurrentChannel; 208816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mCurrentChannel = null; 209816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mInputInfo = null; 210816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mCanReceiveInputEvent = false; 211816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mOnTuneListener != null) { 212816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko OnTuneListener listener = mOnTuneListener; 213816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnTuneListener = null; 214816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko listener.onUnexpectedStop(channel); 215900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 216900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 217900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 218900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho @Override 2195459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang public void onChannelRetuned(String inputId, Uri channelUri) { 2208f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo if (DEBUG) { 2215459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang Log.d(TAG, "onChannelRetuned(inputId=" + inputId + ", channelUri=" 2225459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang + channelUri + ")"); 2238f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo } 22421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang if (mOnTuneListener != null) { 225816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnTuneListener.onChannelRetuned(channelUri); 22621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 22721abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 228fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang 229fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang @Override 230ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) { 231ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mHasClosedCaption = false; 232ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang for (TvTrackInfo track : tracks) { 233ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang if (track.getType() == TvTrackInfo.TYPE_SUBTITLE) { 234ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mHasClosedCaption = true; 235ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang break; 236ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } 237ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } 238512017945a2cd192797d7ca404cba08d792877ddDongwon Kang if (mOnTuneListener != null) { 239512017945a2cd192797d7ca404cba08d792877ddDongwon Kang mOnTuneListener.onStreamInfoChanged(TunableTvView.this); 240512017945a2cd192797d7ca404cba08d792877ddDongwon Kang } 241512017945a2cd192797d7ca404cba08d792877ddDongwon Kang } 242512017945a2cd192797d7ca404cba08d792877ddDongwon Kang 243512017945a2cd192797d7ca404cba08d792877ddDongwon Kang @Override 244ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang public void onTrackSelected(String inputId, int type, String trackId) { 245ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang if (trackId == null) { 246ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang // A track is unselected. 247512017945a2cd192797d7ca404cba08d792877ddDongwon Kang if (type == TvTrackInfo.TYPE_VIDEO) { 248ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mVideoWidth = 0; 249ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mVideoHeight = 0; 250ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; 251816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mVideoFrameRate = 0f; 25248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoDisplayAspectRatio = 0f; 253512017945a2cd192797d7ca404cba08d792877ddDongwon Kang } else if (type == TvTrackInfo.TYPE_AUDIO) { 254ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN; 255ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } 256ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } else { 257ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang List<TvTrackInfo> tracks = getTracks(type); 258ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang boolean trackFound = false; 259ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang if (tracks != null) { 26007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko for (TvTrackInfo track : tracks) { 261ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang if (track.getId().equals(trackId)) { 262ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang if (type == TvTrackInfo.TYPE_VIDEO) { 263ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mVideoWidth = track.getVideoWidth(); 264ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mVideoHeight = track.getVideoHeight(); 265ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mVideoFormat = Utils.getVideoDefinitionLevelFromSize( 266ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mVideoWidth, mVideoHeight); 267816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mVideoFrameRate = track.getVideoFrameRate(); 26848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (mVideoWidth <= 0 || mVideoHeight <= 0) { 26948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoDisplayAspectRatio = 0.0f; 27048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } else if (android.os.Build.VERSION.SDK_INT >= 27148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho android.os.Build.VERSION_CODES.M) { 27248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho float VideoPixelAspectRatio = 27348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho track.getVideoPixelAspectRatio(); 27448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoDisplayAspectRatio = VideoPixelAspectRatio 27548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * mVideoWidth / mVideoHeight; 27648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } else { 27748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoDisplayAspectRatio = mVideoWidth 27848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho / (float) mVideoHeight; 27948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 280ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } else if (type == TvTrackInfo.TYPE_AUDIO) { 281ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mAudioChannelCount = track.getAudioChannelCount(); 282ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } 283ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang trackFound = true; 284ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang break; 285ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } 286ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } 287ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang } 288ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang if (!trackFound) { 289ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang Log.w(TAG, "Invalid track ID: " + trackId); 2905459428da9aca1b91e3a976a80e1db783caac674Dongwon Kang } 291fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang } 292fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang if (mOnTuneListener != null) { 293fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang mOnTuneListener.onStreamInfoChanged(TunableTvView.this); 294fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang } 295fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang } 2964e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim 2974e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim @Override 2984e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim public void onVideoAvailable(String inputId) { 299816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko unhideScreenByVideoAvailability(); 3004e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim if (mOnTuneListener != null) { 3014e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim mOnTuneListener.onStreamInfoChanged(TunableTvView.this); 3024e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim } 3034e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim } 3044e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim 3054e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim @Override 3064e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim public void onVideoUnavailable(String inputId, int reason) { 307816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko hideScreenByVideoAvailability(reason); 3084e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim if (mOnTuneListener != null) { 3094e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim mOnTuneListener.onStreamInfoChanged(TunableTvView.this); 3104e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim } 3117d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko switch (reason) { 3127d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko case TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING: 3137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko case TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN: 3147d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko case TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL: 3157d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTracker.sendChannelVideoUnavailable(mCurrentChannel, reason); 3167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko default: 3177d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // do nothing 3187d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 3194e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim } 320816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 321816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 322816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onContentAllowed(String inputId) { 323816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenForTuneView.setVisibility(View.GONE); 324816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko unblockScreenByContentRating(); 325816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mOnTuneListener != null) { 326816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnTuneListener.onContentAllowed(); 327816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 328816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 329816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 330816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 331816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onContentBlocked(String inputId, TvContentRating rating) { 332816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko blockScreenByContentRating(rating); 333816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mOnTuneListener != null) { 334816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnTuneListener.onContentBlocked(); 335816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 336816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 337816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 338816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 339ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko @TargetApi(Build.VERSION_CODES.M) 340816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onTimeShiftStatusChanged(String inputId, int status) { 34148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho boolean available = status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE; 34248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho setTimeShiftAvailable(available); 343816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 344900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho }; 345900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 346900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public TunableTvView(Context context) { 347d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten this(context, null); 348900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 349900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 350900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public TunableTvView(Context context, AttributeSet attrs) { 351900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho this(context, attrs, 0); 352900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 353900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 354900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public TunableTvView(Context context, AttributeSet attrs, int defStyleAttr) { 355d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten this(context, attrs, defStyleAttr, 0); 356d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 357d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 358d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten public TunableTvView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 359d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten super(context, attrs, defStyleAttr, defStyleRes); 360d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten inflate(getContext(), R.layout.tunable_tv_view, this); 361d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 3621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko ApplicationSingletons appSingletons = TvApplication.getSingletons(context); 36348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mDvrDataManager = CommonFeatures.DVR.isEnabled(context) && BuildCompat.isAtLeastN() 36448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho ? appSingletons.getDvrDataManager() 36548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho : null; 36648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mChannelDataManager = appSingletons.getChannelDataManager(); 36748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mConnectivityManager = (ConnectivityManager) context 36848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho .getSystemService(Context.CONNECTIVITY_SERVICE); 3697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mCanModifyParentalControls = PermissionUtils.hasModifyParentalControls(context); 3701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mTracker = appSingletons.getTracker(); 371816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenType = BLOCK_SCREEN_TYPE_NORMAL; 37248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView = (BlockScreenView) findViewById(R.id.block_screen); 3737d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (!mCanModifyParentalControls) { 37448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.setImage(R.drawable.ic_message_lock_no_permission); 37548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.setScaleType(ImageView.ScaleType.CENTER); 37648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } else { 37748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.setImage(R.drawable.ic_message_lock); 3787d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 37948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.setShrunkenImage(R.drawable.ic_message_lock_preview); 38048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.addFadeOutAnimationListener(new AnimatorListenerAdapter() { 381816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 382816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onAnimationEnd(Animator animation) { 38348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho adjustBlockScreenSpacingAndText(); 384816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 385816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }); 386816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 38748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView = (BlockScreenView) findViewById(R.id.hide_screen); 38848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setImageVisibility(false); 389816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBufferingSpinnerView = findViewById(R.id.buffering_spinner); 390816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenForTuneView = findViewById(R.id.block_screen_for_tune); 391816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView = findViewById(R.id.dim); 392816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.animate().setListener(new AnimatorListenerAdapter() { 393816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 394816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onAnimationEnd(Animator animation) { 395816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mActionAfterFade != null) { 396816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mActionAfterFade.run(); 397816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 398816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 399816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 400816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 401816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onAnimationCancel(Animator animation) { 402816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mActionAfterFade != null) { 403816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mActionAfterFade.run(); 404816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 405816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 406816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }); 407816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 408816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 409816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void initialize(AppLayerTvView tvView, boolean isPip, int screenHeight, 410816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int shrunkenTvViewHeight) { 411816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView = tvView; 412816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mIsPip = isPip; 413816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mScreenHeight = screenHeight; 414816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mShrunkenTvViewHeight = shrunkenTvViewHeight; 415816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setZOrderOnTop(isPip); 416816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko copyLayoutParamsToTvView(); 417900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 418900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 419900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public void start(TvInputManagerHelper tvInputManagerHelper) { 420900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mInputManagerHelper = tvInputManagerHelper; 421816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mContentRatingsManager = tvInputManagerHelper.getContentRatingsManager(); 422900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (mStarted) { 423900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return; 424900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 425900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mStarted = true; 426900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 427900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 428900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public void stop() { 429900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!mStarted) { 430900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return; 431900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 432900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mStarted = false; 433816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mCurrentChannel != null) { 4347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko long duration = mChannelViewTimer.reset(); 4357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTracker.sendChannelViewStop(mCurrentChannel, duration); 4367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (mWatchedHistoryManager != null && !mCurrentChannel.isPassthrough()) { 4377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mWatchedHistoryManager.logChannelViewStop(mCurrentChannel, 4387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko System.currentTimeMillis(), duration); 4397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 440816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 441816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko reset(); 442816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 443816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 444816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void reset() { 445d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mTvView.reset(); 446816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mCurrentChannel = null; 44748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mRecordedProgram = null; 448900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mInputInfo = null; 449829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho mCanReceiveInputEvent = false; 450900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mOnTuneListener = null; 451816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setTimeShiftAvailable(false); 452816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko hideScreenByVideoAvailability(VIDEO_UNAVAILABLE_REASON_NOT_TUNED); 453816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 454816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 455816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void setMain() { 456816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setMain(); 457900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 458900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 4597d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void setWatchedHistoryManager(WatchedHistoryManager watchedHistoryManager) { 4607d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mWatchedHistoryManager = watchedHistoryManager; 4617d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 4627d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 463900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public boolean isPlaying() { 464900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return mStarted; 465900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 466900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 467816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 468816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Called when parental control is changed. 469816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 470816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onParentalControlChanged(boolean enabled) { 471816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mParentControlEnabled = enabled; 472816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!mParentControlEnabled) { 473816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenForTuneView.setVisibility(View.GONE); 474816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 475816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 476816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 477816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 47848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Returns {@code true}, if this view is the recording playback mode. 47948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho */ 48048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public boolean isRecordingPlayback() { 48148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return mRecordedProgram != null; 48248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 48348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 48448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho /** 48548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Returns the recording which is being played right now. 48648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho */ 48748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public RecordedProgram getPlayingRecordedProgram() { 48848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return mRecordedProgram; 48948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 49048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 49148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho /** 492ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Plays a recording. 493ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */ 49448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public boolean playRecording(Uri recordingUri, OnTuneListener listener) { 49548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (!mStarted) { 49648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho throw new IllegalStateException("TvView isn't started"); 49748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 49848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (!CommonFeatures.DVR.isEnabled(getContext()) || !BuildCompat.isAtLeastN()) { 49948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return false; 50048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 50148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (DEBUG) Log.d(TAG, "playRecording " + recordingUri); 50248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho long recordingId = ContentUris.parseId(recordingUri); 50348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mRecordedProgram = mDvrDataManager.getRecordedProgram(recordingId); 50448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (mRecordedProgram == null) { 50548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho Log.w(TAG, "No recorded program (Uri=" + recordingUri + ")"); 50648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return false; 50748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 50848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho String inputId = mRecordedProgram.getInputId(); 50948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho TvInputInfo inputInfo = mInputManagerHelper.getTvInputInfo(inputId); 51048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (inputInfo == null) { 51148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return false; 51248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 51348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mOnTuneListener = listener; 51448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho // mCurrentChannel can be null. 51548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mCurrentChannel = mChannelDataManager.getChannel(mRecordedProgram.getChannelId()); 51648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho // For recording playback, input event should not be sent. 51748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mCanReceiveInputEvent = false; 51848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho boolean needSurfaceSizeUpdate = false; 51948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (!inputInfo.equals(mInputInfo)) { 52048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mInputInfo = inputInfo; 52148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (DEBUG) { 52248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho Log.d(TAG, "Input \'" + mInputInfo.getId() + "\' can receive input event: " 52348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho + mCanReceiveInputEvent); 52448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 52548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho needSurfaceSizeUpdate = true; 52648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 52748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mChannelViewTimer.start(); 52848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoWidth = 0; 52948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoHeight = 0; 53048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; 53148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoFrameRate = 0f; 53248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoDisplayAspectRatio = 0f; 53348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN; 53448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHasClosedCaption = false; 53548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mTvView.setCallback(mCallback); 53648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mTimeShiftCurrentPositionMs = INVALID_TIME; 53748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mTvView.setTimeShiftPositionCallback(null); 53848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho setTimeShiftAvailable(false); 53948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mTvView.timeShiftPlay(inputId, recordingUri); 54048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (needSurfaceSizeUpdate && mFixedSurfaceWidth > 0 && mFixedSurfaceHeight > 0) { 54148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho // When the input is changed, TvView recreates its SurfaceView internally. 54248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView. 54348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho getSurfaceView().getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight); 54448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 54548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho hideScreenByVideoAvailability(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING); 54648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho unblockScreenByContentRating(); 54748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (mParentControlEnabled) { 54848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenForTuneView.setVisibility(View.VISIBLE); 54948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 55048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (mOnTuneListener != null) { 55148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mOnTuneListener.onStreamInfoChanged(this); 55248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 55348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return true; 554ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 555ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 556ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko /** 557816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Tunes to a channel with the {@code channelId}. 558816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 559816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param params extra data to send it to TIS and store the data in TIMS. 560816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @return false, if the TV input is not a proper state to tune to a channel. For example, 561816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * if the state is disconnected or channelId doesn't exist, it returns false. 562816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 563816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public boolean tuneTo(Channel channel, Bundle params, OnTuneListener listener) { 564900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!mStarted) { 565900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho throw new IllegalStateException("TvView isn't started"); 566900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 567816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (DEBUG) Log.d(TAG, "tuneTo " + channel); 568816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko TvInputInfo inputInfo = mInputManagerHelper.getTvInputInfo(channel.getInputId()); 569816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (inputInfo == null) { 570900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return false; 571900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 572816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mCurrentChannel != null) { 5737d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko long duration = mChannelViewTimer.reset(); 5747d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTracker.sendChannelViewStop(mCurrentChannel, duration); 5757d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (mWatchedHistoryManager != null && !mCurrentChannel.isPassthrough()) { 5767d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mWatchedHistoryManager.logChannelViewStop(mCurrentChannel, 5777d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko System.currentTimeMillis(), duration); 5787d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 579816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 580900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mOnTuneListener = listener; 581816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mCurrentChannel = channel; 58248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mRecordedProgram = null; 58307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko boolean tunedByRecommendation = params != null 58407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko && params.getString(NotificationService.TUNE_PARAMS_RECOMMENDATION_TYPE) != null; 585816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko boolean needSurfaceSizeUpdate = false; 586900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!inputInfo.equals(mInputInfo)) { 587900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mInputInfo = inputInfo; 588d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mCanReceiveInputEvent = getContext().getPackageManager().checkPermission( 589816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko PERMISSION_RECEIVE_INPUT_EVENT, mInputInfo.getServiceInfo().packageName) 590829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho == PackageManager.PERMISSION_GRANTED; 591816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (DEBUG) { 592816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.d(TAG, "Input \'" + mInputInfo.getId() + "\' can receive input event: " 593816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + mCanReceiveInputEvent); 594816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 595816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko needSurfaceSizeUpdate = true; 596816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 5977d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTracker.sendChannelViewStart(mCurrentChannel, tunedByRecommendation); 5987d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mChannelViewTimer.start(); 599816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mVideoWidth = 0; 600816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mVideoHeight = 0; 601816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; 602816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mVideoFrameRate = 0f; 60348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoDisplayAspectRatio = 0f; 604816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN; 605816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mHasClosedCaption = false; 606816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setCallback(mCallback); 607816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTimeShiftCurrentPositionMs = INVALID_TIME; 608ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 609816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // To reduce the IPCs, unregister the callback here and register it when necessary. 610816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setTimeShiftPositionCallback(null); 611816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 612816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setTimeShiftAvailable(false); 613816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.tune(mInputInfo.getId(), mCurrentChannel.getUri(), params); 614816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (needSurfaceSizeUpdate && mFixedSurfaceWidth > 0 && mFixedSurfaceHeight > 0) { 615816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // When the input is changed, TvView recreates its SurfaceView internally. 616816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView. 617816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko getSurfaceView().getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight); 618816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 619816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko hideScreenByVideoAvailability(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING); 620816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko unblockScreenByContentRating(); 621816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (channel.isPassthrough()) { 622816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenForTuneView.setVisibility(View.GONE); 623816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else if (mParentControlEnabled) { 624816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenForTuneView.setVisibility(View.VISIBLE); 6259bb548ba08d7e222f276287fead545c6a11704d8Jae Seo } 6269bb548ba08d7e222f276287fead545c6a11704d8Jae Seo if (mOnTuneListener != null) { 627816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnTuneListener.onStreamInfoChanged(this); 628900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 629900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return true; 630900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 631900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 63287c1cbb508c96538d1e69ba1fdf3d9f4d52710d6Jaewan Kim @Override 633816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public Channel getCurrentChannel() { 634816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mCurrentChannel; 635900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 636900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 637816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 638816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Sets the current channel. Call this method only when setting the current channel without 639816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * actually tuning to it. 640816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 641816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param currentChannel The new current channel to set to. 642816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 643816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void setCurrentChannel(Channel currentChannel) { 644816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mCurrentChannel = currentChannel; 645b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang } 646b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang 647561696c364ee330f4316544f1f85498393883526Jae Seo public void setStreamVolume(float volume) { 648900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!mStarted) { 649900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho throw new IllegalStateException("TvView isn't started"); 650900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 651d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten if (DEBUG) Log.d(TAG, "setStreamVolume " + volume); 652d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mVolume = volume; 653d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten if (!mIsMuted) { 654d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mTvView.setStreamVolume(volume); 655d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 656900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 657900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 658816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 659816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Sets fixed size for the internal {@link android.view.Surface} of 660816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * {@link android.media.tv.TvView}. If either {@code width} or {@code height} is non positive, 661816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * the {@link android.view.Surface}'s size will be matched to the layout. 662816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 663816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Note: Once {@link android.view.SurfaceHolder#setFixedSize} is called, 664816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * {@link android.view.SurfaceView} and its underlying window can be misaligned, when the size 665816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * of {@link android.view.SurfaceView} is changed without changing either left position or top 66648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * position. For detail, please refer the codes of android.view.SurfaceView.updateWindow(). 667816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 668816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void setFixedSurfaceSize(int width, int height) { 669816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mFixedSurfaceWidth = width; 670816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mFixedSurfaceHeight = height; 671816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mFixedSurfaceWidth > 0 && mFixedSurfaceHeight > 0) { 672816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // When the input is changed, TvView recreates its SurfaceView internally. 673816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView. 674816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko SurfaceView surfaceView = (SurfaceView) mTvView.getChildAt(0); 675816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko surfaceView.getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight); 676816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 677816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko SurfaceView surfaceView = (SurfaceView) mTvView.getChildAt(0); 678816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko surfaceView.getHolder().setSizeFromLayout(); 679816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 680816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 681816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 682829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho @Override 683829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho public boolean dispatchKeyEvent(KeyEvent event) { 684d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten return mCanReceiveInputEvent && mTvView.dispatchKeyEvent(event); 685829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho } 686829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho 687829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho @Override 688829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho public boolean dispatchTouchEvent(MotionEvent event) { 689d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten return mCanReceiveInputEvent && mTvView.dispatchTouchEvent(event); 690829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho } 691829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho 692829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho @Override 693829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho public boolean dispatchTrackballEvent(MotionEvent event) { 694d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten return mCanReceiveInputEvent && mTvView.dispatchTrackballEvent(event); 695829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho } 696829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho 697829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho @Override 698829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho public boolean dispatchGenericMotionEvent(MotionEvent event) { 699d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten return mCanReceiveInputEvent && mTvView.dispatchGenericMotionEvent(event); 700829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho } 701829ca34b57d208a84430b2ccecd8975598d086daYoungsang Cho 702900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public interface OnTuneListener { 703816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko void onTuneFailed(Channel channel); 704816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko void onUnexpectedStop(Channel channel); 70521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang void onStreamInfoChanged(StreamInfo info); 706816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko void onChannelRetuned(Uri channel); 707816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko void onContentBlocked(); 708816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko void onContentAllowed(); 709816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 710816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 71148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public void unblockContent(TvContentRating rating) { 71248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 71348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho try { 71448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho Method method = TvView.class.getMethod("requestUnblockContent", 71548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho TvContentRating.class); 71648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho method.invoke(mTvView, rating); 71748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) { 71848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho e.printStackTrace(); 71948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 72048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } else { 72148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mTvView.unblockContent(rating); 72248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 72321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 72421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang 72521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang @Override 726e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim public int getVideoWidth() { 727e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim return mVideoWidth; 728e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 729e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 730e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim @Override 731e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim public int getVideoHeight() { 732e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim return mVideoHeight; 733e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 734e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 735e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim @Override 73621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang public int getVideoDefinitionLevel() { 73721abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return mVideoFormat; 738900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 739e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang 740e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang @Override 741816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public float getVideoFrameRate() { 742816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mVideoFrameRate; 743816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 744816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 74548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho /** 74648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Returns displayed aspect ratio (video width / video height * pixel ratio). 74748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho */ 74848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho @Override 74948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public float getVideoDisplayAspectRatio() { 75048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return mVideoDisplayAspectRatio; 75148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 75248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 753816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 754e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang public int getAudioChannelCount() { 755e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang return mAudioChannelCount; 756e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang } 757e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang 758e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang @Override 759e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang public boolean hasClosedCaption() { 760e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang return mHasClosedCaption; 761e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang } 7624e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim 7634e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim @Override 7644e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim public boolean isVideoAvailable() { 765816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mVideoAvailable; 7664e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim } 7674e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim 7684e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim @Override 7694e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim public int getVideoUnavailableReason() { 7704e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim return mVideoUnavailableReason; 7714e5a6a47adb40039a27536236656204f9ad12df3Jaewan Kim } 772d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 773816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 774816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns the {@link android.view.SurfaceView} of the {@link android.media.tv.TvView}. 775816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 77648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private SurfaceView getSurfaceView() { 777816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return (SurfaceView) mTvView.getChildAt(0); 778816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 779816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 780d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten public void setOnUnhandledInputEventListener(OnUnhandledInputEventListener listener) { 781d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mTvView.setOnUnhandledInputEventListener(listener); 782d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 783d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 784816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void setClosedCaptionEnabled(boolean enabled) { 785816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setCaptionEnabled(enabled); 786816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 787816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 788ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang public List<TvTrackInfo> getTracks(int type) { 789ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang return mTvView.getTracks(type); 790d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 791d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 792816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public String getSelectedTrack(int type) { 793816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mTvView.getSelectedTrack(type); 794816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 795816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 796ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang public void selectTrack(int type, String trackId) { 797ec9bd88036279df7421321b2e9945adf8f89db4bDongwon Kang mTvView.selectTrack(type, trackId); 798d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 799d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 800816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 801816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns if the screen is blocked by {@link #blockScreen()}. 802816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 803816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public boolean isScreenBlocked() { 804816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mScreenBlocked; 805816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 806816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 807816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void setOnScreenBlockedListener(OnScreenBlockingChangedListener listener) { 808816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnScreenBlockedListener = listener; 809816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 810816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 811816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 812816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns currently blocked content rating. {@code null} if it's not blocked. 813816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 814816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public TvContentRating getBlockedContentRating() { 815816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mBlockedContentRating; 816816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 817816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 818816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 819816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Locks current TV screen and mutes. 820816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * There would be black screen with lock icon in order to show that 821816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * screen block is intended and not an error. 822816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * TODO: Accept parameter to show lock icon or not. 823816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 824816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void blockScreen() { 825816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mScreenBlocked = true; 826816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko checkBlockScreenAndMuteNeeded(); 827816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mOnScreenBlockedListener != null) { 828816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnScreenBlockedListener.onScreenBlockingChanged(true); 829816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 830816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 831816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 832816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void blockScreenByContentRating(TvContentRating rating) { 833816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockedContentRating = rating; 834816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko checkBlockScreenAndMuteNeeded(); 835816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 836816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 837816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 838816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @SuppressLint("RtlHardcoded") 839816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 840816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko super.onLayout(changed, left, top, right, bottom); 841816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mIsPip) { 842816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int height = bottom - top; 843816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko float scale; 844816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mBlockScreenType == BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW) { 845816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko scale = height * PIP_BLOCK_SCREEN_SCALE_FACTOR / mShrunkenTvViewHeight; 846816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 847816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko scale = height * PIP_BLOCK_SCREEN_SCALE_FACTOR / mScreenHeight; 848816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 849816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // TODO: need to get UX confirmation. 85048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.scaleContainerView(scale); 851816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 852816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 853816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 854816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 855816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void setLayoutParams(ViewGroup.LayoutParams params) { 856816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko super.setLayoutParams(params); 857816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTvView != null) { 858816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko copyLayoutParamsToTvView(); 859816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 860816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 861816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 862816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void copyLayoutParamsToTvView() { 863816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); 864816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko FrameLayout.LayoutParams tvViewLp = (FrameLayout.LayoutParams) mTvView.getLayoutParams(); 865816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (tvViewLp.bottomMargin != lp.bottomMargin 866816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko || tvViewLp.topMargin != lp.topMargin 867816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko || tvViewLp.leftMargin != lp.leftMargin 868816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko || tvViewLp.rightMargin != lp.rightMargin 869816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko || tvViewLp.gravity != lp.gravity 870816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko || tvViewLp.height != lp.height 871816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko || tvViewLp.width != lp.width) { 872816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (lp.topMargin == tvViewLp.topMargin && lp.leftMargin == tvViewLp.leftMargin) { 873816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // HACK: If top and left position aren't changed and SurfaceHolder.setFixedSize is 874816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // used, SurfaceView doesn't catch the width and height change. It causes a bug that 875816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // PIP size change isn't shown when PIP is located TOP|LEFT. So we adjust 1 px for 876816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // small size PIP as a workaround. 877816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.leftMargin = lp.leftMargin + 1; 878816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 879816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.leftMargin = lp.leftMargin; 880816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 881816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.topMargin = lp.topMargin; 882816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.bottomMargin = lp.bottomMargin; 883816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.rightMargin = lp.rightMargin; 884816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.gravity = lp.gravity; 885816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.height = lp.height; 886816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvViewLp.width = lp.width; 887816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setLayoutParams(tvViewLp); 888816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 889816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 890816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 891816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 892816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko protected void onVisibilityChanged(View changedView, int visibility) { 893816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko super.onVisibilityChanged(changedView, visibility); 894816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTvView != null) { 895816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setVisibility(visibility); 896816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 897816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 898816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 899816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 900816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Set the type of block screen. If {@code type} is set to {@code BLOCK_SCREEN_TYPE_NO_UI}, the 901816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * block screen will not show any description such as a lock icon and a text for the blocked 902816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * reason, if {@code type} is set to {@code BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW}, the block screen 903816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * will show the description for shrunken tv view (Small icon and short text), and if 904816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * {@code type} is set to {@code BLOCK_SCREEN_TYPE_NORMAL}, the block screen will show the 905816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * description for normal tv view (Big icon and long text). 906816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 907816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param type The type of block screen to set. 908816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 90948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public void setBlockScreenType(@BlockScreenType int type) { 910816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // TODO: need to support the transition from NORMAL to SHRUNKEN and vice verse. 911816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mBlockScreenType != type) { 912816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenType = type; 913816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko updateBlockScreenUI(true); 914816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 915816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 916816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 917816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void updateBlockScreenUI(boolean animation) { 91848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.endAnimations(); 919816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 920816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!mScreenBlocked && mBlockedContentRating == null) { 921816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenView.setVisibility(GONE); 922816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 923816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 924816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 925816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockScreenView.setVisibility(VISIBLE); 92648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (!animation || mBlockScreenType != TunableTvView.BLOCK_SCREEN_TYPE_NO_UI) { 92748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho adjustBlockScreenSpacingAndText(); 928816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 92948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.onBlockStatusChanged(mBlockScreenType, animation); 930816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 931816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 93248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private void adjustBlockScreenSpacingAndText() { 933816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // TODO: need to add animation for padding change when the block screen type is changed 934816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // NORMAL to SHRUNKEN and vice verse. 93548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.setSpacing(mBlockScreenType); 93648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho String text = getBlockScreenText(); 93748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (text != null) { 93848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBlockScreenView.setText(text); 93948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 94048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 941816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 94248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho /** 94348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Returns the block screen text corresponding to the current status. 94448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Note that returning {@code null} value means that the current text should not be changed. 94548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho */ 94648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho private String getBlockScreenText() { 947816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mScreenBlocked) { 948816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko switch (mBlockScreenType) { 949816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case BLOCK_SCREEN_TYPE_NO_UI: 950816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW: 95148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return ""; 952816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case BLOCK_SCREEN_TYPE_NORMAL: 9537d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (mCanModifyParentalControls) { 95448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getResources().getString(R.string.tvview_channel_locked); 9557d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } else { 95648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getResources().getString( 95748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho R.string.tvview_channel_locked_no_permission); 9587d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 959816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 960816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else if (mBlockedContentRating != null) { 961816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String name = mContentRatingsManager.getDisplayNameForRating(mBlockedContentRating); 962816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko switch (mBlockScreenType) { 963816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case BLOCK_SCREEN_TYPE_NO_UI: 96448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return ""; 965816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW: 966816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (TextUtils.isEmpty(name)) { 96748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getResources().getString(R.string.shrunken_tvview_content_locked); 968816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 96948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getContext().getString( 97048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho R.string.shrunken_tvview_content_locked_format, name); 971816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 972816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case BLOCK_SCREEN_TYPE_NORMAL: 973816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (TextUtils.isEmpty(name)) { 9747d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (mCanModifyParentalControls) { 97548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getResources().getString(R.string.tvview_content_locked); 9767d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } else { 97748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getResources().getString( 9787d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko R.string.tvview_content_locked_no_permission); 9797d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 980816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 9817d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (mCanModifyParentalControls) { 98248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getContext().getString( 98348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho R.string.tvview_content_locked_format, name); 9847d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } else { 98548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return getContext().getString( 98648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho R.string.tvview_content_locked_format_no_permission, name); 9877d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 988816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 989816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 990816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 99148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return null; 992816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 993816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 994816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void checkBlockScreenAndMuteNeeded() { 995816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko updateBlockScreenUI(false); 996816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mScreenBlocked || mBlockedContentRating != null) { 997816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mute(); 998816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mIsPip) { 999816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // If we don't make mTvView invisible, some frames are leaked when a user changes 1000816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // PIP layout in options. 1001816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Note: When video is unavailable, we keep the mTvView's visibility, because 1002816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // TIS implementation may not send video available with no surface. 1003816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setVisibility(View.INVISIBLE); 1004816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1005816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 1006816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko unmuteIfPossible(); 1007816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mIsPip) { 1008816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setVisibility(View.VISIBLE); 1009816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1010816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1011816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1012816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1013816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void unblockScreen() { 1014816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mScreenBlocked = false; 1015816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko checkBlockScreenAndMuteNeeded(); 1016816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mOnScreenBlockedListener != null) { 1017816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mOnScreenBlockedListener.onScreenBlockingChanged(false); 1018816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1019816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1020816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1021816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void unblockScreenByContentRating() { 1022816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBlockedContentRating = null; 1023816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko checkBlockScreenAndMuteNeeded(); 1024816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1025816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 102648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho @UiThread 1027816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void hideScreenByVideoAvailability(int reason) { 102848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoAvailable = false; 102948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mVideoUnavailableReason = reason; 103048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (mInternetCheckTask != null) { 103148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mInternetCheckTask.cancel(true); 103248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mInternetCheckTask = null; 103348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 1034d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten switch (reason) { 10357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko case TvInputManager.VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY: 10367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mHideScreenView.setVisibility(VISIBLE); 103748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setImageVisibility(false); 10387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mHideScreenView.setText(R.string.tvview_msg_audio_only); 10397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mBufferingSpinnerView.setVisibility(GONE); 10407d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko unmuteIfPossible(); 10417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko break; 1042816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING: 1043816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBufferingSpinnerView.setVisibility(VISIBLE); 10447d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mute(); 1045d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten break; 10463a72b93e554bd22a5c64e71a6956d9604ce05108Youngsang Cho case TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL: 104748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setVisibility(VISIBLE); 104848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setText(R.string.tvview_msg_weak_signal); 104948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBufferingSpinnerView.setVisibility(GONE); 105048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mute(); 105148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho break; 105248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho case TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING: 1053816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case VIDEO_UNAVAILABLE_REASON_NOT_TUNED: 105448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setVisibility(VISIBLE); 105548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setImageVisibility(false); 105648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setText(null); 105748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mBufferingSpinnerView.setVisibility(GONE); 105848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mute(); 105948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho break; 106048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho case TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN: 1061816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko default: 1062816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mHideScreenView.setVisibility(VISIBLE); 106348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setImageVisibility(false); 10647d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mHideScreenView.setText(null); 1065816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBufferingSpinnerView.setVisibility(GONE); 10667d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mute(); 106748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (mCurrentChannel != null && !mCurrentChannel.isPhysicalTunerChannel()) { 106848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mInternetCheckTask = new InternetCheckTask(); 106948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mInternetCheckTask.execute(); 107048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 1071d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten break; 1072d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 1073d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 1074d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 1075816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void unhideScreenByVideoAvailability() { 1076816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mVideoAvailable = true; 1077816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mHideScreenView.setVisibility(GONE); 1078816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mBufferingSpinnerView.setVisibility(GONE); 1079816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko unmuteIfPossible(); 1080816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1081816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1082816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void unmuteIfPossible() { 1083816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mVideoAvailable && !mScreenBlocked && mBlockedContentRating == null) { 1084816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko unmute(); 1085816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1086d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 1087d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 1088d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten private void mute() { 1089d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mIsMuted = true; 1090d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mTvView.setStreamVolume(0); 1091d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 1092d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 1093d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten private void unmute() { 1094d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mIsMuted = false; 1095d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten mTvView.setStreamVolume(mVolume); 1096d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 1097d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten 1098816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** Returns true if this view is faded out. */ 1099816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public boolean isFadedOut() { 1100816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mFadeState == FADED_OUT; 1101816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1102816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1103816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** Fade out this TunableTvView. Fade out by increasing the dimming. */ 1104816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void fadeOut(int durationMillis, TimeInterpolator interpolator, 1105816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko final Runnable actionAfterFade) { 1106816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.setAlpha(0f); 1107816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.setVisibility(View.VISIBLE); 1108816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.animate() 1109816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .alpha(1f) 1110816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .setDuration(durationMillis) 1111816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .setInterpolator(interpolator) 1112816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .withStartAction(new Runnable() { 1113816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 1114816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void run() { 1115816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mFadeState = FADING_OUT; 1116816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mActionAfterFade = actionAfterFade; 1117816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1118816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }) 1119816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .withEndAction(new Runnable() { 1120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 1121816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void run() { 1122816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mFadeState = FADED_OUT; 1123816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1124816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }); 1125816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1126816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1127816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** Fade in this TunableTvView. Fade in by decreasing the dimming. */ 1128816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void fadeIn(int durationMillis, TimeInterpolator interpolator, 1129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko final Runnable actionAfterFade) { 1130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.setAlpha(1f); 1131816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.setVisibility(View.VISIBLE); 1132816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.animate() 1133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .alpha(0f) 1134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .setDuration(durationMillis) 1135816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .setInterpolator(interpolator) 1136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .withStartAction(new Runnable() { 1137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 1138816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void run() { 1139816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mFadeState = FADING_IN; 1140816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mActionAfterFade = actionAfterFade; 1141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }) 1143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .withEndAction(new Runnable() { 1144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 1145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void run() { 1146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mFadeState = FADED_IN; 1147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.setVisibility(View.GONE); 1148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }); 1150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** Remove the fade effect. */ 1153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void removeFadeEffect() { 1154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.animate().cancel(); 1155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mDimScreenView.setVisibility(View.GONE); 1156816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mFadeState = FADED_IN; 1157816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1158816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1159816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1160816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Sets the TimeShiftListener 1161816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 1162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param listener The instance of {@link TimeShiftListener}. 1163816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1164816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void setTimeShiftListener(TimeShiftListener listener) { 1165816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTimeShiftListener = listener; 1166816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1167816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void setTimeShiftAvailable(boolean isTimeShiftAvailable) { 1169ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || mTimeShiftAvailable == isTimeShiftAvailable) { 1170816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 1171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTimeShiftAvailable = isTimeShiftAvailable; 1173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (isTimeShiftAvailable) { 117448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mTvView.setTimeShiftPositionCallback(new TvView.TimeShiftPositionCallback() { 1175816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 1176816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onTimeShiftStartPositionChanged(String inputId, long timeMs) { 1177816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTimeShiftListener != null && mCurrentChannel != null 1178816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko && mCurrentChannel.getInputId().equals(inputId)) { 1179816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTimeShiftListener.onRecordStartTimeChanged(timeMs); 1180816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1181816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1182816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1183816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 1184816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) { 1185816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTimeShiftCurrentPositionMs = timeMs; 1186816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1187816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }); 1188816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 1189816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.setTimeShiftPositionCallback(null); 1190816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTimeShiftListener != null) { 1192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTimeShiftListener.onAvailabilityChanged(); 1193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1194816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1195816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1196816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1197816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns if the time shift is available for the current channel. 1198816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1199816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public boolean isTimeShiftAvailable() { 1200816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mTimeShiftAvailable; 1201816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1202816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1203816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1204816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns the current time-shift state. It returns one of {@link #TIME_SHIFT_STATE_NONE}, 1205816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * {@link #TIME_SHIFT_STATE_PLAY}, {@link #TIME_SHIFT_STATE_PAUSE}, 1206816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * {@link #TIME_SHIFT_STATE_REWIND}, {@link #TIME_SHIFT_STATE_FAST_FORWARD} 1207816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * or {@link #TIME_SHIFT_STATE_PAUSE}. 1208816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1209816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @TimeShiftState public int getTimeShiftState() { 1210816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mTimeShiftState; 1211816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1212816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1213816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1214816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Plays the media, if the current input supports time-shifting. 1215816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1216816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void timeshiftPlay() { 1217ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 1218816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Time shifting is not supported in this platform."); 1219816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 1220816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1221816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!isTimeShiftAvailable()) { 1222816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalStateException("Time-shift is not supported for the current channel"); 1223816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1224816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTimeShiftState == TIME_SHIFT_STATE_PLAY) { 1225816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 1226816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1227816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.timeShiftResume(); 1228816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1229816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1230816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1231816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Pauses the media, if the current input supports time-shifting. 1232816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1233816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void timeshiftPause() { 1234ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 1235816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Time shifting is not supported in this platform."); 1236816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 1237816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1238816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!isTimeShiftAvailable()) { 1239816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalStateException("Time-shift is not supported for the current channel"); 1240816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1241816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTimeShiftState == TIME_SHIFT_STATE_PAUSE) { 1242816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 1243816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1244816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.timeShiftPause(); 1245816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1246816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1247816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1248816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Rewinds the media with the given speed, if the current input supports time-shifting. 1249816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 1250816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param speed The speed to rewind the media. e.g. 2 for 2x, 3 for 3x and 4 for 4x. 1251816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1252816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void timeshiftRewind(int speed) { 1253ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 1254816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Time shifting is not supported in this platform."); 1255ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } else if (!isTimeShiftAvailable()) { 1256816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalStateException("Time-shift is not supported for the current channel"); 1257ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } else { 1258ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (speed <= 0) { 1259ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko throw new IllegalArgumentException("The speed should be a positive integer."); 1260ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 1261ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mTimeShiftState = TIME_SHIFT_STATE_REWIND; 1262ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko PlaybackParams params = new PlaybackParams(); 1263ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko params.setSpeed(speed * -1); 1264ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mTvView.timeShiftSetPlaybackParams(params); 1265816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1266816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1267816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1268816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1269816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Fast-forwards the media with the given speed, if the current input supports time-shifting. 1270816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 1271816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param speed The speed to forward the media. e.g. 2 for 2x, 3 for 3x and 4 for 4x. 1272816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1273816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void timeshiftFastForward(int speed) { 1274ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 1275816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Time shifting is not supported in this platform."); 1276ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } else if (!isTimeShiftAvailable()) { 1277816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalStateException("Time-shift is not supported for the current channel"); 1278ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } else { 1279ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (speed <= 0) { 1280ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko throw new IllegalArgumentException("The speed should be a positive integer."); 1281ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 1282ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mTimeShiftState = TIME_SHIFT_STATE_FAST_FORWARD; 1283ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko PlaybackParams params = new PlaybackParams(); 1284ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko params.setSpeed(speed); 1285ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mTvView.timeShiftSetPlaybackParams(params); 1286816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1287816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1288816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1289816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1290816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Seek to the given time position. 1291816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 1292816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param timeMs The time in milliseconds to seek to. 1293816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1294816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void timeshiftSeekTo(long timeMs) { 1295ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 1296816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Time shifting is not supported in this platform."); 1297816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 1298816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1299816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!isTimeShiftAvailable()) { 1300816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalStateException("Time-shift is not supported for the current channel"); 1301816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1302816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTvView.timeShiftSeekTo(timeMs); 1303816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1304816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1305816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1306816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns the current playback position in milliseconds. 1307816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1308816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public long timeshiftGetCurrentPositionMs() { 1309ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 1310816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, "Time shifting is not supported in this platform."); 1311816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return INVALID_TIME; 1312816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1313816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!isTimeShiftAvailable()) { 1314816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalStateException("Time-shift is not supported for the current channel"); 1315816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1316816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (DEBUG) { 1317816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.d(TAG, "timeshiftGetCurrentPositionMs: current position =" 1318816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + Utils.toTimeString(mTimeShiftCurrentPositionMs)); 1319816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1320816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mTimeShiftCurrentPositionMs; 1321816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1322816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1323816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1324816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Used to receive the time-shift events. 1325816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1326816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static abstract class TimeShiftListener { 1327816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1328816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Called when the availability of the time-shift for the current channel has been changed. 1329816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * It should be guaranteed that this is called only when the availability is really changed. 1330816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1331816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public abstract void onAvailabilityChanged(); 1332816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1333816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1334ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Called when the record start time has been changed. 1335816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1336816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public abstract void onRecordStartTimeChanged(long recordStartTimeMs); 1337816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1338816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1339816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1340816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * A listener which receives the notification when the screen is blocked/unblocked. 1341816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1342816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static abstract class OnScreenBlockingChangedListener { 1343816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 1344816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Called when the screen is blocked/unblocked. 1345816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 1346816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public abstract void onScreenBlockingChanged(boolean blocked); 1347d82ca62a0fefaed41493540df7d622cfcfb2cb6cChristofer Åkersten } 134848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 134948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public class InternetCheckTask extends AsyncTask<Void, Void, Boolean> { 135048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho @Override 135148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho protected Boolean doInBackground(Void... params) { 135248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return NetworkUtils.isNetworkAvailable(mConnectivityManager); 135348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 135448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 135548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho @Override 135648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho protected void onPostExecute(Boolean networkAvailable) { 135748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mInternetCheckTask = null; 135848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (!mVideoAvailable && !networkAvailable && isAttachedToWindow() 135948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho && mVideoUnavailableReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN) { 136048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setImageVisibility(true); 136148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setImage(R.drawable.ic_sad_cloud); 136248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mHideScreenView.setText(R.string.tvview_msg_no_internet_connection); 136348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 136448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 136548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 1366900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho} 1367