ProgramInfo.java revision 816a4be1a0f34f6a48877c8afd3dbbca19eac435
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 17package com.android.tv.testing; 18 19import android.content.Context; 20import android.database.Cursor; 21import android.media.tv.TvContentRating; 22import android.media.tv.TvContract; 23 24import java.util.concurrent.TimeUnit; 25 26public final class ProgramInfo { 27 /** 28 * If this is specify for title, it will be generated by adding index. 29 */ 30 public static final String GEN_TITLE = ""; 31 32 /** 33 * If this is specify for episode title, it will be generated by adding index. 34 * Also, season and episode numbers would be generated, too. 35 * see: {@link #build} for detail. 36 */ 37 public static final String GEN_EPISODE = ""; 38 private static final int SEASON_MAX = 10; 39 private static final int EPISODE_MAX = 12; 40 41 /** 42 * If this is specify for poster art, 43 * it will be selected one of {@link #POSTER_ARTS_RES} in order. 44 */ 45 public static final String GEN_POSTER = "GEN"; 46 private static final int[] POSTER_ARTS_RES = { 47 0, 48 R.drawable.blue, 49 R.drawable.red_large, 50 R.drawable.green, 51 R.drawable.red, 52 R.drawable.green_large, 53 R.drawable.blue_small}; 54 55 /** 56 * If this is specified for duration, 57 * it will be selected one of {@link #DURATIONS_MS} in order. 58 */ 59 public static final int GEN_DURATION = -1; 60 private static final long[] DURATIONS_MS = { 61 TimeUnit.MINUTES.toMillis(15), 62 TimeUnit.MINUTES.toMillis(45), 63 TimeUnit.MINUTES.toMillis(90), 64 TimeUnit.MINUTES.toMillis(60), 65 TimeUnit.MINUTES.toMillis(30), 66 TimeUnit.MINUTES.toMillis(45), 67 TimeUnit.MINUTES.toMillis(60), 68 TimeUnit.MINUTES.toMillis(90), 69 TimeUnit.HOURS.toMillis(5)}; 70 private static long DURATIONS_SUM_MS; 71 static { 72 DURATIONS_SUM_MS = 0; 73 for (int i = 0; i < DURATIONS_MS.length; i++) { 74 DURATIONS_SUM_MS += DURATIONS_MS[i]; 75 } 76 } 77 78 /** 79 * If this is specified for genre, 80 * it will be selected one of {@link #GENRES} in order. 81 */ 82 public static final String GEN_GENRE = "GEN"; 83 private static final String[] GENRES = { 84 "", 85 TvContract.Programs.Genres.SPORTS, 86 TvContract.Programs.Genres.NEWS, 87 TvContract.Programs.Genres.SHOPPING, 88 TvContract.Programs.Genres.DRAMA, 89 TvContract.Programs.Genres.ENTERTAINMENT}; 90 91 public final String title; 92 public final String episode; 93 public final int seasonNumber; 94 public final int episodeNumber; 95 public final String posterArtUri; 96 public final String description; 97 public final long durationMs; 98 public final String genre; 99 public final TvContentRating[] contentRatings; 100 public final String resourceUri; 101 102 public static ProgramInfo fromCursor(Cursor c) { 103 // TODO: Fill other fields. 104 Builder builder = new Builder(); 105 int index = c.getColumnIndex(TvContract.Programs.COLUMN_TITLE); 106 if (index >= 0) { 107 builder.setTitle(c.getString(index)); 108 } 109 index = c.getColumnIndex(TvContract.Programs.COLUMN_SHORT_DESCRIPTION); 110 if (index >= 0) { 111 builder.setDescription(c.getString(index)); 112 } 113 index = c.getColumnIndex(TvContract.Programs.COLUMN_EPISODE_TITLE); 114 if (index >= 0) { 115 builder.setEpisode(c.getString(index)); 116 } 117 return builder.build(); 118 } 119 120 public ProgramInfo(String title, String episode, int seasonNumber, int episodeNumber, 121 String posterArtUri, String description, long durationMs, 122 TvContentRating[] contentRatings, String genre, String resourceUri) { 123 this.title = title; 124 this.episode = episode; 125 this.seasonNumber = seasonNumber; 126 this.episodeNumber = episodeNumber; 127 this.posterArtUri = posterArtUri; 128 this.description = description; 129 this.durationMs = durationMs; 130 this.contentRatings = contentRatings; 131 this.genre = genre; 132 this.resourceUri = resourceUri; 133 } 134 135 /** 136 * Create a instance of {@link ProgramInfo} whose content will be generated as much as possible. 137 */ 138 public static ProgramInfo create() { 139 return new Builder().build(); 140 } 141 142 /** 143 * Get index of the program whose start time equals or less than {@code timeMs} and 144 * end time more than {@code timeMs}. 145 * @param timeMs target time in millis to find a program. 146 * @param channelId used to add complexity to the index between two consequence channels. 147 */ 148 public int getIndex(long timeMs, long channelId) { 149 if (durationMs != GEN_DURATION) { 150 return Math.max((int) (timeMs / durationMs), 0); 151 } 152 long startTimeMs = channelId * DURATIONS_MS[((int) (channelId % DURATIONS_MS.length))]; 153 int index = (int) ((timeMs - startTimeMs) / DURATIONS_SUM_MS) * DURATIONS_MS.length; 154 startTimeMs += (index / DURATIONS_MS.length) * DURATIONS_SUM_MS; 155 while (startTimeMs + DURATIONS_MS[index % DURATIONS_MS.length] < timeMs) { 156 startTimeMs += DURATIONS_MS[index % DURATIONS_MS.length]; 157 index++; 158 } 159 return index; 160 } 161 162 /** 163 * Returns the start time for the program with the position. 164 * @param index index returned by {@link #getIndex} 165 */ 166 public long getStartTimeMs(int index, long channelId) { 167 if (durationMs != GEN_DURATION) { 168 return index * durationMs; 169 } 170 long startTimeMs = channelId * DURATIONS_MS[((int) (channelId % DURATIONS_MS.length))] 171 + (index / DURATIONS_MS.length) * DURATIONS_SUM_MS; 172 for (int i = 0; i < index % DURATIONS_MS.length; i++) { 173 startTimeMs += DURATIONS_MS[i]; 174 } 175 return startTimeMs; 176 } 177 178 /** 179 * Return complete {@link ProgramInfo} with the generated value. 180 * See: {@link #GEN_TITLE}, {@link #GEN_EPISODE}, {@link #GEN_POSTER}, {@link #GEN_DURATION}, 181 * {@link #GEN_GENRE}. 182 * @param index index returned by {@link #getIndex} 183 */ 184 public ProgramInfo build(Context context, int index) { 185 if (!GEN_TITLE.equals(title) 186 && !GEN_EPISODE.equals(episode) 187 && !GEN_POSTER.equals(posterArtUri) 188 && durationMs != GEN_DURATION 189 && !GEN_GENRE.equals(genre)) { 190 return this; 191 } 192 return new ProgramInfo( 193 GEN_TITLE.equals(title) ? "Title(" + index + ")" : title, 194 GEN_EPISODE.equals(episode) ? "Episode(" + index + ")" : episode, 195 GEN_EPISODE.equals(episode) ? (index % SEASON_MAX + 1) : seasonNumber, 196 GEN_EPISODE.equals(episode) ? (index % EPISODE_MAX + 1) : episodeNumber, 197 GEN_POSTER.equals(posterArtUri) 198 ? Utils.getUriStringForResource(context, 199 POSTER_ARTS_RES[index % POSTER_ARTS_RES.length]) 200 : posterArtUri, 201 description, 202 durationMs == GEN_DURATION ? DURATIONS_MS[index % DURATIONS_MS.length] : durationMs, 203 contentRatings, 204 GEN_GENRE.equals(genre) ? GENRES[index % GENRES.length] : genre, 205 resourceUri); 206 } 207 208 @Override 209 public String toString() { 210 return "ProgramInfo{title=" + title 211 + ", episode=" + episode 212 + ", durationMs=" + durationMs + "}"; 213 } 214 215 public static class Builder { 216 private String mTitle = GEN_TITLE; 217 private String mEpisode = GEN_EPISODE; 218 private int mSeasonNumber; 219 private int mEpisodeNumber; 220 private String mPosterArtUri = GEN_POSTER; 221 private String mDescription; 222 private long mDurationMs = GEN_DURATION; 223 private TvContentRating[] mContentRatings; 224 private String mGenre = GEN_GENRE; 225 private String mResourceUri; 226 227 public Builder setTitle(String title) { 228 mTitle = title; 229 return this; 230 } 231 232 public Builder setEpisode(String episode) { 233 mEpisode = episode; 234 return this; 235 } 236 237 public Builder setSeasonNumber(int seasonNumber) { 238 mSeasonNumber = seasonNumber; 239 return this; 240 } 241 242 public Builder setEpisodeNumber(int episodeNumber) { 243 mEpisodeNumber = episodeNumber; 244 return this; 245 } 246 247 public Builder setPosterArtUri(String posterArtUri) { 248 mPosterArtUri = posterArtUri; 249 return this; 250 } 251 252 public Builder setDescription(String description) { 253 mDescription = description; 254 return this; 255 } 256 257 public Builder setDurationMs(long durationMs) { 258 mDurationMs = durationMs; 259 return this; 260 } 261 262 public Builder setContentRatings(TvContentRating[] contentRatings) { 263 mContentRatings = contentRatings; 264 return this; 265 } 266 267 public Builder setGenre(String genre) { 268 mGenre = genre; 269 return this; 270 } 271 272 public Builder setResourceUri(String resourceUri) { 273 mResourceUri = resourceUri; 274 return this; 275 } 276 277 public ProgramInfo build() { 278 return new ProgramInfo(mTitle, mEpisode, mSeasonNumber, mEpisodeNumber, mPosterArtUri, 279 mDescription, mDurationMs, mContentRatings, mGenre, mResourceUri); 280 } 281 } 282} 283