1773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi/*
2773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Copyright (C) 2015 The Android Open Source Project
3773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
4773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * you may not use this file except in compliance with the License.
6773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * You may obtain a copy of the License at
7773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
8773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi *
10773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * See the License for the specific language governing permissions and
14773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * limitations under the License.
15773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi */
16773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi
17daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kastenpackage com.android.tv.guide;
18f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi
1975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Triviimport android.animation.Animator;
20773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Triviimport android.animation.ObjectAnimator;
21a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenimport android.animation.PropertyValuesHolder;
22a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenimport android.content.Context;
2375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Triviimport android.content.res.ColorStateList;
241ae30e37f39fcfe7937a707b789e49a7d68112baJean-Michel Triviimport android.content.res.Resources;
2505ccff2aaa3e1507cdc7ab3b244c973c6708e009Jean-Michel Triviimport android.graphics.Bitmap;
2613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.media.tv.TvContentRating;
2713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.media.tv.TvInputInfo;
2813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.os.Handler;
2913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.support.annotation.NonNull;
3013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.support.annotation.Nullable;
3113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.support.v7.widget.RecyclerView;
3213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.support.v7.widget.RecyclerView.RecycledViewPool;
3313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.text.Html;
3413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.text.Spannable;
3513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.text.SpannableString;
3613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.text.TextUtils;
3713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.text.style.TextAppearanceSpan;
3813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.util.Log;
3913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.util.TypedValue;
4013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.view.LayoutInflater;
4113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.view.View;
4213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.view.ViewGroup;
4313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.view.ViewParent;
4413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.view.ViewTreeObserver;
4513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.view.accessibility.AccessibilityManager;
4613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
4713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.widget.ImageView;
4813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.widget.LinearLayout;
4913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport android.widget.TextView;
5013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.R;
5113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.TvSingletons;
5213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.common.feature.CommonFeatures;
5313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.common.util.CommonUtils;
5413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.data.Program;
5513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.data.Program.CriticScore;
5613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.data.api.Channel;
5713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.dvr.DvrDataManager;
5813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.dvr.DvrManager;
5913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.dvr.data.ScheduledRecording;
6013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.guide.ProgramManager.TableEntriesUpdatedListener;
6113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.parental.ParentalControlSettings;
6213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.ui.HardwareLayerAnimatorListenerAdapter;
6313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.util.TvInputManagerHelper;
6413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.util.Utils;
6513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.util.images.ImageCache;
6613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.util.images.ImageLoader;
6713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.util.images.ImageLoader.ImageLoaderCallback;
6813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport com.android.tv.util.images.ImageLoader.LoadTvInputLogoTask;
6913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
7013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport java.util.ArrayList;
7113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviimport java.util.List;
7213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
7313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi/** Adapts the {@link ProgramListAdapter} list to the body of the program guide table. */
7413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviclass ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapter.ProgramRowViewHolder>
7513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        implements ProgramManager.TableEntryChangedListener {
7613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private static final String TAG = "ProgramTableAdapter";
7713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private static final boolean DEBUG = false;
7813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
7913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final Context mContext;
8013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final TvInputManagerHelper mTvInputManagerHelper;
8113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final DvrManager mDvrManager;
8213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final DvrDataManager mDvrDataManager;
8313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final ProgramManager mProgramManager;
8413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final AccessibilityManager mAccessibilityManager;
8513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final ProgramGuide mProgramGuide;
8613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final Handler mHandler = new Handler();
8713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final List<ProgramListAdapter> mProgramListAdapters = new ArrayList<>();
8813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final RecycledViewPool mRecycledViewPool;
8913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    // views to be be reused when displaying critic scores
9013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final List<LinearLayout> mCriticScoreViews;
9113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
9213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mChannelLogoWidth;
9313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mChannelLogoHeight;
94e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi    private final int mImageWidth;
9513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mImageHeight;
9613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final String mProgramTitleForNoInformation;
9713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final String mProgramTitleForBlockedChannel;
9813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mChannelTextColor;
9913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mChannelBlockedTextColor;
10013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mDetailTextColor;
10113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mDetailGrayedTextColor;
10213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mAnimationDuration;
10313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mDetailPadding;
10413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final TextAppearanceSpan mEpisodeTitleStyle;
10513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final String mProgramRecordableText;
10613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final String mRecordingScheduledText;
10713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final String mRecordingConflictText;
10813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final String mRecordingFailedText;
10913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final String mRecordingInProgressText;
11013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mDvrPaddingStartWithTrack;
11113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private final int mDvrPaddingStartWithOutTrack;
11213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
11313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    ProgramTableAdapter(Context context, ProgramGuide programGuide) {
11413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mContext = context;
11513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mAccessibilityManager =
11613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
11713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mTvInputManagerHelper = TvSingletons.getSingletons(context).getTvInputManagerHelper();
11813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        if (CommonFeatures.DVR.isEnabled(context)) {
11913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mDvrManager = TvSingletons.getSingletons(context).getDvrManager();
12013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mDvrDataManager = TvSingletons.getSingletons(context).getDvrDataManager();
12113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        } else {
12213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mDvrManager = null;
12313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mDvrDataManager = null;
12413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        }
12513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mProgramGuide = programGuide;
12613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mProgramManager = programGuide.getProgramManager();
12713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
12813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        Resources res = context.getResources();
12913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mChannelLogoWidth =
13013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                res.getDimensionPixelSize(
13113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        R.dimen.program_guide_table_header_column_channel_logo_width);
13213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mChannelLogoHeight =
13313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                res.getDimensionPixelSize(
13413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        R.dimen.program_guide_table_header_column_channel_logo_height);
13513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mImageWidth = res.getDimensionPixelSize(R.dimen.program_guide_table_detail_image_width);
13613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mImageHeight = res.getDimensionPixelSize(R.dimen.program_guide_table_detail_image_height);
13713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mProgramTitleForNoInformation = res.getString(R.string.program_title_for_no_information);
13813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mProgramTitleForBlockedChannel = res.getString(R.string.program_title_for_blocked_channel);
13913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mChannelTextColor =
14013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                res.getColor(
14113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        R.color.program_guide_table_header_column_channel_number_text_color, null);
14213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mChannelBlockedTextColor =
14313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                res.getColor(
14413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        R.color.program_guide_table_header_column_channel_number_blocked_text_color,
14513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        null);
14613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mDetailTextColor = res.getColor(R.color.program_guide_table_detail_title_text_color, null);
14713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mDetailGrayedTextColor =
14813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                res.getColor(R.color.program_guide_table_detail_title_grayed_text_color, null);
14913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mAnimationDuration =
15013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                res.getInteger(R.integer.program_guide_table_detail_fade_anim_duration);
15113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        mDetailPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_detail_padding);
152a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mProgramRecordableText = res.getString(R.string.dvr_epg_program_recordable);
153a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mRecordingScheduledText = res.getString(R.string.dvr_epg_program_recording_scheduled);
154a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mRecordingConflictText = res.getString(R.string.dvr_epg_program_recording_conflict);
155a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mRecordingFailedText = res.getString(R.string.dvr_epg_program_recording_failed);
156a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mRecordingInProgressText = res.getString(R.string.dvr_epg_program_recording_in_progress);
157a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mDvrPaddingStartWithTrack =
158a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                res.getDimensionPixelOffset(R.dimen.program_guide_table_detail_dvr_margin_start);
159a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mDvrPaddingStartWithOutTrack =
160a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                res.getDimensionPixelOffset(
161a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                        R.dimen.program_guide_table_detail_dvr_margin_start_without_track);
162a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi
163a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        int episodeTitleSize =
164a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                res.getDimensionPixelSize(
165a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                        R.dimen.program_guide_table_detail_episode_title_text_size);
166a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        ColorStateList episodeTitleColor =
167a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                ColorStateList.valueOf(
168a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                        res.getColor(
169a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                                R.color.program_guide_table_detail_episode_title_text_color, null));
170a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi        mEpisodeTitleStyle =
171a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                new TextAppearanceSpan(null, 0, episodeTitleSize, episodeTitleColor, null);
172a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi
1736a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi        mCriticScoreViews = new ArrayList<>();
1746a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi        mRecycledViewPool = new RecycledViewPool();
175712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi        mRecycledViewPool.setMaxRecycledViews(
176712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi                R.layout.program_guide_table_item,
1771fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi                context.getResources().getInteger(R.integer.max_recycled_view_pool_epg_table_item));
1781fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        mProgramManager.addListener(
1796a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi                new ProgramManager.ListenerAdapter() {
180d739e18bea1deaf7c487f99a512c0ae7649615c2Jean-Michel Trivi                    @Override
1816a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi                    public void onChannelsUpdated() {
1826a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi                        update();
1834614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    }
1844614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                });
18545d40b8ac4cd8f3f73813a26334c7e5ecc3cb73cJean-Michel Trivi        update();
1861fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        mProgramManager.addTableEntryChangedListener(this);
1871fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    }
1881fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi
1891fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    private void update() {
1904614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        if (DEBUG) Log.d(TAG, "update " + mProgramManager.getChannelCount() + " channels");
1911fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        for (TableEntriesUpdatedListener listener : mProgramListAdapters) {
1921fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi            mProgramManager.removeTableEntriesUpdatedListener(listener);
1931fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        }
1941fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        mProgramListAdapters.clear();
1951fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        for (int i = 0; i < mProgramManager.getChannelCount(); i++) {
196e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten            ProgramListAdapter listAdapter =
197b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten                    new ProgramListAdapter(mContext.getResources(), mProgramGuide, i);
1981fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi            mProgramManager.addTableEntriesUpdatedListener(listAdapter);
1991fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi            mProgramListAdapters.add(listAdapter);
2001fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        }
2011fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        notifyDataSetChanged();
202b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten    }
2031fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi
2041fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    @Override
2051fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    public int getItemCount() {
2061fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        return mProgramListAdapters.size();
207b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten    }
2081fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi
2091fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    @Override
2101fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    public int getItemViewType(int position) {
2111fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        return R.layout.program_guide_table_row;
2121fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    }
2131fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi
2141fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    @Override
2151fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    public void onBindViewHolder(ProgramRowViewHolder holder, int position) {
2161fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        holder.onBind(position);
217b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten    }
2181fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi
2191fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    @Override
2201fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    public void onBindViewHolder(ProgramRowViewHolder holder, int position, List<Object> payloads) {
2211fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        if (!payloads.isEmpty()) {
222b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten            holder.updateDetailView();
2231fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        } else {
2241fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi            super.onBindViewHolder(holder, position, payloads);
2251fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        }
2261fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    }
227b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten
2281fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    @Override
2291fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    public ProgramRowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
2301fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        View itemView = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
2311fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        ProgramRow programRow = (ProgramRow) itemView.findViewById(R.id.row);
2321fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        programRow.setRecycledViewPool(mRecycledViewPool);
2331fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        return new ProgramRowViewHolder(itemView);
2341fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    }
2351fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi
2361fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi    @Override
2376a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi    public void onTableEntryChanged(ProgramManager.TableEntry tableEntry) {
2386a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi        int channelIndex = mProgramManager.getChannelIndex(tableEntry.channelId);
239172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        int pos = mProgramManager.getProgramIdIndex(tableEntry.channelId, tableEntry.getId());
240172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        if (DEBUG) Log.d(TAG, "update(" + channelIndex + ", " + pos + ")");
241ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi        mProgramListAdapters.get(channelIndex).notifyItemChanged(pos, tableEntry);
242172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        notifyItemChanged(channelIndex, true);
243172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi    }
244a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi
245f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi    class ProgramRowViewHolder extends RecyclerView.ViewHolder
2461fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi            implements ProgramRow.ChildFocusListener {
247f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi
24845d40b8ac4cd8f3f73813a26334c7e5ecc3cb73cJean-Michel Trivi        private final ViewGroup mContainer;
249f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi        private final ProgramRow mProgramRow;
2501fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi        private ProgramManager.TableEntry mSelectedEntry;
251e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        private Animator mDetailOutAnimator;
252e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        private Animator mDetailInAnimator;
253f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi        private final Runnable mDetailInStarter =
254f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                new Runnable() {
2551fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi                    @Override
256e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten                    public void run() {
257e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten                        mProgramRow.removeOnScrollListener(mOnScrollListener);
2586a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi                        if (mDetailInAnimator != null) {
259e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten                            mDetailInAnimator.start();
260e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten                        }
2616a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi                    }
2626a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi                };
263e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        private final Runnable mUpdateDetailViewRunnable =
264e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten                new Runnable() {
265f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                    @Override
266f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                    public void run() {
2671fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi                        updateDetailView();
268ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                    }
269ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                };
270ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi
271ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi        private final RecyclerView.OnScrollListener mOnScrollListener =
272ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                new RecyclerView.OnScrollListener() {
273ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                    @Override
274ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
275ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                        onHorizontalScrolled();
276ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                    }
277ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                };
278ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi
279ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi        private final ViewTreeObserver.OnGlobalFocusChangeListener mGlobalFocusChangeListener =
280ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                new ViewTreeObserver.OnGlobalFocusChangeListener() {
281ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                    @Override
282ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                    public void onGlobalFocusChanged(View oldFocus, View newFocus) {
283ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                        onChildFocus(
284ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                                GuideUtils.isDescendant(mContainer, oldFocus) ? oldFocus : null,
2854614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                                GuideUtils.isDescendant(mContainer, newFocus) ? newFocus : null);
2864614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    }
2874614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                };
288e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi
28949e4076e940559bc204d0f0aa7ab412986445bfaGlenn Kasten        // Members of Program Details
2904614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ViewGroup mDetailView;
2914614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ImageView mImageView;
2924614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ImageView mBlockView;
2934614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mTitleView;
2944614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mTimeView;
2954614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final LinearLayout mCriticScoresLayout;
2964614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mDescriptionView;
2974614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mAspectRatioView;
2984614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mResolutionView;
2994614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ImageView mDvrIconView;
3004614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mDvrTextIconView;
3014614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mDvrStatusView;
3024614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ViewGroup mDvrIndicator;
3034614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi
3044614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        // Members of Channel Header
305e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi        private Channel mChannel;
30649e4076e940559bc204d0f0aa7ab412986445bfaGlenn Kasten        private final View mChannelHeaderView;
3074614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mChannelNumberView;
3084614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final TextView mChannelNameView;
3094614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ImageView mChannelLogoView;
3104614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ImageView mChannelBlockView;
3114614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private final ImageView mInputLogoView;
3124614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi
3134614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private boolean mIsInputLogoVisible;
3144614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        private AccessibilityStateChangeListener mAccessibilityStateChangeListener =
3154614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                new AccessibilityManager.AccessibilityStateChangeListener() {
3164614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    @Override
3174614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    public void onAccessibilityStateChanged(boolean enable) {
3184614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                        enable &= !CommonUtils.isRunningInTest();
3194614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                        mChannelHeaderView.setFocusable(enable);
3204614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    }
3214614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                };
3224614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi
323e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi        ProgramRowViewHolder(View itemView) {
3244614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi            super(itemView);
3254614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi
3264614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi            mContainer = (ViewGroup) itemView;
3274614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi            mContainer.addOnAttachStateChangeListener(
3284614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    new View.OnAttachStateChangeListener() {
3294614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                        @Override
3304614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                        public void onViewAttachedToWindow(View v) {
3314614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                            mContainer
3324614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                                    .getViewTreeObserver()
3334614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                                    .addOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
3344614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                            mAccessibilityManager.addAccessibilityStateChangeListener(
335f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                                    mAccessibilityStateChangeListener);
336f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                        }
337f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi
33824430c9070298f12e68b84c921add38da6ad0490Jean-Michel Trivi                        @Override
339e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                        public void onViewDetachedFromWindow(View v) {
340e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                            mContainer
341e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                                    .getViewTreeObserver()
342e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                                    .removeOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
343e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                            mAccessibilityManager.removeAccessibilityStateChangeListener(
344e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                                    mAccessibilityStateChangeListener);
345e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                        }
346e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi                    });
347e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mProgramRow = (ProgramRow) mContainer.findViewById(R.id.row);
348e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi
349e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mDetailView = (ViewGroup) mContainer.findViewById(R.id.detail);
350e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mImageView = (ImageView) mDetailView.findViewById(R.id.image);
351e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mBlockView = (ImageView) mDetailView.findViewById(R.id.block);
352e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mTitleView = (TextView) mDetailView.findViewById(R.id.title);
353fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            mTimeView = (TextView) mDetailView.findViewById(R.id.time);
354fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            mDescriptionView = (TextView) mDetailView.findViewById(R.id.desc);
35525d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi            mAspectRatioView = (TextView) mDetailView.findViewById(R.id.aspect_ratio);
35625d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi            mResolutionView = (TextView) mDetailView.findViewById(R.id.resolution);
357e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mDvrIconView = (ImageView) mDetailView.findViewById(R.id.dvr_icon);
358e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mDvrTextIconView = (TextView) mDetailView.findViewById(R.id.dvr_text_icon);
359e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mDvrStatusView = (TextView) mDetailView.findViewById(R.id.dvr_status);
360fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            mDvrIndicator = (ViewGroup) mContainer.findViewById(R.id.dvr_indicator);
361ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi            mCriticScoresLayout = (LinearLayout) mDetailView.findViewById(R.id.critic_scores);
362fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten
363e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mChannelHeaderView = mContainer.findViewById(R.id.header_column);
364e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mChannelNumberView = (TextView) mContainer.findViewById(R.id.channel_number);
365e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mChannelNameView = (TextView) mContainer.findViewById(R.id.channel_name);
366e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mChannelLogoView = (ImageView) mContainer.findViewById(R.id.channel_logo);
36725d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi            mChannelBlockView = (ImageView) mContainer.findViewById(R.id.channel_block);
368ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi            mInputLogoView = (ImageView) mContainer.findViewById(R.id.input_logo);
369ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi
370ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi            boolean accessibilityEnabled =
371ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi                    mAccessibilityManager.isEnabled() && !CommonUtils.isRunningInTest();
372fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            mChannelHeaderView.setFocusable(accessibilityEnabled);
373e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi        }
374e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi
375e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi        public void onBind(int position) {
376e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            onBindChannel(mProgramManager.getChannel(position));
37725d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi
378e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mProgramRow.swapAdapter(mProgramListAdapters.get(position), true);
379e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi            mProgramRow.setProgramGuide(mProgramGuide);
380a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mProgramRow.setChannel(mProgramManager.getChannel(position));
381a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mProgramRow.setChildFocusListener(this);
382a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mProgramRow.resetScroll(mProgramGuide.getTimelineRowScrollOffset());
383a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi
384a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mDetailView.setVisibility(View.GONE);
385a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi
386a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            // The bottom-left of the last channel header view will have a rounded corner.
387a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mChannelHeaderView.setBackgroundResource(
388a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                    (position < mProgramListAdapters.size() - 1)
389fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten                            ? R.drawable.program_guide_table_header_column_item_background
390fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten                            : R.drawable.program_guide_table_header_column_last_item_background);
391a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi        }
392a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi
393a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi        private void onBindChannel(Channel channel) {
394fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            if (DEBUG) Log.d(TAG, "onBindChannel " + channel);
395fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten
396fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            mChannel = channel;
397a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mInputLogoView.setVisibility(View.GONE);
398a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mIsInputLogoVisible = false;
399a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            if (channel == null) {
400a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                mChannelNumberView.setVisibility(View.GONE);
401a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                mChannelNameView.setVisibility(View.GONE);
402a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                mChannelLogoView.setVisibility(View.GONE);
403a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                mChannelBlockView.setVisibility(View.GONE);
404a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                return;
405a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            }
406fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten
407fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            String displayNumber = channel.getDisplayNumber();
408fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten            if (displayNumber == null) {
409a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                mChannelNumberView.setVisibility(View.GONE);
410a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            } else {
411a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                int size;
412a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                if (displayNumber.length() <= 4) {
413a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                    size = R.dimen.program_guide_table_header_column_channel_number_large_font_size;
414a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                } else {
415a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                    size = R.dimen.program_guide_table_header_column_channel_number_small_font_size;
416a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                }
417f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                mChannelNumberView.setTextSize(
41875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        TypedValue.COMPLEX_UNIT_PX,
41975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        mChannelNumberView.getContext().getResources().getDimension(size));
42075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannelNumberView.setText(displayNumber);
42175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannelNumberView.setVisibility(View.VISIBLE);
42275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            }
42375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            mChannelNumberView.setTextColor(
42475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    isChannelLocked(channel) ? mChannelBlockedTextColor : mChannelTextColor);
42575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi
42675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            mChannelLogoView.setImageBitmap(null);
42775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            mChannelLogoView.setVisibility(View.GONE);
42875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            if (isChannelLocked(channel)) {
42975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannelNameView.setVisibility(View.GONE);
43075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannelBlockView.setVisibility(View.VISIBLE);
43175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            } else {
43275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannelNameView.setText(channel.getDisplayName());
43375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannelNameView.setVisibility(View.VISIBLE);
43475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannelBlockView.setVisibility(View.GONE);
43575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi
43675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mChannel.loadBitmap(
43775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        itemView.getContext(),
43875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        Channel.LOAD_IMAGE_TYPE_CHANNEL_LOGO,
43975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        mChannelLogoWidth,
44075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        mChannelLogoHeight,
44175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        createChannelLogoLoadedCallback(this, channel.getId()));
44275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            }
44375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        }
44475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi
44575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        @Override
44675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        public void onChildFocus(View oldFocus, View newFocus) {
44775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            if (newFocus == null) {
44875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                return;
44975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            } // When the accessibility service is enabled, focus might be put on channel's header
4505f71e35da153d194d805e030ab38935599e065d2Jean-Michel Trivi            // or
45175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            // detail view, besides program items.
45275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            if (newFocus == mChannelHeaderView) {
45375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mSelectedEntry = ((ProgramItemView) mProgramRow.getChildAt(0)).getTableEntry();
45475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            } else if (newFocus == mDetailView) {
45575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                return;
45675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            } else {
45775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mSelectedEntry = ((ProgramItemView) newFocus).getTableEntry();
45875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            }
45975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            if (oldFocus == null) {
46075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                // Focus moved from other row.
46175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                if (mProgramGuide.getProgramGrid().isInLayout()) {
46275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    // We need to post runnable to avoid updating detail view when
46375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    // the recycler view is in layout, which may cause detail view not
46475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    // laid out according to the updated contents.
46575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    mHandler.post(mUpdateDetailViewRunnable);
46675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                } else {
46775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    updateDetailView();
46875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                }
46975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                return;
47075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            }
47175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi
47275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            if (Program.isProgramValid(mSelectedEntry.program)) {
47375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                Program program = mSelectedEntry.program;
47475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                if (getProgramBlock(program) == null) {
47575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    program.prefetchPosterArt(itemView.getContext(), mImageWidth, mImageHeight);
47675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                }
47775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            }
47875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi
47975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            // -1 means the selection goes rightwards and 1 goes leftwards
48075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            int direction = oldFocus.getLeft() < newFocus.getLeft() ? -1 : 1;
48175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            View detailContentView = mDetailView.findViewById(R.id.detail_content);
48275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi
48375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            if (mDetailInAnimator == null) {
48475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mDetailOutAnimator =
48575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        ObjectAnimator.ofPropertyValuesHolder(
48675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                                detailContentView,
48775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                                PropertyValuesHolder.ofFloat(View.ALPHA, 1f, 0f),
48875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                                PropertyValuesHolder.ofFloat(
48975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                                        View.TRANSLATION_X, 0f, direction * mDetailPadding));
49075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mDetailOutAnimator.setDuration(mAnimationDuration);
49175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                mDetailOutAnimator.addListener(
49275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                        new HardwareLayerAnimatorListenerAdapter(detailContentView) {
49375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                            @Override
49475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                            public void onAnimationEnd(Animator animator) {
49575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                                super.onAnimationEnd(animator);
496f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi                                mDetailOutAnimator = null;
497f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi                                mHandler.removeCallbacks(mDetailInStarter);
498f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi                                mHandler.postDelayed(mDetailInStarter, mAnimationDuration);
499f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi                            }
500f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi                        });
501f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi
502f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi                mProgramRow.addOnScrollListener(mOnScrollListener);
503f7b852d914faa49d3e4b7d02bb5d9d254762c0b7Jean-Michel Trivi                mDetailOutAnimator.start();
50413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            } else {
50513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (mDetailInAnimator.isStarted()) {
50613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    mDetailInAnimator.cancel();
50713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    detailContentView.setAlpha(0);
50813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                }
50913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
51013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                mHandler.removeCallbacks(mDetailInStarter);
51113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                mHandler.postDelayed(mDetailInStarter, mAnimationDuration);
51213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            }
51313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
51413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mDetailInAnimator =
51513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    ObjectAnimator.ofPropertyValuesHolder(
51613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            detailContentView,
51713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            PropertyValuesHolder.ofFloat(View.ALPHA, 0f, 1f),
51813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            PropertyValuesHolder.ofFloat(
51913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    View.TRANSLATION_X, direction * -mDetailPadding, 0f));
52013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mDetailInAnimator.setDuration(mAnimationDuration);
52113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mDetailInAnimator.addListener(
52213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    new HardwareLayerAnimatorListenerAdapter(detailContentView) {
52313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        @Override
52413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        public void onAnimationStart(Animator animator) {
52513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            super.onAnimationStart(animator);
52613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            updateDetailView();
52713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        }
52813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
52913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        @Override
53013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        public void onAnimationEnd(Animator animator) {
53113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            super.onAnimationEnd(animator);
53213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            mDetailInAnimator = null;
53313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        }
53413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    });
53513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        }
53613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
53713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        private void updateDetailView() {
53813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            if (mSelectedEntry == null) {
53913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                // The view holder is never on focus before.
54013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                return;
54113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            }
54213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            if (DEBUG) Log.d(TAG, "updateDetailView");
54313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mCriticScoresLayout.removeAllViews();
54413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            if (Program.isProgramValid(mSelectedEntry.program)) {
54513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                mTitleView.setTextColor(mDetailTextColor);
54613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                Context context = itemView.getContext();
54713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                Program program = mSelectedEntry.program;
54813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
54913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                TvContentRating blockedRating = getProgramBlock(program);
55013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
55113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                updatePosterArt(null);
55213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (blockedRating == null) {
55313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    program.loadPosterArt(
55413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            context,
55513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            mImageWidth,
55613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            mImageHeight,
55713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            createProgramPosterArtCallback(this, program));
55813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                }
55913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
56013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                String episodeTitle = program.getEpisodeDisplayTitle(mContext);
56113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (TextUtils.isEmpty(episodeTitle)) {
56213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    mTitleView.setText(program.getTitle());
56313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                } else {
56413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    String title = program.getTitle();
56513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    String fullTitle = title + "  " + episodeTitle;
56613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
56713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    SpannableString text = new SpannableString(fullTitle);
56813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    text.setSpan(
56913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            mEpisodeTitleStyle,
57013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            fullTitle.length() - episodeTitle.length(),
57113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            fullTitle.length(),
57213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
57313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    mTitleView.setText(text);
57413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                }
57513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
57613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                updateTextView(
57713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        mTimeView,
57813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        Utils.getDurationString(
57913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                context,
58013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                program.getStartTimeUtcMillis(),
58113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                program.getEndTimeUtcMillis(),
58213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                false));
58313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
58413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                boolean trackMetaDataVisible =
58513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        updateTextView(
58613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                mAspectRatioView,
58713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                Utils.getAspectRatioString(
58813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                        program.getVideoWidth(), program.getVideoHeight()));
58913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
59013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                int videoDefinitionLevel =
59113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        Utils.getVideoDefinitionLevelFromSize(
59213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                program.getVideoWidth(), program.getVideoHeight());
59313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                trackMetaDataVisible |=
59413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        updateTextView(
59513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                mResolutionView,
59613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                Utils.getVideoDefinitionLevelString(context, videoDefinitionLevel));
59713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
59813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (mDvrManager != null && mDvrManager.isProgramRecordable(program)) {
59913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    ScheduledRecording scheduledRecording =
60013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            mDvrDataManager.getScheduledRecordingForProgramId(program.getId());
60113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    String statusText = mProgramRecordableText;
60213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    int iconResId = 0;
60313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    if (scheduledRecording != null) {
60413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        if (mDvrManager.isConflicting(scheduledRecording)) {
60513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            iconResId = R.drawable.ic_warning_white_12dp;
60613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            statusText = mRecordingConflictText;
60713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        } else {
60813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            switch (scheduledRecording.getState()) {
60913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                case ScheduledRecording.STATE_RECORDING_IN_PROGRESS:
61013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    iconResId = R.drawable.ic_recording_program;
61113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    statusText = mRecordingInProgressText;
61213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    break;
61313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                case ScheduledRecording.STATE_RECORDING_NOT_STARTED:
61413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    iconResId = R.drawable.ic_scheduled_white;
61513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    statusText = mRecordingScheduledText;
61613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    break;
61713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                case ScheduledRecording.STATE_RECORDING_FAILED:
61813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    iconResId = R.drawable.ic_warning_white_12dp;
61913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    statusText = mRecordingFailedText;
62013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    break;
62113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                default:
62213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                                    iconResId = 0;
62313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                            }
62413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        }
62513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    }
62613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    if (iconResId == 0) {
62713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        mDvrIconView.setVisibility(View.GONE);
6288a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                        mDvrTextIconView.setVisibility(View.VISIBLE);
6298a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                    } else {
6308a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                        mDvrTextIconView.setVisibility(View.GONE);
6318a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                        mDvrIconView.setImageResource(iconResId);
6328a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                        mDvrIconView.setVisibility(View.VISIBLE);
6338a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                    }
6343ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    if (!trackMetaDataVisible) {
6353ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                        mDvrIndicator.setPaddingRelative(mDvrPaddingStartWithOutTrack, 0, 0, 0);
6363ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    } else {
6373ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                        mDvrIndicator.setPaddingRelative(mDvrPaddingStartWithTrack, 0, 0, 0);
6383ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    }
6393ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    mDvrIndicator.setVisibility(View.VISIBLE);
640de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                    mDvrStatusView.setText(statusText);
6413ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                } else {
64237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi                    mDvrIndicator.setVisibility(View.GONE);
643de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                }
644de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi
645de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                if (blockedRating == null) {
646f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                    mBlockView.setVisibility(View.GONE);
647de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                    updateTextView(mDescriptionView, program.getDescription());
64824430c9070298f12e68b84c921add38da6ad0490Jean-Michel Trivi                } else {
649de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                    mBlockView.setVisibility(View.VISIBLE);
650f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi                    updateTextView(mDescriptionView, getBlockedDescription(blockedRating));
65168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi                }
6523ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi            } else {
653581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                mTitleView.setTextColor(mDetailGrayedTextColor);
654f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                if (mSelectedEntry.isBlocked()) {
655f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                    updateTextView(mTitleView, mProgramTitleForBlockedChannel);
6563ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                } else {
6573ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    updateTextView(mTitleView, mProgramTitleForNoInformation);
6583ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                }
6593ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                mImageView.setVisibility(View.GONE);
6603ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                mBlockView.setVisibility(View.GONE);
661f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                mTimeView.setVisibility(View.GONE);
662f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                mDvrIndicator.setVisibility(View.GONE);
663f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                mDescriptionView.setVisibility(View.GONE);
664f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                mAspectRatioView.setVisibility(View.GONE);
665f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                mResolutionView.setVisibility(View.GONE);
666f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            }
667f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi        }
668f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi
669f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi        private TvContentRating getProgramBlock(Program program) {
670f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            ParentalControlSettings parental = mTvInputManagerHelper.getParentalControlSettings();
671f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            if (!parental.isParentalControlsEnabled()) {
672f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                return null;
673f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            }
674f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            return parental.getBlockedRating(program.getContentRatings());
675f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi        }
676f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi
677f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi        private boolean isChannelLocked(Channel channel) {
678f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            return mTvInputManagerHelper.getParentalControlSettings().isParentalControlsEnabled()
679f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                    && channel.isLocked();
680f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi        }
681f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi
682f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi        private String getBlockedDescription(TvContentRating blockedRating) {
683f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            String name =
684f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                    mTvInputManagerHelper
685f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                            .getContentRatingsManager()
686f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                            .getDisplayNameForRating(blockedRating);
687f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            if (TextUtils.isEmpty(name)) {
688f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                return mContext.getString(R.string.program_guide_content_locked);
689f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            } else {
690f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                return TvContentRating.UNRATED.equals(blockedRating)
691f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                        ? mContext.getString(R.string.program_guide_content_locked_unrated)
6923ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                        : mContext.getString(R.string.program_guide_content_locked_format, name);
693f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            }
694f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi        }
695b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi
696581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi        /**
697581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi         * Update tv input logo. It should be called when the visible child item in ProgramGrid
698581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi         * changed.
699581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi         */
700581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi        void updateInputLogo(int lastPosition, boolean forceShow) {
701581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi            if (mChannel == null) {
702581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                mInputLogoView.setVisibility(View.GONE);
703581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                mIsInputLogoVisible = false;
704581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                return;
705581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi            }
70613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
70713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            boolean showLogo = forceShow;
70813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            if (!showLogo) {
709e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi                Channel lastChannel = mProgramManager.getChannel(lastPosition);
710581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi                if (lastChannel == null
71124430c9070298f12e68b84c921add38da6ad0490Jean-Michel Trivi                        || !mChannel.getInputId().equals(lastChannel.getInputId())) {
7123ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    showLogo = true;
713f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi                }
714f536948a85be5e3f3731b64b01cfacdf90ed1157Jean-Michel Trivi            }
7153ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi
7163ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi            if (showLogo) {
71713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (!mIsInputLogoVisible) {
71813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    mIsInputLogoVisible = true;
7193ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    TvInputInfo info = mTvInputManagerHelper.getTvInputInfo(mChannel.getInputId());
72013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    if (info != null) {
7215d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                        LoadTvInputLogoTask task =
72296ad4989121d0119d47e4ff14f5c3341eafd64bdGlenn Kasten                                new LoadTvInputLogoTask(
72396ad4989121d0119d47e4ff14f5c3341eafd64bdGlenn Kasten                                        itemView.getContext(), ImageCache.getInstance(), info);
72496ad4989121d0119d47e4ff14f5c3341eafd64bdGlenn Kasten                        ImageLoader.loadBitmap(createTvInputLogoLoadedCallback(info, this), task);
72596ad4989121d0119d47e4ff14f5c3341eafd64bdGlenn Kasten                    }
7265d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                }
7275d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi            } else {
7285d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                mInputLogoView.setVisibility(View.GONE);
7295d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                mInputLogoView.setImageDrawable(null);
7305d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                mIsInputLogoVisible = false;
7315d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi            }
7325d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi        }
73396ad4989121d0119d47e4ff14f5c3341eafd64bdGlenn Kasten
7345d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi        // The return value of this method will indicate the target view is visible (true)
7355d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi        // or gone (false).
7365d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi        private boolean updateTextView(TextView textView, String text) {
7375d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi            if (!TextUtils.isEmpty(text)) {
7385d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                textView.setVisibility(View.VISIBLE);
7395d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                textView.setText(text);
7405d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                return true;
7415d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi            } else {
7425d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                textView.setVisibility(View.GONE);
7435d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi                return false;
7445d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi            }
74513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        }
74613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
7475d9a1aa19d218c9e4ed22d4d773471c01362442eJean-Michel Trivi        private void updatePosterArt(@Nullable Bitmap posterArt) {
74813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            mImageView.setImageBitmap(posterArt);
749a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            mImageView.setVisibility(posterArt == null ? View.GONE : View.VISIBLE);
750a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi        }
751a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi
752ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi        private void updateChannelLogo(@Nullable Bitmap logo) {
753ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi            mChannelLogoView.setImageBitmap(logo);
7548a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi            mChannelNameView.setVisibility(View.GONE);
755ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi            mChannelLogoView.setVisibility(View.VISIBLE);
756ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi        }
757ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi
758ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi        private void updateInputLogoInternal(@NonNull Bitmap tvInputLogo) {
759ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi            if (!mIsInputLogoVisible) {
760ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi                return;
761ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi            }
762ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi            mInputLogoView.setImageBitmap(tvInputLogo);
7638a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi            mInputLogoView.setVisibility(View.VISIBLE);
764ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi        }
765ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi
766ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi        private void updateCriticScoreView(
767ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi                ProgramRowViewHolder holder,
768ff037a1f697a15fb4249e62fe783f22398572cbeJean-Michel Trivi                final long programId,
76913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                CriticScore criticScore,
77013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                View view) {
771de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi            TextView criticScoreSource = (TextView) view.findViewById(R.id.critic_score_source);
77213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            TextView criticScoreText = (TextView) view.findViewById(R.id.critic_score_score);
773a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            ImageView criticScoreLogo = (ImageView) view.findViewById(R.id.critic_score_logo);
774a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi
775a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            // set the appropriate information in the views
77606a1b91fb42d3ecc9da725e673b56ca849b9b9a4Jean-Michel Trivi            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
777de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                criticScoreSource.setText(
7788a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                        Html.fromHtml(criticScore.source, Html.FROM_HTML_MODE_LEGACY));
779de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi            } else {
7808a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi                criticScoreSource.setText(Html.fromHtml(criticScore.source));
781de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi            }
782de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi            criticScoreText.setText(criticScore.score);
783de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi            criticScoreSource.setVisibility(View.VISIBLE);
784de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi            criticScoreText.setVisibility(View.VISIBLE);
7854614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi            ImageLoader.loadBitmap(
786de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                    mContext,
7874614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    criticScore.logoUrl,
7884614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                    createCriticScoreLogoCallback(holder, programId, criticScoreLogo));
7894614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi        }
7904614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi
791de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi        private void onHorizontalScrolled() {
7924614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi            if (mDetailInAnimator != null) {
7934614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi                mHandler.removeCallbacks(mDetailInStarter);
794de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                mHandler.postDelayed(mDetailInStarter, mAnimationDuration);
7958a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi            }
7968a1b7f28c1c3de212a302182022310ab7b227788Jean-Michel Trivi        }
797de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi    }
79806a1b91fb42d3ecc9da725e673b56ca849b9b9a4Jean-Michel Trivi
799de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi    private static ImageLoaderCallback<ProgramRowViewHolder> createCriticScoreLogoCallback(
80006a1b91fb42d3ecc9da725e673b56ca849b9b9a4Jean-Michel Trivi            ProgramRowViewHolder holder, final long programId, ImageView logoView) {
80113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
80213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            @Override
803de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logoImage) {
80413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (logoImage == null
805fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten                        || holder.mSelectedEntry == null
80624430c9070298f12e68b84c921add38da6ad0490Jean-Michel Trivi                        || holder.mSelectedEntry.program == null
8073ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                        || holder.mSelectedEntry.program.getId() != programId) {
8083ddf7a34cc617e52a9b9a5593a0d1c5ef8d22bd9Jean-Michel Trivi                    logoView.setVisibility(View.GONE);
80913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                } else {
81013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    logoView.setImageBitmap(logoImage);
811de16b4c2bc71c163c7c821a475a53a3b567789b2Jean-Michel Trivi                    logoView.setVisibility(View.VISIBLE);
8126a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi                }
8136a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi            }
8146a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi        };
815a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi    }
816a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi
81775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi    private static ImageLoaderCallback<ProgramRowViewHolder> createProgramPosterArtCallback(
818a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi            ProgramRowViewHolder holder, final Program program) {
819d739e18bea1deaf7c487f99a512c0ae7649615c2Jean-Michel Trivi        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
820c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi            @Override
82113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap posterArt) {
82213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (posterArt == null
82313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                        || holder.mSelectedEntry == null
824c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                        || holder.mSelectedEntry.program == null) {
825c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                    return;
826c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                }
82713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                String posterArtUri = holder.mSelectedEntry.program.getPosterArtUri();
82813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                if (posterArtUri == null || !posterArtUri.equals(program.getPosterArtUri())) {
8294b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten                    return;
83013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                }
83113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                holder.updatePosterArt(posterArt);
83213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            }
83313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        };
83413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    }
83513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
83613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    private static ImageLoaderCallback<ProgramRowViewHolder> createChannelLogoLoadedCallback(
837c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi            ProgramRowViewHolder holder, final long channelId) {
838c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
83901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            @Override
84001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logo) {
84101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten                if (logo == null
842c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                        || holder.mChannel == null
8434b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten                        || holder.mChannel.getId() != channelId) {
844c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                    return;
84513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                }
846a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi                holder.updateChannelLogo(logo);
847c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi            }
848c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi        };
849c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    }
850c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi
851c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    private static ImageLoaderCallback<ProgramRowViewHolder> createTvInputLogoLoadedCallback(
852c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi            final TvInputInfo info, ProgramRowViewHolder holder) {
853c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
8544b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            @Override
8554b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logo) {
8564b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten                if (logo != null
857c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                        && holder.mChannel != null
858c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                        && info.getId().equals(holder.mChannel.getInputId())) {
859c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                    holder.updateInputLogoInternal(logo);
860c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi                }
861c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi            }
862c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi        };
863c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi    }
864c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi}
865c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi