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