• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.dvr.ui.browse;
18 
19 import android.content.Context;
20 import android.media.tv.TvContract;
21 import android.support.annotation.Nullable;
22 import android.text.TextUtils;
23 import com.android.tv.R;
24 import com.android.tv.TvSingletons;
25 import com.android.tv.data.api.Channel;
26 import com.android.tv.dvr.data.RecordedProgram;
27 import com.android.tv.dvr.data.ScheduledRecording;
28 import com.android.tv.dvr.data.SeriesRecording;
29 import com.android.tv.dvr.ui.DvrUiHelper;
30 
31 /** A class for details content. */
32 class DetailsContent {
33     /** Constant for invalid time. */
34     public static final long INVALID_TIME = -1;
35 
36     private CharSequence mTitle;
37     private long mStartTimeUtcMillis;
38     private long mEndTimeUtcMillis;
39     private String mDescription;
40     private String mLogoImageUri;
41     private String mBackgroundImageUri;
42     private boolean mUsingChannelLogo;
43 
createFromRecordedProgram( Context context, RecordedProgram recordedProgram)44     static DetailsContent createFromRecordedProgram(
45             Context context, RecordedProgram recordedProgram) {
46         return new DetailsContent.Builder()
47                 .setChannelId(recordedProgram.getChannelId())
48                 .setProgramTitle(recordedProgram.getTitle())
49                 .setSeasonNumber(recordedProgram.getSeasonNumber())
50                 .setEpisodeNumber(recordedProgram.getEpisodeNumber())
51                 .setStartTimeUtcMillis(recordedProgram.getStartTimeUtcMillis())
52                 .setEndTimeUtcMillis(recordedProgram.getEndTimeUtcMillis())
53                 .setDescription(
54                         TextUtils.isEmpty(recordedProgram.getLongDescription())
55                                 ? recordedProgram.getDescription()
56                                 : recordedProgram.getLongDescription())
57                 .setPosterArtUri(recordedProgram.getPosterArtUri())
58                 .setThumbnailUri(recordedProgram.getThumbnailUri())
59                 .build(context);
60     }
61 
createFromSeriesRecording( Context context, SeriesRecording seriesRecording)62     static DetailsContent createFromSeriesRecording(
63             Context context, SeriesRecording seriesRecording) {
64         return new DetailsContent.Builder()
65                 .setChannelId(seriesRecording.getChannelId())
66                 .setTitle(seriesRecording.getTitle())
67                 .setDescription(
68                         TextUtils.isEmpty(seriesRecording.getLongDescription())
69                                 ? seriesRecording.getDescription()
70                                 : seriesRecording.getLongDescription())
71                 .setPosterArtUri(seriesRecording.getPosterUri())
72                 .setThumbnailUri(seriesRecording.getPhotoUri())
73                 .build(context);
74     }
75 
createFromScheduledRecording( Context context, ScheduledRecording scheduledRecording)76     static DetailsContent createFromScheduledRecording(
77             Context context, ScheduledRecording scheduledRecording) {
78         Channel channel =
79                 TvSingletons.getSingletons(context)
80                         .getChannelDataManager()
81                         .getChannel(scheduledRecording.getChannelId());
82         String description =
83                 !TextUtils.isEmpty(scheduledRecording.getProgramDescription())
84                         ? scheduledRecording.getProgramDescription()
85                         : scheduledRecording.getProgramLongDescription();
86         if (TextUtils.isEmpty(description)) {
87             description = channel != null ? channel.getDescription() : null;
88         }
89         return new DetailsContent.Builder()
90                 .setChannelId(scheduledRecording.getChannelId())
91                 .setProgramTitle(scheduledRecording.getProgramTitle())
92                 .setSeasonNumber(scheduledRecording.getSeasonNumber())
93                 .setEpisodeNumber(scheduledRecording.getEpisodeNumber())
94                 .setStartTimeUtcMillis(scheduledRecording.getStartTimeMs())
95                 .setEndTimeUtcMillis(scheduledRecording.getEndTimeMs())
96                 .setDescription(description)
97                 .setPosterArtUri(scheduledRecording.getProgramPosterArtUri())
98                 .setThumbnailUri(scheduledRecording.getProgramThumbnailUri())
99                 .build(context);
100     }
101 
createFromFailedScheduledRecording( Context context, ScheduledRecording scheduledRecording, String errMsg)102     static DetailsContent createFromFailedScheduledRecording(
103             Context context, ScheduledRecording scheduledRecording, String errMsg) {
104         Channel channel =
105                 TvSingletons.getSingletons(context)
106                         .getChannelDataManager()
107                         .getChannel(scheduledRecording.getChannelId());
108         String description;
109         if (scheduledRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED
110                 && errMsg != null) {
111             description = errMsg
112                     + " (Error code: " + scheduledRecording.getFailedReason() + ")";
113         } else {
114             description =
115                     !TextUtils.isEmpty(scheduledRecording.getProgramDescription())
116                             ? scheduledRecording.getProgramDescription()
117                             : scheduledRecording.getProgramLongDescription();
118         }
119         if (TextUtils.isEmpty(description)) {
120             description = channel != null ? channel.getDescription() : null;
121         }
122         return new DetailsContent.Builder()
123                 .setChannelId(scheduledRecording.getChannelId())
124                 .setProgramTitle(scheduledRecording.getProgramTitle())
125                 .setSeasonNumber(scheduledRecording.getSeasonNumber())
126                 .setEpisodeNumber(scheduledRecording.getEpisodeNumber())
127                 .setStartTimeUtcMillis(scheduledRecording.getStartTimeMs())
128                 .setEndTimeUtcMillis(scheduledRecording.getEndTimeMs())
129                 .setDescription(description)
130                 .setPosterArtUri(scheduledRecording.getProgramPosterArtUri())
131                 .setThumbnailUri(scheduledRecording.getProgramThumbnailUri())
132                 .build(context);
133     }
134 
DetailsContent()135     private DetailsContent() {}
136 
137     /** Returns title. */
getTitle()138     public CharSequence getTitle() {
139         return mTitle;
140     }
141 
142     /** Returns start time. */
getStartTimeUtcMillis()143     public long getStartTimeUtcMillis() {
144         return mStartTimeUtcMillis;
145     }
146 
147     /** Returns end time. */
getEndTimeUtcMillis()148     public long getEndTimeUtcMillis() {
149         return mEndTimeUtcMillis;
150     }
151 
152     /** Returns description. */
getDescription()153     public String getDescription() {
154         return mDescription;
155     }
156 
157     /** Returns Logo image URI as a String. */
getLogoImageUri()158     public String getLogoImageUri() {
159         return mLogoImageUri;
160     }
161 
162     /** Returns background image URI as a String. */
getBackgroundImageUri()163     public String getBackgroundImageUri() {
164         return mBackgroundImageUri;
165     }
166 
167     /** Returns if image URIs are from its channels' logo. */
isUsingChannelLogo()168     public boolean isUsingChannelLogo() {
169         return mUsingChannelLogo;
170     }
171 
172     /** Copies other details content. */
copyFrom(DetailsContent other)173     public void copyFrom(DetailsContent other) {
174         if (this == other) {
175             return;
176         }
177         mTitle = other.mTitle;
178         mStartTimeUtcMillis = other.mStartTimeUtcMillis;
179         mEndTimeUtcMillis = other.mEndTimeUtcMillis;
180         mDescription = other.mDescription;
181         mLogoImageUri = other.mLogoImageUri;
182         mBackgroundImageUri = other.mBackgroundImageUri;
183         mUsingChannelLogo = other.mUsingChannelLogo;
184     }
185 
186     /** A class for building details content. */
187     public static final class Builder {
188         private final DetailsContent mDetailsContent;
189 
190         private long mChannelId;
191         private String mProgramTitle;
192         private String mSeasonNumber;
193         private String mEpisodeNumber;
194         private String mPosterArtUri;
195         private String mThumbnailUri;
196 
Builder()197         public Builder() {
198             mDetailsContent = new DetailsContent();
199             mDetailsContent.mStartTimeUtcMillis = INVALID_TIME;
200             mDetailsContent.mEndTimeUtcMillis = INVALID_TIME;
201         }
202 
203         /** Sets title. */
setTitle(CharSequence title)204         public Builder setTitle(CharSequence title) {
205             mDetailsContent.mTitle = title;
206             return this;
207         }
208 
209         /** Sets start time. */
setStartTimeUtcMillis(long startTimeUtcMillis)210         public Builder setStartTimeUtcMillis(long startTimeUtcMillis) {
211             mDetailsContent.mStartTimeUtcMillis = startTimeUtcMillis;
212             return this;
213         }
214 
215         /** Sets end time. */
setEndTimeUtcMillis(long endTimeUtcMillis)216         public Builder setEndTimeUtcMillis(long endTimeUtcMillis) {
217             mDetailsContent.mEndTimeUtcMillis = endTimeUtcMillis;
218             return this;
219         }
220 
221         /** Sets description. */
setDescription(String description)222         public Builder setDescription(String description) {
223             mDetailsContent.mDescription = description;
224             return this;
225         }
226 
227         /** Sets logo image URI as a String. */
setLogoImageUri(String logoImageUri)228         public Builder setLogoImageUri(String logoImageUri) {
229             mDetailsContent.mLogoImageUri = logoImageUri;
230             return this;
231         }
232 
233         /** Sets background image URI as a String. */
setBackgroundImageUri(String backgroundImageUri)234         public Builder setBackgroundImageUri(String backgroundImageUri) {
235             mDetailsContent.mBackgroundImageUri = backgroundImageUri;
236             return this;
237         }
238 
setProgramTitle(String programTitle)239         private Builder setProgramTitle(String programTitle) {
240             mProgramTitle = programTitle;
241             return this;
242         }
243 
setSeasonNumber(String seasonNumber)244         private Builder setSeasonNumber(String seasonNumber) {
245             mSeasonNumber = seasonNumber;
246             return this;
247         }
248 
setEpisodeNumber(String episodeNumber)249         private Builder setEpisodeNumber(String episodeNumber) {
250             mEpisodeNumber = episodeNumber;
251             return this;
252         }
253 
setChannelId(long channelId)254         private Builder setChannelId(long channelId) {
255             mChannelId = channelId;
256             return this;
257         }
258 
setPosterArtUri(String posterArtUri)259         private Builder setPosterArtUri(String posterArtUri) {
260             mPosterArtUri = posterArtUri;
261             return this;
262         }
263 
setThumbnailUri(String thumbnailUri)264         private Builder setThumbnailUri(String thumbnailUri) {
265             mThumbnailUri = thumbnailUri;
266             return this;
267         }
268 
createStyledTitle(Context context, Channel channel)269         private void createStyledTitle(Context context, Channel channel) {
270             CharSequence title =
271                     DvrUiHelper.getStyledTitleWithEpisodeNumber(
272                             context,
273                             mProgramTitle,
274                             mSeasonNumber,
275                             mEpisodeNumber,
276                             R.style.text_appearance_card_view_episode_number);
277             if (TextUtils.isEmpty(title)) {
278                 mDetailsContent.mTitle =
279                         channel != null
280                                 ? channel.getDisplayName()
281                                 : context.getResources().getString(R.string.no_program_information);
282             } else {
283                 mDetailsContent.mTitle = title;
284             }
285         }
286 
createImageUris(@ullable Channel channel)287         private void createImageUris(@Nullable Channel channel) {
288             mDetailsContent.mLogoImageUri = null;
289             mDetailsContent.mBackgroundImageUri = null;
290             mDetailsContent.mUsingChannelLogo = false;
291             if (!TextUtils.isEmpty(mPosterArtUri) && !TextUtils.isEmpty(mThumbnailUri)) {
292                 mDetailsContent.mLogoImageUri = mPosterArtUri;
293                 mDetailsContent.mBackgroundImageUri = mThumbnailUri;
294             } else if (!TextUtils.isEmpty(mPosterArtUri)) {
295                 // thumbnailUri is empty
296                 mDetailsContent.mLogoImageUri = mPosterArtUri;
297                 mDetailsContent.mBackgroundImageUri = mPosterArtUri;
298             } else if (!TextUtils.isEmpty(mThumbnailUri)) {
299                 // posterArtUri is empty
300                 mDetailsContent.mLogoImageUri = mThumbnailUri;
301                 mDetailsContent.mBackgroundImageUri = mThumbnailUri;
302             }
303             if (TextUtils.isEmpty(mDetailsContent.mLogoImageUri) && channel != null) {
304                 String channelLogoUri = TvContract.buildChannelLogoUri(channel.getId()).toString();
305                 mDetailsContent.mLogoImageUri = channelLogoUri;
306                 mDetailsContent.mBackgroundImageUri = channelLogoUri;
307                 mDetailsContent.mUsingChannelLogo = true;
308             }
309         }
310 
311         /** Builds details content. */
build(Context context)312         public DetailsContent build(Context context) {
313             Channel channel =
314                     TvSingletons.getSingletons(context)
315                             .getChannelDataManager()
316                             .getChannel(mChannelId);
317             if (mDetailsContent.mTitle == null) {
318                 createStyledTitle(context, channel);
319             }
320             if (mDetailsContent.mBackgroundImageUri == null
321                     && mDetailsContent.mLogoImageUri == null) {
322                 createImageUris(channel);
323             }
324             DetailsContent detailsContent = new DetailsContent();
325             detailsContent.copyFrom(mDetailsContent);
326             return detailsContent;
327         }
328     }
329 }
330