1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.menu;
18 
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.support.annotation.Nullable;
22 import android.text.TextUtils;
23 import android.util.AttributeSet;
24 import android.util.Log;
25 import android.view.View;
26 import android.widget.ImageView;
27 import android.widget.ProgressBar;
28 import android.widget.TextView;
29 
30 import com.android.tv.MainActivity;
31 import com.android.tv.R;
32 import com.android.tv.data.Channel;
33 import com.android.tv.data.Program;
34 import com.android.tv.parental.ParentalControlSettings;
35 import com.android.tv.util.ImageLoader;
36 
37 /**
38  * A view to render channel card.
39  */
40 public class ChannelCardView extends BaseCardView<Channel> {
41     private static final String TAG = MenuView.TAG;
42     private static final boolean DEBUG = MenuView.DEBUG;
43 
44     private final int mCardImageWidth;
45     private final int mCardImageHeight;
46 
47     private ImageView mImageView;
48     private View mGradientView;
49     private TextView mChannelNumberNameView;
50     private ProgressBar mProgressBar;
51     private Channel mChannel;
52     private Program mProgram;
53     private final MainActivity mMainActivity;
54 
ChannelCardView(Context context)55     public ChannelCardView(Context context) {
56         this(context, null);
57     }
58 
ChannelCardView(Context context, AttributeSet attrs)59     public ChannelCardView(Context context, AttributeSet attrs) {
60         this(context, attrs, 0);
61     }
62 
ChannelCardView(Context context, AttributeSet attrs, int defStyle)63     public ChannelCardView(Context context, AttributeSet attrs, int defStyle) {
64         super(context, attrs, defStyle);
65         mCardImageWidth = getResources().getDimensionPixelSize(R.dimen.card_image_layout_width);
66         mCardImageHeight = getResources().getDimensionPixelSize(R.dimen.card_image_layout_height);
67         mMainActivity = (MainActivity) context;
68     }
69 
70     @Override
onFinishInflate()71     protected void onFinishInflate() {
72         super.onFinishInflate();
73         mImageView = (ImageView) findViewById(R.id.image);
74         mGradientView = findViewById(R.id.image_gradient);
75         mChannelNumberNameView = (TextView) findViewById(R.id.channel_number_and_name);
76         mProgressBar = (ProgressBar) findViewById(R.id.progress);
77     }
78 
79     @Override
onBind(Channel channel, boolean selected)80     public void onBind(Channel channel, boolean selected) {
81         if (DEBUG) {
82             Log.d(TAG, "onBind(channelName=" + channel.getDisplayName() + ", selected=" + selected
83                     + ")");
84         }
85         mChannel = channel;
86         mProgram = null;
87         mChannelNumberNameView.setText(mChannel.getDisplayText());
88         mChannelNumberNameView.setVisibility(VISIBLE);
89         mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default);
90         mImageView.setBackgroundResource(R.color.channel_card);
91         mGradientView.setVisibility(View.GONE);
92         mProgressBar.setVisibility(GONE);
93 
94         setTextViewEnabled(true);
95         if (mMainActivity.getParentalControlSettings().isParentalControlsEnabled()
96                 && mChannel.isLocked()) {
97             setText(R.string.program_title_for_blocked_channel);
98             return;
99         } else {
100             setText("");
101         }
102 
103         updateProgramInformation();
104         // Call super.onBind() at the end intentionally. In order to correctly handle extension of
105         // text view, text should be set before calling super.onBind.
106         super.onBind(channel, selected);
107     }
108 
createProgramPosterArtCallback( ChannelCardView cardView, final Program program)109     private static ImageLoader.ImageLoaderCallback<ChannelCardView> createProgramPosterArtCallback(
110             ChannelCardView cardView, final Program program) {
111         return new ImageLoader.ImageLoaderCallback<ChannelCardView>(cardView) {
112             @Override
113             public void onBitmapLoaded(ChannelCardView cardView, @Nullable Bitmap posterArt) {
114                 if (posterArt == null || cardView.mProgram == null
115                         || program.getChannelId() != cardView.mProgram.getChannelId()
116                         || program.getChannelId() != cardView.mChannel.getId()) {
117                     return;
118                 }
119                 cardView.updatePosterArt(posterArt);
120             }
121         };
122     }
123 
124     private void updatePosterArt(Bitmap posterArt) {
125         mImageView.setImageBitmap(posterArt);
126         mGradientView.setVisibility(View.VISIBLE);
127     }
128 
129     private void updateProgramInformation() {
130         if (mChannel == null) {
131             return;
132         }
133         mProgram = mMainActivity.getProgramDataManager().getCurrentProgram(mChannel.getId());
134         if (mProgram == null || TextUtils.isEmpty(mProgram.getTitle())) {
135             setTextViewEnabled(false);
136             setText(R.string.program_title_for_no_information);
137         } else {
138             setText(mProgram.getTitle());
139         }
140 
141         if (mProgram == null) {
142             return;
143         }
144 
145         long startTime = mProgram.getStartTimeUtcMillis();
146         long endTime = mProgram.getEndTimeUtcMillis();
147         long currTime = System.currentTimeMillis();
148         mProgressBar.setVisibility(View.VISIBLE);
149         if (currTime <= startTime) {
150             mProgressBar.setProgress(0);
151         } else if (currTime >= endTime) {
152             mProgressBar.setProgress(100);
153         } else {
154             mProgressBar.setProgress((int) (100 * (currTime - startTime) / (endTime - startTime)));
155         }
156 
157         if (!(getContext() instanceof MainActivity)) {
158             Log.e(TAG, "Fails to check program's content rating.");
159             return;
160         }
161         ParentalControlSettings parental = mMainActivity.getParentalControlSettings();
162         if ((!parental.isParentalControlsEnabled()
163                 || !parental.isRatingBlocked(mProgram.getContentRatings()))
164                 && !TextUtils.isEmpty(mProgram.getPosterArtUri())) {
165             mProgram.loadPosterArt(getContext(), mCardImageWidth, mCardImageHeight,
166                     createProgramPosterArtCallback(this, mProgram));
167         }
168     }
169 }
170